原文链接: https://www.computer.org/csdl/proceedings-article/sp/2023/933600b765/1Js0Ek1SE6c
Background
SMM是一种面向x86处理器的,由Unified Extensible Firmware Interface (UEFI)固件提供的安全操作模式,在SMM模式下运行的程序就是SMM driver,功能包括电量管理,访问敏感数据以及控制系统硬件等。
在系统启动的时候,这些driver被加载到一块单独的内存空间,称为SMRAM,并且在启动后这块SMRAM就被锁定。
另外值得一提的是,SMM driver的权限为-2,而我们知道kernel的权限一般是0,因此SMM driver可以通过物理地址访问所有的内存空间。对SMM driver进行fuzzing也是建立在0级权限之上的,也就是基于0级权限的威胁模型。
这些driver通常包含3个部分:
1. 一套vendor提供的协议,用于与其他driver通信
2. 一组SMI handlers,每个代表一项运行时的服务,通过CommBuffer与kernel交换数据
3. 初始化函数,用来注册上述协议和handler,将它们存放至SMRAM
其中,SMI handler既是SMM driver的入口,也是与kernel交换数据的唯一接口。因此,对SMM drivr进行fuzzing的理想目标就是SMI handler。
Running Example
第18行将buffer指向的位置改为0,而buffer在第12行可以由输入数据控制,第16行的签名又可以由第7行控制。
可以看出,一个漏洞的触发涉及多个不同输入格式的handler,是一个较为复杂的过程。
Challenges
- SMI handler存在不同的输入接口
- SMI handler的输入需要满足不同的格式
- 触发漏洞可能需要多个handler共同参与
- 漏洞可能被路径约束保护
- 漏洞可能仅为静默的内存污染,并不导致crash
Insights
为了解决以上5个挑战,本文提出以下insights:
- 为了生成有价值的测试用例,需要知道输入相关的知识,包括输入接口和输入的数据格式
- 为了有效地测试SMI handler, 需要跨handler相关的知识,包括handler之间的producer-consumer关系和涉及的跨handler变量
- 为了提高代码覆盖率,需要解决路径约束
- 为了找出更多内存相关的漏洞,需要检测静默的内存破坏
Contribution
本文贡献如下:
- 提出了一个灰盒测试工具,能够识别SMI handler的输入接口,恢复输入格式并进行多个handler的fuzzing
- 实现了RSFuzzer,评价了16个UEFI的固件,并且表现得比state-of-the-art的工具都好
- 检测了65个新漏洞,33个得到开发商确认,获得14个CVE
- 计划开源RSFuzzer
Overview
在执行单handler的fuzzing的时候,RSFuzzer通过concolic execution提取输入知识(符号化输入相关的变量,实例化其他变量)同时也会收集对其他SMI handler的调用,识别用于其他handler的变量,从而更好地进行跨handler的fuzzing。
当一定时间内没有触发新的block的时候,RSFuzzer切换为跨handler模式,选择一个跨handler变量,根据依赖生成一系列SMI handler调用进行fuzzing。触发新的block之后,再切换回单handler模式继续fuzz。
Design
RSFuzzer的设计主要包含以下四个部分:
Input Knowledge Extraction
输入知识包括输入接口和输入格式。
输入接口:CommBuffer总是第三个参数,因此不需要识别实际的内存地址;硬编码的地址通过递归式的方法进行识别。
输入格式在解引用操作使用过的变量识别为指针,其他的通过递归的方式识别基本类型(只需要大小);
识别struct的结构基于两点观察:
1.指向struct的指针通常式通过间接地址访问的;
2.上级结构总是包含指向下级结构的指针
也是提出了一种递归式的算法识别整个struct。
Test Case Generation
生成测试用例主要根据三种模式:
1.基于格式的:每当取得新的输入格式相关的知识,RSFuzzer就会按照对应的格式分配内存,填充随机数据并生成一个新的test case种子
2.基于约束的:如果约束求解长时间无法解出,RSFuzzer会变异与未触发的分支相关的变量,变异为与分支条件相同或是略大、略小的值。
3.基于污点的:由于SMI handler拥有-2级权限,对内存的污染很可能不会触发crash。RSFuzzer在fuzz之前分配一块不可读不可写不可执行作为Red Zone,之后在concolic execution中标记所有用户可控的内存指令为危险指令,最后在fuzzing的时候通过变异潜在的危险指令使其指向red zone,从而触发crash
Cross-handler Knowledge Extraction
本文关注的跨handler知识主要包括跨handler的变量及代码片段。其中代码片段具有如下特征:
1.总是访问相同的内存空间
2.至少一个代码片段对其进行写操作
3.该变量生存周期涵盖多个handler的执行
而这些片段涉及的变量即为跨handler变量。
Evaluation
RSFuzzer基于AFL++实现,在16个UEFI固件镜像中进行测试,得到如下结果:
Vulnerabilities
RSFuzzer找出65个漏洞,包括六种类型:
- Improper input validation
- Out-of-bound write
- Buffer overflows
- Use of uninitialized variables
- Untrusted pointer dereference
- Use after free
Coverage
与sota工作(Syzgen和SPENDER)相比,RSFuzzer的代码覆盖率提升到了617%,另外漏洞发现率也提高到了828%。
Effectiveness of Knowledge Extraction
为了证明知识提取的效果,作者去除Knowledge Extraction模块,使用随机变异的字节填充输入,得到如下结果:
可以看出Knowledge Extraction在fuzzing中发挥了重要作用。
Discussion
Limitation
本文主要存在如下局限性:
- 虽然用的是partial emulation,开销还是很大
- 官网上仅提供是待升级的固件镜像,可能有所疏漏
Further Research
另外有两类bug不能被RSFuzzer检测,需要进一步的工作:
- Information leak
- Inproper access control