目录
基于堆栈的缓冲区溢出检测 (/GS)
安全异常处理 (/SafeSEH)
DEP 兼容性 (/NXCompat)
映像随机化 (/DynamicBase)
更安全的函数调用
C++ Operator::new
如果失败会怎样?
许 多代码都是使用 C 和 C++ 编写的,但遗憾的是,其中很多此类代码都有一些甚至连开发人员都不知道的安全漏洞。以任何语言编写的程序都存在可能会使其用户受到攻击的漏洞,但 C 和 C++ 语言在 Internet 历史上占有特殊的地位,原因是它们的许多安全漏洞都源自使其大受欢迎的功能:对计算机硬件无限制的访问以及随之而来的性能优势。在阅读有关安全和 C 或 C++ 方面的资料时,通常很容易看到“缓冲”和“溢出”等术语,因为缓冲通常就是直接访问内存的一个示例。这种类型的直接访问虽然功能非常强大,但也非常非常危险。
对于在生成 C 和 C++ 代码过程中出现的许多缓冲区溢出问题,其原因有多种。第一个原因我在上面已提到过:编程语言提供对易受攻击内存的直接访问。第二个原因是开发人员出错。第三个原因是编译器通常不提供防御功能。对于第一个问题很容易提供补救措施,但自此 C 和 C++ 开始成为不同的语言。
开发人员出错问题可通过培训来部分加以解决,但是我还没有真正看到在这方面教育机构的兴起。行业中也确实有一些进行安全培训的机构,但是我们只能提供部分解决方案或解决部分问题,我非常希望看到各所大学能对学生进行更多有关软件安全方面的教育。您可能要问“为什么教育机构不尝试培训这一非常重要的主题?”说实话,我也不知道为什么。不过这确实非常让人郁闷。
最后,即使有一流的培训,但有些安全问题真的非常复杂,就算是受过良好教育的工程师也不能完全解决。我们人类并不是完美的。
在编译器中建立更多防御措施是 Microsoft Visual C++ 团队多年以来一直试图解决的问题,在我们安全团队的协助下目前正逐渐得到改进。本专栏将概述一些在 Visual C++ 2005 中可用的缓冲区溢出防御措施及其他内容。请注意,一些其他编译器也提供防御措施,但 Visual C++ 有两个主要优势超越了 gcc 等编译器。首先,所有这些防御措施都默认集成在工具集中,无需下载某些稀奇古怪的加载项。其次,这些选项易于使用。
Visual C++ 工具集提供的防御措施包括(不分先后顺序):
基于堆栈的缓冲区溢出检测 (/GS)
安全异常处理 (/SafeSEH)
数据执行保护 (DEP) 兼容性 (/NXCompat)
映像随机化 (/DynamicBase)
自动使用更安全的函数调用
C++ operator::new
在详细讨论每一项之前,我要指出的是这些防御措施并不能弥补不安全的代码。您应该始终尽最大努力编写最安全的代码,如果不知道该怎样做,可以先阅读一些有关这一主题的专业书籍。
Typical Stack Compared to One Compiled with /GS
另外我还要指出,这些都是 Microsoft 的“安全开发生命周期”(SDL) 的要求,这意味着编写 C 和 C++ 代码时必须使用这些选项,否则不能交付。偶尔会有些例外,但是非常少,因此在这里不对其做详细讨论。
最后必须要牢记的要点是:这些精心设计的防御措施也是可以被绕过的,具体视代码问题而定。代码使用的防御措施越多,解决起来就越困难,但是没有任何防御措施是尽善尽美的。它们都是为了减少被侵入的机会。您一定对此已经有所了解!唯一的应对方案就是使用更安全的函数调用,这是真正能够堵上漏洞的防御措施。让我们详细了解一下各个防御措施。