CNVD-2013-11625
CNVD-2013-11625
漏洞描述:
D-Link DIR-645是一款无线路由器设备。
D-Link DIR-645 “post_login.xml”,”
hedwig.cgi
“,”authentication.cgi”不正确过滤用户提交的参数数据,允许远程攻击者利用漏洞提交特制请求触发缓冲区溢出
,可使应用程序停止响应,造成拒绝服务攻击。
测试环境:
复现的物理机为:ubuntu-20.04
安装
qemu / binwalk / sasquatch / gdb-multiarch
等对mips架构下的汇编有一定了解。
- 查看一下虚拟机的环境
- 开启桥接模式
- 进入root管理员模式,进入/opt/tools目录下,并且所有工具均保存到其目录下
略
- 安装binwalk、sasquatch、qemu。
安装binwalk
1 sudo apt install binwalk安装Sasquarch
1
2
3
4
5
6 sudo apt-get install build-essential liblzma-dev liblzo2-dev zlib1g-dev
cd /opt/tools/
sudo git clone https://github.com/devttys0/sasquatch
cd ./sasquatch
chmod +x build.sh
./build.sh安装qemu
1
2
3
4 sudo apt update && sudo apt install qemu qemu-user qemu-user-static qemu-system
sudo apt-get install binfmt-support libncurses5-dev gcc-arm-linux-gnueabi build-essential synaptic gcc-aarch64-linux-gnu
#安装依赖库
sudo apt-get install -y gcc-arm-linux-gnueabi 查看是否安装成功
qemu-system-x86_64 --version
- 环境配置搭建
我们使用qemu-system-mipsel从系统角度进行模拟
首先下载其mips架构下对应的内核和镜像
1
2 wget https://people.debian.org/~aurel32/qemu/mipsel/vmlinux-3.2.0-4-4kc-malta #内核镜像
wget https://people.debian.org/~aurel32/qemu/mipsel/debian_squeeze_mipsel_standard.qcow2 #文件系统然后编辑qemu启动脚本start.sh:
1
2
3
4
5
6
7
8 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 \(这三个文件放在同一目录下)
然后给运行这个start.sh 就行了(跑不起来,看看加一个可执行权限就行)
启动后输入用户名/密码 root/root或user/user即可登录qemu模拟的系统。
- 在宿主机创建一个网卡,使qemu内能和宿主机通信
因为我们创建的虚拟机是没网的,so我们给他配一个网卡就行了
安装依赖库:
1 sudo apt-get install bridge-utils uml-utilities在宿主机运行下面命令:
1
2
3
4
5
6 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查看一下
ip addr
这时我们给tap0配一个IP地址
1 ip addr add 192.168.100.254/24 dev tap0然后我们在配一下qmu虚拟系统的路由
1
2 ip addr add 192.168.100.2/24 dev eth0
route add default gw 192.168.100.254
- 最后一步,将binwalk解压出来的squashfs-root文件夹上传到qemu系统中的/root路径下
下载的固件进行解压即可
1 binwalk -Me DIR-815A1_FW101SSB03.bin找到squashfs-root文件进行scp上传,输入root密码即可
1 scp -r squashfs-root/ root@192.168.100.2:/root备份(在qemu虚拟机里进入/root/squashfs-root目录下)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 cp sbin/httpd /
cp -rf htdocs/ /
rm -rf /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接下来在qemu虚拟系统的根目录( / )下,创建一个名为conf的文件,此文件是httpd服务的配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 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 }
}
}
}这里还是建议scp传过去就行
1 scp conf/ root@192.168.100.2:/启动httpd服务
1 ./httpd -f conf我们在虚拟机访问一下这个服务
设置环境变量:
1
2
3
4
5 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"这样差不多环境就配完了
这里有一个小问题,我们模拟的环境是开启了地址随机化的,但是我们原本的固件是没有开着的。
1 >echo 0 > /proc/sys/kernel/randomize_va_space关掉之后就会发现我们是可以打通的了
但是qemu模拟的环境的shell十分难用
这里建议直接拿ssh连一下(
ps -aux查看进程
)
1 ssh 192.168.100.2
漏洞分析:
- gdb调试
首先下载一下使用异构gdb
1 sudo apt install gdb-multiarch然后embedded-tools/binaries at master · rapid7/embedded-tools在这下载我们的gdbserver传到我们的qemu虚拟机里面
1 scp -r gdbserver/ root@192.168.100.2:/在qemu虚拟机里起命令
1 ./gdbserver.mipsle 192.168.100.2:8888 /htdocs/web/hedwig.cgi然后我们在宿主机上启动
1
2
3 gdb-multiarch cgibin
set architecture mips
target remote 192.168.100.2:8888然后就能正常调试了
注意这里调试的时候建议直接下一个断点,然后直接让它走到我们的hedwigcgi_main函数就行
1
2 b *0x0409480
b *0x0409A54因为我们在尝试的正常调试的时候,他会先走到/lib/ld-uClibc.so.0这,但是我们这块会报错说我们找不到这个,所以建议直接下断点到hedwigcgi_main函数这,直接
c
进行跳过
- 逆向分析
事实上,固件的cgi都是实现在/htdocs/cgibin
中的。我们对cgibin
进行分析即可。
用ida32位打开
因为我web方向比较薄弱(逆向也一般),这里是直接进行对照[漏洞复现进行逆向分析的
首先取环境变量REQUEST_METHOD
,然后必须是post进行传参。
接着走到下面的函数cgibin_parse_request
,这个函数大致的理解就是对url
进行解析,然后将post
的内容读出来,然后在通过
sub_409A6C
函数进行解析。
cgibin_parse_request
函数内
这里需要获取环境变量,需要我们进行传入一些东西
这里我们获取CONTENT_TYPE
与application/
进行比较,之后调用数组off_42c014
中的函数。该数组在data段,查看该数组内容。
大致就是,根据CONTENT_TYPE
类型,调用不同的函数进行初始化。这里知道我们的参数类型大致为ONTENT_TYPE/x-www-form-urlencoded
。
然后走到我们的sess_get_uid(v4)
函数,这个函数里面对环境变量HTTP_COOKIE
的获取,并且对HTTP_COOKIE
中的=
进行分离
=
前面的内容被存入了v2,后面的内容被存入了v4
这里最后对v2进行了一个验证
也就是判断等号前的内容是否为uid
,判断通过了以后,就会将等号后面的字符串拼接入a1
,也就是主函数传进来的参数v4
。
然后就到了我们发现栈溢出的点
1 | sprintf(v27, "%s/%s/postxml", "/runtime/session", string); |
string
中存的V4
,也就是uid=
后面的内容是我们可以控制的,我们可以看见V27
的大小正好是1024
,正好是存在栈溢出的
然后继续往下看,还有一个,这里的string
仍然是v4
,进一步观察,发现v4
在两个sprintf
之间未被改变过,也就是说,这里的string
仍然是cookie
中uid=
后面的字符串,如果能走到这第二个sprintf
的话,那么这里才是真正的溢出漏洞点,因为仍然是v27
数组的溢出,两次拼接的字符串又一样,所以这里能覆盖上一次sprintf
的内容。
这里有两个函数判断,这里直接是可以不管的,因为一般情况下这两种情况一般机器都可以正常绕过。
漏洞验证:
这里也是直接粘贴脚本验证的
1 |
|
这里呢就是设置传入的环境变量,和我们进行查找偏移(这里我是直接使用cyclic 1024进行生成,并且用 cyclic进行查找的)
命令在qemu虚拟机里面敲,然后我们正常使用gdb-multiarch
远程进行调试就行了
然后我们也是看见了我们的偏移为1009也就验证了复现的时候,它这里是1009的主要原因了
我们现在知道了偏移,并且能控制几个寄存器,然后我们就可以正常进行构造ROP链进行攻击了
这里我还是看了l1s00t师傅-Mips栈溢出常见ROP构造 进行构建ROP链的
1 | from pwn import * |
然后还有正常反弹shell的
1 | from pwn import * |
libc基址是直接看就行,system函数命令找
1 | readelf -s ./libc.so.0 | grep system |
这里我找不到它对应的命令地址。准备先放着
插件安装:
IDA安装使用MIPSROP插件
把压缩包下的东西放到plugins目录下即可
通过网盘分享的文件:mipsrop.zip 链接: https://pan.baidu.com/s/10VZxc_Er0fXLo9WGoOCHaQ
提取码: Rweb
mipsrop简单使用
在idapython里面敲
1
2 import mipsrop
mipsrop = mipsrop.MIPSROPFinder()然后在下面的命令行查找就行了
常用的命令
1
2
3
4
5
6 rop = mipsrop.MIPSROPFinder()
rop.stackfinder() # 寻找栈数据可控的 rop,建立栈和 a类型与s类型 寄存器的关系
rop.find(xxx) # 查找指定的rop,可以使用正则表达式匹配
rop.tails() # 列出将栈上的数据保存在$ra等寄存器中的rop
rop.system() # 寻找命令执行的的 rop,建立栈与寄存器$a0的关系
rop.summary() # 查找可用的完整调用链
总结:
怎么说呢,算是真正第一次完整的吧一个漏洞完整的复现出来了,但是不会的地方还是有很多,比如对mips架构汇编指令的掌握,以及对其架构下ROP链构造的理解程度。以及一些web知识的掌握还要对逆向分析的理解都不是特别明了,并且花费时间周期很长,特别在环境的搭建和在上网查找复现文章的筛选上。
关闭qemu虚拟机并删除进程
- 首先查看进程
1 | ps -aux | grep qemu |
然后kill进程就行了
1 | kill -9 8143 8144 |
注意!注意!注意!
我们如果意外关闭虚拟机或者在想起一遍进程就需重新跟换文件系统即可!!
1 | rm vmlinux-3.2.0-4-4kc-malta |
参考文章:
DLink 815路由器栈溢出漏洞分析与复现 - unr4v31 - 博客园 (cnblogs.com)
从零到一:复现 DIR-815 栈溢出漏洞_dir815漏洞复现-CSDN博客
原创] 从零开始复现 DIR-815 栈溢出漏洞-二进制漏洞-看雪-安全社区|安全招聘|kanxue.com
dir-815 栈溢出漏洞复现 - Hexo (lst-oss.github.io)
特别感谢:
inf_师傅:https://blog.next-infinite.top/
l1s00t师傅:https://lst-oss.github.io/
再次感谢上面的文章和师傅,对我的漏洞复现和学习提供了很多的帮助并且收益匪浅!!!