快捷搜索:

帮助程序员解脱困境的十条技巧

安然专家 Michael Howard 和 Keith Brown 提出了十条技术来赞助您解脱逆境。

安然问题涉及许多方面。安然风险可能来自任何地方。您可能编写了无效的差错处置惩罚代码,或者在付与权限时过于慷慨。您可能忘怀了在您的办事器上正在运行什么办事。您可能吸收了所有用户输入。如斯等等。为使您在保护自己的谋略机、收集和代码方面有个优越起头,这里展示了十条技术,遵照这些技术可以得到一个更安然的收集策略。

1. 相信用户的输入会将自己置于险境

纵然不涉猎余下的内容,也要记着一点,“不要相信用户输入”。假如您老是假设数据是有效的并且没有恶意,那么问题就来了。大年夜多半安然懦弱环节都与进击者向办事器供给恶意编写的数据有关。

相信输入的精确性可能会导致缓冲区溢出、跨站点脚本进击、SQL 插入代码进击等等。

让我们具体评论争论一下这些潜在进击要领。

2. 防止缓冲区溢出

当进击者供给的数据长度大年夜于利用法度榜样的预期时,便会发生缓冲区溢出,此时数据会溢出到内部存储器空间。缓冲区溢出主如果一个 C/C++ 问题。它们是种要挟,但平日很轻易修补。我们只看到过两个不显着且难以修复的缓冲区溢出。开拓职员没有预感到外部供给的数据会比内部缓冲区大年夜。溢出导致了内存中其他数据布局的破坏,这种破坏平日会被进击者使用,以运行恶意代码。数组索引差错也会造成缓冲区下溢和超限,但这种环境

没那么普遍。

请看以下 C++ 代码片段:

void DoSomething(char *cBuffSrc, DWORD cbBuffSrc)

{

char cBuffDest[32];

memcpy(cBuffDest,cBuffSrc,cbBuffSrc);

}

问题在哪里?事实上,假如 cBuffSrc 和 cbBuffSrc 来自可托赖的源(例如不相信数据并是以而验证数据的有效性和大年夜小的代码),则这段代码没有任何问题。然而,假如数据来自弗成信赖的源,也未获得验证,那么进击者(弗成信赖源)很轻易就可以使cBuffSrc 比 cBuffDest 大年夜,同时也将 cbBuffSrc 设定为比 cBuffDest 大年夜。当 memcpy将数据复制到 cBuffDest 中时,来自 DoSomething 的返回地址就会被变动,由于cBuffDest 在函数的客栈框架上与返回地址相邻,此时进击者即可经由过程代码履行一些恶意操作。

增补的措施便是不要相信用户的输入,并且不相信 cBuffSrc 和 cbBuffSrc 中携带的任何数据:

void DoSomething(char *cBuffSrc, DWORD cbBuffSrc)

{

const DWORD cbBuffDest = 32;

char cBuffDest[cbBuffDest];

#ifdef _DEBUG

memset(cBuffDest, 0x33, cbBuffSrc);

#endif

memcpy(cBuffDest, cBuffSrc, min(cbBuffDest, cbBuffSrc));

}

此函数展示了一个能够削减缓冲区溢出的精确编写的函数的三个特点。首先,它要求调用者供给缓冲区的长度。当然,您不能盲目信托这个值!接下来,在一个调试版本中,代码将探测缓冲区是否真的足够大年夜,以便能够寄放源缓冲区。假如不能,则可能触发一个造访冲突并把代码载入调试器。在调试时,您会惊奇地发明竟有如斯多的差错。着末也是最紧张的是,对 memcpy 的调用是防御性的,它不会复制多于目标缓冲区寄放能力的数据。

在 Windows Security Push at Microsoft(Microsoft Windows? 安然推动活动)中,我们为 C 法度榜样员创建了一个安然字符串处置惩罚函数列表。您可以在 Strsafe.h: SaferString Handling in C(英文)中找到它们。

3. 防止跨站点脚本

跨站点脚本进击是 Web 特有的问题,它能经由过程单个 Web 页中的一点隐患迫害客户真个数据。想像一下,下面的 ASP.NET 代码片段会造成什么后果:

有若干人曾经见过类似的代码?但令人惊疑的是它有问题!平日,用户会应用类似如下的 URL 造访这段代码: http://explorationair.com/welcome.aspx?name=Michael

4. 不要哀求 sa 权限

我们要评论争论的着末一种输入相信进击是 SQL 插入代码。许多开拓职员编写这样的代码,即获取输入并应用该输入来建立 SQL 查询,进而与后台数据存储(如 Microsoft SQL Server 或 Oracle)进行通信。

请看以下代码片段:

void DoQuery(string Id)

{

SqlConnection sql=new SqlConnection(@"data source=localhost;" + "user id=sa;password=password;");

sql.Open();

sqlstring= "SELECT hasshipped" + " FROM shipping WHERE id='" + Id + "'";

SqlCommand cmd = new SqlCommand(sqlstring,sql);

...

}

这段代码有三个严重缺陷。首先,它因此系统治理员帐户 sa 建立从 Web 办事到SQL Server的连接的。不久您就会看到这样做的缺陷所在。第二点,留意应用“password”作为 sa帐户密码的智慧做法!但真正值得关注的是构造 SQL 语句的字符串连接。假如用户为 ID 输入 1001,您会获得如下 SQL 语句,它是完全有效的。

SELECT hasshipped FROM shipping WHERE id = '1001'

但进击者比这要有创意得多。他们会为 ID 输入一个“'1001' DROP table shipping --”,它将履行如下查询:

SELECT hasshipped FROM shipping WHERE id = '1001' DROP table shipping -- ';

它变动了查询的事情要领。这段代码不仅会考试测验判断是否装运了某些货物,它还会继承 drop(删除)shipping 表!操作符 -- 是 SQL 中的注释操作符,它使进击者能够更轻易地构造一系列有效但危险的 SQL 语句!

6. 削减自己被进击的可能性

假如没有百分之九十以上的用户要求,则不应默认安装某一功能。Internet Information Services (IIS) 6.0 遵照了这一安装建议,您可以在这个月宣布的 Wayne Berry 的文章“Innovations in Internet Information Services Let You Tightly Guard Secure Data and Server Processes”中读到相关内容。这种安装策略背后的思惟是您不会留意自己并未应用的办事,假如这些办事正在运行,则可能被其他人使用。假如默认安装某功能,则它应在最小授权原则下运行。也便是说,除非需要,否则不要容许应用治理员权限运行利用法度榜样。最好遵照这一箴规针砭。

7. 应用最小授权原则

出于多少缘故原由,操作系统和公共说话运行时有一个安然策略。很多人以为此安然策略存在的主要缘故原由是防止用户故意破坏:造访他们无权造访的文件、从新设置设置设备摆设摆设收集以达到他们的要求以及其他恶劣行径。切实着实,这种来自内部的进击很普遍,也必要警备,但还有另一个缘故原由必要严守这一安然策略。即在代码周围建立起警备壁垒以防止用户故意或(正如常常发生的)无意的操作对收集造成严重破坏。例如,经由过程电子邮件下载的附件在Alice

的机械上履行时被限定为只能造访 Alice 可以造访的资本。假如附件中含有特洛伊木马,那么好的安然策略便是限定它所能孕育发生的破坏。当您设计、建立并支配办事器利用法度榜样时,您不能假设所有哀求都来自合法用户。假如一个坏家伙发送给您一个恶意哀求(但愿不会如斯)并使您的代码孕育发生恶劣操作,您会盼望您的利用法度榜样拥有所有可能的防护来限定侵害。是以我们觉得,您的公司实施安然策略不仅是由于它不相信您或您的代码,同时也是为了保护不受外界有妄图的代码的危害。

8. 留意掉败模式

吸收它吧。其他人和您一样仇恨编写差错处置惩罚代码。导致代码掉败的缘故原由如斯浩繁,一想到这些就让人沮丧。大年夜多半法度榜样员,包括我们,更乐意关注正常的履行路径。那里才是真正完成事情的地方。让我们尽可能快而无痛地完成这些差错处置惩罚,然后继承下一行真正的代码吧。

只可惜,这种情绪并不安然。相反,我们必要更亲昵地关注代码中的掉败模式。人们对这些代码的编写平日很少深入留意,并且经常没有颠末完全测试。还记得着末一次您完全肯定调试过函数的每一行代码,包括此中每一个很小的差错处置惩罚法度榜样是什么时刻?

未经测试的代码常会导致安然破绽。有三件工作可以赞助您减轻这个问题。首先,对那些很小的差错处置惩罚法度榜样给予和正常代码同样的关注。斟酌当您的差错处置惩罚代码履行时系统的状态。系统是否处于有效并且安然的状态中?其次,一旦您编写了一个函数,请慢慢将它彻底调试几遍,确保测试每一个差错处置惩罚法度榜样。留意,纵然应用这样的技巧,也可能无法发明异常隐秘的计时差错。您可能必要给您的函数通报差错参数,或者以某种要领调剂系统的状态,以使您的差错处置惩罚法度榜样得以履行。经由过程花光阴单步调试代码,您可以慢下来并有足够的光阴来查看代码以及系统运行时的状态。经由过程在调试器中仔细单步履行代码,我们在自己的编程逻辑中发清楚明了许多缺陷。这是一个已获得证实的技巧。请应用这一技巧。着末,确保您的测试组合能使您的函数进行掉败测试。只管即便使测试组合能够查验函数中的每一行代码。这能赞助您发明规律,分外是当使测试自动化并在每次建立代码后运行测试时。关于掉败模式还有一件异常紧张的工作必要阐明。当您的代码掉败时要确保系统处于可能的最安然状态。下面显示了一些有问题的代码:

那么您的运行情况将有两种不合的安然情况:您将具有一个进程标记和一个线程标记,一样平常来说,线程标记会被用来做造访反省(见图)。假设您正在编写一个在 Web 办事器进程中运行的 ISAPI 利用法度榜样,并假定大年夜多半哀求未经身份验证,则您的线程标记可能是 IUSR_MACHINE,而进程标记却是 SYSTEM!假设您的代码能被一个坏家伙经由过程缓冲区溢出使用。您觉得他会只满意作为 IUSR_MACHINE 运行吗?当然不会。他的进击代码很可能会调用 RevertToSelf 以删除模拟标记,从而盼望前进他的权限级别。在这种环境下,他会很轻易得到成功。他还可以调用 CreateProcess。它不会从模拟标记复制新进程的标记,而是从进程标记复制,这样新进程便可以作为 SYSTEM 运行。

那么如何办理这个小问题呢?除了首先确保不呈现任何缓冲区溢出外,还要记着最小授权原则。假如您的代码不必要具有 SYSTEM 这样大年夜的权限,则不要将 Web 利用法度榜样设置设置设备摆设摆设为在 Web 办事器进程中运行。假如只是将 Web 利用法度榜样设置设置设备摆设摆设为在中等或较高的隔离情况中运行,您的进程标记将会是 IWAM_MACHINE。您实际上没有任何权限,因而这种进击险些不会生效。留意,在 IIS 6.0(即将成为 Windows .NET Server 的一个组件)中,默认环境下用户编写的代码不会作为 SYSTEM 运行。基于这样的熟识,即开拓职员确凿会犯差错,Web 办事器就削减付与代码的权限而供给的任何赞助都是有益的,以免万一代码中存在安然问题。

下面是别的一个 COM 法度榜样员可能碰到的隐患。COM 有一个不好的倾向便是应付线程。假如您调用一个进程内 COM 办事器,而其线程模型与调用线程的模型不匹配,则 COM会在另一个线程上履行调用。COM 不会传播调用者线程上的模拟标记,这样结果便是调用会在进程的安然情况中履行,而不是在调用线程的安然情况中。多么令人吃惊!

您可能还会对下面的文章感兴趣: