2.软件开发过程中的防范策略
发生缓冲区溢出的主要及各要素是:数组没有边界检查而导致的缓冲区溢出;函数返回地址或函数指针被改变,使程序流程的改变成为可能;植入代码被成功的执行等等。
所以针对这些要素,从技术上我们就可以采取一定的措施。
(1)编写正确的代码
只要我们在所有拷贝数据的地方进行数据长度和有效性的检查,确保目标缓冲区中数据不越界并有效,则就可以避免缓冲区溢出,更不可能使程序跳转到恶意代码上。但是诸如C/C++自身是一种不进行强类型和长度检查的一种程序设计语言,而程序员在编写代码时由于开发速度和代码的简洁性,往往忽视了程序的健壮性,从而导致缓冲区溢出,因此我们必须从程序语言和系统结构方面加强防范。

很多不安全程序的出现是由于调用了一些不安全的库函数,这些库函数往往没有对数组边界进行检查。这些函数有strcpy()、sprintf()、strcat()等,所以一种简单的方法是利用grep搜索源程序,找出对这些函数的调用,然后代以更安全的函数,如strncpy()替换strcpy()。进一步的查找可以是检查更广范围的不安全操作,如在一个不定循环中对数组的赋值等。
可用的另一种措施是漏洞探测。利用一些工具,人为随机地产生一些缓冲区溢出来寻找代码的安全漏洞。已有这方面的一些高级的查错工具,如fault injection等。
(2)缓冲区不可执行
通过使被攻击程序的数据段地址空间不可执行,从而使得攻击者不可能执行被植入被攻击程序输入缓冲区的代码,这种技术被称为缓冲区不可执行技术。事实上,很多老的Unix系统都是这样设计的,但是近来的Unix和MS Windows系统为实现更好的性能和功能,往往在数据段中动态地放入可执行的代码。所以为了保持程序的兼容性不可能使得所有程序的数据段不可执行。但是我们可以设定堆栈数据段不可执行,这样就可以最大限度地保证了程序的兼容性。Linux和Solaris都发布了有关这方面的内核补丁。因为几乎没有任何合法的程序会在堆栈中存放代码,这种做法几乎不产生任何兼容性问题。
通过使被攻击程序的数据段地址空间不可执行,从而使得攻击者不可能执行被殖入被攻击程序输入缓冲区的代码,这种技术被称为非执行的缓冲区技术。事实上,很多老的Unix系统都是这样设计的,但是近来的Unix和MS Windows系统由于实现更好的性能和功能,往往在在数据段中动态地放入可执行的代码。所以为了保持程序的兼容性不可能使得所有程序的数据段不可执行。
Linux和Solaris也发布了有关这方面的内核补丁。因为几乎没有任何合法的程序会在堆栈中存放代码,这种做法几乎不产生任何兼容性问题,除了在Linux中的两个特例,这时可执行的代码必须被放入堆栈中:a.信号传递:
Linux通过向进程堆栈释放代码然后引发中断来执行在堆栈中的代码来实现向进程发送Unix信号。非执行缓冲区的补丁在发送信号的时候是允许缓冲区可执行的。
b.GCC的重用:
研究发现gcc在堆栈区里放置了可执行的代码作为重用之用。然而,关闭这个功能并不产生任何问题,只有部分功能似乎不能使用。
非执行堆栈的保护可以有效地对付把代码植入自动变量的缓冲区溢出攻击,而对于其他形式的攻击则没有效果。通过引用一个驻留的程序的指针,就可以跳过这种保护措施。其他的攻击可以采用把代码殖入堆或者静态数据段中来跳过保护。
(3)改进C语言函数库
C语言中存在缓冲区溢出攻击隐患的系统函数有很多。例如gets(),sprintf(),strcpy(),strcat(),fscanf(),scanf(),vsprintf()等。可以开发出更安全的封装了若干已知易受堆栈溢出攻击的库函数。修改后的库函数实现了原有功能,但在某种程度上可以确保任一缓冲区溢出都被控制在现有堆栈帧之内。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-30355-7.html
国际法并没有规定人工岛具有12海里的领海