What You Corrupt Is Not What You Crash Challenges in Fuzzing Embedded Devices 论文笔记

你破坏的不是你破坏的: Fuzzing 嵌入式设备的挑战
作者:Marius Muench
单位:巴黎高等电信学院
国家: #法国
年份: #2018年
来源: #NDSS会议
关键字: #嵌入式 #综述
[[What You Corrupt Is Not What You Crash_ Challenges in Fuzzing Embedded Devices.pdf]]

Abstract

  • 传统的测试方法依赖于程序中看的见的崩溃, 而二进制插装技术是用来改善针对这些缺陷状态的检测方法
  • 演示了 memory corruption 漏洞,展示 embedded devices 和 desktop systems 的不同
  • 分析了几种 embedded devices 设备的差异

Introduction

  • Memory corruption 导致的漏洞普遍存在,模糊测试是发现这些漏洞最流行的技术之一,适合大规模自动化
  • 因为 embedded devices 的有限的 I/O 和计算能力,受限的成本,其上没有大部分 desktop systems 拥有的防御机制,所以发生内存损坏的概率更高
  • 但是 embedded devices 存在缺少源码,识别 memory corruption 的传统方法不适用于的问题。
  • 本文首次全面分析了内存损坏对不同类别的嵌入式系统的影响,并且提出的技术可以 100%检测到在模糊过程中触发的内存损坏状态

FUZZING EMBEDDED SYSTEMS

首先介绍将在本文其余部分使用的嵌入式系统的分类。然后,我们讨论了之前将模糊测试应用于不同嵌入式设备的实验,最后我们提出了在该领域应用模糊测试所遇到的挑战。

Classes of Embedded Devices

将嵌入式设备分为以下三类

  • 基于 OS 的通用设备:此类设备搭载了被改装为嵌入式设备操作系统的桌面级系统。(例如,Linux 操作系统内核广泛用于嵌入式领域,通常与轻量级用户空间环境(例如 busybox 和 uClibc)结合使用。)
  • 基于嵌入式操作系统的设备:此类设备搭载了为嵌入式设备定制的操作系统,内核和应用程序代码之间的逻辑分离仍然存在。(例如 uClinux、ZephyrOS 和 VxWorks)
  • 没有操作系统抽象的设备:此类设备采用所谓的“单片固件”,其操作通常基于单个控制环路和从外围设备触发的中断,以处理来自外部世界的事件。固件将包含编译的系统和应用程序代码在一起,形成了一个单一的软件。(单体方法可以在各种硬件组件控制器中找到,例如 CD 读取器、WiFi 卡或 GPS 加密狗。在这些设备上运行的代码可以是完全自定义的,也可以基于操作系统库,如 Contiki、TinyOS 或 mbed OS 22。)

Past Experiments

下表展示了近几年来针对嵌入式设备 fuzzing 的论文
image.png

Main Challenges of Fuzzing Embedded Devices

Fault detection

  • 作者认为模糊测试可以通过检测程序是否崩溃来判断输入是否触发漏洞,而桌面系统存在各种防御机制来检测恶意输入从而产生崩溃,但是嵌入式设备的操作系统没有各种各样的防御机制,所以很有可能触发漏洞但是没有产生崩溃,这种情况 fuzzing 器检测不到。
  • 对于嵌入式设备可以检测到的崩溃,可能因为缺少输出错误信息的 I/O 功能,而导致 fuzzing 器监测不到
  • 作者给出的解决方案是部署复杂的活性探测
    • 主动探测:将特殊请求插入到与设备或其环境的通信中
    • 被动探测:旨在检索有关设备状态的信息而不改变它。

Performance and Scalability

  • 嵌入式设备的 fuzzing 难以并行化
  • 每轮 fuzzing (为了清空状态)重启设备拖慢测试过程

Instrumentation

  • 嵌入式设备很难进行编译时检测和运行时检测来收集覆盖信息,或者通过别的一些什么技术来收集有关被测系统状态的信息。因为对于嵌入式设备而言,测试对象往往是固件映像,现有的工具不适用,不需要访问应用程序源代码的常见解决方案是求助于二进制动态检测框架。
  • 但是作者最后指出上述所有静态和动态检测工具都与目标操作系统和 CPU 体系结构紧密相关,并且在撰写本文时,它们都不提供对 Type-II 和 Type-III 嵌入式设备的支持。

MEMORY CORRUPTIONS IN EMBEDDED SYSTEMS

Bugs, Faults, Corruptions & Crashes

  • Van der Veen 等人区分了空间记忆错误和时间记忆错误。第一种类型表示对内存对象的越界访问,第二种类型表示对不再存在的内存对象的访问
  • 有的内存损坏不会立即引起系统崩溃,作者称之为静默崩溃。
    • 静默内存损坏的重要后果是,实际故障可能只会在稍后请求特定功能或接收到特定事件序列时才会变得明显。
  • 桌面系统因为有多种防御机制,所以更容易触发这种静默内存损坏,但是对于嵌入式设备缺乏防御机制,很难检测到静默内存损坏

Experimental Setup

在不同的系统上触发相同的内存损坏条件,以分析它们是否屈服于可观察到的崩溃或导致静默损坏。

  • 设备选择:选择了现有的商用现成 (COTS) 产品:代表 Type-I 系统的路由器和代表 Type-II 设备的 IP 摄像机。
  • 漏洞程序部署:对于 I II 型设备,直接编译漏洞程序然后加载到设备上便可,对于 III 型设备需要将测试代码包含在固件中然后对其编译,然后将固件加载到设备上。

Atificial Vulnerabilities

  • 使用基于堆栈的缓冲区溢出和基于堆的缓冲区溢出作为空间内存损坏的示例,并使用空指针取消引用和双重释放漏洞作为时间内存损坏的示例。
  • 还插入了一个格式字符串漏洞,可以用于信息泄漏或任意内存损坏。

Observed Behavior

  • 桌面系统每次都可以触发崩溃
  • 嵌入式设备并不总是能够检测到故障,在某些情况下,它们甚至继续执行而没有明显的影响——尽管系统的底层内存已损坏。观测到以下六种状态
    • R1:可以观测到的崩溃
    • R2:设备重启
      • R1 和 R2 对于 fuzzing 器来说是可以检测到的,是最好的结果
    • R3:挂起:目标挂起并停止响应新请求,可能陷入死循环
    • R4:随后崩溃:目标系统继续执行一段不可忽视的时间后崩溃
      • 挂起和后期崩溃(R3 和 R4)可能更难处理,特别是当崩溃延迟足够长以至于模糊器可能已经向目标系统发送了多个其他输入并且因此导致损坏的输入将是难以识别。
    • R5:故障:系统没有崩溃,但是报告了错误的数据和不正常的结果
      • 为了检测这种情况,模糊器需要知道正确的输出是什么,一种可能的变通方法包括在两个连续的输入之间插入一些输出已知的功能测试请求。然而,即使这个解决方案足以检测到故障,它也会在模糊测试中引入相当大的延迟。
    • R6:无影响:尽管内存已损坏,目标仍然正常运行,没有明显的副作用。
      • 这种最难检测
        image.png

MITIGATIONS

Static Instrumentation.

  • 前提是需要源代码和编译工具链
  • 典型的 instrumentation 包括多种技术的组合:收集执行轨迹以测量覆盖率以改变模糊输入,添加内存分配检查,或使用例如控制流完整性来强化程序。不幸的是,这些工具中的大多数还不能用于嵌入式系统。

Binary Rewriting

  • 前提要有二进制固件镜像,设备
  • 反汇编固件的二进制镜像,恢复内存语义、边界和数据结构具有挑战性,其次嵌入式设备的内存使用经常被优化来降低成本,几乎没有留给添加复杂 instrumentation 的空间。

Physical Re-Hosting

  • 前提需要源代码,编译链,不同的设备
  • 某些情况下,可以将 II 型设备的系统重新编译到更易于检测的 I 型设备上,或者 I 型设备编译到桌面系统上
  • 除了先决条件难以实现外,在不同设备上重现原设备上的漏洞也具有挑战性,由于不同的体系结构或者重新编译引入的更改可能会让原有的漏洞不再出现。

Full Emulation

  • 前提要有固件镜像,外设模拟器
  • 在某些情况下,从 Type-I 固件中提取的应用程序可以虚拟地重新托管,即,它们可以在默认模拟器上运行的通用操作系统中执行。
  • 扩展 Qemu 以模拟 STM32 芯片的 Qemu STM32 项目表明,当完整的硬件文档可用时,通过相当大的努力来实现硬件模拟,也可以完全模拟 Type-III 固件映像。
  • 这个解决方案可以大大改善模糊。首先,测试实验可以在没有物理设备的情况下进行,因此可以实现更大的并行化。其次,动态检测技术可以很容易地应用,仿真器可以用来收集大量关于运行固件的信息。
  • 这种解决方案的缺点是,它只适用于目标所访问的所有外设都是已知的并且可以成功模拟的情况,不幸的是,这种情况很少发生。总的来说,能够在模拟器中运行任意固件仍然是一个开放的研究问题。

Partial Emulation

  • 前提需要固件映像、设备
  • 这种方法首先由 Avatar[54]和 Surrogates[28]提出用于 Type-III 设备,然后在 PROSPECT[24],[25]中扩展到 Type-I 系统。此解决方案背后的一般思想是使用经过修改的模拟器 (其中执行固件代码) 将外围交互转发到实际的物理设备。其结果提供了完全模拟解决方案的优点,而无需了解和模拟 I/O 操作。然而,此解决方案在灵活性方面所获得的好处是牺牲了性能 (由于与实际设备的额外交互) 和可伸缩性 (由于当前需要将每个模拟实例与物理设备配对)。

Hardware-Supported Instrumentation

  • 前提需要设备,高级调试功能 (例如,跟踪调试端口和调试器)
  • 如果测试人员可以访问具有先进硬件检测机制 (如实时跟踪) 的物理设备,则可能收集足够的信息来改进设备执行期间的故障检测。例如,芯片制造商通常嵌入硬件跟踪功能,如 ARM 的嵌入式跟踪 Macrocell (ETM) 和 Coresight 调试和跟踪,或英特尔的处理器跟踪 (PT) 技术。不幸的是,这种跟踪硬件的可用性是可变的。在低端设备 (通常是 iii 型设备) 中,制造商往往不包括任何跟踪功能,因为这种机制会对芯片表面产生相对较大的影响,因此对成本也会产生影响。开发设备可能有这样的设施 (有时在制造之前在 FPGA 上测试微控制器设计),但这在商业生产设备中不太常见。最后,在某些情况下,调试访问可能存在,但不可用,以防止第三方分析。
  • 在测试真实设备时,找到可用的硬件跟踪支持的可能性非常低。

总结

  • 方案 ABC 要求测试人员修改固件镜像,但是因为种种困难,在执行第三方安全测试时,这很少是一个选项。
  • 方案 DEF 不需要修改固件镜像,但是需要额外的技术 (软件模拟器或硬件跟踪支持) 来收集有关正在运行的固件的信息。

FAULT DETECTION HEURISTICS(故障检测启发式)

这些启发式算法是独立于实现的,这样不仅可以在实时分析设置中工作 (就像固件在模拟器中运行时那样),而且还可以对以前收集的执行跟踪进行“事后分析”(就像在基于硬件的跟踪机制中那样)。

Segment Tracking

段跟踪可能是旨在检测非法内存访问的最简单技术。核心思想是观察所有内存读写并验证它们是否发生在有效位置,从而以某种方式模仿 MMU 检测分段错误。这种技术只需要了解目标的内存访问和内存映射。两者都可以在模拟器中轻松访问,但是,当只有跟踪可用时,可以通过逆向工程获得内存映射。

Format Specifier Tracking

本质上,此保护验证格式字符串说明符在进入 printf () 系列函数时指向有效位置。在最简单的情况下,如果不存在动态生成的格式字符串说明符,那些有效位置必须位于只读段内。总而言之,这项技术不仅需要了解格式处理函数的位置,还需要了解输入其中一个函数时的寄存器状态和参数顺序。相应函数的位置及其参数顺序都可以通过逆向工程或固件的自动静态分析获得。

Heap Object Tracking

该技术旨在检测与时间和空间堆相关的错误,并受到 [43] 中介绍的检测和运行时验证方法的影响。它通过评估分配和释放函数的参数和返回值以及记录堆对象的位置和大小来实现其目标。这允许轻松检测越界内存访问或对已释放对象的访问。然而,这种启发式方法取决于多种信息:已执行的指令、寄存器的状态、内存访问以及有关分配和释放函数的知识。后者可以通过逆向工程或通过使用高级方法来发现自定义分配器来检索,如 MemBrush 所展示的。

Call Stack Tracking

调用堆栈跟踪正在复制传统的影子堆栈保护 [53],因此旨在检测不返回被调用者的函数。这有助于识别覆盖函数返回地址的基于堆栈的内存损坏。它通过监视所有直接和间接函数调用和返回指令来实现。然而,由于嵌入式设备通常是中断驱动的,这种试探法可能会导致漏报。但是它需要最少的信息:只需要执行指令的知识。

Call Frame Tracking

调用帧跟踪是调用堆栈跟踪技术的更高级版本,它可以在发生时检测粗粒度的基于堆栈的缓冲区溢出,而不会出现漏报。本质上,堆栈帧是通过跟踪函数调用来定位的,然后检查连续的内存访问是否跨越堆栈帧。因此,这需要识别执行的指令以及寄存器值,以在函数入口时提取堆栈指针值。然后,必须观察内存访问以检测实际损坏。

Stack Object Tracking

堆栈对象跟踪包括对堆栈变量越界访问的细粒度检测,这是受 Serebryany 等人提出的堆对象跟踪方法的启发。 [43]。因此,根据堆栈中的各个变量大小和位置检查执行期间观察到的内存读取和写入。显然,这需要跟踪执行的指令和内存访问,以及有关堆栈变量的详尽信息。为了简单起见,我们使用调试符号中存在的变量信息。然而,在一般情况下,可以从二进制代码中以自动方式检索此类信息,正如之前的几项研究 [22]、[47] 所提出的那样。
image.png

IMPLEMENTATION

  • 作者基于 PANDA (动态分析平台) 和 Avatar (用于嵌入式设备动态分析的编排框架),编写了程序,并将其开源
  • 总之,我们使用 PANDA 来模拟固件,并依赖其插件系统来获得部分或完全模拟固件执行时的实时反馈。所有这一切都由 Avatar 编排执行,并有选择地将执行和内存访问重定向到物理设备。
  • Avatar 还提供了保存快照的功能。

EXPERIMENTS

目的:

  • 将启发式方法集成到工具中
  • 测量方法带来的系统开销

目标设置

四种实验设置:

  • NAT不添加任何启发式方法的模糊测试,作为基准
  • PE/MF带有内存转发的部分仿真:将 I/O 操作转发到实际设备
  • PE/PM具有外围建模的部分仿真:固件是模拟的,外围设备交互是通过使用 Avatar 内部的专用脚本模拟外围设备行为来处理的,这允许在没有物理设备存在的情况下进行实验。
  • FE完全仿真:固件及其外围设备都在 PANDA 中完全模拟。

Fuzzing Setup

  • 基于 boofuzz 构建实验
  • 使用 fuzzer 强制生成输入这些输入将以给定的概率触发插入的内存损坏漏洞之一。
  • 添加了一个监视器(活性检查 liveness checks):在每次模糊输入之后,模糊器接收设备的响应并评估它是否符合预期的行为。当收到的响应与预期的不同时,或者当连接超时时,模糊器报告崩溃并重新启动目标。
    • 这个监视器是为了检测启发式方法没有检测到的崩溃,从而评估启发式方法的有效性

Result

  • 目标处理的输入数量 (Itot)、损坏输入被发送到目标的次数 (IC)、活性检查 (DL) 检测到的故障数量以及故障数量由启发式 (DH) 检测到。此外,我们将未检测到的故障数表示为 (DU)。
  • I C = D L + D H + D U ≈ I t o t ∗ P C I_C =D_L+D_H+D_U\approx I_{tot}*P_C IC=DL+DH+DUItotPC

Fault Detection

实验结果表明启发式方法确实产生了更多的崩溃,从而提高了 fuzz 的效率

性能

  • 具有内存转发 (PE/MF) 的部分仿真正在使模糊测试减慢一个数量级以上。这种开销是由固件和设备外围设备之间的通信引入的。这种开销的主要部分是由于 Avatar 和物理设备之间的低带宽连接,它依赖于通过 USB 连接的标准 JTAG 调试器。 Surrogates [28] 已经表明,这个问题可以通过使用专用硬件来解决,这将能够以接近实时的速度进行部分仿真。
  • 观察单个启发式,我们可以观察到它们在 PE/MF 场景中的开销可以忽略不计,其中 MMIO 请求的转发瓶颈完全决定了模糊实验的速度。然而,在 PE/PM 和 FE 场景中,我们可以观察到 PC = 0 的启发式分析代码带来了相当大的放缓 (在 x1.5 到 x6 之间)。
  • 另一个重要的观察结果是,只要检测到的损坏量较低,针对完全模拟目标的模糊处理速度明显快于针对物理设备的模糊处理。这主要是由于三个因素。首先,TCP 上的通信比串行端口上的通信允许更高的吞吐量。第二,即使固件是仿真的,仿真器通常比 (低资源) 嵌入式设备具有更高的时钟速度。第三,检测到的损坏与强制重新启动目标有关,这意味着高容量的 pc 会导致花费大量时间重新启动,而不是向目标发送新的输入。
  • 然而,我们实验中最重要的结果是,在启用组合启发式的 PANDA (完全仿真) 中执行的固件在 PC 的实际值下可以比原始嵌入式设备更快地模糊化。虽然第一种方法可以检测到我们在其代码中插入的所有类型的漏洞,但第二种方法需要依赖于只能识别其中两种漏洞的活动检查。

DISCUSSION

  • 仅仅依靠活性测试是一个糟糕的策略。仅依靠活跃度测试进行故障检测来模糊嵌入式系统是一种很可能遗漏许多漏洞的糟糕策略。同样,一次只使用一个启发式方法并不能保证检测到更多的漏洞。直观地说,通过结合几种启发式方法可以达到腐败检测的最高潜力。
  • 完全仿真模拟器很少
  • 部分仿真速度慢——一个数量级
  • 这项工作也适用于嵌入式设备固件上的二进制符号执行。如果没有及时检测到损坏,符号执行可能会花费大量时间来计算无用状态。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值