怎么选择 fuzz 测试点
1. 优先选择处理复杂格式输入的代码
处理复杂、非结构化输入的代码是 Fuzzing 的首选目标。这类代码通常包含复杂的解析逻辑和状态机,容易在处理畸形数据时出错
- 文件解析器:这是最典型的 Fuzzing 目标。例如,图片格式(JPEG, PNG)、视频格式(MP4, AVI)、文档格式(PDF, DOCX)的解析库或应用程序。Fuzzer 可以轻松生成无数个格式畸形的样本,测试解析器对异常情况的处理能力
- 网络协议栈:处理网络协议的代码是高价值目标。例如,Web 服务器、FTP 守护进程、或者物联网设备的通信协议。Fuzzer 可以向这些服务发送不符合协议规范的数据包,测试其鲁棒性
- 编译器和解释器:对编程语言的编译器或解释器进行 Fuzzing,可以发现它们在处理语法错误或逻辑异常的代码时的漏洞。例如,对 JavaScript 引擎的 Fuzzing 已经发现了无数高价值的漏洞
2. 考虑执行权限和攻击面
选择 Fuzzing 点时,要将漏洞的潜在危害考虑在内
- 高权限代码:如果一个程序以
root
、SYSTEM
或其他高权限运行,那么它的漏洞危害会更大。对这类程序的 Fuzzing 应该作为首要任务。例如,内核驱动、特权服务、或者安全软件 - 暴露在外部的接口:攻击者可以直接访问的接口是 Fuzzing 的高优先级目标。例如,通过网络监听端口、接受外部文件的服务,或者处理命令行参数的程序。这些接口是攻击者的第一道入口
3. 基于代码复杂性分析
如果可以访问源码,可以更精确地选择 Fuzzing 点
- 复杂的控制流:在代码中寻找包含大量
if-else
、switch
语句、嵌套循环或复杂状态机的函数。这些地方的代码路径多且复杂,很容易出现逻辑错误和漏洞 - 涉及内存操作的代码:寻找使用
malloc
、free
、memcpy
、read
等内存相关函数的代码。这些函数是缓冲区溢出、Use-After-Free 等内存安全漏洞的常见源头 - 缺乏边界检查的代码:在代码中寻找缺乏对输入数据大小进行严格检查的地方。这通常是缓冲区溢出漏洞的温床
4. 结合自动化工具进行决策
为了避免盲目选择,可以使用自动化工具来辅助决策
- 代码覆盖率工具:使用像
gcov
或llvm-profdata
这样的工具,运行已知的测试用例,分析哪些代码区域没有被覆盖到。这些未覆盖的区域往往是 Fuzzing 的好目标 - 静态分析工具:使用静态分析工具(如
Coverity
、Clang Static Analyzer
)来扫描代码,寻找潜在的漏洞模式,比如整数溢出或空指针解引用。然后,将这些潜在的漏洞位置作为 Fuzzing 的重点