热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【漏洞分析】CVE20179765:深入分析一个影响数百万IoT设备的漏洞(含演示视频)

译者:興趣使然的小胃 & 童话 预估稿费:200RMB 投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿 一、前言

http://p4.qhimg.com/t014792f5e74f18fb22.png




译者:興趣使然的小胃 & 童话

预估稿费:200RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿



一、前言

在另一篇文章中,我们初步介绍了Devil’ Ivy这个漏洞的整体情况及影响范围,本文从技术角度深入分析了这一漏洞的细节。

从去年起,我们开始分析远程配置类服务的安全性,彼时我们并不知道我们会发现那么多漏洞,也不知道这些漏洞会影响那么多用户。我们一直在研究远程配置类服务中漏洞的普遍性及共同特性,因此当我们接触到M3004这个设备时,我们自然会去寻找这类服务。首先我们枚举了M3004设备的开发端口,检查负责处理输入数据的那些代码。我们发现了一个名为wsd的服务,该服务会从gSOAP中导入一个第三方库。我们利用IDA Pro这个逆向分析工具来检查负责将输入数据写到栈缓冲区中的那些代码,最终在这些代码中发现了一个漏洞。

http://p1.qhimg.com/t0165933b053288f098.png

图1. IDA Pro中正在分析的某个函数

作为一款安全摄像头,M3004在80端口上提供了一个ONVIF服务,如果向该服务发送一个POST命令就会触发存在漏洞的代码。该设备内部预置了gdbserver工具,我们通过Web界面启用SSH接口,然后利用SSH接口对设备服务进行远程调试,通过这种方式,我们得以观察服务的内部工作流程以及我们代码的输出结果。我们在栈上设置了一个断点,当溢出数据覆盖掉栈上保存的某个返回指针时,我们观察到程序会发生崩溃,进而验证了漏洞的存在。接下来我们需要做的就是实现目标设备上的代码执行。

虽然将数据写入栈上时我们没有受到字节数的限制,但仅凭这一点我们还是无法实现代码执行,并且设备存在过滤机制,要求我们发送的数据值必须大于31。我们使用了一种名为ROP(Return Oriented Programming,返回导向编程)的技术,以便将地址信息写入栈中,强迫程序执行libc中的代码片段,从而实现对栈上代码执行限制条件的规避。通过这种技术,我们分配了可以执行的空间,将我们的shellcode复制到该空间中,然后将执行过程引向此地址。虽然我们所使用的地址中包含的值必须大于31,这在某种程度上的确给我们造成一些限制,但我们仍然可以完成代码执行目标。

一旦我们研究到这一步,我们就可以编写shellcode(当然所有值都应该大于31),利用shellcode打开端口,使远程用户可以连接到设备的shell。此时我们利用Devil’s Ivy(CVE-2017-9765)已经拿到了代码执行权。由于Axis做了些安全设置,利用这个漏洞我们只能在M3004上以非特权用户身份访问shell。然而,我们可以执行ONVIF中包含的某些命令,而通常情况下只有特权用户能够执行这些命令。我们可以将摄像头恢复到出厂设置状态,可以控制摄像头,可以重启摄像头防止操作员监控视频,也可以更改网络设置。

读者可以继续阅读下文的技术细节,也可以直接拉到文章末尾,观看演示视频。



二、访问设备

首先我们从Axis的官网上下载了M3004设备的最新版固件。官网的确要求注册账户才能下载固件,但并没有去验证用户是否是合法的客户。我们构造了一个Nate Johnson身份,使用了一个可达的邮箱地址,然后非常顺利地下载到了设备固件。我们使用binwalk以及专用于JFFS2文件系统的Jefferson提取器提取了固件中的文件系统以及Linux内核。

http://p8.qhimg.com/t01ad0e5aeec405ba20.png

图2. binwalk的输出结果

我们运行nmap来扫描摄像头开放的端口,发现1900(upnp)、3702(ws-discover)以及5353(mdns)开放。对文件系统做了一些分析后,我们发现ws-discover与处理SOAP协议的wsd有关。wsd需要导入libsoap.so库(来自于Genivia提供的gSOAP产品)来解析输入的SOAP消息,我们仔细检查了负责将输入数据写入栈中的那些代码,然后使用IDA Pro查找栈缓冲区,手动跟踪复制到缓冲区中的那些数据的来源。通过这种方法,我们只花了1天时间,就从汇编代码中找到了这个漏洞。

http://p6.qhimg.com/t01ebfcc6f1038f0670.png

图3. 从libsoap.so中导入的数据



三、代码分析

我们发现soap_get()函数中有一段代码,将输入数据写入大小为0x40字节的栈缓冲区中。这段代码会在一个循环中检查“?”结束符是否存在,或者会检查某个结尾符是否存在,条件成立才会跳出循环,而没有去检查已写入0x40字节堆缓冲区中的实际字节数。

http://p0.qhimg.com/t013ef14658a4c35d4b.png

图4. soap_get()中存在漏洞的代码

在上图中,R11为数据计数器,其值被设置栈缓冲区的大小,R7为栈缓冲区指针,R12为从网络中读取的输入字节。如果R11计数器的值小于0,函数会跳过栈缓冲区的写入过程,但会继续使用j_soap_getchar()读入数据。如果我们向wsd写入足够多的数据,就能将计数器的值重新恢复到正整数值,这样一来我们就能绕过0x40字节数的限制,将数据写入栈中。这个过程需要好几分钟,但对输入数据的数量没有作限制,并且在netcat的帮助下我们很容易就能完成这一过程。经过计算,我们发现我们需要发送0x8000000个字节才能将计数器重新恢复到一个正整数值,然后发送0x40个字节来填充大小固定的栈缓冲区,在覆盖返回地址前我们还需要再发送0x30个字节。

我们向80端口上的“onvif/device_service”服务发送了一个POST命令,进而接触到漏洞利用点。为了发送0x80000070个字节,我们构造了一个文本文件,文件开头为“POST /onvif/device_service”,在随后新的一行中使用“

nc [camera_ip] 80

我们需要更多的信息才能确定我们是否能够利用这个漏洞,此时此刻,当我们将全部数据发送完毕后,目标服务已经没有任何响应了。在Asix官方支持中心的指引下,我们通过ssh接口成功连接上摄像头。摄像头内置了一个Web服务器,我们转到高级菜单页面,编辑/etc/ocnf.d/ssh,启用了ssh功能。重启摄像头后,我们使用已有的用户名及密码成功连入设备的ssh接口。随后我们发现摄像头已经预先安装了gdbserver,因此我们在本地计算机上使用ARM编译的gdb来观察漏洞触发时服务的工作过程。正如我们预期的那样,当服务处理到我们提供的溢出数据时就会发生崩溃。

http://p8.qhimg.com/t0161e92b3fba3e236c.png

图5. wsd发生崩溃



如上图所示,此时wsd已经崩溃,R4-R11以及当前的PC值都存放在栈上,从输出结果中可知,我们已经成功使用输入的数值覆盖掉原始值。



四、代码执行

我们面临的下一个挑战是获得代码执行,因为栈上是没有执行权限的。与我们最近看过的其他设备不同,传入的数据没有被存储在可执行堆的固定值上,这增加了一些难度,减缓了我们的研究进度。

但是,我们可以根据需要将多个字节写入栈中,并且libc处于静态位置。我们使用libc中的代码片段构造一个ROP链达到执行代码的目的。其中的棘手之处在于,我们不能使用任何包含低于0x20、0x3F、0xFF字节的地址。低于0x20的值会被替换为0x20,0x3F或0xFF的意义是标记缓冲区的结尾。幸运的是,libc处在一个固定的地址,允许我们在ROP链中使用大量的代码。

http://p5.qhimg.com/t01f7cc225ca1db9e75.png

我们手动去寻找ROP地址,使用IDA和正则表达式功能进行查找。我们将ROP链附加到我们的大文本文件中,并写了一个脚本来检查是否有坏字符。总而言之,我们花了几天的时间稳定地整理了包含19个地址的长链。我们首先调用pvalloc()来分配页对齐的内存缓冲区,然后使用strcpy()将我们的shellcode从栈中的较低层复制到缓冲区中。我们通过调用mprotect()来标记缓冲区可执行文件,然后跳转到可执行缓冲区以开始执行我们的shellcode。

令人惊讶的是,编写shellcode是最麻烦的。我们开始bind到socket,并允许远程用户连接到一个shell。因为我们被限制在固定的范围内,我们要做的第一件事是xor编码大部分的shellcode代码,然后在有限制shellcode的位置进行解码。ARM处理器缓存的指令和数据,你可以使用ISB或MCR指令清除。虽然网上目前有一个通过改变MCR指令来清除指令路劲的例子,但是对我们来说没什么效果。我们也了解到,在某些芯片上,由于处理器仅缓存顺序指令,所以可以简单的分支到你的代码中。但是,也没有什么效果。研究其他的可能性,还要花费一个小时到几个星期的时间。

为了编写value-restricte shellcode,我们很大程度上依赖于在libc中执行代码的能力。我们在我们的代码中设置参数,然后调用libc中的函数执行我们需要的系统调用。例如,要使socket系统调用,我们编写了如下代码片段。

http://p0.qhimg.com/t01442d53569eba0f14.png

基于这点,我们通过利用Devil's Ivy漏洞获得了一个代码执行权限和摄像头的交互式shell。虽然其他设备可以使用gSOAP以一个root用户运行服务,但此特定设备仅授予wsd用户(非root用户)的访问权限。尽管如此,我们能够执行通常只允许root权限用户执行的ONVIF规范中的命令。权限设置位于摄像头的文本文件中,wsd用户具有该文件的写权限。

sed -i /SystemReboot=8/SystemReboot=f/ access_policy

关闭连接后,导致wsd重新启动并重新加载access_policy文件,我们可以发送SystemReboot命令并重新启动摄像头。攻击者可能会持续重启摄像头或更改其网络设置,以防止访问Feed。

http://p8.qhimg.com/t01f0e9e4bce5ff717f.png

修改权限后发送,部分执行SystemReboot命令后的响应

http://p1.qhimg.com/t0194dd7b1d9804449b.png

相机在重置为出厂设置后会提示输入新密码

下面为Axis M3004安全摄像机上Devil's Ivy漏洞的演示视频,你可以访问我们的博客,了解更多详细信息。




推荐阅读
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
  • 浅解XXE与Portswigger Web Sec
    XXE与PortswiggerWebSec​相关链接:​博客园​安全脉搏​FreeBuf​XML的全称为XML外部实体注入,在学习的过程中发现有回显的XXE并不多,而 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • POCOCLibraies属于功能广泛、轻量级别的开源框架库,它拥有媲美Boost库的功能以及较小的体积广泛应用在物联网平台、工业自动化等领域。POCOCLibrai ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 本文比较了eBPF和WebAssembly作为云原生VM的特点和应用领域。eBPF作为运行在Linux内核中的轻量级代码执行沙箱,适用于网络或安全相关的任务;而WebAssembly作为图灵完备的语言,在商业应用中具有优势。同时,介绍了WebAssembly在Linux内核中运行的尝试以及基于LLVM的云原生WebAssembly编译器WasmEdge Runtime的案例,展示了WebAssembly作为原生应用程序的潜力。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了win7系统休眠功能无法启动和关闭的解决方法,包括在控制面板中启用休眠功能、设置系统休眠的时间、通过命令行定时休眠、手动进入休眠状态等方法。 ... [详细]
  • 嵌入式处理器的架构与内核发展历程
    本文主要介绍了嵌入式处理器的架构与内核发展历程,包括不同架构的指令集的变化,以及内核的流水线和结构。通过对ARM架构的分析,可以更好地理解嵌入式处理器的架构与内核的关系。 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • 解决浏览器打开网页后提示“dns_probe_possible 怎么解决”的方法
    在使用浏览器进行网上冲浪的时候遇到故障是一件很常见的事情,很多用户都遇到过系统提示:dns_probe_possible。从提示中可以看出和DNS是有一定的关系的,经过小编测试之后 ... [详细]
  • 转自:微点阅读(www.weidianyuedu.com)微点阅读-范文大全-免费学习知识的网站电脑唯独搜不到自己家wifi,别人家的都能搜到,手机也可以搜到自己家的,就是电脑不可 ... [详细]
author-avatar
EGO-Underwear
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有