万物互联便利了人们的生活。如果想要远程打开和关闭电灯或电器,并且在线监视他们,使用“智能插座”—— wifi 连接的插座是一种简单的方法。但是如果 IoT 设备没有得到妥善的保护,也会成为一种攻击向量。
McAfee实验室威胁发现团队致力于发现软件和硬件中的安全问题,帮助开发人员为企业和消费者提供更安全的产品。我们最近调查了Belkin生产的产品。我们在Wemo Insight智能插座中发现了未报告的 libUPnPHndlr.so 库文件缓冲区溢出漏洞。该溢出会允许攻击者执行远程代码,cve编号为 CVE-2018-6692。根据我们负责任的披露政策,我们在5月21日向Belkin报告了此研究。
根据说明书建议,团队使用Wemo手机应用程序来设置智能插座。我们可以远程开关插座。接下来,我们测试了软件,包括端口扫描,监控正常网络流量,阅读在线研究。Wemo监听通用即插即用(UPnP)协议49152和49153端口,使用TCP协议。手册,反汇编镜像,通用编程语言(GPL)都可以在网上找到;他们还提供了CPU架构、操作系统和应用程序相关的信息。
我们转向研究硬件并拆解了设备。我们在主板上识别出了芯片,发现用于与设备通信的标头,并且从闪存中取出了内存。我们通过在线研究得到了主板上的每一个芯片的数据表。
电路板上发现的闪存芯片是Maxronix MX25L12835F,由flashrom支持,flashrom是一种众所周知的用于提取固件的开源工具。用flashrom和XI Breakout板,我们从Wemo设备中提取了固件。在我们获得设备附带的原始固件映像后,我们使用Wemo移动应用程序对其进行了更新。设备更新后,我们再次从设备中提取固件,为我们提供第二个镜像。我们对新固件进行了基本的健全性检查,以确保我们早期的软件侦察信息没有改变。
由于空间原因,一些有效载荷已被删除。(“EnergyPerUnitCostVersion”中的原始数据为2,828个字符。)在分析崩溃数据和数据包之后,发现这似乎是一个标准的缓冲区溢出,数据溢出到栈上。我们继续进行模糊测试,着力于“EnergyPerUnitCost”字段,发现只需32个字符便能使应用程序崩溃。
虽然崩溃转储为我们提供了很多信息,但仍然有很多我们不知道的。例如,崩溃发生在“WemoApp”中并为我们提供了一个偏移量,但这个库的基地址是什么?栈上的什么被覆盖了?如果在运行期间不访问应用程序,则很难回答这些问题。因为我们之前获得了文件系统,所以我们可以静态分析WemoApp二进制文件; 但我们仍然无法轻易确定崩溃的确切位置。
从提取的文件系统中,我们了解到Wemo运行嵌入式Linux系统OpenWRT,用户帐户信息保存在标准的/ etc / passwd或/ etc / shadow文件中。我们从/ etc / passwd中提取了root密码的哈希值,并将其提交给了一个破解平台。这种方法在合理的时间内证明是无效的。
凭借我们读取芯片的能力,我们有可能去写入芯片。除非校验和或验证是在固件上完成的,否则我们可以使用已知密码替换/ etc / passwd文件。
为了验证这个理论,我们需要重新打包固件。由于wemo的GPL是公开的,我们选择使用与开发人员相同的工具。通过GPL,我们使用Izma编译了相同版本的squash tools 3.0,并使用修改后的/ etc / passwd文件重新打包了固件文件系统。我们进行了填充,确保固件与其原始版本大小相同。然后,我们使用了“dd”指令,将新文件系统段插入到二进制固件中。在这个过程中,我们发现使用binwalk提取的固件无法正确的重新打包。我们使用“dd”命令加上binwalk提供的信息提取固件的正确部分以进行重新打包。
有了wemo的root权限之后,我们可以在对UPnP模糊测试期间收集更多崩溃信息。首先,我们需要编译深入分析这种特定体系结构所需的工具。使用GPL,我们为设备编译了gdbserver和gdb。Wemo有很多预装工具,例如“wget”,使添加文件更加简单。我们从 /tmp 目录下载并运行了这些工具。
因为开发人员将二进制文件保存为unstripped(未去除符号表),我们将此函数命名为TokenParser。段错误发生在分支指令处,但是,在MIPS架构,延迟槽指令在分支发生前执行。因此,0x22B9C处的指令造成了崩溃。在这里,应用程序尝试加载$v1中的地址,将其存入$v0。查看寄存器之后,我们发现数据包中XML标签” EnergyPerUnitCostVersion”的数据在$v1中,产生“无效的写访问”的段错误。
当函数将数据复制到堆栈时,它最终会超过原始缓冲区地址。一旦该地址被覆盖,该函数就会尝试以新值写入下一个字节,在这种情况下是无效地址。这种溢出为攻击者提供了两个可利用的向量:write-what-where这一条件允许攻击者将数据写入内存中的任意位置; 通过继续覆盖堆栈上的数据,攻击者可以覆盖$RA寄存器或函数返回地址,从而为攻击者提供对执行流程的控制。
既然我们了解了漏洞,我们可以利用它吗?因为这是一个标准的缓冲区溢出,我们需要回答两个问题。堆栈上有多少可用空间,是否有任何“坏”字节无法写入堆栈?为了确定可用空间,通过用有效地址修复栈上被覆盖的地址,我们可以检查有效负载有多少进入堆栈。我们发现只有91个字节可以写入堆栈。
下一步是确定是否存在任何“坏”字节。在运行一些测试之后,我们注意到只有ASCII字符才能进入堆栈。在执行易受攻击的代码之前,数据包由开源XML解析器“mxml”解析。该库遵循允许标记之间仅存在ASCII和Unicode字符的标准。
这个标准对于shellcode和面向返回的编程(ROP)技术很不利,因为内存地址和shellcode使用的几乎都是不可读的字符。我们应该使用某些技术利用栈上的空间;然而,由于在XML过滤字符上的严格限制,最好使用已经加载进内存的函数。一种不需要大量shellcode的方法是使用“return to libc”攻击来执行system命令。由于system调用通常将字符串作为参数,因此可能会通过过滤器。因为Wemo没有使用地址随机化,理论上可以进行system调用而无需通过XML过滤器传递额外的shellcode。
我们还面临一个重大挑战:只有全是ascii码的地址才能通过XML过滤器。这极大的限制了找到可用gadget的可能性。我们使用IDA查看libc和system加载到内存中的位置,并找到了两个实例:在0x2B0C0FD4处的libuClibc-0.9.33.2.so和0x2AD104F4处的libpthread-0.9.33.2.so。但是,这些地址都不符合通过XML过滤器的要求。因此,即使我们可以创建ROP链,我们也无法仅在数据包中发送system地址。
包含有坏字符的地址不是漏洞利用的新问题。一个最常见的绕过方法是通过对ROP gadgets 进行加法或减法在寄存器中构造需要的地址并调用。但是,我们面临的限制在于由于XML过滤器的存在,哪些操作数可以用于此加法或减法方程。
在研究过内存布局之后,我们发现libuClibc-0.9.33.2.so位于一个可以绕过XML过滤器的地址。幸运的是,这是一个大型库,提供了一个很大的地址列表,这是此空间中唯一的满足条件的库。通过这一发现,我们开发了一个工具辅助形成exploit。这个工具从可用的内存地址提取所有可能的ROP gadgets,并确定加法或减法是否可以仅使用将绕过过滤器的值,调用内存中找到的两个系统调用之一。libuClibc-0.9.33.2.so中的system地址0x2B0C0FD4没有任何可用的操作数。但是,0x2AD104F4有可用操作数。我们发现了几个“防过滤”操作数,当加在一起时等于0x2AD104F4。
我们使用我们的工具输出所有可以绕过过滤的可能的ROP gadgets,构建ROP链,使用加法指令为system创建最终地址并将其存储在$s0中。加法指令之后,另一个gadget将system地址移动到$t9并调用system。这个最后的gadget还将可以从堆栈控制的地址移动到保存system调用参数的寄存器中。整个ROP链只包含三个gadget,可轻松适应缓冲区溢出提供的堆栈空间。
之前我们发现了两种可以与此漏洞一起使用的攻击技术:write-what-where,并覆盖堆栈上的返回地址。发送的每个数据包可以使用每种技术一次。要获取system调用的参数,我们必须使用write-what-where将参数放在可写的内存地址中,并将此地址传递给system。幸运的是,这个易受攻击的应用程序预留了大量不会使用的可写内存,并且在我们绕过过滤器的受限地址可访问的范围内。不幸的是,调用system的ROP链需要使用write-what-where来处理其中一个ROP gadgets中的额外指令。这意味着执行漏洞需要两个数据包:一个用于将system参数写入内存,另一个用于调用system。因此第一个包无痕地存在且不造成程序崩溃很重要。
干净地执行的一种方法是在有效负载内使用三个位置正确的管道(“|”)来停止写入并在适当的时间退出TokenParser。不重写RA指针也很重要,这样程序可以在收到数据包后继续正常执行。然后发送包含ROP链system调用的第二个数据包,其中包含前一个数据包写入的参数的地址。
通过发现可以调用system的有效ROP链,我们必须决定应该使用哪种system调用。因为system以root身份执行,所以我们可以完全控制设备。我们的研究表明该设备安装了许多Linux命令。我们之前使用wget将gdbserver复制到设备。攻击者还可以从system调用wget来下载并执行任何脚本。我们进一步探索了已安装的应用程序并发现了NetCat,它可能允许攻击者编写脚本来创建反向shell。攻击者可以使用wget下载脚本,并执行包含NetCat命令的脚本来创建反向shell。我们测试并证明以root身份打开反向shell是一种简单有效的方法。攻击者可以选择许多其他方法来利用此漏洞并执行代码。下面的视频展示了反向shell的漏洞利用。
视频链接:https://players.brightcove.net/21712694001/Sypf9RNV_default/index.html?videoId=5823570
为了说明,团队编写了一个攻击场景。插件被攻破后,它可以使用内置的UPnP库在网络路由器中形成漏洞。这个洞为攻击者创建了一个后门,可以远程连接,而不会在网络上被注意到。在下面的视频中,我们使用远程shell来控制连接到网络的TCL智能电视。电视上的Roku API实现使用简单的未加密HTTP GET / POST请求来发出命令,并且不对发送这些命令的机器进行身份验证,从而使远程控制变得很容易。使用Wemo作为中间人,攻击者可以打开和关闭电视,安装或卸载应用程序,以及访问任意在线内容。智能电视只是使用Wemo攻击其他设备的一个例子。由于攻击者已经在网络上建立了立足点并且能够打开任意端口,因此连接到网络的任何计算机都处于危险之中。由于攻击可以通过Wemo进行,并且使用此漏洞利用生成的端口映射在路由器的管理页面中不可见,因此攻击者的足迹仍然很微小并且难以检测。
视频链接:https://players.brightcove.net/21712694001/Sypf9RNV_default/index.html?videoId=5823567767001
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2019-1-11 19:36
被kanxue编辑
,原因: