除了缓冲区溢出的威胁,但是相对而言代价比较大。在四4中介绍一种间接的方法,这个方法在程序指针失效前进行完整性检查。虽然这种方法不能使得所有的缓冲区溢出失效,但它能阻止绝大多数的缓冲区溢出攻击。然后在四5,分析这种保护方法的兼容性和性能优势。四1非执行的缓冲区通过使被攻击程序的数据段地址空间不可执行,从而使得攻击者不可能执行被植入被攻击程序输入缓冲区的代码,这种技术被称为非执行的缓冲区技术。在早期的U
ix系统设计中,只允许程序代码在代码段中执行。但是近来的U
ix和MSWi
dows系统由于要实现更好的性能和功能,往往在数据段中动态地放入可执行的代码,这也是缓冲区溢出的根源。为了保持程序的兼容性,不可能使得所有程序的数据段不可执行。但是可以设定堆栈数据段不可执行,这样就可以保证程序的兼容性。Li
ux和Solaris都发布了有关这方面的内核补丁。因为几乎没有任何合法的程序会在堆栈中存放代码,这种做法几乎不产生任何兼容性问题,除了在Li
ux中的两个特例,这时可执行的代码必须被放入堆栈中:(1)信号传递:Li
ux通过向进程堆栈释放代码然后引发中断来执行在堆栈中的代码来实现向进程发送U
ix信号。非执行缓冲区的补丁在发送信号的时候是允许缓冲区可执行的。的在线重用:(2)GCC的在线重用:研究发现gcc在堆栈区里放置了可执行的代码作为在线重用之用。然而,关闭这个功能并不产生任何问题,只有部分功能似乎不能使用。非执行堆栈的保护可以有效地对付把代码植入自动变量的缓冲区溢出攻击,而对于其它形式的攻击则没有效果。通过引用一个驻留的程序的指针,就可以跳过这种保护措施。其它的攻击可以采用把代码植入堆或者静态数据段中来跳过保护。四2编写正确的代码编写正确的代码是一件非常有意义的工作,特别象编写C语言那种风格自由而容易出错的程序,这种风格是由于追求性能而忽视正确性的传统引起的。尽管花了很长的时间使得人们知道了如何编写安全的程序,具有安全漏洞的程序依旧出现。因此人们开发了一些工具和技术来帮助经验不足的程序员编写安全正确的程序。
f最简单的方法就是用grep来搜索源代码中容易产生漏洞的库的调用,比如对strcpy和spri
tf的调用,这两个函数都没有检查输入参数的长度。事实上,各个版本C的标准库均有这样的问题存在。此外,人们还开发了一些高级的查错工具,如faulti
jectio
等。这些工具的目的在于通过人为随机地产生一些缓冲区溢出来寻找代码的r