标题:
开放源码软件:它会使我安全吗?
[打印本页]
作者:
无悔
时间:
2004-4-4 12:07
标题:
开放源码软件:它会使我安全吗?
一个常见的错误概念是:开放软件的源代码会改进您软件的安全性。实际上,如果您这样做,是要冒很大的安全性风险的。仅当您意识到这些风险,并寻求方法积极地解决它们时,开放源代码才有可能改进您软件的安全性。本文作者 John Viega 是安全性领域的专家研究员及顾问,如果您决定加入开放源码行列,本文将向您阐述由此带来的风险,并就应该如何有效地将这些风险降到最低,提供了很好的建议。
开放您软件的源代码会改进其安全性吗?开放源码软件与安全性相关联主要好处是所谓的“许多双眼睛”现象 — 让更多的人仔细检查您的代码,这使您能及时地发现和纠正错误,尤其是与安全性相关的错误。的确,这种现象能够帮助您找到代码中一些如果不开放源代码,您就可能找不到的问题。但是,无法保证这些仔细检查您开放源码的人会找到代码中的任何安全性问题,更不用说找到所有问题了。也无法保证任何找到安全性问题的人会真正报告这些问题。
并非所有查看者都总是能看出问题
尽管有许多双眼睛在注视着,但即使是一些经受了最广泛仔细检查的开放源码软件,也还是有一些重大的错误存在了若干年都没有被检测出来。例如,最近向全球发布了防止 wu-ftpd 中堆栈粉碎攻击(一种缓冲区溢出)的利用和补丁。安全性专家和破解者社团的成员曾多次检查过这个代码,但如果开发人员以前就发现了这个问题,他们早就将它自行解决了。
具有讽刺意义的是,在学术界中,wu-ftpd 曾经被用作弱点检测技术的案例研究。实际上,有一个工具曾确认该代码可能有可以被利用的地方,但进一步的研究使得研究人员相信他们检测到的是一个不可利用的情况。一年多以后,他们得知自己是错的;位于圣路易斯市的华盛顿大学迅速修正了这个问题。
使弱点检测更容易
在 wu-ftpd 中找到的安全性问题是一个简单的缓冲区溢出情况。为什么这么多人都遗漏了这个问题呢?事实证明:判断某个特定函数的个别用法是否危险可能是很难的。并非危险函数的每种用法生来都是危险的。
在缓冲区溢出这种情况中(也称为堆栈粉碎攻击),应该避免使用 C 标准库中的许多函数,因为它们容易引起缓冲区溢出。但是,可以用安全的方式使用这些函数中的大多数。例如,strcpy 是所有危险库函数中最声名狼籍的一个。下列代码是 strcpy 的一种危险用法:
void main(int argc, char **argv) {
char program_name[256];
strcpy(program_name, argv[0]);
}
如果程序名大于 255 个字符(终结的空值字符不计在内),则缓冲区 program_name 将溢出。对于大多数体系结构,可以操作这种溢出,来将带有该程序权限的命令提示符赋予恶意用户。因此,如果程序有管理员特权(例如,在 UNIX 系统上是 setuidroot),这种性质的错误把对您机器的管理访问权赋予攻击者。
作一个简单的修改,就可以使上面的代码变得无害:
void main(int argc, char **argv) {
char program_name[256];
strncpy(program_name, argv[0], 256);
}
上面对 strncpy 的调用将从 argv[0] 复制到 program_name,就象常规的 strcpy 所做的一样。但是,它绝不会复制 256 个以上的字符。
在这两个示例中,很容易确定是否存在问题。但是在更复杂的代码中,判断会困难得多。如果在源代码中某处看到 strcpy,并且在使用之前立即检查字符串的长度,那么,假定编写的检查正确的话,则可以肯定不会出问题。但是,如果没有立即进行此类显式检查,会怎么样呢?也许程序员省略了这种检查,但也可能在程序中的其它地方进行了检查。对于象 wu-ftpd 这样的大型程序,根据程序逻辑沿着所有可能到达的路径进行反向遍历是非常困难的。通常,此类调用实际上看起来没有问题,但由于广泛分离的各段代码之间极微妙的交互作用,其实它是可利用的。
当然,在可以使用标准库函数中“安全的”版本时,应该优先选择使用它们。例如,snprintf 是 sprintf 的“安全的”版本,但它并不是在每个平台上都可以使用。但是,甚至这些“安全的”调用也会被误用。例如,就安全性而言,strncpy 优于 strcpy,但对于缓冲区溢出错误它也并非绝对安全。考虑下列代码片段: strncpy(dst, src, n);
如果由于某些错误,使 n 大于 dst 的长度,那么,当这个代码执行时,缓冲区溢出情况仍有可能出现。
并非所有查看者都总是会报告问题
开放您软件的源代码使其中的任何安全性问题更有可能被发现,但到底是好人还是坏人发现问题就是另一回事了。确实有必要担心,黑客找到了错误却不向您报告它们。虽然大多数黑客有道德规范,不会做这种事情,但违反规则的也很多。
即使当好人发现问题时,坏人也还是可以在未来相当长时间内利用该问题,因为,与在黑客社区中散布那些可利用问题相比,通知用户和使他们进行升级是一个缓慢得多的过程。
例如,于 1998 年 12 月发现的十分流行的 Cold Fusion 服务器上的错误,现在还仍然作为重要新闻见报。尽管于 1999 年 4 月人们认识到了该错误的严重性,但一个多月以后,报告显示基于这个错误的攻击仍然保持了惊人的比例(尽管最近的报告正在逐渐减少)。部分被攻击的站点甚至是几个月以前就得到关于该弱点的警告,但它们没有采取足够的预防措施。
让黑客站在您这边
其实,将这类信息据为己有并将它用于无耻目的的坏家伙并不是那么多。谢天谢地,黑客社区中的许多人都怀有好意。他们喜欢破解东西,但他们这样做是为了提高每个人在安全性方面的警惕性。
此类黑客往往在破解了您的程序之后通知您。当他们这样做时,请确保修正该问题并尽快分发补丁,因为黑客倾向于完全公开。完全公开意味着黑客将公开散布关于您的安全性问题的信息,通常包含一个能够用来利用该安全性问题的程序。完全公开背后的实质应该是很自然的:它鼓励人们确保自己的软件更安全,并且还帮助教育用户社区。
封闭源码不是答案
老练的黑客不需要源代码就可以找出安全性问题。黑客能够观察程序行为、分析二进制文件以及甚至通过反编译器运行代码以获得一个过得去的源代码副本。尽管这个任务肯定比分析源代码困难,但它仍然可以产生结果。
但即使他们获得成功,您也无法从“许多双眼睛”现象中获益。很可能绝大多数分析封闭程序以发现安全性问题的人都带有邪恶动机,因此,他们很可能不会与您分享其信息。为什么?通过拿走源代码,您使他人更难以分析程序,因此他们就更不愿意帮助您改进产品。
请一定不要相信这个常识:独自保留源代码而不发布就意味着安全性。这种称为“通过不明确性实现安全性”的实践通常不灵验。
您的最佳防御
尽量减少往程序中添加安全性问题所带来的风险的最佳方法是彻底使自己学习应用程序安全性,并从一开始设计应用程序时就留心安全性。(Security for Developers 是专门关于从头开始构建安全应用程序的。)
当您考虑应用程序需求时,将安全性作为重要的事情来考虑。例如,是否可以用其它语言,而不用 C 或 C++ 来编写程序呢?这两种语言充满了缺陷,它们可能误导一般程序员在甚至不知情的情况下将安全性错误添加到程序中。除非很了解这些安全性方面,否则尽可能使用其它语言。Java 是不错的选择,因为它很类似于 C,但它从一开始设计就考虑了安全性。对安全性了解不多的程序员不太可能偶然地写出非安全的 Java 程序。但是,Java 毕竟还是相对年轻而又复杂的语言;该语言平台中可能潜伏着黑客能够攻击的错误。对于所选择的任何语言,尝试让自己了解其潜在安全性风险。这可能很难,因为关于任何特定语言的安全性参考资料可能很少(请参阅下面的参考资料以获得一些链接)。
如果必须使用 C,则了解一下对您的程序使用 StackGuard 的可能性。StackGuard 是由 Oregon Graduate Institute of Science and Technology 开发的工具,它将制止几乎所有堆栈分配的缓冲区溢出攻击,即使您的代码中充斥着本来可以被利用的可溢出的静态缓冲区。 StackGuard 不能解决您代码中可能具有的其它类型的安全性问题。但是,使用这样的工具还是很重要的,因为在过去两年中报告的安全性漏洞有大约 50% 是堆栈粉碎攻击。不幸的是,目前 StackGuard 仅运行在运行 gcc 编译器的 x86 机器上,对于其它平台则没有类似工具可用。
在基于 UNIX 的系统上的任何语言中,都不要对 system() 和 popen() 进行库调用。这些调用的使用几乎总是造成安全性问题。如果需要运行另一个进程,随 fork() 一起使用 execv()。尽管仍有可能误用 execv()/fork() 组合,但它产生错误的可能性小得多。
当标识了您软件中的安全性问题后,如果一有可用的补丁版本就通知用户,那么用户团体就得到了最好的服务。一个好方法是使用仅用于宣布安全性错误用途的电子邮件分发列表。但您需要使人们容易加入该列表,这样当出现问题时,可以警告尽可能多的用户群。应该在软件中放置醒目的通知,并带有简单的指示,譬如:
“安全性注意事项:本程序目前包含未知的安全性问题。如果发现可能影响您的安全性问题,我们很愿意通知您。如果出现这样的情况,而您愿意接收通知,请向 my-software-security@mydomain.com 发一封电子邮件。我们不会将您的电子邮件地址用于除通知您重要安全性问题信息以外的任何其它用途。”
您之外的眼睛总是有助于从不同的角度来检查您的代码。所以从安全性角度来看,最好开放您软件的源代码。如果许多人根据自己的安全性来审核您的软件,那么,最后,您很可能因此获得一个更安全的软件。但是,请确保在公开发布源代码之前,获得尽可能多可信的眼睛来检查您的代码。如果在交付软件之前发现问题,则很容易限定问题的范围。
结束语
开放您软件的源代码有助于改进安全性,但是如果您想理解由此带来的真正益处,则应该理解和考虑相关的风险。开放您软件的源代码并不能包治百病;它是巩固开发实践和预发行源码级审核的有效补充。
欢迎光临 黑色海岸线论坛 (http://bbs.thysea.com/)
Powered by Discuz! 7.2