IOT入门--路由器命令执行漏洞
D-Link DI_8100命令执行漏洞复现
所需工具
Burp Suite-Linux下载
BurpSuite v2024.10汉化无cmd框版(2024.11.03更新) - 吾爱破解 - 52pojie.cn
配置Burp Suite教程
Burp Suite代理和火狐浏览器的设置(超详细)_burpsuite firefox-CSDN博客
固件下载地址:
http://www.dlink.com.cn/techsupport/ProductInfo.aspx?m=DI-8100
漏洞分析
使用binwalk
对固件进行分解
1 | binwalk -Me DI_8100-16.07.26A1.trx |
查看一下系统架构以及保护
下面使用FirmAE对固件进行仿真
进入FirmAE工具文件夹下,使用 run.sh
来进行启动
1 | sudo ./run.sh -d dlink <DI_8100-16.07.26A1.trx的路径> |
选择2进入终端,然后使用ps
命令查看进程
我们发现程序启动之后 jhttpd
这个服务就启动了,所以我们主要的程序就是这个 jhttpd
服务,接下来我们也需要使用IDA分析这个程序
下面来看官方的漏洞描述
1 | Description |
也就是说在 msp_info.htm
页面中 cmd
参数造成命令执行。
下面我们使用 ida
来分析 jhttpd
程序,
我们可以通过 msp_info
字符串来进行定位接着查找到 msp_info_htm
函数
函数存在的漏洞逻辑如下
在 msp_info_htm
函数的开头,会从传进来的值中 获取flag字符串
,如果成功获取到flag字符串然后会执行不同的命令,当我们传入的 flag=cmd
的时候就会执行到漏洞点,后续的 cmd的内容
就会被放入到 system
中执行
我们打开本机的浏览器,访问 192.168.0.1:80
(需要注意FirmAE启动的这是内网,只能使用本机访问,后续还需要用到Burp Suite也需要提前准备好) D-Link路由器的初始账号和密码都是admin,直接登入后就可以得到下面这个页面
我们先来试一下这个漏洞,我们按照这个漏洞的利用逻辑来写一个url进行注入
1 | 192.168.0.1/msp_info.htm?flag=cmd&cmd=`echo%20aaaa>a.txt` |
在浏览器输入这个url后,我们可以查看一下我们路由器的系统终端中是否多出了一个 a.txt
文件
可以发现已经执行了我们的命令,根目录下确实多出了a.txt
exp编写
重新回到登入的那个界面,然后刷新界面使用Burp Suite进行抓包
然后按照抓包得到的信息编写下面的exp
1 | import requests |
运行脚本
随后我们可以查看根目录下文件发现已经执行命令生成了xidp.txt
简单调试
1 | # mygdb.sh |
使用命令 gdb-multiarch -x mygdb.sh
这里A0寄存器作为第一次参数,然后调用system函数
DI_8100的第二个命令执行漏洞
同样这个固件中还有另外一个命令执行漏洞在 upgrade_filter_asp
这个函数也存在
同样回到登入页面然后抓包查看信息
编写exp
1 | import requests |
D-Link DIR 615/645/815 命令执行漏洞
固件下载
固件下载:
https://ftp.dlink.ru/pub/Router/DIR-815/Firmware/RevA/
漏洞描述
官方漏洞描述:
国家信息安全漏洞共享平台
我们使用 binwalk
分解固件之后我们进入 _DIR815A1_FW103b01.bin.extracted/squashfs-root/htdocs/web
文件夹下,使用 ls -la
命令就可以看到,这个 service.cgi
实际是一个软连接,本质上是 cgibin
这个文件
下面我们将这个 cgibin
放入ida中分析
同样通过字符串定位
找到这个叫做 servicecgi_main
的函数
也就是漏洞利用的路径为 servicecgi_main -> lxmldbc_system -> system
下面详细分析漏洞的利用过程
在 servicecgi_main函数
的开头获取传参方式并进行判断
这里的逻辑为 如果为 POST
则进入 大if
将 v2赋值为1024
如果不为 POST
则进入 大else
然后判断是否为 GET
如果为 GET
则将 v2赋值为64
如果既不是 POST
也不是 GET
则会执行 goto LABEL_10
而 goto LABEL_10
会导致直接跳过 lxmldbc_system函数
,所以我们的传参方式需要为 POST
或者 GET
其中之一
在往下看,这里有一个 cgibin_parse_request(sub_40A63C, 0, v2) >= 0
的判断
也就是说 cgibin_parse_request(sub_40A63C, 0, v2)
的返回值不能为负数,否则也会执行 goto
导致无法运行到 system
我们进入 cgibin_parse_request
这个函数中
可以看到函数开头使用 getenv
函数获取了几个环境变量,这里我们就可以判断出,如果我们想要利用漏洞就一定需要使用POST传参方式,原因如下
CONTENT_LENGTH
表示请求体长度- GET 请求的请求体长度为 0,因此
getenv("CONTENT_LENGTH")
返回NULL
- 只有 POST 请求才有非零的
CONTENT_LENGTH
然后下面的 v12
是获取到环境变量中的 ?
后面的内容,并且后续将作为参数传入到函数sub_402B40
中
下面我们进入 sub_402B40(&v20, v12, v13);函数
中查看
我们可以看到传入的 v12
是 其中的 a2
并且其中还有一个 v12
而这个 v12 = *(a2+v6)
并且这个 v6从0
开始计算,也就相当于将 a2
一个个取出并且用于判断,通过判断 &
和 =
来对 v12
进行拆分
所以根据分析 我们可以知道 sub_402B40函数
是一个 HTTP查询字符串解析器
,专门用于 解析URL中的查询参数
(如 ?key1=value1&key2=value2
)
下面我们回到 cgibin_parse_request
继续往下看
我们必须进入这个if分支
,并且执行这个 return ((&off_42C014)[3 * v16 - 1])(a1, a2, v7, &v14[v17]);
因为下面全都是 return 负数
这会导致我们返回到 servicecgi_main
中的时候会进入上述我们提到的 if分支
然后就会执行 goto
导致无法执行 system函数
而这里的return逻辑 if ( !strncasecmp(v14, v18, v17) )
就是我们的 v14
的 前v17个字节
需要和 v18相同
而这里的 v18 = *v15 = off_42C014
所以需要看这个 全局变量off_42C014
而 off_42C014
开头的字符串为 application/
(其实这里固定套路了,大多数时候都是 application/x-www-form-urlencoded
)
我们继续往下分析我们可以知道他最终是会调用 sub_403B10
这个函数
这个函数的开头同样也是一个判断,继续进行比较后续的字符串是否为 x-www-form-urlencoded
所以其实我们最终需要传入的那个环境变量Content-Type
为 application/x-www-form-urlencoded
才符合条件
而这个 application/x-www-form-urlencoded
是一种 HTTP 请求内容编码格式,主要用于 HTML 表单(<form>
)提交数据时的默认编码方式,它是 Web 开发中最基础的数据传输格式之一,用于 POST
所以接着我们会进入 sub_402FFC
在 sub_402FFC
中同样有 sub_402B40
用于切割字符串,这里不再详细分析
下面回到 servicecgi_main
继续往下看有一个 sess_ispoweruser
这个函数里面有很多子函数,里面的子函数会打开很多文件,如果我们直接使用qemu之类去模拟仿真的时候会因为缺少这些文件而导致复现失败,所以这里复现的时候我们一般就直接将它nop掉就行了
然后终于就是到了我们的漏洞部分
这里可以看到 v5
的内容会被拼接到system的指令中去,而 v5
是我们用户可控的部分,这也是漏洞产生的原因
漏洞复现
使用FirmAE进行仿真
这里我们先不修改直接使用下载的.bin文件来试一下
1 | sudo ./run.sh -d dlink <DIR815A1_FW103b01.bin的路径> |
仿真成功后可以使用浏览器进行访问 192.168.0.1:80
下面编写exp
1 | import requests |
这里如果我们直接运行脚本然后输入指令最后显示的结果是FAILED也就是失败了,这是因为我们还没有去掉上面我们提到的 sess_ispoweruser
下面我们将.bin
文件使用binwalk
进行分解,然后使用IDA将cgibin
中sess_ispoweruser
函数去掉
下面是程序nop修改之后的样子 下面的 v4
就是我们上面提到的 v5
去掉之后我们通过IDA将修改后的部分保存,然后替换掉原本的 cgibin
文件
然后我们回到 squashfs-root
文件夹执行下面指令
1 | mksquashfs ./squashfs-root/ ./rootfs.squashfs -comp gzip |
然后我们就可以得到 rootfs.squashfs
这个文件
我们再次使用FirmAE进行仿真
使用下面指令
1 | sudo ./run.sh -d dlink <rootfs.squashfs的路径> |
仿真成功后再次使用我们的exp,发现现在是显示 OK
了,创建文件也可以成功了 (但是我试了一下,ls依旧是没有回显的)
这里虽然我们直接使用ls没有回显,但是我们可以创建文件来读取,如下
想要读取完整内容,我们可以直接通过浏览器网址访问对应文件
浏览器可以直接下载我们使用命令创建的文件
那么这个漏洞就复现到这里
参考:
D-Link DI-8100命令执行漏洞复现 - IOTsec-Zone
D-Link DI-8100命令注入 && 调试分析 - IOTsec-Zone
D-Link DIR 615/645/815 service.cgi远程命令执行漏洞