CVE-2017-17215 复现
华为 HG532 路由器 RCE 漏洞
信息收集
上一次复现的时候就直奔漏洞点去, 这次决定模拟一下从零开始的过程
老样子找到固件并且 binwalk 一下, 本来是想看 /etc/init.d 看看这个路由器启动的时候做了什么, 里面只有一个 rcS
|
设定了一下环境变量, 看不出来什么, 但这时候注意到了
有个 upnp 文件夹, ai 一下发现是一套网络协议的集合, 主打一个零配置, 就像 USB 一样.
当一个支持 UPnP 的设备连上局域网后,它可以自动发现网络上的其他设备,并告诉大家:“我来了,我能提供这些服务”
UPnP 可以分成这些阶段
设备刚连上 Wi-Fi 或插上网线,就会立刻向局域网内进行组播,通常使用的是 UDP 的 1900 端口。
- 设备大喊:“大家好,我是一个华为路由器!我的控制接口在
http://192.168.1.1:37215/ctrl!” - 这个过程使用的是 SSDP
第二阶段:描述 —— 核心:XML 文件
当局域网里的其他设备(比如你的手机、电脑)听到了这个广播,就会去请求了解这个路由器到底能干什么。此时,路由器就会甩出一份“个人简历”**。
- 这份简历,正是就在
/etc/upnp/下, 会有一大堆 xml 文件 - 这些 XML 文件里巨细无遗地定义了设备支持的各种服务,以及每个服务包含的具体动作和所需参数。
还真是
第三阶段:控制 —— 协议:SOAP
现在,你的电脑看完了 XML 简历,决定让路由器干点活,比如“重启”或者“升级固件”。电脑会向路由器发送一个特殊的 HTTP 请求,里面的数据格式也是 XML,这种专门用于下达指令的协议叫做 SOAP
(好熟悉的 SOAP
- 电脑发送 SOAP 报文: “根据你的简历,我要调用你的 xx 动作,请把 xx参数的值设为 xxx。”
- 路由器收到后,解析这个 XML,提取出参数,然后去执行对应的底层代码。
那我们就从 UPnP 入手吧, 在 bin 目录下能找到 upnp 的 elf, checksec 一下
Arch: mips-32-big |
经典 mips, 顺手 file 一下
./squashfs-root/bin/upnp: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, no section header |
这次是 dynamically linked ,不是 static 了, 先用 ida 看看
进来就看到了非常熟悉的 system, 顺着引用去找
还好不是很多, 在最后面这个 system 这里
一看这个 GetChildNodeByName , 然后 snprintf 拼接命令之后 system 执行就知道这一定有问题. 接收到 SOAP XML 请求时就会解析 XML 树, 然后找到 <NewDownloadURL> 和 <NewStatusURL> 两个标签, 提取其中的内容, 通过 snprintf 拼接在一起, 最后送到 system 去执行, 所以可以通过 ; 去进行命令截断
环境搭不起来, 我真的要哭了
环境搭建
环境搭建参考
https://www.iotsec-zone.com/article/312
https://blog.csdn.net/2401_88244350/article/details/143403838
值得一提的是, 现在 vmware 的 vmtools 可以直接 apt 安装了
sudo apt update |
成功看到路由器登陆页面, 这里可能我下的固件不太一样, 没有华为那个标, 不过问题不大
抄了一段 poc 来发送, 来自
只不过他是用 Burp suite 直接发的, 我用 python 的 requent 库
import requests |
RCE 成功
POC 解析
简单解析一下 poc 为什么是这样的
xml中的<u:Upgrade>
这个函数一开始我按 x 没找到他的引用, 所以我也不知道它是怎么到这里触发这个漏洞的, 后面就简单研究了一下. 因为 snprintf 拼接的字符串中有个 Upgrade, 翻翻字符串找到
X 看了一下引用发现
下方正好就是 sub_40751C, 右边的 UPnPGetActionByName引用了这个字符串, 猜测这应该是 action 注册表/分发表项, 具体逻辑就不细看了, 所以 poc 里面构造的 xml 都有
<u:Upgrade xxxxx> |
Upgrade 里面包含的是
<NewStatusURL>xxxx</NewStatusURL> |
用于截断命令, 构造 RCE
url中的/ctrlt/DeviceUpgrade_1
溯源一下 UPnPGetActionByName
溯源 LABEL_23
发现一个路径检测
看到了 poc 中的 /ctrlt/ 几个分支分别做了去除前缀的功能, 大概作用如下
/ctrlt/DeviceUpgrade_1 -> DeviceUpgrade_1 |
然后进入
for (...) { |
这里在构造一个这样的字符串
service_name + "_" + instance_id |
也就是 poc 中 url 的 DeviceUpgrade_1, 至于 DeviceUpgrade_1 应该是来自下面这些函数的
大概找到了, 在
ATP_UPnP_RegService() |
继续找引用, 发现
这下看懂为什么 url 是 ctrlt/DeviceUpgrade_1 了
37215 端口是啥
剩下最后一个问题, 就是 37215
扫下端口发现是 mic
这里大概看了下 mic
点击 upnp ,找到了一串 inetd/服务配置字符串
所以 poc 中的 url 中的
37215/ctrlt/DeviceUpgrade_1 |
也能解释清楚为什么是这些了, 完整的链路是这样的
mic |
经历千辛万苦也是捋清楚整个流程了, 参考来自:
https://mdr.skyeye.qianxin.com/forum/share/4044
https://www.secrss.com/articles/52434
https://www.iotsec-zone.com/article/312
https://bbs.kanxue.com/thread-274713.htm
