逛IOT安全情报板块的时候看到的一个刚刚公开的D-link的CVE,想到自己好像还没怎么搞过D-link的漏洞,于是有了这篇文章
准备工作:
固件下载链接:https://support.dlink.com/resource/PRODUCTS/COVR-C1203-US/REVA/COVR-C1203_REVA_FIRMWARE_v1.08B10.zip
固件解包:
binwalk -Me COVR-C1200_A1_FW103b10.bin
直接解包会发现没有任何反应:
此时怀疑是不是固件被加密了,于是选择能下载到的最老的版本试了一下:
但是发现最老的版本也是18年10月的,仍然是加密后的,此时需要找其他固件的中间版本
来看个经典老图
意思就是说当一个固件一开始不是加密的,后来变成加密的了,就必然存在一个中间版本。
加密前:固件包未加密,包中没有解密程序
中间版本:固件包未加密,包中有解密程序
加密后:固件包加密,包中有解密程序
所以关键其实就是找到中间版本,然后在中间版本中找到解密程序即可完成解密,一般来说一个路由器厂家不会开发多个加解密程序,所以可以通过寻找其他老版本路由器的中间版本获得解密程序,来解密我们想解密的其他路由器固件包。
现在选择一些经典的路由器款式,这里选择DIR-882,将它每一个版本的固件包下载下来,发现17年的固件包是可以直接解包的,18年下半年开始变成了加密包,所以中间版本就在变成加密包之前的一次版本中。
找到中间版本的固件包,然后全局搜搜一下de关键字:
可以看到在bin目录下有一个程序叫imgdecrypt,几乎可以确定这就是我们要找的固件解密程序了,查看一下程序架构:
发现是mispel的,选用合适的qemu,然后将被加密的固件的绝对路径作为参数执行一下:
发现没有任何报错,再次执行binwalk解包命令,可以解出来东西了:
文件系统直接解出,说明这个程序能够将加密的固件包解密:
模拟执行
好消息是D-link可以直接用firmAE模拟,坏消息是我们卡在了一个地方
用firm-AE直接模拟可以看到两个true,ip是192.168.0.50
尝试访问一下会发现,界面在/info/login这里迅速闪了一下,然后就到了初始化设置这里:
第一步我们顺利点过,然后发现第二步这里需要真机设备联网才能通过:
但是我们手头并没有设备,尝试过直接访问其他url,最后都会跳转到这里,现在想要继续模拟就要涉及到修改固件代码了,利用抓包软件找一下到底是在哪里进行的网络判断:
能够看到有一个字符串ERROR_WANLinkDown,我们以此为线索,在固件包中搜索一下:
然后将/usr/sbin/prog.cgi拖进IDA中进行分析,通过字符串搜索然后查找交叉引用,定位到了如下代码:
如果将如下代码中的if和else对应逻辑翻转一下,就可以在检测不到网络的情况下依然能够往下进行进一步设置。
但是因为是直接模拟的整个固件包,所以如果想更改固件代码需要重新打包固件,比较麻烦,如果是用qemu来模拟的话可以直接更改固件程序然后替换进去,但是用qemu模拟也有点麻烦,此时懒狗附体,看看能不能通过丢包的方式来绕过吧,于是发现真他喵的可以。
将如图所示的包直接丢掉,然后尝试登录:
嗯歪瑞奈斯,这次没有那个烦人的设置网络页面了。代码模拟执行阶段就到这里,接下来看看具体的漏洞情况
漏洞分析
其实绕过那个地方更主要的是为了通过拦截登录包的方式了解包内参数与代码的逻辑,将登录包拦截下来和prog.cgi里的代码逻辑进行对比:
通过对比可以轻松直观的看出来,想要修改传入prog.cgi代码里的参数,只需要修改包里对应位置的数据即可。
CVE详情的github页面已经删了,所以我们除了CVE中给出的几句话简介之外,没有其他任何详细信息了,来看看原文:
D-Link COVR 1200,1202,1203 v1.08 was discovered to contain a command injection vulnerability via the /SetTriggerWPS/PIN parameter at function SetTriggerWPS
查找字符串交叉引用
可以看到当ACTION参数为PIN的时候,可以利用PIN参数的值做一个命令注入,大致形式如下:
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body>
<SetTriggerWPS xmlns="http://purenetworks.com/HNAP1/">
<ACTION>PIN</ACTION>
<PIN>`COMMAND`</PIN>
</SetTriggerWPS>
</soap:Body></soap:Envelope>
但是仅如此仍然不能成功进行命令注入,需要计算正确的HNAP_AUTH和cookie:
具体方法涉及到HNAP协议,可以参考这篇文章:
https://xz.aliyun.com/t/5808
先发送request获取public key,然后经过计算登录上去,最后构造poc即可,经过构造以后可以看到成功执行操作:
由于作者已经将github上的漏洞详情删除,所以脚本我也不好直接放在这里了,有兴趣的话可以自行编写一下。这个洞虽然很新,但是整体原理很简单,由于本人没有弄过D-link的路由器,所以显得有些磕磕绊绊的。