缓冲区溢出实验

缓冲区溢出实验

0.前言

  缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况。这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段。这一漏洞的出现是由于数据缓冲器和返回地址的暂时关闭,溢出会引起返回地址被重写

  本实验来自 Syracuse SEED labs,需要在虚拟机上完成。安装完虚拟机镜像后, ubuntu 系统的登录用户为 seed,口令字为 dees,而 root 用户的口令字为 seedubuntu

1.什么是缓冲区溢出

  缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量溢出的数据覆盖在合法数据上,理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间相匹配,这就为缓冲区溢出埋下隐患,操作系统所使用的缓冲区,又被称为”堆栈”。在各个操作进程之间,指令会被临时储存在”堆栈”当中,”堆栈”也会出现缓冲区溢出。

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

  缓冲区溢出攻击之所以成为一种常见安全攻击手段其原因在于缓冲区溢出漏洞太普遍了,并且易于实现。而且,缓冲区溢出成为远程攻击的主要手段其原因在于缓冲区溢出漏洞给予了攻击者他所想要的一切:植入并且执行攻击代码。被植入的攻击代码以一定的权限运行有缓冲区溢出漏洞的程序,从而得到被攻击主机的控制权

2.文件准备

  点击 HOME,将 infosec-lab8.zip 下载到该文件夹并解压

3.取消随机地址空间分配

  点击终端(Terminal),进入命令行状态,su root 按回车后,输入 root 的口令 seedubuntu。注意取消随机地址空间分配的命令

1
#sysctl -w kernel.randomize_va_space=0

4.改变 shell 链接

  必须在 root 用户下完成

1
2
3
# cd /bin
# rm sh
# ln -s /bin/zsh /bin/sh

5.编译代码

  注意对 stack 的编译方法

1
#gcc -o stack –g -z execstack -fno-stack-protector stack.c

  

6.运行

  注意到这个实验成功进行了缓冲区溢出攻击,由普通用户权限拿到了 root 用户的权限

7.进一步实验

需要重复上述过程

  • 情形 1
    1
    2
    #sysctl -w kernel.randomize_va_space=0
    #gcc -o stack –g -z execstack stack.c
  • 情形 2
    1
    2
    #sysctl -w kernel.randomize_va_space=0
    #gcc -o stack –g -fno-stack-protector stack.c
  • 情形 3
    1
    2
    #sysctl -w kernel.randomize_va_space=2
    #gcc -o stack –g -z execstack -fno-stack-protector stack.c

    该情形下,还需运行 ./exploit 至少 3 次

8.步骤 5 的攻击成功了,而其余的攻击不成功的原因

  第一次实现是完全关闭了系统的所有相关保护机制,所以一开始的步骤5能够攻击成功。

  • 情形1:

      保留了栈保护,尽管关闭了地址随机化,所以会导致攻击不成功。

  • 情形2:

      保留了内存页不可执行,尽管关闭了地址随机化,也会导致攻击不成功。

  • 情形3:

      关闭了栈保护,关闭了内存页不可执行,但是开启了地址随机化,所以也不成功。

9.现有的对付缓冲区溢出攻击的方法

  目前有四种基本的方法保护缓冲区免受缓冲区溢出的攻击和影响。 这个方法使得缓冲区溢出不可能出现,从而完全消除了缓冲区溢出的威胁,但是相对而言代价比较大。

  • ① 完整性检查

      在程序指针失效前进行完整性检查。虽然这种方法不能使得所有的缓冲区溢出失效,但它能阻止绝大多数的缓冲区溢出攻击。

  • ② 非执行的缓冲区

      通过使被攻击程序的数据段地址空间不可执行,从而使得攻击者不可能执行被植入被攻击程序输入缓冲区的代码,这种技术被称为非执行的缓冲区技术。在早期的Unix系统设计中,只允许程序代码在代码段中执行。但是Unix和MS Windows系统由于要实现更好的性能和功能,往往在数据段中动态地放入可执行的代码,这也是缓冲区溢出的根源。为了保持程序的兼容性,不可能使得所有程序的数据段不可执行。

  可以设定堆栈数据段不可执行,这样就可以保证程序的兼容性。Linux和Solaris都发布了有关这方面的内核补丁。

  • ① 信号传递

      Linux通过向进程堆栈释放代码然后引发中断来执行在堆栈中的代码来实现向进程发送Unix信号。非执行缓冲区的补丁在发送信号的时候是允许缓冲区可执行的。

  • ② GCC的在线重用

      研究发现gcc在堆栈区里放置了可执行的代码作为在线重用之用。然而,关闭这个功能并不产生任何问题,只有部分功能似乎不能使用。

  • ③ 综合

      非执行堆栈的保护可以有效地对付把代码植入自动变量的缓冲区溢出攻击,而对于其它形式的攻击则没有效果。通过引用一个驻留的程序的指针,就可以跳过这种保护措施。其它的攻击可以采用把代码植入堆或者静态数据段中来跳过保护。 编写正确的代码是一件非常有意义的工作,特别象编写C语言那种风格自由而容易出错的程序,这种风格是由于追求性能而忽视正确性的传统引起的


缓冲区溢出实验
https://one-null-pointer.github.io/2023/03/26/Liunx——缓冲区溢出实验/
Author
liaoyue
Posted on
March 26, 2023
传送口