带你读《物联网渗透测试》之三:固件分析与漏洞利用-阿里云开发者社区

开发者社区> 华章出版社> 正文

带你读《物联网渗透测试》之三:固件分析与漏洞利用

简介: 本书介绍物联网渗透测试的原理和实用技术。主要内容包括IOT威胁建模、固件分析及漏洞利用、嵌入式web应用漏洞、IOT移动应用漏洞、IOT设备攻击、无线电入侵、固件安全和移动安全最佳实践、硬件保护以及IOT高级漏洞的利用与安全自动化。

点击查看第一章
点击查看第二章

第3章

固件分析与漏洞利用
本章将主要讨论以下主题:

  • 固件分析方法。
  • 固件提取。
  • 固件分析。
  • 文件系统分析。
  • 基于固件仿真的动态分析。
  • ARM与MIPS架构下二进制文件的分析入门。
  • MIPS架构下的漏洞利用。

3.1 简介

到目前为止,我们已经介绍了IoT生态系统中的所有基本原理,并且通过威胁建模确定了各种威胁对应的风险,这些内容对于我们开展渗透测试大有帮助。虽然单纯借助当前普遍应用的漏洞扫描技术,有些漏洞和威胁识别起来可能会更简单一些,但是,在本章中,我们将把注意力聚焦在固件的逆向分析上,希望通过对固件内容的分析实现运行时对固件的操作。我们需要撸起袖子讨论如何对固件进行反汇编,如何使用常见的固件工具分析固件内容与固件架构,以及如何修改固件用于攻击。同其他软件逆向分析方法类似,固件分析也绝对是一门艺术。读者将会了解到有很多工具都可以用来帮助自己挖掘常见的漏洞,但是,针对固件二进制镜像的安全性分析仍需要大量的手工分析。
在我们开始固件分析之前,重要的是讨论固件提取的通用方法,以及分析勾勒出哪些数据较为重要。在之前介绍的轻量级固件威胁建模演练过程中,这一内容已经讨论过了,但是这里我们依然从讨论固件分析的目标开始接下来的内容。

3.2 固件分析方法

固件是控制IoT设备的核心,这也是我们在分析IoT设备的其他组件之前,希望从固件分析开始的原因。根据IoT设备所面向的行业,提取固件镜像并且对其内容进行反汇编的过程可能非常简单。与之类似,对于某些行业的垂直细分领域而言,其采取了专用保护措施,而这些保护措施可能会导致逆向分析过程更加困难或更加耗时。尽管如此,固件分析时还是存在一些通用模式的。通常,测试人员在固件分析时最关注的内容主要包括:

  • 口令。
  • API Token。
  • API Endpoint(URL)。
  • 存在漏洞的服务。
  • 后门账户。
  • 配置文件。
  • 源代码。
  • 私钥。
  • 数据的存储方式。

在后面的章节中,进行固件分析时我们也会重点关注这些内容。本节将向读者概要介绍固件正向分析与逆向分析的方法。
下面列出了IoT固件分析时所用到的基本方法:
1)固件提取。
2)固件分析。
3)文件系统提取。
4)文件系统加载。
5)文件系统分析。
6)基于固件仿真的动态分析。

3.3 固件提取

在对固件内容进行分析前,我们首先需要获取固件的二进制文件。本节将会对目标设备固件提取所涉及的各种技术进行介绍。

3.3.1 准备工作

提取固件的过程中我们会用到多个工具。由于Kali Linux中已经默认安装了所需要的大多数工具,因此在这里将主要使用Kali Linux系统。下面是需要用到的工具:

此外,还可以通过链接https://www.flashrom.org/Downloads 下载Flashrom。

3.3.2 测试流程

目前,从IoT设备中提取固件的方法有很多。我们将在本节中对其中的大部分方法进行介绍。固件镜像的获取方法主要包括:

  • 从厂商网站下载。
  • 代理或镜像设备更新时的流量。
  • 直接从设备转储固件。
  • 通过Google搜索引擎搜索/科研渠道。
  • 反编译与之相关的移动应用。

1.从厂商网站下载
获取固件最简单的方法就是从厂商网站下载固件。
图3-1~图3-5中的截图展示了如何从厂商网站获取固件:
1)进入目标厂商的网站。
2)在搜索栏中输入目标设备,如图3-1所示。
3)选择Support选项卡,如图3-2所示。
4)单击Drivers&Tools按钮,如图3-3所示。
5)单击下载链接,如图3-4所示。
6)用户也可以选择Copy Link Address,在测试主机上直接执行wget(wget http://URL.com)命令进行文件下载,如图3-5所示。

image.png


image.png


image.png



image.png


image.png

2.代理或镜像设备更新时的流量
有时候厂商网站可能并不支持固件下载,此时读者可以选择第2种方法(即在设备固件更新过程中,代理转发设备更新时的流量),或者选择第3种方法(直接从设备转储固件)。为了在设备更新过程中实现对固件更新流量的代理转发,读者必须在更新期间实施中间人(Man-In-The-Middile,MITM)攻击或者镜像设备流量。或者,读者也可以代理转发Web或移动应用的流量,从中提取出固件下载的URL地址。
众所周知,厂商会对固件下载请求中的user-agent字段进行验证,所以读者可能还需要调整数据包首部中的user-agent字段。以下是针对IoT设备实施MITM攻击进而监控设备流量的基本步骤,用到的工具包括Kali Linux、Ettercap、Wireshark和SSLstrip。其中Kali Linux中已经安装了本节中需要用到的所有工具。
当前有多种方法和工具可以对目标设备发起MITM攻击,进而实现流量转发。下面介绍的就是其中一种捕获设备流量的方法。
1)启用IP转发功能:
image.png

2)配置iptables,将目的端口80的流量重定向至SSLstrip监听的端口10000。
image.png

3)启动SSLstrip:
image.png

4)启动Ettercap GUI:
image.png

5)图3-6展示了上述操作的运行结果。

image.png

6)单击菜单栏中的Sniff菜单,再单击Unified sniffing选项,如图3-7所示。

image.png

7)选择所要监听的网卡,如图3-8所示。

image.png

8)选择Scan for hosts选项,如图3-9所示。

image.png

9)此时即启动Wireshark程序,可以看到部分接口有流量通过,如图3-10所示。
10)单击Start capturing packets按钮开始捕获目标设备的网络流量,如图3-11所示。

image.png

11)根据实际需求过滤出所关注的网络报文。在本例中,目标设备的IP地址为192.168.1.137,如图3-12所示。

image.png

3.直接从设备转储固件
如果通过厂商网站或者流量代理的方法均无法获取固件,还可以尝试通过UART、SPI或者JTAG接口直接转储固件。直接进行固件转储需要拿到物理设备,并拆解设备找到其中的闪存芯片。找到闪存芯片之后,读者可以直接通过UART接口也可以使用SOIC8测试夹来连接芯片进而转储固件,其中用到了工具Flashrom以及支持SPI的硬件开发板,例如Shikra。图3-13展示了如何使用SOIC测试夹和Shikra连接设备。

image.png

将固件内容转储为bin文件的命令如下所示:
image.png

使用Flashrom或者前面介绍的某种方法提取到了设备固件之后,分析人员就可以开始对固件的二进制文件进行分析了。
4. Google搜索
如果出于某些原因,我们难以借助前面介绍的方法提取出固件镜像,那么最后的选择就是求助于Google搜索。可以直接在Google中输入想要查找的固件名称,搜索是否存在目标固件的下载链接,也可以搜索一下其他人的工作成果,看看是否已经有人对该设备的固件进行了研究。此外,设备厂商在岗或者离职的工作人员也可能会将固件文件上传到其个人的存储空间或Web服务器上。无论哪种情况,都可以使用Google dorking技术缩小指定目标设备的搜索范围。我们还可以通过链接https://www.exploit-db.com/google-hacking-database利用Google Hacking数据库来搜索固件或设备。

3.3.3 测试分析

在本节中,我们简要介绍了如何通过厂商站点、部署MITM测试环境捕获设备流量、直接从设备转储固件以及Google搜索等方法来获取固件。现在,我们来解释下为什么需要通过这些方法获取固件,难道不是直接从厂商网站下载就行了吗?
当从厂商网站下载固件时,通常情况下,用户可以通过厂商提供的服务链接、文件共享或社区论坛下载到需要的固件。但有时厂商在下载固件前要求用户提供口令,或者将固件打包为需要口令才能解压的ZIP文件。如果碰到了这种情况,为了节省时间我们就可以直接采用其他方法获取固件。
接下来,我们简要介绍了如何使用Kali Linux、SSLstrip、Ettercap和Wireshark搭建MITM测试环境,以在设备更新期间捕获设备流量。

3.4 固件分析

一旦我们提取到了固件,接下来的主要工作就是对固件进行分析。其中涉及如何深入固件内部,发现尽可能多的安全隐患,这也正是本节中我们所要做的主要工作。

3.4.1 准备工作

在本节中,我们将会了解提取出固件二进制文件后如何开展固件分析。在这一过程中,有多种固件分析方法供我们选择,帮助我们找到固件中的安全隐患。
正如前面提过的,固件中包含了很多渗透测试人员感兴趣的内容,如API key、私有证书、硬编码的认证信息以及后门等。

3.4.2 测试流程

为了分析固件,我们将对其逆向以查看其内部组件。固件中的内部组件包括boot-loader、内核、文件系统以及其他内容。其中我们最感兴趣的是文件系统,因为文件系统中保存了我们需要的所有信息。显然,读者也可以分析bootloader并查看其中包含的内容,还可以篡改固件并构建新的固件(我们将在接下来的章节中讨论),但是现在我们只关心如何对固件进行逆向分析以及从中提取出文件系统。
正如之前已经介绍过的,固件是一个二进制文件压缩包,而文件系统只是其中的一个组件,存储在二进制文件的特定偏移地址中,且具有一定的尺寸。然而,此时我们还不知道关于固件中文件系统的任何信息,包括其偏移量和尺寸。为了找到这些信息,需要使用hexdump和grep等工具来搜索我们所关注内容的特征信息。下面以Squashfs文件系统为例进行介绍:
1)如果想要查找Squashfs文件系统,可以使用grep命令在hexdump的执行结果中查找“hsqs”字符串,如图3-14所示。

image.png

2)读者可以看到,我们在地址0x000e20c0处发现了Squashfs文件系统。获得了这些信息之后,就可以使用dd命令将从该地址开始到文件末尾的内容全部转储下来,如图3-15所示。

image.png

3)一旦获得了从固件二进制文件中截取出来的Squashfs文件系统,就可以运行unsquashfs等命令来查看整个文件系统,这一过程非常简单。
接下来使用unsquashfs命令来看一下我们是否能够提取出整个文件系统,如图3-16所示。

image.png

4)正如在前面的截图中所看到的,我们提取出了Squashfs文件系统镜像。读者可以忽略图3-16中的警告和错误,这只是在提示我们没有以root用户权限运行该命令。一旦我们提取出了文件系统,就可以浏览文件系统中的各个目录,对其中的各个文件分别进行分析来挖掘漏洞。图3-17是对整个文件系统目录的截图。

image.png

上面就是对固件进行逆向分析并从固件二进制镜像中提取文件系统的方法。我们还可以采用Binwalk等工具自动执行前面的所有操作。Binwalk由Craig Heffner开发,借助Binwalk我们只需要一条命令就能够从固件二进制镜像中提取文件系统。
5)为了安装Binwalk,首先需要从位于https://github.com/devttys0/binwalk.git的Git-Hub 代码库中克隆Binwalk代码,命令如下:
image.png

6)然后运行./deps.sh命令安装Binwalk需要的所有依赖文件和二进制文件。
7)Binwalk安装成功后,读者可以在命令行中敲入Binwalk命令并按回车键来确认安装是否成功。如果安装成功,此时命令行窗口会显示出Binwalk的帮助菜单,如图3-18所示。
8)下面我们使用Binwalk命令从相同的固件中提取出文件系统。这里在执行提取操作时将用到-e参数:
image.png

9)接下来窗口中会显示出固件中的所有分段,并提取出固件内容,如图3-19所示。

image.png


image.png

10)参数-t和-vv可以采用可读性更强以及更加详细的方式打印出命令执行结果。Binwalk执行完毕之后,会生成名为_[firmwarename].extracted的文件夹,该文件夹中保存了Binwalk提取出的整个文件系统,如图3-20所示。
以上就是采用手工和自动两种方式从固件的二进制文件中提取文件系统的过程。

3.4.3 测试分析

本例中的文件系统提取方法同我们之前采用的方法相同,均是首先使用magic字节以及首部特征字符串(例如Squashfs文件系统中的sqsh字符串等)检测文件系统以及其他组件的偏移。在下面的URL链接中可以查看Binwalk所能识别的文件系统类型:
https://github.com/devttys0/binwalk/blob/62e9caa164305a18d7d1f037ab27d14ac933d3cf/src/binwalk/magic/filesystems

image.png

读者还可以在Binwalk中手工添加更多特征,然后重新编译Binwalk源代码,从而实现对其他文件系统的识别。

3.4.4 拓展学习

除了提取文件系统,读者还可以使用Binwalk进行一系列其他操作,例如针对某个特定固件镜像进行熵分析,该操作能够帮助读者判断固件镜像是否进行了压缩或者加密。熵分析需要在运行Binwalk时带上-E参数,之后再跟固件名,操作命令如图3-21所示。

image.png

从上面的截图中可以看出,该固件并未加密,因为加密的固件镜像熵值会出现大幅波动。

3.4.5 延伸阅读

想了解更多关于固件分析与逆向分析的内容,可以访问Binwalk开发者Craig Heffner的博客。读者可以从博文中了解到不同的固件镜像会如何变化,以及可能存在哪些漏洞。Craig Heffner的博客链接为http://www.devttys0.com/

3.5 文件系统分析

现在我们已经知道如何逆向固件并从中提取出文件系统了,在本节中将关注文件系统中的内容并对其开展漏洞分析。这部分内容能够帮助读者更加深入地了解如何从固件镜像中挖掘漏洞并加以利用,进而入侵IoT设备。

3.5.1 准备工作

针对文件系统内容的分析主要包括两种方法:

  • 手工分析。
  • 自动化工具和脚本。

1.手工分析
采用手工方法挖掘固件文件系统漏洞时,需要对文件系统中的各个文件与文件夹进行分析。分析内容包括查看配置文件、Web目录、口令文件以及查找后门等。手工分析方法是在指定固件中挖掘漏洞的理想方法,本节我们也将主要关注这种方法。
2.自动化工具和脚本
本书出版时,除了部分自动化分析脚本,尚没有一套完整的框架或者工具能够帮助我们挖掘固件漏洞。因此,如果读者对Web应用安全或者网络安全比较熟悉,那么应该了解目前在固件安全分析领域也没有类似于Arachni、w3af、Metasploit之类的工具。

3.5.2 测试流程

我们首先从固件分析开始,看看是否能够发现敏感信息或者后门。
在这个练习中我们使用的是路由器D-Link DWR 932B的固件,版本号为DWR-932_fw_revB_2_02_eu_en_20150709。安全研究员Gianni Carabelli和Pierre Kim已经在这款固件中挖掘出了漏洞:
1)第一步是从固件中提取文件系统。但是,本例中的固件为经过加密的ZIP文件。因此,在本例中首先使用fcrackzip工具进行口令破解,破解出的口令是beUT9Z。运行结果如图3-22所示。

image.png

2)获取了固件镜像之后,可以采用Binwalk从固件的ZIP文件中提取出yaffs2格式的文件系统。接下来,读者可以使用针对yaffs2格式的工具解压文件系统,也可以直接通过Binwalk来完成提取工作。
3)在yaffs2-root文件夹中,我们提取得到了完整的文件系统,如图3-23所示。

image.png

4)从这里开始,我们开始遍历文件系统中不同的目录,并从安全视角查找其中可能存在漏洞的文件。我们需要做的第一件事是查找所有配置文件,这可以通过运行find命令查找所有后缀为.conf的文件来实现,搜索结果如图3-24所示。
5)接着查看配置文件的内容。举个例子,图3-25所示为配置文件wpa-supplicant.conf中的内容。
6)接下来查看其他配置文件,例如inadyn-mt.conf,如图3-26所示。

image.png
image.png

出乎意料的是,该文件中包含了大量敏感信息,而这些信息本不应该被其他人访问到。正如我们在前面的截图中看到的,文件inadyn-mt.conf中存储了路由器的no-IP配置信息,包括用于访问网站https://www.no-ip.com 的用户名和口令。
这就是我们在固件中查找隐藏敏感信息的方法。显然,读者可以在固件的文件系统中进行更加全面的查找,从而发现更多的敏感信息。
现在我们已经知道了如何对固件进行手工分析,接下来将介绍如何采用自动化的方式来挖掘漏洞。为此,我们将用到Craig Smith开发的工具Firmwalker,该工具通过静态分析来识别固件中可能包含的常见敏感信息。
1)克隆GitHub代码库中的Firmwalker代码并完成部署,命令如下:
image.png

2)Firmwalker代码库克隆完成后,我们以提取出的文件系统位置为参数,运行./firm-walker.sh脚本:
image.png

3)Firmwalker脚本能够识别出多种敏感信息,包括二进制文件、证书、IP地址、私钥等,同时将输出结果都保存在firmwalker.txt文件之中(用户也可指定存储文件)。如图3-27所示。

image.png

拿到Firmwalker生成的报告之后,我们就可以分别查看报告中所列出的各个文件并对其开展进一步分析了。在某些情况下,读者还需要对基于ARM和MIPS架构的二进制文件进行逆向分析,以便更好地了解文件执行流程进而挖掘出漏洞。

3.5.3 测试分析

分析并理解文件系统及其中的内容取决于攻击者的手工分析技巧。而这正是能否挖掘出漏洞的关键。即使采用了各种自动化工具,读者也会意识到分析过程最终都会转化为针对二进制文件的手工分析与漏洞挖掘。

3.5.4 拓展学习

为了更加深入地对固件的文件系统开展分析,读者还可以使用诸如firmware diffing之类的技术,即将固件同之前的固件版本进行比较,进而查找出两者之间的差异。通过比较,读者能够了解新版本中所做的安全修复和改动,甚至发现之前版本中未公开的安全漏洞。
我们还可以基于固件文件系统开展另一项工作,就是查看系统使用的库文件和组件,并判断这些组件是否是早期存在漏洞的版本。

3.5.5 延伸阅读

在分析固件文件系统中的内容时,最好多了解一些关于二进制分析和逆向分析的相关知识,并且熟悉Linux二进制文件分析、调试以及针对ARM和MIPS等平台的反汇编技术。

3.6 基于固件仿真的动态分析

通常,开展IoT设备分析会受到这样或那样的限制,其中一个就是我们难以在没有实体设备的情况下开展大量测试并进行漏洞利用。但是在本节中,我们将讨论固件仿真方法,读者可以同仿真设备进行交互,就如同和网络中的实体设备交互一样。

3.6.1 准备工作

为了进行固件仿真,我们将用到由本书作者开发的脚本Firmware Analysis Toolkit(FAT)。FAT采用Firmadyne工具实现固件镜像的仿真。
Firmadyne工具底层基于QEMU虚拟机,这使得用户能够对整个系统架构进行仿真并在该架构之上运行固件,其中还用到了工具开发者编写的其他脚本,例如NVRAM仿真器,该仿真器可以从地址https://github.com/firmadyne/libnvram 下载。同时还使用了类似于Binwalk之类的工具,在前面的章节中我们对Binwalk已经进行了介绍,借助该工具能够从固件中提取出文件系统,继而开展固件仿真。
接下来从GitHub中克隆FAT的代码库,并部署固件仿真实验环境。我们强烈建议读者在Ubuntu系统上进行操作,这样可以避免在仿真过程中出现各种奇奇怪怪的问题。

3.6.2 测试流程

固件仿真步骤如下:
1)从链接https://github.com/attify/firmware-analysis-toolkit/ 处克隆FAT代码库,然后安装:
image.png

安装过程中将为Firmadyne创建数据库,将关于固件的信息存储起来并进行管理。数据库密码默认设置为firmadyne。
全部设置完毕之后,下一步就是选择固件并对其进行仿真,下面来看看我们能够针对仿真固件开展哪些工作。
在本节练习中,我们将以D-Link固件DWP2360b为例进行演示,D-Link公司出品的PoE供电无线接入点采用了该固件。
2)此时,我们要做的第一件事就是运行./fat.py,该脚本运行后会请求用户输入固件名称和固件镜像的品牌。输入固件镜像品牌的作用主要在于创建数据库,这样我们就可以在需要时搜索数据库,查看我们已经对哪些品牌的固件进行了仿真。运行后的执行结果如图3-28所示。

image.png

3)接下来工具会多次请求用户输入数据库的口令,在本例中我们将口令设置为fir-madyne。程序完成初始化、镜像创建、网络配置并分配IP地址之后,FAT将会在命令行窗口中显示其IP地址,并提示用户已经完成了固件仿真,如图3-29所示。
4)获得了IP地址之后,我们就可以在浏览器中输入该IP地址,之后就可以打开仿真路由器的登录页面了,本例中设备的登录页面如图3-30所示。
以上就是在没有物理设备的情况下如何借助FAT实现固件仿真的过程。

image.png

3.6.3 测试分析

前面的仿真实验主要基于QEMU和NVRAM仿真器。NVRAM是非易失性随机访问存储器,固件能够访问该存储器获取设备信息。然而,由于没有物理设备,固件需要访问该存储器时就会导致服务运行出错或崩溃,而这正是NVRAM仿真器发挥作用的地方。使用Firmadyne工具集还能对固件进行修改,以便让用户访问Console口以进行调试。
以下是FAT脚本能够执行的操作:
1)从固件中提取文件系统。
2)获取固件架构。
3)制作所需的镜像。
4)网络设置。
5)镜像仿真。
上述所有操作均可手工完成,但是利用FAT之类的脚本可以帮助我们快速完成操作。

3.6.4 拓展学习

另一种仿真方法是手工下载目标架构的Debian镜像文件,然后将镜像文件从固件中复制到新创建的Debian实例中,再使用chroot命令运行Web服务器(或是其他需要测试的组件)。读者可以从链接https://people.debian.org/~aurel32/qemu/ 下载最新的Debian镜像。

3.7 ARM与MIPS架构下二进制文件的分析入门

现在我们知道了如何进行固件仿真并开展基本的分析,但是读者会发现在现实工作中经常会遇到不同架构的二进制文件,对此需要开展进一步分析。由于我们难以在一本书中涵盖嵌入式设备用到的所有架构,因此在这里我们主要关注两款流行架构—ARM和MIPS。
然而,在这里我们将只介绍针对MIPS架构下的漏洞利用,并对ARM架构下的二进制文件逆向分析进行简单介绍。从漏洞利用的角度来看,ARM架构和MIPS架构非常相似,只要分析其中一个架构同样也有助于读者了解其他架构。

3.7.1 准备工作

现在开始我们的二进制分析之旅,首先从基本分析开始,看看如何从D-Link固件中发现后门。这个后门是由Pierre Kim首先发现的。为了验证这个后门的存在,要求读者对基于ARM架构的二进制文件逆向分析具备一定的基础。尽管我们不会深入分析寄存器和架构(因为我们将在MIPS架构中介绍这些内容),但是本节内容将帮助读者了解二进制文件的分析过程以及如何发现较为简单的漏洞。
本例中我们将要使用的固件是D-Link设备的固件DWR 932B。使用Binwalk提取出固件后,可以注意到其中包含一个名为appmgr的二进制文件,这正是我们感兴趣的文件。
在分析过程中,我们可以使用读者熟悉的所有反汇编工具,例如Radare2、IDA、Hopper等。本例中我们使用Hopper来对二进制文件appmgr进行逆向分析,这是一个基于ARM架构的小端序(Little Endian)二进制文件。

3.7.2 测试流程

可以使用Hopper的伪代码生成功能来更好地理解二进制文件。步骤如下:
1)在Hopper中加载目标二进制文件进行分析,如图3-31所示。
2)文件加载成功后,搜索telnet字符串,然后就可以看到telnet字符串在样本代码中的位置,如图3-32所示。

image.png

3)为了找到该字符串的调用位置,可以右键单击该字符串并选择References to address选项,然后将展示出字符串的调用位置和调用指令。在本例中,如果执行References to address操作,我们会发现调用该字符串的内存地址为0x13048,如图3-33所示。

image.png

4)双击该内存地址跳转到引用该字符串的地址,在本例中即0x13048地址处。跳转到该地址之后,就可以看到所有的反汇编代码了,单击Pseudo-code mode按钮会生成伪代码,如图3-34所示。

image.png

5)伪代码生成功能对于我们的分析工作而言非常有用,因为如果用户对反汇编不是太熟悉的话,借助伪代码就可以把一段反汇编指令看作一个逻辑上相对独立完整的程序,这样理解起来更为容易。本例中的伪代码如图3-35所示。

image.png

正如我们从前面的截图中看到的那样,程序调用了strncmp函数,参数为字符串HELODBG 。我们知道,strncmp函数用于字符串比较,在本例中的作用是在运行Telnet前对二进制文件的输入字符串进行检查,上述操作在图3-35中以高亮方框的形式进行了标记。
因此我们可以肯定,appmgr文件中存在后门,程序查找字符串HELODBG,一旦接收到该字符串,它就会使用bin/sh shell启动Telnet服务。
上面的内容就是我们对ARM架构下二进制文件进行的分析,所采用的方法也是对二进制文件进行分析以查找敏感信息、挖掘漏洞与后门的基本方法。

3.7.3 拓展学习

既然读者已经知道了对ARM架构二进制文件开展分析的基本方法,我们建议对ARM汇编语言以及架构进行更加深入的了解。对汇编指令和底层架构的了解能够帮助读者更好地理解反汇编代码,即使在不借助伪代码的情况下也能够开展二进制文件的分析。

3.8 MIPS架构下的漏洞利用

现在我们已经掌握了逆向二进制文件的基本方法,那么是时候深入了解如何对IoT设备所采用的主要平台架构开展漏洞利用了。由于本节内容只是帮助读者了解二进制文件漏洞利用的基础知识,所以在这里我们只关注MIPS架构,但是强烈建议读者采用相同的方法自行针对基于ARM的架构开展漏洞利用练习。

3.8.1 准备工作

为了开展MIPS架构下的漏洞利用,在这里我们主要使用QEMU仿真器和chroot命令,这些内容我们在本章开头已经进行了简要介绍。现在将研究如何在MIPS二进制文件中进行缓冲区溢出漏洞利用,并改变程序的执行流程使其跳转到我们想要执行的内容,而不是程序原本应该执行的代码。为了简化漏洞利用过程,在这里我们不会涉及诸如面向返回的编程(Return Oriented Programming,ROP)之类的内容,这样可以使利用过程尽量简单一些。

3.8.2 测试流程

在这个练习中需要用到以下工具:

  • 路由器漏洞攻防演练靶机(Damn Vulnerable Router Firmware,DVRF)—该靶机可以从GitHub下载
  • GDB-Multiarch
  • GDB Enhanced Features(GEF脚本)
  • QEMU
  • chroot
  • IDA Pro/Radare2(可选)

下面我们将对上述工具及其安装部署方式进行逐一介绍。首先从下面的URL链接下载DVRF固件:
https://github.com/praetorian-inc/DVRF/tree/master/Firmware
DVRF是由b1ack0wl专门为MIPS平台开发的固件。尽管该固件原本用于Linksys E1550设备,但其也可以在基于QEMU的仿真环境中运行,我们随后开展的漏洞利用也在该环境中加以演示:
1)现在我们已经拿到了固件,为了便于漏洞利用过程中的调试,接下来安装GDB(GNU调试器)和GEF:
image.png

同时还要确保已经在系统中安装了所需的QEMU软件包。现在我们已经准备就绪了,接下来利用QEMU提供的二进制仿真功能运行其中的二进制文件。
2)仿真之前,首先需要使用Binwalk工具从固件中提取出文件系统,操作命令如图3-36所示。

image.png

3)提取出文件系统后,就可以将对应架构下的QEMU二进制文件复制到文件系统的根目录下,在本例中是squashfs-root文件夹,如图3-37所示。但是在此之前需要确认目标二进制文件是基于MIPS架构的,通过readelf命令可以查看目标二进制文件的架构信息。

image.png


4)根据图3-37所示,目标二进制文件需要运行在小端的MIPS架构上,如图3-38所示。

image.png

5)此时将针对小端MIPS(mipsel)架构的QEMU二进制文件复制到squashfs-root文件夹下:
image.png

6)将qemu-mipsel-static文件复制到当前文件夹下后,再使用chroot命令和QEMU虚拟机仿真运行目标二进制文件,同时使二进制文件认为其根目录就是当前我们执行命令的目录。上述操作命令如下:
image.png

7)运行结果如图3-39所示,即使某个二进制文件最初是针对其他架构开发的,我们依然能够运行该文件。基于QEMU虚拟机对目标系统的仿真,再通过chroot命令对根目录进行调整,上述操作是可能实现的。

image.png

8)正如我们在命令输出结果所看到的那样(如图3-39所示),该二进制文件在运行时需要输入参数。此外,如果我们查看目标二进制文件的源代码,会发现该文件存在栈溢出漏洞。图3-40是二进制文件stack_bof_01的源代码。

image.png

从源代码中不难发现,变量buf在栈中的缓冲区容易遭受缓冲区溢出攻击,而实施溢出攻击的目的则在于修改程序执行流程,使其指向dat_shell的地址,这样我们就可以利用该漏洞来获得shell。
9)现在开始调试程序,运行QEMU和chroot命令,运行chroot命令时使用参数-g把调试器GDB附加到进程之上:
image.png

10)如图3-41所示,此时程序暂停执行,等待调试器的连接。

image.png

11)程序暂停运行后,我们即可以启动GDB调试器,使用之前分配的端口连接目标进程进行远程调试。另外我们还需要将架构设置为MIPS以确保能够正确地反汇编二进制文件,如图3-42所示。

image.png

12)当我们连接上目标进程时,会发现进程已经暂停,此时可以输入字符c让进程继续执行。
13)我们还可以输入info functions命令在屏幕上打印出二进制文件中可用函数的列表,如图3-43所示,这样可以帮助分析人员从渗透测试的角度查找可能存在漏洞的函数。

image.png

14)接下来输入disass main命令反汇编main函数查看函数内部结构。
15)disass main命令的执行结果如图3-44所示,此时得到main函数的反汇编代码。

image.png

如果读者熟悉反汇编结果中的某些指令,会发现这些指令非常有用。反汇编结果中依次指示了指令地址、指令和操作数。
MIPS架构中共包含32个通用寄存器,分别是$zero、$at、$v0~$v1、$a0~$a3、$t0~$t9、$s0~$s7、$k0、$k1、$gp、$sp、$fp和$ra。在这些寄存器中,$a0~$a3寄存器的作用是存放函数参数,$t0~$t9寄存器用于临时数据存储,$gp寄存器存放全局指针(在利用过程中尽量不要修改$gp寄存器的值),$sp寄存器存放栈指针,$fp寄存器存放帧指针,$ra寄存器存放返回地址。另外还有一个专用寄存器即程序计数器(Program Counter, PC),其作用是存储下一条指令的内存地址,也就是当前正在执行指令的下一条指令。
为了控制基于MIPS架构的二进制代码执行流程,我们主要关注2个寄存器,即RA寄存器和PC寄存器。在处理MIPS架构下的二进制文件时,读者可能已经意识到相对于RA寄存器而言,控制PC寄存器中的内容更加复杂。因此,为了简单起见,在本练习中我们将主要关注如何控制RA寄存器中的内容。
16)由于我们已经知道了当前分析的二进制文件stack_bof_01中存在栈溢出漏洞,因此在程序运行时可以尝试带上一个非常长的参数。我们将使用GEF的模式字符串创建功能生成该参数,运行结果如图3-45所示。

image.png

17)生成了测试用的模式字符串后,我们就可以将其作为程序stack_bof_01的参数运行程序,看看执行过程中是否会导致RA寄存器溢出。本例中,我们使用GEF生成了300个字符长的字符串,以该字符串为参数,程序stack_bof_01后的执行情况如图3-46所示。

image.png

18)正如我们所预期的一样,由于在命令中使用了-g参数,命令执行后二进制文件处于暂停状态,等待调试器附加进来。现在打开GEF终端窗口敲入target命令,命令执行结果如图3-47所示。


image.png

19)使用target命令完成远程主机IP与端口的设置后,我们输入命令c,程序将继续执行直到出现以下三种情况之一,即运行完成、命中断点或者出现异常。本例中,程序在执行过程中出现了SIGSEGV错误,如图3-48所示。

image.png

GEF还显示出了捕获异常时栈和寄存器的全部状态。在本例中,我们可以看到RA寄存器中的值被覆盖为0x63616162,这正是字符串baac的十六进制形式。
了解了上述信息后,可以使用模式搜索功能找到覆盖RA寄存器的字节的偏移。取得了偏移之后,我们就找到了放置恶意地址的位置,进而能够控制程序的执行流程。
20)我们可以使用命令pattern search RA-overflown-bytes-in-hex实现模式字符串的搜索工作,搜索命令如图3-49所示。

image.png

根据命令执行结果,我们找到了导致寄存器RA溢出的字符串的偏移,在本例中该偏移为204。这意味着访问到RA寄存器之前需要填充204字节的垃圾字节,而接下来的4个字节就是填充RA寄存器的值。
21)如果读者还记得本次练习的目的在于更改程序的执行流程,并调用在程序正常流程中原本不会调用的dat_shell函数,那么下一步工作就是确定dat_shell函数的地址。为了找到dat_shell函数的地址,我们要么打印出dat_shell函数的地址,要么通过反汇编查找dat_shell函数的起始地址。这可以通过命令disass function-name来完成,执行结果如图3-50所示。

image.png

从在上面的截图中我们可以看到,dat_shell函数的起始地址为0x00400950。然而,前3条指令中用到了全局指针(GP寄存器),而我们并不希望在这个时候使用该指针,这就是我们跳转到0x0040095c而不是0x00400950的原因。
22)接下来在地址0x0040095c后填充204个垃圾字符后,继续运行二进制文件,这次我们去掉了参数-g,执行如下命令:
image.png

在图3-51中可见,二进制文件现在已经执行了我们想要执行的dat_shell函数。上述内容就是如何在MIPS架构下开展栈溢出漏洞利用的过程。

3.8.3 测试分析

缓冲区溢出漏洞的基本思路是在缓冲区中放入超过程序预期长度的字符串,这样就可以控制栈中的寄存器。而控制了栈中的寄存器就可以跳转到shellcode的位置或系统的libc库来执行其他载荷。

image.png

3.8.4 拓展学习

尽管在实验环境中我们成功对存在漏洞的二进制文件实现了漏洞利用,但通常在现实情况中遇到的场景更为复杂。其中一种情况是我们希望利用的函数在现实二进制文件中却并不存在,此时攻击者就需要跳转到system函数来执行bin/sh,或者创建ROP链执行自己的shellcode。

3.9 使用firmware-mod-kit(FMK)在固件中添加后门

在漏洞利用过程中,经常需要用到的一种方法就是篡改固件。也就是从固件中提取文件系统,对其内容进行修改,然后再将其重新打包成新的固件,随后攻击者可以将这个新打包的固件刷进设备。

3.9.1 准备工作

固件篡改的过程会用到工具FMK,该工具由Jeremy Collake和Craig Heffner开发。FMK不仅可以利用Binwalk或其他工具从固件中提取出文件系统,还具有将篡改后的文件系统重新打包成新固件的功能。
FMK可以从https://github.com/brianpow/firmware-mod-kit/ 下载,如果读者之前从GitHub中克隆了FAT代码,那么该工具应该已经存在于读者的系统中了。下载完该工具后,接下来我们就可以找一个固件一试身手了。出于简单起见,同时让本书的读者在无须投入资金购买硬件的情况下也能够复现以下步骤,我们主要以能够采用FAT进行仿真的固件为例进行介绍。

3.9.2 测试流程

篡改固件的步骤如下:
1)在本例中我们使用的固件来自D-Link DIR-300路由器。在这里我们使用FMK目录下的extract-firmware.sh脚本从固件中提取文件系统,而未使用Binwalk。操作命令如图3-52所示。


xt-align:center">

提取出固件后,脚本会生成一个新目录,其中包括rootfs、image_part和logs等文件夹。由于攻击者的目的大多是添加后门和修改固件,因此这里我们只关心rootfs文件夹。
rootfs文件夹中包含了固件中的整套文件系统。而我们所要做的工作就是在固件中添加后门,然后找到固件启动后自动调用后门的方法。
2)首先查看固件所基于的架构。对固件中任一文件执行readelf命令就可以查看其架构,以BusyBox文件为例,命令执行结果如图3-53所示。

image.png

3)正如我们从图3-53中看到的,固件是基于MIPS小端架构的。这意味着我们需要开发符合MIPS小端架构的后门并进行编译。下面是我们将要使用的后门源码,该后门由Osanda Malith开发编写:

image.png

代码写好后,我们就可以使用针对MIPSEL架构的Buildroot,并使用该Buildroot构建的交叉编译器编译代码。这里不对安装配置Buildroot的过程进行过多介绍,因为这个过程非常简单,并且在Buildroot的说明文档中已经进行了详细说明。
4)为MIPSEL架构创建了交叉编译器后,我们接下来将bindshell.c编译为能够植入文件系统的二进制文件bindshell:

image.png

下一步是在文件系统中寻找可以放置该二进制文件的地方,以及如何在启动过程中将其设置为自启动。这里我们的思路是分析在启动过程中自动调用的脚本,看看是否能够实现自启动。
5)在文件系统中,我们可以在etc/templates/目录中放入后门的二进制文件,然后在system.sh脚本中调用该二进制文件,其中system.sh脚本位于/etc/scripts/目录下,脚本编写如图3-54所示。

image.png

6)接下来使用build-firmware.sh脚本将修改后的文件系统重新打包为新的固件,打包过程如图3-55所示。

image.png

执行完成后,会在目录firmware-name/中生成新的固件,新固件名为new-firmware.bin。
7)此时就创建完成了新的固件镜像,我们可以将新固件复制到FAT目录中,并通过仿真来验证新添加的后门是否能够正常运行。这里同之前固件仿真的步骤相同。操作步骤如图3-56所示。

image.png

如图3-56所示,固件仿真时获得的IP地址为192.168.0.1,此时可以尝试访问该地址。但我们更关注在固件中添加的后门bindshell是否已经成功启动。
8)现在尝试运行Netcat连接目标IP的9999端口,检查后门是否成功启动,如图3-57所示。

image.png

根据执行结果,可以看到我们已经对固件进行了修改并成功植入了后门,因此此时成功获得了设备中具有root权限的shell。而获得拥有root权限的shell之后,用户还可以修改设备的其他配置,或者将其作为跳板远程访问其他植入恶意固件的设备。

3.9.3 测试分析

固件篡改的功能强大,对于攻击者而言是梦寐以求的目标。这是因为,如果能够实现对固件的篡改,那么攻击者就能够实现绕过保护机制、移除安全防护措施等操作。而利用本章介绍的FMK等工具,攻击者可以很容易地将自己开发的恶意软件或后门植入到任意IoT设备固件中,这样攻击者就可以在全球任何地方通过后门访问IoT设备了。
正是由于固件篡改在攻击者手中具有如此强大的威力,所以如果能够对固件进行签名和校验值验证,那么对于防止恶意修改固件的攻击而言将具有非常重要的意义。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

华章出版社

官方博客
官网链接