PeriScope: An Effective Probing and Fuzzing Framework for the Hardware-OS Boundary
开源项目地址:https://github.com/securesystemslab/periscope
本文发表在ISOC Network and Distributed System Security Symposium(NDSS)2019,第一作者是来自University of California的Dokyung Song。
主要内容
之前安全研究人员在分析kernel安全问题时,更多的是关注system call boundary,即认为kernel漏洞通常可由syscall触发。作者在本文中指出,针对hardware-OS boundary的安全分析同样不容忽视。在已知的针对kernel的攻击中,存在以下方式:攻击者首先通过远程攻击,获取了外接设备如WiFi芯片的控制权,然后进一步通过被控制的设备攻击相关的driver,进而在不调用任何syscall的情况下获取kernel控制权。因此,针对该攻击方式,作者提出了一种用于分析设备与driver之间交互的动态分析框架PeriScope,并将其扩展提出了专门用于该场景的fuzz框架PeriFuzz。在技术上主要通过hook page fault handler来分析针对driver与设备共享内存的读写操作。最后作者用PeriFuzz在两种WiFi的driver上发现了15个不同的漏洞,其中有9个是新的漏洞。
背景知识
本文的核心贡献在于,提出了分析硬件和驱动之间交互的分析框架和fuzz框架。
硬件和驱动之间的交互方式可以分为以下3类:
(1) 设备中断
这里的设备中断亦指外部中断,外部中断来自CPU外部,由设备提出请求。Linux将中断处理分为两个部分,顶半部(top-half)和底半部(bottom-half)。顶半部通常处理紧急事务,它往往仅读取寄存器中的中断状态,清除中断标志,而通常由底半部执行耗时的操作。实现底半部的机制主要包括tasklet和workqueue。
(2) MMIO
MMIO(Memory mapping IO),即把IO设备的内部存储和寄存器都映射到kernel的虚拟地址中。在MMIO下,driver可通过正常的访存指令和设备进行交互。
(3) DMA
DMA(Direct Memory Access),即允许设备直接访问物理内存,设备通过DMA传输数据并通过中断的方式通知CPU。DMA的buffer主要分为两种:Coherent DMA buffer和Streaming DMA Buffer。Coherent DMA buffer通常仅在driver初始化时才会被分配。Streaming DMA Buffer的生命周期较短,通常仅被用于一次消息传输。
相关工作对比
目前已有的有关分析设备和driver之间的方法主要包括以下3种:
(1) Device Adaption。主要通过为设备加入额外的能力来分析交互流程,好处是不依赖于操作系统,但是缺点也十分明显,即要求设备的可编程性或者分析人员即设备开发者。
(2) Virtual Machine。即分析driver与虚拟设备在虚拟运行环境下的交互,但要求比较苛刻,对每款设备的分析都需要与之对应的虚拟化设备支持。
(3) Symbolic Execution。即将设备向driver传输的数据都认为是symbolic的值,从而进行symbolic execution。该做法虽然不需要虚拟化设备和可编程设备的支持,但缺点是会继承symbolic execution一贯的缺陷,如路径爆炸问题。
作者通过hook MMIO或DMA下的allocate函数来标记共享的memory region,进一步通过hook page fault handler,将针对这些memory region的读写都记录下来,从而达到分析的效果。好处是不依赖任何的可编程设备和虚拟化设备,同时很容易在其之上实现一个fuzz框架,从而拥有symbolic execution所不能比拟的漏洞发现能力。
Threat-Model
作者所设计的分析框架PeriScope和fuzz框架PeriFuzz主要用于以下攻击场景:
(1) 攻击者已远程控制了如WiFi芯片这样的外接设备。
(2) 攻击者能够控制外接设备向driver传输任意的恶意数据。
(3) 攻击者仅能访问用于设备和driver交互的内存区域。
简单概括即为:已控制外接设备的攻击者想进一步通过设备向driver发送恶意数据,进而控制kernel或者使其crash。一个实际场景下的攻击流程可参考BroadPwn: Remotely compromising Android and iOS via a bug in Broadcom’s Wi-Fi chipsets【BlackHat’17】
设计与实现
作者设计的动态分析框架PeriScope主要包含以下主要模块:
(1) Tracking Allocations.首先hook DMA和MMIO相关的allocate和deallocate API,进而可以知道哪些地址用于设备和driver之间的交互。
(2) Enabling Monitoring.让每次对于步骤1中标记的内存地址的访问都触发page fault,然后进入到自定义的page fault handler中。
(3) Instruction Decoding.主要用于记录读写指令的信息,如源地址,目的地地址以及访存字节数等。
(4) Pre-instruction Hook.在PeriScope下,该模块会返回default-value,即进入single-step环节进行读写操作。在PeriFuzz下,该模块会放回skip-single-step,即不执行该指令的读写操作,用fuzzer来模拟新的读写。
(5) Post-instruction Hook.将Page再次置为not present并进行相关的信息收集(可自定义)。
总结一下,作者的核心思路在于hook page fault handler以便捕捉到设备和driver之间通过MMIO/DMA的读写操作。
作者在PeriScope的基础上做了扩展,设计出了fuzz设备和driver之间交互的框架PeriFuzz。
主要包含以下主要模块:
(1) Fuzzer.可直接用现有的fuzzer实现,如AFL,主要用于生成fuzz input,并处理feedback。
(2) Executor.用于沟通Fuzzer和Injector,通过共享内存的机制将user space生成的input传输至kernel space。
(3) Injector.利用上文介绍的PeriScope,将原本要读写的内容替换成fuzz input,PC指向下一条指令。
实验与分析
作者挑选了qcacld-3.0和bcmdhd4358两款driver作为实验对象,总计fuzz出了15个漏洞,包括Buffer Overflow,Null-pointer Dereference,Address Leak和Reachable Assertion,其中有9个是新发现的漏洞。除此以为,作者还提出了4个double fetch的issue,当PeriFuzz对同一地址的读置换为了两个不同的fuzz input就可能产生double fetch。
评价
本文作者针对设备和driver之间的交互设计了完整的分析框架和fuzz框架,在实验部分也对发现的各种类型的bug做了详尽的分析。但该工具的应用场景要求略显苛刻,即要求攻击者已经完全控制外接设备。换言之,作者仅关注在设备-driver-kernel攻击链的一环上,但依然不可否认这是一篇完整优秀的工作。
文丨DJR, Robin, Harry