ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

OSS-Fuzz 理想集成指南:如何把 fuzz target 无缝嵌入你的项目

OSS-Fuzz 理想集成指南:如何把 fuzz target 无缝嵌入你的项目 网络安全开发工具CI/CD【免费下载链接】oss-fuzzOSS-Fuzz - continuous fuzzing for open source software.项目地址https://gitcode.com/gh_mirrors/oss/oss-fuzz点击查看免费下载OSS-Fuzz 面向的是拥有不同构建与测试系统的开源项目无法要求所有项目都用同一种方式维护 fuzz target。本文基于 OSS-Fuzz 官方文档《Ideal integration with OSS-Fuzz》系统梳理从 fuzz target 入库、构建支持、种子语料seed corpus、字典dictionary、覆盖率、回归测试到性能优化的一整套最佳实践并结合仓库内 projects/example/my-api-repo 示例项目与 infra/base-images/base-builder 构建脚本从源码级说明每个环节如何落地。读完本文你将掌握如何把 fuzzing 以最小侵入的方式集成进项目自身版本库让自动化 fuzzing 在开发周期早期就持续发现回归。为什么需要理想集成开源项目各有各的构建系统和测试框架OSS-Fuzz 不可能为每个项目定制一套接入方案。因此官方文档给出了一套推荐做法把与 fuzzing 相关的全部资产fuzz target 源码、字典、种子语料放进项目自己的版本库并让构建系统以标准化的方式暴露给 OSS-Fuzz。这样做的收益是fuzz target 由项目代码所有者code owners在 Git/SVN 等 RCS 中直接维护随源码演进同步更新fuzz target 与项目其余测试一起构建避免位腐烂bit rot——即代码长期不编译、不与 API 变化同步而失效种子语料在版本控制中可追溯、可扩展持续沉淀曾经触发过 bug 的输入回归测试把 fuzz target 当作普通测试执行在每次提交时验证其不崩溃。一句话总结理想集成的目标每个 fuzz target 都被项目代码所有者维护在 RCS 中与其余测试一起构建拥有高质量种子语料与必要字典在 ASan/UBSan/MSan 下持续回归测试并且运行快速、无内存耗尽OOM。仓库里的完整样例OSS-Fuzz 仓库自带一个演示理想集成的示例项目 projects/example其中 my-api-repo 目录模拟位于项目自身仓库中的文件而 Dockerfile 与 project.yaml 模拟 OSS-Fuzz 侧需要的最小配置。下面的小节会反复引用该示例来印证文档中的每一条建议。Fuzz Target放在项目自己的仓库里fuzz target 是暴露给 fuzzing 引擎的入口函数其与引擎之间的接口是纯 C 接口因此既可以用 C 也可以用 C 实现。官方推荐的形态是 libFuzzer 所定义的LLVMFuzzerTestOneInputextern C int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);组织方式fuzz target 的源码应当属于项目自身源码仓库的一部分而不是散落在 OSS-Fuzz 仓库里所有 fuzz target 应当易于发现放在同一目录、遵循同一命名模式例如*_fuzzer.cpp/*_fuzzer.cc提交前先在本地短时间运行 fuzz target确保它不会立即崩溃crash、挂起hang或耗尽内存OOM。示例项目中的 fuzz target do_stuff_fuzzer.cpp 是一个典型的实现它把输入字节串构造为std::string交给被测 APIDoStuff()执行并忽略返回值extern C int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { std::string str(reinterpret_castconst char *(data), size); DoStuff(str); // Disregard the output. return 0; }本地验证文档强调在接入 OSS-Fuzz 之前应先本地跑一小段时间确认目标不会瞬间崩溃。如果 fuzz target 本身写得不好可以参考what makes a good fuzz target这类资料改进入口函数的写法例如避免std::terminate、避免只读第一个字节、正确处理超大输入等。Build Support让构建系统只做通用的事OSS-Fuzz 的构建环境会注入一组环境变量理想的项目构建系统应当直接消费这些变量而不是把 OSS-Fuzz 特定的编译器参数硬编码进构建文件。官方给出的理想构建规则如下对项目中的每个 fuzz targetfoo存在一条构建规则生成foo_fuzzer二进制该二进制包含 fuzzing 入口点包含LLVMFuzzerTestOneInput及其全部依赖代码使用$LIB_FUZZING_ENGINE环境变量由 OSS-Fuzz 环境提供所提供的main()函数构建系统支持更换编译器并透传额外编译标志因此构建命令大致形如# Assume the following env vars are set: # CC, CXX, CFLAGS, CXXFLAGS, LIB_FUZZING_ENGINE $ make_or_whatever_other_command foo_fuzzer之所以不要在构建系统里硬编码具体编译器标志是因为这些标志 a) 可能随版本变化b) 依赖当前使用的 fuzzing 引擎与 sanitizerASan/UBSan/MSan 各有不同的-fsanitize*标志。让 OSS-Fuzz 越少了解你的构建系统细节它就越容易大规模扩展。源码级的证据OSS-Fuzz 在基础镜像中预置了LIB_FUZZING_ENGINE环境变量见 infra/base-images/base-builder/DockerfileENV LIB_FUZZING_ENGINE/usr/lib/libFuzzingEngine.a在启用不同引擎的编译脚本中该变量会被替换为对应引擎的驱动libFuzzer 时是-fsanitizefuzzer见 compile_libfuzzerAFL 时被指向预编译的libAFLDriver.a见 compile_afl。因此项目构建文件只需引用${LIB_FUZZING_ENGINE}即可自动适配 libFuzzer、AFL、honggfuzz 等不同引擎。示例项目的 Makefile 写法projects/example/my-api-repo/Makefile 完整演示了这一模式# 默认使用自己的 standalone runner不做 fuzzing只按参数逐个执行输入 # 运行 e.g. make all LIB_FUZZING_ENGINE/path/to/libFuzzer.a 即可链接真实引擎 # OSS-Fuzz 会定义自己的 LIB_FUZZING_ENGINE 值。 LIB_FUZZING_ENGINE ? standalone_fuzz_target_runner.o # CC / CFLAGS / CXX / CXXFLAGS 由 OSS-Fuzz 提供 # 在 OSS-Fuzz 之外请使用你自己偏好的值或依赖默认值。 # 不要在默认情况下使用 -fsanitize* 标志 # OSS-Fuzz 对不同构建asan、ubsan、msan……会使用不同的 -fsanitize* 标志。 CXXFLAGS -stdc11 all: do_stuff_unittest do_stuff_fuzzer # 持续集成系统应运行 make clean make check check: all ./do_stuff_unittest ./do_stuff_fuzzer do_stuff_test_data/* # Fuzz target链接 $LIB_FUZZING_ENGINE让你可以自由选择 fuzzing 引擎。 do_stuff_fuzzer: do_stuff_fuzzer.cpp my_api.a standalone_fuzz_target_runner.o ${CXX} ${CXXFLAGS} $ my_api.a ${LIB_FUZZING_ENGINE} -o $ zip -q -r do_stuff_fuzzer_seed_corpus.zip do_stuff_test_data这段 Makefile 同时演示了三个要点LIB_FUZZING_ENGINE使用?提供默认值本地开发时可用自带 runnerOSS-Fuzz 构建时会覆盖为真实引擎编译器与标志全部来自外部环境变量构建文件本身不硬编码 sanitizer 标志check目标把 fuzz target 当作普通测试来跑对do_stuff_test_data/*逐个执行实现回归测试。Seed Corpus高质量的种子语料种子语料seed corpus是一组以独立文件形式存储的测试输入在 fuzzing 开始时提供给 fuzz target 作为变异起点seed 变异过程。种子语料的质量对 fuzzing 效率影响巨大质量越高fuzzer 越容易发现新的代码路径。理想语料是能提供最大代码覆盖的最少输入集合。对 OSS-Fuzz 集成而言种子语料应当纳入版本控制可与源码同库也可独立成库定期补充曾经触发过 bug 的输入以及能触达代码新部分的输入。示例项目把种子语料放在 do_stuff_test_data 目录文件以内容哈希命名Makefile 在构建 fuzz target 时同步生成do_stuff_fuzzer_seed_corpus.zip方便 OSS-Fuzz 直接消费。这也印证了文档所说语料库是活的资产应与 bug 修复历史一同演进。Dictionary为特定输入格式准备的字典对某些输入类型一个包含输入语言常用 token 的字典dictionary能对 fuzzing 效率产生戏剧性提升。例如 fuzzing 一个 XML 解析器时一份 XML token 字典就非常有用。理想情况下字典应与 fuzz target 一起维护在项目仓库中字典必须遵循 libFuzzer 定义的正确语法每行一个用双引号包裹的 token支持\xNN转义与注释行。示例字典 do_stuff_fuzzer.dict 内容如下# A dictionary for more efficient fuzzing of DoStuff(). # If the inputs contain multi-byte tokens, list them here. foo bar ouch从单元测试 do_stuff_unittest.cpp 可以看到DoStuff()的返回值与输入中出现的foo、bar、ouch等子串相关——字典恰好把这些关键 token 提供给 fuzzer帮助它更快构造出能深入逻辑的输入。这说明字典的价值在于让 fuzzer 不必从随机字节里重新发明语言关键字。Coverage用覆盖率报告指导投入方向要让 fuzz target 真正有用它必须对被测代码有良好覆盖率。你可以通过两种途径观察覆盖率ClusterFuzz 的 fuzzer stats 仪表盘查看速度、覆盖率信息、内存占用等统计见 docs/further-reading/clusterfuzz.md 中 Fuzzer stats 一节覆盖率报告coverage reports报告会高亮源码中已被 fuzz target 触达的部分重点关注标红的未覆盖代码并补充相应 fuzz target 来覆盖这些用例。要生成项目聚合的代码覆盖率报告请参考 OSS-Fuzz 文档的 代码覆盖率页面。覆盖率通常可以通过以下手段提升补充字典dictionary为种子语料增加更多输入修复 fuzz target 中的超时timeout与内存耗尽OOM问题。Regression Testing让 fuzz target 成为日常测试的一部分fuzz target 应当定期作为项目回归测试的一部分被执行注意不一定非要持续 fuzzing。一种推荐做法是把 fuzz target 链接一个简单的独立驱动standalone driver该驱动只负责逐个运行给定的输入文件不做任何变异用上一步创建的种子语料作为输入通过这个驱动执行 fuzz target回归测试期间建议开启 sanitizerASan/UBSan/MSan以便捕获内存类问题。示例standalone runner 与 make checkprojects/example/my-api-repo/standalone_fuzz_target_runner.cpp 是一个典型实现它把命令行参数中的每个文件读入内存依次喂给LLVMFuzzerTestOneInput。关键设计点包括精确按文件长度分配缓冲区从而可靠捕获缓冲区溢出源码注释中明确说明读取后assert(in)校验完整性不链接任何 fuzzing 引擎因此可以在任何 CI 中编译运行。Makefile 中的check目标正是回归测试入口make clean make check会先运行单元测试do_stuff_unittest再运行do_stuff_fuzzer do_stuff_test_data/*用独立驱动执行 fuzz target。只要构建系统能跑fuzz target 就不会腐烂——这正是文档强调与其余测试一起构建的价值。Performance让 fuzz target 保持轻快fuzz target 的性能很重要高内存占用或慢执行速度会拖慢覆盖率增长和新 bug 的发现。为此 ClusterFuzz 为每个 fuzz target 提供性能分析器performance analyzer可以查看目标遇到的具体性能问题如内存泄漏、超时等——在 fuzzer stats 仪表盘点击Performance链接即可进入见 docs/further-reading/clusterfuzz.md 中 Performance analyzer 一节。文档建议修复其中列出的所有问题让 fuzz target 保持高效运行并持续发现新 bug。不是项目成员怎么办OSS-Fuzz 仓库代管方案如果你是目标项目的成员上述步骤大多很简单。但有时项目之外的人想 fuzz 某段代码而项目维护者无意配合。此时 OSS-Fuzz 允许把 fuzz target、字典等资产托管在 OSS-Fuzz 仓库中并在项目的Dockerfile中提及它们缺点由于不在项目 CI 中持续测试fuzz target 可能很快位腐烂bitrot另外如果你不是项目维护者OSS-Fuzz 可能无法把你加入安全 bug 的抄送CC列表。仓库中 projects/libxml2、projects/c-ares、projects/expat 等即属于此类代管模式它们的 fuzz target 源码直接放在 OSS-Fuzz 仓库内。这应视为兜底方案而非推荐做法——理想集成始终是把 fuzz target 放进项目自己的版本库。小结理想集成的检查清单结合原文档与示例项目一个理想集成的项目应满足维度理想做法仓库依据Fuzz Target源码归项目所有同目录、同命名模式、易发现接口用 C 或 Cdo_stuff_fuzzer.cppBuild Support消费$CC/$CXX/$CFLAGS/$CXXFLAGS/$LIB_FUZZING_ENGINE不硬编码 sanitizer 标志my-api-repo/Makefile、compile_libfuzzerSeed Corpus纳入版本控制最小输入集最大化覆盖随 bug 历史扩展do_stuff_test_dataDictionary与 fuzz target 同库维护遵循 libFuzzer 字典语法do_stuff_fuzzer.dictCoverage通过 ClusterFuzz stats 与覆盖率报告监控针对性补充输入/字典docs/further-reading/clusterfuzz.mdRegression Testingstandalone driver 种子语料 sanitizer纳入 CIstandalone_fuzz_target_runner.cpp 与make checkPerformance用性能分析器定位并修复泄漏、超时、OOMdocs/further-reading/clusterfuzz.md 中 Performance analyzer把以上各项落实到位你的项目就能以最小维护成本接入 OSS-Fuzz 的持续 fuzzing 流水线在每次代码变更的早期阶段捕获回归与内存安全缺陷。相关参考材料还包括 新项目接入指南 与 进阶主题总览可作为接入流程的进一步指引。赞分享网络安全开发工具CI/CD【免费下载链接】oss-fuzzOSS-Fuzz - continuous fuzzing for open source software.项目地址https://gitcode.com/gh_mirrors/oss/oss-fuzz点击查看免费下载相关推荐OSS-Fuzz 理想集成指南为开源项目设计可持续的 Fuzz Target 与自动化模糊测试方案OSS Fuzz 理想集成指南为开源项目设计可持续的 Fuzz Target 与自动化模糊测试方案 本文是 OSS Fuzz 文档《Ideal integra测试应用安全质量保障OSS-Fuzz Java/JVM 项目接入指南基于 Jazzer 的 fuzz target 编写与构建OSS Fuzz Java/JVM 项目接入指南基于 Jazzer 的 fuzz target 编写与构建 OSS Fuzz 对 Java 及任何运行在 JV测试应用安全质量保障OSS-Fuzz 中的 LLM 驱动 Fuzz Harness 合成为未接入项目自动生成 OSS-Fuzz 集成OSS Fuzz 中的 LLM 驱动 Fuzz Harness 合成为未接入项目自动生成 OSS Fuzz 集成 OSS Fuzz 团队在其 OSS Fuzz测试应用安全质量保障上一篇Mac Mouse Fix让普通鼠标超越苹果触控板的专业优化方案下一篇qmcflac2mp3终极指南3步解锁QQ音乐加密实现跨平台自由播放创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表