美文网首页网络与信息安全
缓冲区溢出 - 攻击原理与防范

缓冲区溢出 - 攻击原理与防范

作者: Franchen | 来源:发表于2019-02-25 23:51 被阅读10次

    0x00原理

    通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,使程序转而执行其它指令,以达到攻击的目的。造成缓冲区溢出的原因是程序中没有仔细检查用户输入的参数。

    0x01实现

    1. 在程序的地址空间里安排适当的代码。

      • 植入法:攻击者向被攻击的程序输入一个字符串,程序会把这个字符串放到缓冲区里。这个字符串包含的资料是可以在这个被攻击的硬件平台上运行的指令序列。在这里,攻击者用被攻击程序的缓冲区来存放攻击代码。缓冲区可以设在任何地方:堆栈(stack,自动变量)、堆(heap,动态分配的内存区)和静态资料区。
      • 利用已经存在的代码:有时,攻击者想要的代码已经在被攻击的程序中了,攻击者所要做的只是对代码传递一些参数。比如,攻击代码要求执行“exec (bin/sh)”,而在libc库中的代码执行“exec (arg)”,其中arg是一个指向一个字符串的指针参数,那么攻击者只要把传入的参数指针改向指向“/bin/sh”。
    2. 通过适当的初始化寄存器和内存,让程序跳转到入侵者安排的地址空间执行。

      • 活动纪录(Activation Records)
        每当一个函数调用发生时,调用者会在堆栈中留下一个活动纪录,它包含了函数结束时返回的地址。攻击者通过溢出堆栈中的自动变量,使返回地址指向攻击代码。通过改变程序的返回地址,当函数调用结束时,程序就跳转到攻击者设定的地址,而不是原先的地址。这类的缓冲区溢出被称为堆栈溢出攻击(Stack Smashing Attack),是最常用的缓冲区溢出攻击方式。

      • 函数指针(Function Pointers)
        函数指针可以用来定位任何地址空间。例如:“void (* foo)()”声明了一个返回值为void的函数指针变量foo。所以攻击者只需在任何空间内的函数指针附近找到一个能够溢出的缓冲区,然后溢出这个缓冲区来改变函数指针。在某一时刻,当程序通过函数指针调用函数时,程序的流程就按攻击者的意图实现了。它的一个攻击范例就是在Linux系统下的superprobe程序。

      • 长跳转缓冲区(Longjmp buffers)
        在C语言中包含了一个简单的检验/恢复系统,称为setjmp/longjmp。意思是在检验点设定“setjmp(buffer)”,用“longjmp(buffer)”来恢复检验点。然而,如果攻击者能够进入缓冲区的空间,那么“longjmp(buffer)”实际上是跳转到攻击者的代码。象函数指针一样,longjmp缓冲区能够指向任何地方,所以攻击者所要做的就是找到一个可供溢出的缓冲区。一个典型的例子就是Perl 5.003的缓冲区溢出漏洞;攻击者首先进入用来恢复缓冲区溢出的的longjmp缓冲区,然后诱导进入恢复模式,这样就使Perl的解释器跳转到攻击代码上了

    0x02避免缓冲区溢出的方法

    1. 对于C语言中不安全的函数我们要使用安全的函数来替代,用fgets()、strncpy()、strncat()来替代gets()、strcpy()、strcat()等不限制字符串长度,不检查数组越界的函数。实际上编译器在编译完代码之后就已经提示了一个警告warning, this program uses gets(), which is unsafe.,所以,我们应该重视编译器给我们的提示,这样往往能避免常见的错误。
    2. 在向一块内存中写入数据之前要确认这块内存是否可以写入,同时检查写入的数据是否超过这块内存的大小。
    3. 栈随机化法。也就是说让栈的位置在程序每次运行时都不一样,然后黑客将可执行代码插入内存之后就不容易找到指向该字符串的地址,也就不能执行插入的程序了。
    4. 栈破坏检测。也就是说在实际的缓冲区上面做个标记,保存这个标记,然后在函数返回之前检查这个标记,如果这个标记和函数调用之前不一样了,就说明在函数调用的过程中发生了溢出,这是就抛异常,让程序异常终止。
    5. 操作系统限制可执行代码的区域来阻止黑客代码的执行。

    这里面1,2是业务开发人员需要注意的,3,4,5是操作系统或者编译,链接器的开发人员需要考虑的。

    相关文章

      网友评论

        本文标题:缓冲区溢出 - 攻击原理与防范

        本文链接:https://www.haomeiwen.com/subject/lfqoyqtx.html