缓冲区溢出 十年来攻击和防卫的弱点(4)

2008-02-23 07:09:38来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

随机符号:

利用一个在函数调用时产生的一个32位的随机数来实现保密,使得攻击者不可能猜测到附加字节的内容。而且,每次调用,附加字节的内容都在改变,也无法预测。

通过检查堆栈的完整性的堆栈保护法是从Synthetix方法演变来的。Synthetix方法通过使用准不变量来确保特定变量的正确性。这些特定的变量的改变是程序实现能预知的,而且只能在满足一定的条件才能可以改变。这种变量我们称为准变量。Synthetix开发了一些工具用来保护这些变量。

攻击者通过缓冲区溢出而产生的改变可以被系统当做非法的动作。在某些极端的情况下,这些准不变量有可能被非法改变,这是就需要堆栈保护来提供更完善的保护了。

实验的数据表明,堆栈保护对于各种系统的缓冲区溢出攻击都有很好的保护作用,并能保持较好的兼容性和系统性能。随后,我们用堆栈保护的方法重新构造了一个完整的Linux系统(Red Hat 5.1)。然后我们用XFree86-3.3.2-5和lsof的漏洞对此进行了攻击,结果表明,这个系统有效地抵御了这些攻击。这些分析表明,堆栈保护能有效抵御现在的和将来的基于堆栈的攻击。

堆栈保护版本的Red Hat Linux 5.1已经在各种系统上运行了多年,包括个人的笔记本电脑和工作组文件服务器。从我们的Web服务器上可以得到这个版本,而且在我们的邮件列表里已经有了55个成员。出了仅有的一次例外,这个系统和本来的系统工作完全一样,这表明堆栈保护并不对系统的兼容性构成很大的影响。

我们已经用各种性能测试来评测堆栈保护的性能。Mircobenchmarks的结果表明在函数的调用,堆栈保护中增加了系统的

开销。而在网络的测试中(需要用到堆栈保护的地方),则表明这种开销不是很大。

我们的第一个测试对象是SSH,它提供了极强的加密和认证,用来替代Berkeley的r系列指令。SSH使用了软件加密,因此系统的占用的带宽不大,我们用网络间复制一个大的文件来测试带宽:

scp bigsource localhost:bigdest


测试结果表明:堆栈保护几乎不影响SSH的网络吞吐性能。

第二个测试使用了Apache Web服务器。如果这种服务器存在基于堆栈的攻击,那么攻击者就可以轻易地取得Web服务器的控制权,允许攻击者阅读隐秘的内容和肆意篡改主页的内容。同时,Web服务器也是对性能和带宽要求较高的一个服务器部件。

我们用WebStone对带有和不带堆栈保护的Apache Web服务器进行了测试。

和SSH一样,他们的性能几乎没有区别。在客户数目较少的情况下,带有保护的服务器性能比不带保护的略微好些,在客户端数目多的时候,不带保护的性能好些。在最坏的情况下,带保护的服务器比不带保护的要差8%的连接性能,而在平均延时上保持优势。象以前一样,我们把这些归结为噪声的影响。因此,我们的结论是:堆栈保护对Web服务器系统性能没有重大的影响。

3.4.3 指针保护:编译器生成程序指针完整性检查

在堆栈保护设计的时候,冲击堆栈构成了缓冲区溢出攻击的常见的一种形式。有人推测存在一种模板来构成这些攻击(在1996年的时候)。从此,很多简单的漏洞被发现,实施和补丁了,很多攻击者开始用在第二部分中描述的更一般的方法实施缓冲区溢出攻击。

指针保护是堆栈保护针对这种情况的一个推广。通过在所有的代码指针之后放置附加字节来检验指针在被调用之前的合法性。如果检验失败,会发出报警信号和退出程序的执行,就如同在堆栈保护中的行为一样。这种方案有两点需要注意:

附加字节的定位:

附加字节的空间是在被保护的变量被分配的时候分配的,同时在被保护字节初始化过程中被初始化。这样就带来了问题;为了保持兼容性,我们不想改变被保护变量的大小,因此我们不能简单地在变量的结构定义中加入附加字。还有,对各种类型也有不同附加字节数目。

检查附加字节:

每次程序指针被引用的时候都要检查附加字节的完整性。这个也存在问题;因为“从存取器读”在编译器中没有语义;编译器更关心指针的使用,而各种的优化算法倾向于从存储器中读入变量。

还有随着不同类型的变量,读入的方法也各自不同。

我们已经开发了指针保护的一个原型(还是基于gcc的),通过附加字节来保护静态分配的函数指针,但不适用于结构和数组类型。这个计划还远没有完成。一旦这个项目完成了,那么用它和堆栈保护构成的可执行代码将不会受到缓冲区溢出的攻击了。

目前为止,只有很少一部分使用非指针变量的攻击能逃脱指针保护的检测。但是,可以通过在编译器上强制对某一变量加入附加字节来实现检测,这时需要程序员自己手工加入相应的保护了。

3.5 兼容性和性能的考虑

程序指针完整性检查与边界检查相比,并不能防止所有的缓冲区溢出问题。然而在执行的性能和兼容性上具有相当的优势:

性能:

边界检查必须在每个数组元素操作时完成一次检查。相比之下,程序指针检查只在被引用的时候实现检查。无论在C还是在C 中,这种花在程序指针引用上的开销始终比数组的指针引用小。

应用效能:

边界检查最难实现之处在于在C语言中,很能确定数组的边界。这是由于在C中,数组的概念和通用指针的混用造成的。由于一个指针是一个独立的对象,没有与特定的边界条件关联,只有一个系统的机器字来存储它,而标识边界信息的数据却没有存放。因此需要特殊的方法来恢复这些信息;数组的引用将不在是一个简单的指针,而是一个对缓冲区描述的指针组。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:网络攻击知识之几种IP地址攻击方式

下一篇:系统安全系列之Windows账户安全设置