Exercise1 找漏洞
1.[http.c:165] <sprintf(envvar, "HTTP_%s", buf);>
在http_request_headers()函数调用了不安全的sprintf()函数。sprintf()函数有三个参数:envvar, “HTTP_%s” 和 buf。这个函数的作用是先将“HTTP__”和buf拼接,然后复制到envvar中,这里buf的最大长度是8192,而envvar长度是512,我们可以将buf溢出到返回地址中,这里buf为http头部的key,我们可以选择将2000个‘A’填充在buf中。
2. [http.c:105] <url_decode(reqpath, sp1);>
在http_request_line中调用了url_decode函数,这里传入了参数reqpath和sp1,作用是将sp1处的字符串拷贝到reqpath地址处,但url_decode此处并不做长度的检查。reqpath的长度为4096,而sp1这里最长可以达到8192,因此我们可以考虑将sp1指向的内容设置为5000,这里溢出的内容可以覆盖到返回地址,最终使得程序崩溃。
3.[http.c:159] <url_decode(value, sp);>
在http_request_header中同样调用了url_decode,这里传入的参数是value和sp,这里value的长度是512,而sp的长度是8192,这里需要修改的内容是http报文头部。
4.[zookd.c:70] <http_request_line(fd, reqpath, env, &env_len)>
reqpath缓冲区的大小应小于2048字节。发送长度超过2048字节的请求路径将导致缓冲区溢出。
5.[http.c:282] <strcat(pn, name);>
http_server中的pn缓冲区只有1024字节。如果传递足够长的URI值,将导致缓冲区溢出。
6.[http.c:344] <strcpy(dst, dirname);>
dst是大小为1024的名称缓冲区。如果reqpath大于1024,则可能导致缓冲区溢出。
Exercise2 测试漏洞
exploit-2a.py
[http.c:105]在http_request_line中调用了url_decode函数,这里传入了参数reqpath和sp1,作用是将sp1处的字符串拷贝到reqpath地址处,但url_decode此处并不做长度的检查。reqpath的长度为4096,而sp1这里最长可以达到8192,因此可以考虑将sp1指向的内容设置为2000,这里溢出的内容可以覆盖到返回地址,最终使得程序崩溃。
代码:
def build_exploit(shellcode):
req = b"GET /"
for i in range(2000):
req = req + b"A"
req = req + b" HTTP/1.0\r\n"
req = req + b"\r\n"
return req
执行效果:
exploit-2b.py
[http.c:159] 在http_request_header中调用了url_decode,这里传入的参数是value和sp,这里value的长度是512,而sp的长度是8192,这里我们修改http报文头部。
代码:
def build_exploit(shellcode):
req = b"GET / HTTP/1.0\r\n"
req = req + b"HOST"
for i in range(777):
req = req + b"7"
req = req + b"\r\n"
return req
执行效果:
检查攻击是否有效:make check-crash
Exercise3 可执行栈注入shellcode攻击
首先获得shellcode在内存中的地址,先使用gdb -p $(pgrep zookfs-extack)进入gdb调试模式,然后使用break http_serve设置断点,然后使用continue继续运行。
再打开一个新的cmd调用./exploit-3.py locahost 8080请求网站,此时,该请求被阻塞。
再回到gdb调试界面,print &pn即可获得其在内存中的地址。
可以看出需要的地址是0xbfffd9fc。
接下来编写需要注入的汇编代码,写入shellcode.S文件,其功能是调用unlink删除/home/httpd/grades.txt文件。汇编代码如下:
编写完毕后,将S文件编译成bin文件,需要两条指令,为了方便使用,可以将这两条指令写成一个sTobin.sh文件,方便调用。该文件内容如下:
最后编写exploit-3.py进行攻击,根据exploit-template.py进行修改即可,需要修改的内容如下:
然后,使用touch /home/httpd/grades.txt创建文件,使用make check-exstack测试,测试结果如下:
可以看见,grades.txt也确实被删除了
Exercise4 不可执行栈上return-to-libc攻击
这一步首先改变zoobar网站的启动指令为
./clean-env.sh ./zookld zook-nxstack.conf
采用这条指令启动的zoobar网站,上一个实验的汇编代码无法注入内存栈,所以采用return-to-libc攻击,将程序的控制权跳转到系统自己的可执行代码,实验目标也是为了删除grades.txt文件。
攻击代码如下:
exploit-4a.py:
exploit-4b.py
然后,使用touch /home/httpd/grades.txt创建文件,使用make check-libc测试,测试结果如下:
可以看见,grades.txt也确实被删除了
Exercise5 再找出两个漏洞
(1)在http.c第129行,有一个缓冲区溢出bug。我们能够通过发送超过8192长度的请求攻击这个漏洞。但是,这个缓冲区中所有的字符都会转换为大写,使它很难像实验4一样进行攻击。
(2)在http_serve_directory()函数中,允许所有攻击者通过。
Exercise6 修复漏洞
1.将sprintf()替换为snprintf();
2.将strcat()替换为strncat();
3.对于由url_decode引起的缓冲区溢出,将dst变量设置为静态变量。
4.将http.c中http_request_headers()函数中value数字的大小修改为大于8192.
5.将zookd.c中process_client()函数的reqpath数组修改为8192大小