分析一个D-Link的漏洞学习一下路由器漏洞方面的知识,《路由器0day》这本书提到的DIR-815 cookie溢出漏洞的固件在官网上已经找不到了,但是此漏洞影响的范围包括了DIR-645,故用DIR-645 1.01版本的固件分析
分析用到的工具:
IDA Pro:反汇编和远程调试
Ghidra 9.1.2:我的IDA不能生成mips的伪代码,所以我用ghidra来看伪代码
Ubuntu + qemu:模拟路由器运行环境
固件下载链接:ftp://ftp2.dlink.com/PRODUCTS/DIR-645/REVA/DIR-645_FIRMWARE_1.01.ZIP
使用如下命令将文件系统提取出来:
从书中得知漏洞存在于./htdocs/cgibin中,将cgibin拷贝到物理机中,使用IDA分析,shift+F12打开字符串窗口,搜索“HTTP_COOKIE”
双击这一项,定位到rodata段查看详细信息,选中aHttpCookie,按X键查看调用信息(ghidra则是选中函数名,右键->References->find References to #function name#)
双击后进入sess_get_uid函数,此函数只是使用了“HTTP_COOKIE”字符串,继续按X键查看调用信息
双击进入hedwigcgi_main函数,看到调用sess_get_uid函数之后紧接着调用了sprintf函数(PS:之所以用sprintf而不是strcpy是因为strcpy只能是字符串到字符串,而sprintf可以是从任意类型到字符串),而sprintf函数就是导致栈溢出的重要函数;接下来需要用IDA进行远程调试,调试之前需要对书中自带的脚本进行一些修改,修改后如下:
使用第二行注释中的命令运行脚本,开启远程调试,接下来会详细讲解如何用IDA远程调试DIR-645路由器固件(主要是本人使用IDA时花一天才解决此问题o(╥﹏╥)o);首先用IDA打开cgibin文件,并定位到上面讲的sprintf函数(注意是“jalr $t9 ; sprintf”那一行),然后F2下断点
然后在Ubuntu中运行pentest_cgi.sh脚本(运行命令在文件的第二行注释),并等待调试
在IDA中选择Debugger->select Debugger…在对话框中选择GDB debugger然后点击OK
重新选择Debugger->Process options… 输入远程路径、hostname和端口,然后单击OK
最后点击Debugger->Attach to process… 我的选择框中只有一项,所以就选这一项,然后单击OK
附加成功后无需再下断点,直接按F9就可以停在调用sprintf函数的位置上
在Hex View窗口右键Synchronize with -> SP,这样窗口就会跟着程序走了,方便观察栈溢出
修改pentest_cgi.sh然后配合patternLocOffset.py算出溢出位置,修改后的pentest_cgi.sh代码如下:
这个pentest_cgi.sh脚本在之后漏洞利用测试的时候也会用到
使用patternLocOffset.py测试固件溢出位置,命令如下:
直接执行pentest_cgi.sh,并且用IDA附加调试,得到溢出的偏移
将程序报错时显示的字符串带入patternLocOffset工具中,得出偏移位置
查找ROP链时需要用到mipsrop插件,这个插件对IDA7的支持不好,需要用到IDA68,使用时将GitHub上下载的ida工程中的shims和mipsrop两个文件夹下的py文件全都复制到IDA的plugin目录中
在IDA68中输入命令:mipsrop.stackfinder()
得到以下可做ROP的地址,选择0x159cc
IDA中的mipsrop只是得到ROP的偏移,还需要找到libc.so.0的基地址,
使用qemu模拟mips系统运行时需要先解决网络问题,否则无法传文件;有两种方法,其中一种是修改/etc/network/interfaces文件,这种方法我始终无法成功,所以我选择创建网桥的方法,命令如下:
创建网桥:
创建tap接口,并添加到网桥:
使用命令,启动镜像:
进入虚拟机(虚拟机账号/密码:root/root)后需要设置IP,这一步并不是必须的,例如我并没有设置IP就直接可以联网了:
我在没有设置IP的情况下直接ping www.baidu.com可以ping通
接下来需要用scp命令把路由器的所有文件从Ubuntu中复制到Debian中,命令如下(IP改成自己的Debian的IP):
运行漏洞代码前先将ASLR关闭
第一个看似libc.so.0的基地址,实则并不是,有前辈分析此漏洞时使用这种方法成功找到过libc基址,但是我始终无法成功,所以我采用第二种方法
第二种方法是使用qemu的用户模式调试,需要注意的是这种调试方式当qemu-user版本过低时,使用gdb远程调试会出现如下问题
此时gdb会显示这是一个bug,并要求你上报
这个错误其实是qemu的一个bug,Ubuntu18.04适配的是2.11.1版本的qemu,此时需要将qemu升级到4.2以上的版本,有两种方法:
1、在GitHub上下载源码,并编译
2、使用Ubuntu20.04及以上版本下载qemu,因为Ubuntu20.04适配的就是qemu 4.2
我选择的是使用Ubuntu20.04运行qemu调试,而Ubuntu20.04是个大坑;首先Ubuntu20.04的源仓库中并没有包含Python2的pip,所以需要使用get-pip.py来安装pip2:
使用GitHub或者apt安装好binwalk后使用binwalk提取固件,可能会报此错误
需要手动安装一下sasquatch,命令如下:
当一切就绪时,运行pentest_cgi.sh脚本,然后使用gdb远程调试
使用之前获得的libc基址+偏移构造ROP链,poc代码如下:
以上是《路由器0day》一书中的原版poc脚本,接下来是简单版本的poc脚本:
运行脚本,将payload打印到之前用patternLocOffset.py创建的文件dir645_patternLocOffset_test中,然后运行pentest_cgi.sh,启动远程调试
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-11-25 16:24
被pureGavin编辑
,原因: 修改内容