术语表

什么是模糊测试:向自有软件批量输入异常数据以发现缺陷

模糊测试自动向软件输入异常数据,以发现漏洞和缺陷。介绍其工作原理以及如何在自有代码上开始使用。

发布于 2026-11-15 更新于 2026-11-15 2 分钟阅读
本页目录

模糊测试是一种测试技术,它会自动向软件输入异常数据以发现缺陷。本页介绍其工作原理,以及如何在自有代码上开始使用(不涉及对他人系统的测试)。

什么是模糊测试

OWASP 将模糊测试描述为一种旨在发现缺陷、漏洞或异常行为的软件测试技术。它会自动提供无效、异常或部分无效的输入,并观察程序是否出现异常行为。NIST 术语表(引用 NIST SP 800-95)同样将模糊测试描述为:称为模糊器(fuzzer)的工具向测试目标提交各种输入组合,以揭示其响应方式。

它的优势在于,对系统应有的行为所做的假设很少。人工编写的测试只覆盖有人想到的情况,而模糊测试器可以发现在人们未曾设想的输入下出错的地方。

工作原理

1. 准备一些初始输入(种子)
2. 模糊测试器对种子进行变异,并将每个输入传递给目标函数
↓ 运行,并观察执行了哪些代码以及程序的行为
3. 保存任何导致崩溃的输入;将到达新路径的输入反馈到第 2 步
生成、运行、观察、重复。覆盖率引导的模糊测试器会保留能够到达新路径的输入,并由此构建下一批输入。

大多数现代模糊测试器都是覆盖率引导的。它们测量哪些代码被执行,保留能够到达新代码的输入,并对这些输入进行变异以生成下一批输入。这样比单纯的随机输入更能深入程序内部。LLVM 的 libFuzzer 文档将其描述为一种进程内、覆盖率引导、演化式的模糊测试引擎,它会被链接到被测库中。

常用工具

工具主要目标说明
libFuzzerC/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 添加种子输入。

如何在自有软件上开始

  1. 选择一个解析输入的函数(文件格式解析器、配置加载器、协议处理程序)
  2. 编写一个简单的模糊测试目标,仅将输入传递给该函数。保持其运行快速且具有确定性,调用之间不保留状态
  3. 添加几个典型的有效输入作为种子
  4. 开启 AddressSanitizer 等 sanitizer,并运行设定的时长(在 Go 中,-fuzztime 用于设置时长)
  5. 将每个导致失败的输入转化为可复现的测试,并在修复后将其保留为回归测试
  6. 若要持续进行,可在 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++,请查阅其官方文档以了解当前用法

延伸阅读

FAQ

Q什么是模糊测试?
A

模糊测试是一种测试技术,它会自动大量输入无效或异常的数据,并检查程序是否出现崩溃或异常行为。OWASP 将其描述为一种旨在发现缺陷、漏洞或异常行为的软件测试技术。它也被称为 fuzz testing。

Q模糊测试能发现哪些问题?
A

通常包括崩溃、内存损坏(如越界读写)、无限循环和意外异常。它对解析输入的代码效果尤其好,例如图像、文档或协议解析器。OWASP 指出,模糊测试工具往往能发现简单的缺陷,而判断其发现的问题的影响则较为困难。

Q什么是覆盖率引导的模糊测试?
A

模糊测试工具会测量每个输入覆盖到了哪些代码(即覆盖率),保留能够触发新代码的输入,并对其进行变异以生成下一批输入。这样比纯随机输入更能深入程序内部。libFuzzer 的文档将其描述为一种进程内、覆盖率引导、演化式的模糊测试引擎。

Q开始模糊测试需要什么?
A

需要一小段测试代码,称为模糊测试目标(fuzz target),它将生成的输入传递给要测试的函数。对于 C/C++,可以使用 libFuzzer 或 AFL++;对于 Go 1.18 或更高版本,可以使用标准工具(go test -fuzz)。通常会结合 AddressSanitizer 等 sanitizer,以便及时发现内存误用。

Q我可以对他人的服务进行模糊测试吗?
A

不可以。未经许可向他人的系统发送大量格式错误的输入,可能构成未授权访问或服务中断。请只对您开发或管理的软件,在您自己的环境中进行模糊测试。对于开源项目,请使用既有的正规途径,例如 OSS-Fuzz。

Q什么是 OSS-Fuzz?
A

这是谷歌为开源软件提供的一项免费模糊测试服务。根据其官方页面,它于 2016 年推出,起因是 OpenSSL 中的 Heartbleed 漏洞;它使用 libFuzzer、AFL++、Honggfuzz 和 Centipede 等引擎,并会私下通知开发者其发现的缺陷。