缓冲区溢出攻击实验
原理:
缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况。这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段。这一漏洞的出现是由于数据缓冲器和返回地址的暂时关闭,溢出会引起返回地址被重写。
注:
数据缓冲器:当数据在具有不同传输能力的元件之间通过时,用来暂存这些数据的存储器;
实验准备:
系统用户名 shiyanlou
实验楼提供的是 64 位 Ubuntu linux,而本次实验为了方便观察汇编语句,我们需要在 32 位环境下作操作,因此实验之前需要做一些准备。
输入命令安装一些用于编译 32 位 C 程序的软件包:
初始设置
1、Ubuntu 和其他一些 Linux 系统中,使用地址空间随机化来随机堆(heap)和栈(stack)的初始地址,这使得猜测准确的内存地址变得十分困难,而猜测内存地址是缓冲区溢出攻击的关键。因此本次实验中,我们使用以下命令关闭这一功能
2、此外,为了进一步防范缓冲区溢出攻击及其它利用 shell 程序的攻击,许多shell程序在被调用时自动放弃它们的特权。因此,即使你能欺骗一个 Set-UID 程序调用一个 shell,也不能在这个 shell 中保持 root 权限,这个防护措施在 /bin/bash 中实现。
linux 系统中,/bin/sh 实际是指向 /bin/bash 或 /bin/dash 的一个符号链接。为了重现这一防护措施被实现之前的情形,我们使用另一个 shell 程序(zsh)代替 /bin/bash。下面的指令描述了如何设置 zsh 程序:
ln命令
所以,就是将原链接sh删除,之后重建一个链接sh指向shell从而撤销防御
3、
- 输入命令 linux32 进入32位linux环境。
编写漏洞代码
功能:读取一个名为“badfile”的文件,并将文件内容装入“buffer”。
编写攻击代码
- 我们的目的是攻击刚才的漏洞程序,并通过攻击获得 root 权限。
这个代码是用来进行攻击的,但是在后来攻击失败,出现了segmentation fault
后来发现是因为复制时出现了缩进混乱导致汇编语言那里多了一个‘/’
- 现在我们要得到 shellcode 在内存中的地址,输入命令进入 gdb 调试:
由此得到了shell的地址,并且将之填入了"??"处
- 注:“disass”是"disassemble"反汇编命令的缩写
反汇编
现在修改 exploit.c 文件,将 \x??\x??\x??\x?? 修改为计算的结果 \x14\xd0\xff\xff,注意顺序是反的。
- 然后,编译 exploit.c 程序
运行
- 成功获得root权限
原理及其防范:
- 原理:通过往程序的缓冲区,写入超出其长度的内容,造成缓冲区的溢出,从而破坏程序的“堆栈”,使程序转而执行其它指令,以达到攻击的目的。
- 随便往缓冲区中填东西造成它溢出,一般只会出现“分段错误”,而不能达到攻击的目的。最常见的手段是,通过制造缓冲区溢出,使程序运行一个用户shell(计算机壳层,属于“命令解析器”,用于接收用户的命令),再通过shell执行其它命令。如果该程序属于root且有suid权限的话,攻击者就获得了一个有“root权限”(系统权限的一种,也叫“根权限”)的shell,这样就可以对系统进行任意操作了。
- 防范方法:
1.系统管理上:
1)关闭不需要的特权程序。
2)及时给程序漏洞打补丁。
2.软件开发过程中的防范策略
1)强制写正确的代码的方法。
只要在所有拷贝数据的地方进行数据长度和有效性的检查,确保目标缓冲旦中数据不越界并有效,则就可以避免缓冲区溢出,更不可能使程序跳转到恶意代码上。
2)通过操作系统使得缓冲区不可执行,从而阻止攻击者殖入攻击代码。
通过使被攻击程序的数据段地址空间不可执行,从而使得攻击者不可能执行被植入被攻击程序输入缓冲区的代码,这种技术被称为缓冲区不可执行技术。
3)利用编译器的边界检查,来实现缓冲区的保护
这个方法使得缓冲区溢出不可能出现,从而完全消除了缓冲区溢出的威胁,但是相对而言,代价比较大。
4)在程序指针失效前进行完整性检查
虽然这种方法不能使得所有的缓冲区溢出失效,但它能阻止绝大多数的缓冲区溢出攻击;而能够逃脱这种方法保护的缓冲区溢出,也很难实现。
5)改进C语言函数库
C语言中存在缓冲区溢出攻击隐患的系统匾数有很多。例如gets(),sprintf(),strcpy(),strcat(),fscanf(),scanf(),vsprintf()等。可以开发出更安全的封装了若干己知易受堆栈溢出攻击的岸函数。
6)使堆栈向高地址方向增长
使用的机器堆栈压入数据时向高地址方向前进,那么无论缓冲区如何溢出,都不可能覆盖低地址处的函数返回地址指针,也就避免了缓冲区溢出攻击。但是这种方法仍然无法防范利用堆和静态数据段的缓冲区进行溢出的攻击。