模糊测试是一种测试技术,它会自动向软件输入异常数据以发现缺陷。本页介绍其工作原理,以及如何在自有代码上开始使用(不涉及对他人系统的测试)。
什么是模糊测试
OWASP 将模糊测试描述为一种旨在发现缺陷、漏洞或异常行为的软件测试技术。它会自动提供无效、异常或部分无效的输入,并观察程序是否出现异常行为。NIST 术语表(引用 NIST SP 800-95)同样将模糊测试描述为:称为模糊器(fuzzer)的工具向测试目标提交各种输入组合,以揭示其响应方式。
它的优势在于,对系统应有的行为所做的假设很少。人工编写的测试只覆盖有人想到的情况,而模糊测试器可以发现在人们未曾设想的输入下出错的地方。
工作原理
大多数现代模糊测试器都是覆盖率引导的。它们测量哪些代码被执行,保留能够到达新代码的输入,并对这些输入进行变异以生成下一批输入。这样比单纯的随机输入更能深入程序内部。LLVM 的 libFuzzer 文档将其描述为一种进程内、覆盖率引导、演化式的模糊测试引擎,它会被链接到被测库中。
常用工具
| 工具 | 主要目标 | 说明 |
|---|---|---|
| libFuzzer | C/C++ 等(LLVM) | 链接到被测目标中。根据其文档,原作者已转向 Centipede 引擎,libFuzzer 现在仅接收重要的缺陷修复 |
| AFL++ | C/C++ 等 | 广泛使用的覆盖率引导模糊测试器 |
| Go 内置模糊测试 | Go(1.18 或更高版本) | 使用 go test -fuzz 运行。导致失败的输入会保存在 testdata 下,并由普通测试重放 |
| OSS-Fuzz | 开源软件 | 谷歌提供的免费持续模糊测试服务,使用多种引擎和 sanitizer |
libFuzzer 的模糊测试目标是一个函数(LLVMFuzzerTestOneInput),它接收输入字节及其长度。在 Go 中,您需要编写一个名为 FuzzXxx 的测试函数,它接收 *testing.F 参数,并使用 f.Add 添加种子输入。
如何在自有软件上开始
- 选择一个解析输入的函数(文件格式解析器、配置加载器、协议处理程序)
- 编写一个简单的模糊测试目标,仅将输入传递给该函数。保持其运行快速且具有确定性,调用之间不保留状态
- 添加几个典型的有效输入作为种子
- 开启 AddressSanitizer 等 sanitizer,并运行设定的时长(在 Go 中,
-fuzztime用于设置时长) - 将每个导致失败的输入转化为可复现的测试,并在修复后将其保留为回归测试
- 若要持续进行,可在 CI 中运行短时会话;对于开源项目,可考虑加入 OSS-Fuzz
Go 的模糊测试每次执行有 1 秒的时间限制,覆盖率引导在 AMD64 和 ARM64 上可用。请查阅官方文档以了解您所在环境的限制。
只对您管理的软件进行模糊测试
模糊测试会持续发送大量格式错误的输入。若对您没有测试权限的服务或服务器这样做,可能构成未授权访问或服务中断。请将其限制在您开发或管理的软件上,并在您自己的环境中进行。
能做什么,不能做什么
OWASP 指出,模糊测试是对人工代码审查和调试的补充,而非替代。它还指出,模糊测试工具往往能发现简单的缺陷,并且在黑盒测试中,判断发现问题的影响较为困难。
因此,模糊测试擅长“让机器搜索代码可能出错的方式”,而在设计层面的问题(如缺失的授权检查)上则较弱。对于这类问题,例如 IDOR,应依赖检查预期规则的测试。
本站观点:找到输入只是一半工作,还要将其保留为回归测试
关键不仅在于运行模糊测试器,还在于将其发现的内容保存为回归测试。Go 内置的模糊测试会将导致失败的输入保存在 testdata 下,并在普通测试中重放,正是遵循这一理念。它可以防止已修复的缺陷在后续修改中再次出现。如果您负责维护解析输入的代码,一个切实可行的第一步是对单个函数进行模糊测试。
主要来源
- OWASP Community,"Fuzzing" — owasp.org(定义、特征、局限)
- NIST CSRC 术语表,"fuzz testing" — csrc.nist.gov(来源:NIST SP 800-95)
- LLVM,"libFuzzer" — llvm.org(工作原理、模糊测试目标、维护状态)
- Go,"Fuzzing" — go.dev(Go 1.18 或更高版本、运行方法、限制)
- Google,"OSS-Fuzz" — google.github.io(概述、支持的引擎)。缺陷数量会随时间变化,因此此处不引用具体数字。关于 AFL++,请查阅其官方文档以了解当前用法
延伸阅读
- 术语表:什么是 DAST(动态应用程序安全测试) · 什么是路径遍历 · 什么是 CVE
- 术语表:什么是 OWASP Top 10
- 指南:使用 OSV-Scanner 审计依赖项