C和C++安全编码(原书第2版)
上QQ阅读APP看书,第一时间看更新

2.6.8 检测和恢复

地址空间布局随机化(Address Space Layout Randomization,ASLR)是许多操作系统的一项安全功能,其目的是为了防止执行任意代码。该功能对程序所使用的内存页的地址随机化。ASLR不能防止在栈上的返回地址被基于栈的溢出覆写。然而,通过对栈页地址随机化,可以防止攻击者正确地预测外壳代码、系统函数,或他们想调用的面向返回值编程的小工具地址。一些ASLR实现在每次程序运行时对内存地址随机化。因此,如果重新启动该程序(也许是因为崩溃),泄漏的内存地址就没用了。

ASLR降低成功攻击的可能性,但并没有消除这种可能性。因为在理论上,攻击者是有可能正确地预测或猜测他们的外壳代码的地址并用这个值覆写栈上的返回指针的。

此外,即使基于每次调用都随机化地址的实现,ASLR仍可以被一个长期运行的进程上的攻击者绕过。如果攻击者能发现它的地址,他们就可以执行他们的外壳代码,而无须终止进程。例如,通过利用一个格式字符串漏洞或其他信息泄露来显示内存的内容,就可以做到这一点。

Linux。ASLR技术于2000年首次引入到Linux的PaX项目。虽然PaX补丁并没有被提交到主流Linux内核,但它的许多功能都被纳入主流的Linux发行版。例如,自2008年以来和自2007年以来的ASLR一直是Ubuntu和Debian的一部分。这两个平台都允许通过下面的命令对ASLR进行精细的调优:


sysctl -w kernel.randomize_va_space=2

大多数平台在引导过程中执行此命令。randomize_va_space参数可能会取以下值:

0.完全关闭ASLR。这仅在不支持此功能的平台上是默认的。

1.对栈、库和位置无关的二进制程序打开ASLR。

2.对堆以及对由选项1随机化的内存打开ASLR。

Windows。自从Vista以来,ASLR一直在Windows中可用。在Windows中,当系统启动后,ASLR把可执行映像移动到任意位置,使利用代码更难执行可预见的操作。对于一个支持ASLR技术的组件,它加载的所有组件也必须支持ASLR。例如,如果A.exe依赖于B.dll和C.dll,那么所有这三个程序都必须支持ASLR。默认情况下,Windows Vista和Windows操作系统的后续版本对系统的动态链接库(DLL)和可执行文件(EXE文件)进行随机化。然而,自定义DLL和EXE的开发人员必须选择使用/DYNAMICBASE链接器选项以支持ASLR。

Windows的ASLR也随机化堆和栈内存。堆管理器会在一个随机位置创建堆,以帮助减少企图利用基于堆的缓冲区溢出的漏洞利用获得成功的机会。对运行于Windows Vista和更高版本上的所有应用程序,默认情况下,堆随机化都是启用的。当一个线程在一个用/DYNAMICBASE链接的进程中启动时,Windows Vista和更高版本的Windows把线程的栈移动到一个随机位置,以帮助减少基于栈的缓冲区溢出的利用代码获得成功的机会。

要在Microsoft Windows下启用ASLR,你应该遵循如下规范。

·用微软的链接器版本8.00.50727.161(第一个支持ASLR的版本)或更高版本来链接

·用/DYNAMICBASE链接开关链接,若使用微软链接器版本10.0或更高版本,则默认启用/DYNAMICBASE

·在Windows Vista和更高版本测试你的应用程序,并记录和修复由于使用ASLR产生的故障