网络 电子商务 编程
一次例外,这个系统和本来的系统工作完全一样,这表明堆栈保护并不对系统的兼容性构成很大的影响。 我们已经用各种性能测试来评测堆栈保护的性能。Mircobenchmarks的结果表明在函数的调用,堆栈保护中增加了系统的开销。而在网络的测试中(需要用到堆栈保护的地方),则表明这种开销不是很大。
我们的第一个测试对象是SSH,它提供了极强的加密和认证,用来替代Berkeley的r系列指令。SSH使用了软件加密,因此系统的占用的带宽不大,我们用网络间复制一个大的文件来测试带宽:
scp bigsource localhost:bigdest
测试结果表明:堆栈保护几乎不影响SSH的网络吞吐性能。
第二个测试使用了Apache Web服务器。如果这种服务器存在基于堆栈的攻击,那么攻击者就可以轻易地取得Web服务器的控制权,允许攻击者阅读隐秘的内容和肆意篡改主页的内容。同时,Web服务器也是对性能和带宽要求较高的一个服务器部件。
我们用WebStone对带有和不带堆栈保护的Apache Web服务器进行了测试,测试的结果在表二中列出。 和SSH一样,他们的性能几乎没有区别。在客户数目较少的情况下,带有保护的服务器性能比不带保护的略微好些,在客户端数目多的时候,不带保护的性能好些。在最坏的情况下,带保护的服务器比不带保护的要差8%的连接性能,而在平均延时上保持优势。象以前一样,我们把这些归结为噪声的影响。因此,我们的结论是:堆栈保护对Web服务器系统性能没有重大的影响。
3)指针保护:编译器生成程序指针完整性检查
在堆栈保护设计的时候,冲击堆栈构成了缓冲区溢出攻击的常见的一种形式。有人推测存在一种模板来构成这些攻击(在1996年的时候)。从此,很多简单的漏洞被发现,实施和补丁了,很多攻击者开始用在第二部分中描述的更一般的方法实施缓冲区溢出攻击。
指针保护是堆栈保护针对这种情况的一个推广。通过在所有的代码指针之后放置附加字节来检验指针在被调用之前的合法性。如果检验失败,会发出报警信号和退出程序的执行,就如同在堆栈保护中的行为一样。这种方案有三点需要注意:
a.附加字节的定位:
附加字节的空间是在被保护的变量被分配的时候分配的,同时在被保护字节初始化过程中被初始化。这样就带来了问题;为了保持兼容性,我们不想改变被保护变量的大小,因此不能简单地在变量的结构定义中加入附加字。还有,对各种类型也有不同附加字节数目。
b.检查附加字节:
每次程序指针被引用的时候都要检查附加字节的完整性。这个也存在问题;因为―从存取器读‖在编译器中没有语义;编译器更关心指针的使用,而各种的优化算法倾向于从存储器中读入变量。
c.还有随着不同类型的变量,读入的方法也各自不同。
已经开发的指针保护的一个原型(还是基于gcc的),通过附加字节来保护静态分配的函数指针,但不适用于结构和数组类型。这个计划还远没有完成。一旦这个项目完成了,那么用它和堆栈保护构成的可执行代码将不会受到缓冲区溢出的攻击了。
目前为止,只有很少一部分使用非指针变量的攻击能逃脱指针保护的检测。但是,可以通过在编译器上强制对某一变量加入附加字节来实现检测,这时需要程序员自己手工加入相应的保护了。
(7)利用编译器将静态数据段中的函数地址指针存放地址和其他数据的存放地址分离
我们知道缓冲区溢出的一个基本条件是在缓冲区的高地址附近存放着可供溢出覆盖的函数地址指针,如果我们破坏了这一条件,就会使缓冲区溢出不能覆盖函数地址指针。比如,我们可以假定编译器在编译程序时会将静态数据段中的函数地址指针存放地址和其他数据的存放地址隔开相当大的一段距离,例如数10M,数100M,这样才会迫使攻击者只有送入长的出乎想象数据才能抵达函数地址指针存放地址并覆盖它,以这样的不可操作性来制止攻击者实现攻击意图。另外,我们还可以使这两种数据段间的线形地址空间不分配物理地址并设置为不可读写,这些都可以通过硬件实现,这样每当缓冲区溢出进入这段区域,就会出现地址保护错误,从而阻止了缓冲区溢出攻击。