DIR-815漏洞复现
固件分析
确定固件架构
1 | cd /bin |
binwalk分离固件
1 | binwalk -Me file |
mipsrop下载,ida9.0版本
IDA插件 MIPSROP的安装和使用方法_ida mips-CSDN博客
漏洞点分析
官方漏洞批漏:https://www.cnvd.org.cn/flaw/show/CNVD-2013-11625

官方的漏洞报告中只提及了DIR-645型号的hedwig.cgi中会存在缓冲区溢出的漏洞,其实D-Link的DIR-815/300/600/645等型号都存在这个漏洞
根据漏洞描述,可知漏洞点在hedwig.cgi,同时这个文件指向/htdocs/cgibin,这个就是我们要分析的二进制文件

main中定位主要函数

1 | // 函数入口,保存寄存器,分配栈空间,初始化局部变量。 |
getenv去检查环境变量,然后全检测是不是post传参

cgibin_parse_request,函数中获取三个环境变量,这里参数的需要设置,并且有一定的要求

漏洞点就在sess_get_uid中

获取cookie环境变量,并解析,首先是检查cookie名是否是uid,然后将uid=后的ip给v4,而且没有限制,这里就存在栈溢出


然后是将v4->string->s,但s只有0x400字节,然后就会溢出


然后就是劫持程序流程,但实际上还需要绕过,也不是说绕过,参考正常pwn栈溢出的思路,我们肯定需要让程序执行完,然后才能执行到我们布置的rop链上,如何让程序能正常去执行
后续有两个要求
1./var/tmp/temp.xml存在
2.haystack != null
第一个只要我们不去破坏程序环境就不会出问题
关键是第二个,通过交叉引用我们发现控制haystack值的地方
这里实际上有两种处理方式,因为目的就是让程序走到我们的gadget上
1.CONTENT_TYPE=application/x-www-form-urlencoded
也是网上很多师傅分析的

sub_409a6c
每当cgibin_parse_request解析到一段需要处理的数据时,就会调用sub_409A6C,把数据交给它处理。这样,haystack就始终保存着最新的请求数据内容
正常执行的话haystack是不为空的

之后就是获取两个环境变量,REQUEST_URI/CONTENT_LENGTH

主要是CONTENT_TYPE,会检测”application/“这个字符串,同时会跳转到一个地方,ida中是看不到的,我们可以下断点调试看看

这里返回的是0x403b10

0x403b10

然后还是返回到0x409a6c,需要保证REQUEST_URI存在,然后程序就可以返回到我们布置好的rop上getshell




实际上我们可以CONTENT_TYPE=任意,仅需设置post传参其他参数都不用控制,这样岂不是更简单
在sub_403B10不进入sub_402FFC,而是往下走,最后到sub_403794->cgibin_print_http_status
此时程序也可以走完,同时不触发报错,可以利用栈溢出漏洞,栈溢出的偏移不一样罢了


偏移

poc:
1 | from pwn import* |

qemu用户态模拟
这个比较简单,就跟本地调试异架构一样,但参数不一样
直接gdb调试
进入 squashfs-root 文件夹中,执行下列指令
1 | cyclic 2000 > payload |
init.sh脚本启动
1 | #!/bin/bash |
mygdb.sh
gdb-multiarch -x mygdb.sh
1 | set architecture mips |
脚本调试
1 | from pwn import* |
qemu系统态模拟
step1 下载对应内核+镜像
Index of /~aurel32/qemu/mipsel

step2 创建网桥
安装网络配置器
1 | apt-get install bridge-utils uml-utilities |
修改interfaces文件
1 | sudo vim /etc/network/interfaces |
修改之前可以先备份
sudo cp /etc/network/interfaces /etc/network/interfaces.brk
修改为
1 | auto lo |
在 /etc/qemu-ifup 文件中写入下面内容(如果没有则需要创建,然后使用 sudo chmod a+x /etc/qemu-ifup)
注意是写入,不是改成下面内容
1 | #!/bin/sh |
开启物理机的转发功能
1 | #! /bin/sh |
然后在到/etc文件中创建一个 /qemu/bridge.conf 在这个文件中写入 allow br0
配置好之后reboot
step3 配置qemu网络
qemu启动脚本
1 | # start.sh |
将start.sh与下载的内核+镜像放置在一起,启动qemu
账号密码都是root
执行后会出现一个黑色小窗口,然后里面在加载程序,最后可能会有一个 fail 但是不要紧,不影响我们复现漏洞,太多 fail 可能就有点问题了需要问AI检查一下
nano 来修改 /etc/network/interfaces
将eth0改为eth1,(ip -a查看一下qemu网卡,不一定是eth1)

启用eth1接口
1 | ifup eth1 |
之后执行ip -a就可以看到qemu的ip了
互ping,检测是否互通,按照上述步骤来是没问题的
在qemu中输入应该不方便,可以用ssh链接
1 | # 低版本Ubutnu |
step4 启动环境
将路由器文件分解得到的 /squashfs-root 文件传入到 qemu虚拟机的 /root 文件夹下面
1 | # 低版本Ubutnu |
/squashfs-root 文件中使用 nano指令 创建一个 http_conf 文件用于开启httpd服务
1 | Umask 026 |
qemu执行以下脚本,启动web服务
1 | #init.sh |
然后就应该可以去访问了

可以用nmap去扫描qemu,检测端口是否开放
1 | nmap 192.168.10.67 |
step4 远程
需要用到gdbserver
已经编译完成的程序(但是作者好像命名错误了把mipsel打成了mipsle, 所以如果使用这个下面的脚本也需要改一改)
https://github.com/rapid7/embedded-tools/tree/master/binaries/gdbserver
远程调试
qemu /root/squashfs-root/路径下创建run.sh
调试ip地址是虚拟机主机ip
1 | #!/bin/bash |
注:
1 | #echo "winmt=pwner"|./gdbserver.mipsel 192.168.10.60:6666 /htdocs/web/hedwig.cgi |
需要将gdbserver.mipsel传入qemu中
然后gdb-multiarch 接过来即可
1 | set architecture mips |
file ./file
可以把文件加载到gdb里面获取函数名
qemu虚拟机要获取shell只能去打反弹shell,这里需要运行脚本,gdb-multiarch那边可以接收到我们发送的paylaod
1 | from pwn import * |
./run之后,然后Ubuntu的gdb去连接,然后Ubuntu在开个终端发送exp然后gdb里面就可以收到,这样子调试,反弹shell,还要再开一个终端监听端口,一共需要四个终端
1 | nc -lvnp 8888 |
远程攻击
法一:向 QEMU 虚拟机上传 payload
这种方式我们直接将 payload 写入文件,然后上传到 QEMU 虚拟机,通过设置环境变量来读取 payload 作为 uid,从而触发漏洞反弹 shell
run.sh
1 | #!/bin/bash |
1 | from pwn import * |
将生成的payload scp过去
法二:向 httpd 服务发送 HTTP 报文
1 | from pwn import * |
退出仿真环境
退出是执行fini.sh,要不然下次进去qemu会报错,init.sh脚本已经破坏了根目录,如果忘记的话重新下载内核和镜像
1 | #fin.sh |
关于虚拟桥接网络,可以不用去关闭
要关闭的话就这样,但后续配置还需要去配置虚拟桥连网络

参考链接
DIR-815 栈溢出漏洞(CNVD-2013-11625)复现-先知社区
从零到一:复现 DIR-815 栈溢出漏洞_dir815漏洞复现-CSDN博客
D-Link DIR-815路由器溢出漏洞分析 | ZIKH26's Blog