本地缓冲区溢出
【实验目的】
1、掌握缓冲区溢出的基本原理;
2、熟练利用jmp.egp指令实现缓冲区溢出;
3、掌握缓冲区溢出的危害及其防范手段。
【实验环境】
登录Linux靶机环境,在无root权限的情况下,通过编译运行程序,利用本地缓冲溢出,达到获取root权限的目的。
备注:使用Linux靶机作为本地环境。
【实验预备知识点】
本小节利用如下的一段程序来说明本地缓冲区溢出的工作原理:
void function (char *str)
{
char buffer [16];
strcpy (buffer,str);
}
void main( )
{
int t;
char buffer [128];
for (I=0;I<127;I++)buffer [I]='A';
buffer [127]=0;
function (buffer);
print("this is a test \n");
}
这个是一个典型的存在缓冲区溢出错误的程序,在函数 function()中,将一个128字节长度的字符串复制到只有16字节长的局部缓冲区中去。在这个例子中,将128字节的字符床复制到只有16字节长的缓冲区中,必然导致16字节长的缓冲区溢出,进而覆盖栈中的返回地址,当子函数执行完毕后,不能正确返回到主程序,导致程序运行出错,系统必然会弹出一个错误的显示,显示程序运行失败。
在系统中,如果具有root权限的程序带有缓冲区溢出漏洞,那么攻击者(黑客)就可以对其进行本地缓冲区溢出攻击,当攻击成功后,攻击者就可以获得root权限了,实现了权限提升的目的。
防御策略。本缓冲区溢出攻击是针对本地系统或者运行的软件的缓冲区溢出漏洞,因此,用户对此的主要防御措施是要及时更新自己的系统,以及系统里安装的软件,将缓冲区溢出漏洞打上补丁。
【实验内容】
缓冲区溢出可以分为本地缓冲区溢出和远程缓冲区溢出。本地缓冲区溢出是指缓冲区溢出行为发生在攻击者本身使用的系统上,而攻击者采用本地缓冲区溢出进行攻击的目的主要是为了提升权限。发动本地缓冲区溢出攻击可以分为两种情况:一是远程入侵者已经成功入侵了主机,但是只有一般用户权限,能够访问的资源比较有限,要想获得更大的访问权限,一般可以通过本地缓冲区溢出攻击的方法来实现;二是某个攻击者本身是系统的一个普通账户,当该用户想非法获取更高访问权限时,也可以通过本地缓冲区溢出攻击的方法来实现。
【实验步骤】
1、在LINUX系统中打开终端,当前用户是root用户。使用su wist命令切换到普通用户wist,然后使用whoami命令查看身份。确认身份为wist,如下图1所示。
图 1用户为wist
2、在基于Linux内核的系统中,目前都使用内存地址随机化的机制来初始化堆栈,这将会使得猜测具体的内存地址变得十分困难,所以在本试验中,使用命令sysctl -w kernel.randomize_va_space=0来关闭内存随机化机制。(注意需要在root用户下才能关闭系统变量,并在关闭后退出root用户)如下图2所示。
图 2关闭内润随机机制
3、进入overflow文件夹,看到该文件夹下面有两个文件exe.c(攻击程序)和toto.c(攻击对象)。
4、将上面两个程序分别编译为可执行程序,执行命令
gcc exe.c –o exe
gcc toto.c –o toto
切换到root用户,将toto改为属主为root的setuid程序,执行命令
su
输入root密码
chown root.root toto
chmod +s toto
最后退出root用户,执行命令exit
如下图3所示
图 3编译exe.c和toto.c程序
5、用whoami看下当前的身份为wist,然后再执行命令./exe ./toto 0xbfffffff,会给出一个内存地址,例如为0xbxxxxxxx,该地址即为系统的漏洞所在。再执行一次该命令./exe ./toto 0xbxxxxxxx,即可破解成功。用whoami验证目前已经为root用户了。
图 4成功破解root权限的执行步骤
【实验思考题】
-
缓冲区溢出的危害有哪些?
答:缓冲区溢出是指当计算机向缓冲区填充数据时超出了缓冲区本身的容量,溢出的数据覆盖在合法数据上。
危害有以下两点:
1、程序崩溃,导致拒绝服务
2、跳转并且执行一段恶意代码
原因:造成缓冲区溢出的主要原因是程序中没有仔细检查用户输入。 -
我们可以如何利用jmp.egp指令实现缓冲区溢出?
答:JMP ESP在函数返回返回指令处填入在dll中搜索的 jmp esp的源码,在函数退出时将会把返回值处地址填入到EIP(即下一句要执行的指令地址)中,即程序跳到jmp esp处的地址执行该处的指令,此时ESP指向的地址也变为存储函数返回指令+4位置处的地址。
add esp,-X
jmp esp
第一条指令抬高了栈指针到shellcode之前。X代表shellcode起始地址与esp的偏移。如果shellcode从缓冲区起始位置开始,那么就是buffer的地址偏移。这里不使用sub esp,X指令主要是避免X的高位字节为0的问题,很多情况下缓冲区溢出是针对字符串缓冲区的,如果出现字节0会导致缓冲区截断,从而导致溢出失败。
第二条指令就是跳转到shellcode的起始位置继续执行。(又是jmp esp!) -
如何发现系统存在缓冲区溢出时, 我们可以如何实现缓冲区溢出攻击?
答:取得机器的控制权甚至是最高权限,利用缓冲区溢出漏洞攻击root程序,执行类似“exec(sh)”的执行代码来获得root 的shell。需要完成两个任务,就是在程序的地址空间里安排适当的代码和通过适当的初始化寄存器和存储器,让程序跳转到安排好的地址空间执行。
1) 在程序的地址空间里安排适当的代码,通过“植入法”的方式来完成,
2) 控制程序转移到攻击代码的形式,缓冲区溢出漏洞攻击都是在寻求改变程序的执行流程,使它跳转到攻击代码,最为基本的就是溢出一个没有检查或者其他漏洞的缓冲区,这样做就会扰乱程序的正常执行次序。
4.有什么好的方法保护缓冲区免受缓冲区溢出的攻击和影响?
答:目前有四种基本的方法保护缓冲区免受缓冲区溢出的攻击和影响:
1)强制写正确的代码的方法;
2)通过操作系统使得缓冲区不可执行,从而阻止攻击者殖入攻击代码,这种方法有效地阻止了很多缓冲区溢出的攻击,但是攻击者并不一定要殖入攻击代码来实现缓冲区溢出的攻击,所以这种方法还是存在很多弱点的;
3)利用编译器的边界检查来实现缓冲区的保护,这个方法使得缓冲区溢出不可能出现,从而完全消除了缓冲区溢出的威胁,但是相对而言代价比较大;
4)在程序指针失效前进行完整性检查,这样虽然这种方法不能使得所有的缓冲区溢出失效,但它的确确阻止了绝大多数的缓冲区溢出攻击,而能够逃脱这种方法保护的缓冲区溢出也很难实现;
- 缓冲区溢出漏洞攻击方式有哪些?
答:利用缓冲区溢出漏洞攻击root程序,大都通过执行类似“exec(sh)”的执行代码来获得root 的shell。有两种方式,就是在程序的地址空间里安排适当的代码和通过适当的初始化寄存器和存储器,让程序跳转到安排好的地址空间执行。