缓冲区溢出原理浅析连同防护

2008-02-23 05:40:53来源:互联网 阅读 ()

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

  【摘要】本文从程式语言本身的缺陷,不够健壮的角度出发,周详分析了缓冲溢出攻击的基本原理,描述了黑客利用缓冲区漏洞进行系统攻击的一般过程,最后又简单讨论了几种防范溢出攻击的策略.

  【关键字】缓冲溢出; 程式跳转; 长跳转缓冲区;

  近些年来,黑客攻击事件频繁发生,尤其是缓冲区溢出漏洞攻击占据了网络远程攻击的绝大多数. 因为这类攻击能够使任何人获得系统主机的完全控制权,所以他代表了一类十分严重的攻击.

  缓冲区溢出攻击之所以常见,是因为他太常见了,且易于实现, 这完全是软件发展史上不可避免的问题. 缓冲区漏洞是程式员在编写程式时未检查内存空间,导致内存泄漏而引起,以下我们先来简单了解一下他:

  一、认识缓冲区溢出

  缓冲溢出是一种系统攻击的手段,借着在程式缓冲区编写超出其长度的代码,造成溢出,从而破坏其堆栈,使程式执行攻击者在程式地址空间中早已安排好的代码,以达到其目的. 一般黑客攻击root程式,然后执行类似exec(sh)的代码获得root的shell. 他造成了两种严重的后果:

  1. 覆盖堆栈的相邻单元. 使程式执行失败, 严重可导致系统崩溃.

  2. 可执行认识指令代码,最后获得系统root特级权限.

  现在很多人使用C或C 编写程式,但同时太多的人忽略了对其的数组边界检查和类型安全检查,所以现今的大多数溢出都和C语言有关, C语言中中有可能产生溢出的函数有:char s[n],strlen(s),strcpy(dst, src),p=malloc(n),strcat(s,suffix)等等,所以我们要尽可能地避免使用这些危险函数,即使使用,也一定要做严格的检查.为容易理解,我们来看一个简单的程式:

/*
* example.c
* written by Devil_Angel <Devil___Angel@126.com>
* gcc –o example example.c
*/
void func(char * str)
{
char buf[8];
strcpy(buf, str);
printf(“%sn”,buf);
}
int main(int argc, char * argv[])
{
If(argc >1)
Func(argv[1]);
}//end of main

  该程式在输入时,并没有对str的大小进行检查便直接送入数组buf,一旦输入超出buf长度,就产生了最简单的溢出,当然象这样的溢出一般只会出现Segmentation fault错误,而不能达到攻击的目的. 这里并没有进一步深入分析,只是让大家对溢出有一个大概的概念,在以后将会对其做进一步的分析.

  二、缓冲区溢出漏洞攻击方式

  最常见的攻击手段是通过制造缓冲区溢出使程式运行一个用户shell,在通过shell执行其他命令. 若该程式输入root且有suid权限的话,攻击者就获得了一个有root权限的shell,此时就能够对系统进行随意操作了.下面我来介绍一下如何控制程式跳转到攻击代码:

  ·打开记录(Activation Records)

  在程式中,每一个函数调用发生,在堆栈中会留下一个Activation Records,他包括函数结束时返回的地址,攻击者通过溢出这些自动变量,使地址指向攻击程式代码. 通过改变程式的返回地址,当调用结束时,程式就跳到攻击者设定的地址,而不是原地址.这类溢出被称为 stacks mashing attack.

  ·函数指针(Function Pointers)

  void(*foo)(1)定义一个返回函数指针的变量foo, Function Pointers可用来定位任何地址空间. 所以只需在任何空间内的Function Pointers附近找到一个能溢出的缓冲区,然后溢出他来改变Function Pointers. 在某时刻,当程式通过Function Pointers调用函数时,程式的流程就按黑客的意图实现了(典型的溢出程式有:Linux下的Superprobe程式).

  ·长跳转缓冲区(Longjmpbuffers)

  在C语言中,包含了一个简单的检验/恢复系统,称为setjmp/longjmp.即在检验点设定setjmp(buffer),用longjmp(buffer)恢复. 但若攻击者能够进入缓冲区空间,则longjmp(buffer)实际上跳转到攻击者的程式代码. 像Function Pointers, longjmp缓冲区能指向任何地方,所以攻击者要做的就是找到一个可供溢出的buffer即可.

  最常见的是在一个字符串中综合了代码植入和打开记录. 攻击者定位或提供溢出的自动变量,然后向程式传一个超大字符串,在引发buffer溢出改变打开记录时植入程式代码,由此达到入侵系统的目的.

  三、应对远程缓冲区溢出攻击

  对付缓冲区溢出攻击的方法不少,但常见的也是最重要有一下四种方式:

  1. 编写严格的代码

  编写正确严格的代码是一件有意义但很耗时的工作, 有C程式设计或汇编语言经验的人会深有体会,尽管软件的发展经历了不短的时间了,但漏洞程式依旧存在,因此人们研发了一些工具和技术来帮助经验不足的程式员编写安全的程式.例如高级查错工具,如faultinjection等. 这些工具的目的在于通过人为随机地产生一些缓冲区溢出来寻找代码的安全漏洞.但由于C语言的特点,这些工具不可能找出任何的缓冲区溢出漏洞. 所以,侦错技术只能用来减少缓冲区溢出漏洞,并不能完全地消除其存在. 错误的消除还是要靠程式员来编写.

  2. 不可执行堆栈数据段

  通过操作系统时数据断地址空间不可执行,从而使得攻击者不能执行被植入的攻击代码,但攻击者不一定是非要植入攻击代码来实现缓冲区溢出的攻击,所以这种方法还是存在很多弱点的.

  3. 利用程式编译器的边界检查

  植入代码是引起缓冲区溢出的一个方面,改变程式执行流程是另一方面. 而利用编译器边界检查则使得缓冲区溢出不可能实现,从而完全消除了缓冲区溢出的威胁,但相对而言代价较大.

  4. 指针完整性检查

  程式指针完整性检查和边界检查略微不同. 程式指针完整性检查在程式指针被改变之前检测.因此,即便攻击者成功改变了程式的指针,也会因先前检测到指针的改变而失效,这样虽然不能解决任何问题,但他的确阻止了大多数的缓冲区攻击,而且这种方法在性能上有很大的优势,兼容性也很好.

  从长远来看,要想从根本上消除缓冲区溢出攻击,需要对编程模式或CPU体系的基础性修改才能解决问题. 但是,随着信息技术的飞速发展和人们对网络安全的重视程度不断加深, 缓冲区溢出攻击总会有解决的一天.

标签:

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

上一篇: C builder 的文档读写操作总结

下一篇: 《C 0x漫谈》系列之:右值引用