文章目录
- 1. 简介
- 2. 环境部署
- 2.1 系统前置准备
- 2.2 Docker 安装与配置
- 2.2.1 安装 Docker
- 2.2.2 配置 Docker 加速(可选,根据网络情况)
- 2.2.3 配置 Docker 权限
- 2.3 克隆 OSS-Fuzz 仓库并验证基础工具
- 2.3.1 克隆官方仓库
- 2.3.2 验证 OSS-Fuzz 核心辅助脚本
- 2.4 配置代理(国内必配)
- 2.5 拉取 OSS-Fuzz 基础镜像
- 2.6 环境完整校验
- 3. 项目示例
- 3.1 示例项目准备
- 3.2 项目配置文件编写
- 3.2.1 Dockerfile 编写与参数解释
- 3.2.2 project.yaml 编写与参数解释
- 3.3 编译脚本 build.sh 编写与参数解释
- 3.4 模糊测试代码编写与规范说明
- 3.4.1 libFuzzer 固定格式
- 3.4.2 fuzzer 编写重点
- 3.5 测试步骤与参数解释
- 3.5.1 构建项目镜像
- 3.5.2 构建模糊测试用例
- 3.5.3 验证构建结果
- 3.5.4 运行模糊测试
- 3.6 模糊测试日志解读
- 4. 总结
⚠️本博文所涉安全渗透测试技术、方法及案例,仅用于网络安全技术研究与合规性交流,旨在提升读者的安全防护意识与技术能力。任何个人或组织在使用相关内容前,必须获得目标网络 / 系统所有者的明确且书面授权,严禁用于未经授权的网络探测、漏洞利用、数据获取等非法行为。
1. 简介
OSS-Fuzz 是由 Google 主导打造的开源模糊测试(Fuzz Testing)平台,核心目标是为全球开源软件提供标准化、自动化、可持续的漏洞检测能力,从根源上提升开源生态的安全性。
该平台基于 Docker 容器实现环境隔离,集成了 libFuzzer、HongFuzz、AFL++ 等主流模糊测试引擎,并配套了崩溃分析、覆盖率统计、测试用例精简等全链路工具链,让开发者无需关注环境适配、引擎运维等底层细节,只需聚焦于业务逻辑的模糊测试适配。
2. 环境部署
2.1 系统前置准备
OSS-Fuzz 对操作系统有明确要求,本文基于Ubuntu 24.04.3 LTS完成部署。
首先需更新系统并安装核心依赖工具(OSS-Fuzz 的辅助脚本基于 Python3 开发,Git 用于克隆仓库):
sudoaptupdate&&sudoaptupgrade -ysudoaptinstall-ygitpython3 python3-pipcurlwgetbuild-essentialgit--version python3 --version2.2 Docker 安装与配置
OSS-Fuzz 完全基于 Docker 运行(核心优势是环境隔离),需安装官方稳定版 Docker 并完成权限、加速配置。
2.2.1 安装 Docker
# 安装证书、GPG 密钥相关依赖,确保软件源验证合法sudoaptinstall-y ca-certificatescurlgnupg lsb-release# 创建 Docker 软件源密钥目录并设置权限sudoinstall-m 0755 -d /etc/apt/keyrings# 下载阿里云 Docker 源的 GPG 密钥并写入密钥文件curl-fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg|sudogpg --dearmor -o /etc/apt/keyrings/docker.gpg# 赋予密钥文件全局可读权限,确保 apt 能读取验证sudochmoda+r /etc/apt/keyrings/docker.gpg# 添加阿里云 Docker 软件源到系统源列表(适配当前系统架构和版本)echo"deb [arch=$(dpkg --print-architecture)signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu$(lsb_release -cs)stable"|sudotee/etc/apt/sources.list.d/docker.list>/dev/null# 安装 Docker 全套组件sudoaptinstall-y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin2.2.2 配置 Docker 加速(可选,根据网络情况)
国内访问 Docker 官方镜像源速度较慢,可配置国内镜像加速:
sudomkdir-p /etc/dockersudoapt-getinstallvim-ysudovim/etc/docker/daemon.json# 写入国内镜像加速地址(DaoCloud 镜像,国内可用性高){"registry-mirrors":["https://docker.m.daocloud.io"]}# 重新加载系统服务配置并重启 Docker 服务,使加速配置生效sudosystemctl daemon-reload&&sudosystemctl restartdockersudosystemctl statusdocker2.2.3 配置 Docker 权限
默认情况下 Docker 命令需sudo执行,配置普通用户权限可简化后续操作:
sudogroupadd-fdockersudousermod-aGdocker$USERnewgrpdocker2.3 克隆 OSS-Fuzz 仓库并验证基础工具
2.3.1 克隆官方仓库
OSS-Fuzz 的核心脚本和配置都在官方仓库中,需先克隆到本地(国内慢可导入 Gitee 后克隆):
gitclone https://github.com/google/oss-fuzz.gitcdoss-fuzz2.3.2 验证 OSS-Fuzz 核心辅助脚本
infra/helper.py是 OSS-Fuzz 最核心的辅助脚本,负责镜像构建、模糊测试编译/运行等全流程,需验证其可用性:
python3 infra/helper.py --help2.4 配置代理(国内必配)
国内直接拉取 OSS-Fuzz 的海外 Docker 镜像(gcr.io 源)会超时,仅靠镜像加速无法解决,需配置代理:
# 创建 Docker 服务的代理配置目录sudomkdir-p /etc/systemd/system/docker.service.d# 编辑 HTTP/HTTPS 代理配置文件sudovim/etc/systemd/system/docker.service.d/http-proxy.conf# 配置代理环境变量(需替换为自身代理的 IP 和端口)[Service]Environment="HTTP_PROXY=http://192.168.10.3:7897"# HTTP 代理地址Environment="HTTPS_PROXY=http://192.168.10.3:7897"# HTTPS 代理地址Environment="NO_PROXY=localhost,127.0.0.1"# 无需代理的本地地址# 重新加载服务配置并重启 Docker,使代理生效sudosystemctl daemon-reloadsudosystemctl restartdocker2.5 拉取 OSS-Fuzz 基础镜像
OSS-Fuzz 为不同编程语言提供了预构建的基础镜像,首次拉取较慢,建议提前拉取:
# 拉取 C/C++ 项目基础构建镜像dockerpull gcr.io/oss-fuzz-base/base-builder# 拉取 Java/Go 项目基础构建镜像(按需选择)dockerpull gcr.io/oss-fuzz-base/base-builder-jvmdockerpull gcr.io/oss-fuzz-base/base-builder-go2.6 环境完整校验
运行以下命令验证整个环境是否满足 OSS-Fuzz 运行要求:
# 验证 Docker 服务状态sudosystemctl statusdocker--no-pager# 验证 helper.py 能否识别基础镜像python3 infra/helper.py build_image --help3. 项目示例
3.1 示例项目准备
tinyxml2 是轻量级 C++ XML 解析库,也是 OSS-Fuzz 官方内置的测试项目,但是官方的配置是拉取在线的 tinyxml2 源码进行测试,本次演示本地源码测试(而非官方在线拉取),先明确目录结构:
/home/xxx/Desktop/ ├── oss-fuzz/# OSS-Fuzz 根目录(所有操作的核心目录)└── tinyxml2/# tinyxml2 源码目录(与 oss-fuzz 同级,本地测试用)克隆 tinyxml2 源码:
gitclone https://github.com/leethomason/tinyxml2.git3.2 项目配置文件编写
进入 OSS-Fuzz 的 projects 目录,创建本地测试配置目录:
cdoss-fuzz/projectsmkdir-p tinyxml2_local# 创建 tinyxml2 本地测试配置目录cdtinyxml2_local目录结构如下:
3.2.1 Dockerfile 编写与参数解释
vimDockerfile文件内容:
FROM gcr.io/oss-fuzz-base/base-builder:latest # 基于 OSS-Fuzz C/C++ 基础镜像构建(必选,提供编译环境) RUN apt-get update && apt-get install -y cmake make # 安装 tinyxml2 编译所需的 cmake 和 make 工具 COPY build.sh $SRC/ # 将本地 build.sh 复制到容器内的 $SRC 目录(OSS-Fuzz 约定的源码目录) COPY tinyxml2_local_fuzzer.cpp $SRC/ # 将模糊测试代码复制到 $SRC 目录参数/指令解释:
FROM:指定基础镜像,OSS-Fuzz 要求必须基于官方base-builder系列镜像(保证编译环境统一);RUN:在容器内执行命令,此处安装 tinyxml2 编译依赖(cmake 用于生成 Makefile,make 用于编译);COPY:将本地文件复制到容器内,$SRC是 OSS-Fuzz 约定的源码工作目录,所有编译脚本/测试代码需放入该目录。
3.2.2 project.yaml 编写与参数解释
vimproject.yaml# 创建项目元信息配置文件文件内容:
homepage:"https://github.com/leethomason/tinyxml2"# 项目官网/仓库地址language:c++# 项目开发语言(OSS-Fuzz 用于匹配对应编译环境)primary_contact:"xxx@xx.com"# 漏洞通知的主联系人main_repo:"https://github.com/leethomason/tinyxml2"# 项目主仓库地址参数解释:
homepage:用于 OSS-Fuzz 平台展示项目信息;language:核心参数,OSS-Fuzz 会根据该值加载对应语言的编译工具链(如 C++ 加载 clang++、libFuzzer 等);primary_contact:当 OSS-Fuzz 发现漏洞时,会通过该邮箱通知开发者;main_repo:用于 OSS-Fuzz 自动拉取最新源码(本地测试时仅作元信息,无实际作用)。
3.3 编译脚本 build.sh 编写与参数解释
vimbuild.sh# 创建编译脚本(OSS-Fuzz 核心脚本,负责编译项目和模糊测试用例)# 保持后添加文件权限chmod755build.sh文件内容:
#!/bin/bash -eucd$SRC/tinyxml2_local cmake -DCMAKE_CXX_COMPILER=$CXX-DCMAKE_CXX_FLAGS="$CXXFLAGS".make-j$(nproc)$CXX$CXXFLAGS-std=c++17 -I.$SRC/tinyxml2_local_fuzzer.cpp -o$OUT/tinyxml2_local_fuzzer$LIB_FUZZING_ENGINE./libtinyxml2.a -DTINYXML2_NO_EXCEPTIONS核心参数解释:
#!/bin/bash -eu:脚本解释器声明,-e和-u是 OSS-Fuzz 要求的脚本规范(避免静默失败);$CXX/$CC:OSS-Fuzz 约定的编译器变量(C++ 用 $CXX,C 用 $CC),默认绑定 clang 系列编译器(内置 libFuzzer 支持);$CXXFLAGS/$CFLAGS:OSS-Fuzz 预设的编译参数,包含-fsanitize=address(ASAN,内存漏洞检测)、-O1(编译优化)、-fno-omit-frame-pointer(保留栈帧,方便崩溃调试)等核心参数;$LIB_FUZZING_ENGINE:OSS-Fuzz 内置的 libFuzzer 库路径(无需手动指定,平台自动注入);$OUT:OSS-Fuzz 约定的输出目录,所有编译生成的模糊测试二进制文件必须放入该目录(helper.py 会自动读取该目录的二进制);-j$(nproc):编译并行度优化,利用所有 CPU 核心加速编译,是 OSS-Fuzz 编译脚本的通用优化手段。
3.4 模糊测试代码编写与规范说明
vimtinyxml2_local_fuzzer.cpp文件内容:
#include"tinyxml2.h"#include<fuzzer/FuzzedDataProvider.h>// OSS-Fuzz 提供的模糊数据解析工具#include<stdint.h>// 必选,LLVMFuzzerTestOneInput 函数参数依赖#include<stddef.h>// 必选,LLVMFuzzerTestOneInput 函数参数依赖#include<string>// 必须命名为 LLVMFuzzerTestOneInput,参数固定为 const uint8_t* data 和 size_t sizeextern"C"intLLVMFuzzerTestOneInput(constuint8_t*data,size_t size){if(size==0)return0;// 初始化模糊数据解析器:将原始字节数据转换为可按需提取的结构化数据FuzzedDataProviderprovider(data,size);std::string xml_input=provider.ConsumeRandomLengthString(size);// 调用被测函数:tinyxml2 的 XML 解析逻辑tinyxml2::XMLDocument doc;doc.Parse(xml_input.c_str(),xml_input.size());// 覆盖错误处理逻辑if(doc.Error()){doc.ErrorStr();doc.ErrorName();doc.ErrorLineNum();}return0;// 函数必须 0 表示正常结束}3.4.1 libFuzzer 固定格式
- 入口函数:必须命名为
LLVMFuzzerTestOneInput,且必须用extern "C"修饰(避免 C++ 名字修饰导致 libFuzzer 无法识别); - 函数参数:固定为
const uint8_t* data(模糊测试的原始字节数据)和size_t size(数据长度),无其他参数; - 返回值:必须为 int 类型,返回 0 表示正常结束(非 0 无特殊意义,libFuzzer 仅关注崩溃/内存错误);
- 头文件依赖:必须引入
stdint.h和stddef.h(保证uint8_t/size_t类型定义),fuzzer/FuzzedDataProvider.h是 OSS-Fuzz 推荐的辅助工具(可选但建议使用)。
3.4.2 fuzzer 编写重点
- 数据解析:避免直接使用原始
data,通过FuzzedDataProvider将字节数据转换为被测函数需要的类型(如字符串、整数、数组等),覆盖更多输入场景; - 核心逻辑调用:聚焦被测项目的核心函数(如 tinyxml2 的
Parse方法),确保模糊测试覆盖核心业务逻辑; - 异常/错误处理:主动调用错误处理函数(如
ErrorStr()/ErrorLineNum()),提升代码覆盖率; - 避免无关逻辑:不添加复杂的日志、休眠等逻辑,避免干扰模糊测试的执行效率;
- 边界处理:对空输入、超长输入等边界场景做基础处理(如
size == 0时返回),避免无意义的崩溃。
3.5 测试步骤与参数解释
3.5.1 构建项目镜像
python3 infra/helper.py build_image tinyxml2_local参数解释:
infra/helper.py:OSS-Fuzz 核心辅助脚本;build_image:子命令,用于构建指定项目的 Docker 镜像;tinyxml2_local:项目名称(对应 projects 目录下的 tinyxml2_local 目录)。
3.5.2 构建模糊测试用例
python3 infra/helper.py build_fuzzers --sanitizer address tinyxml2_local /home/jerry/Desktop/tinyxml2参数解释:
build_fuzzers:子命令,用于编译模糊测试二进制文件;--sanitizer address:指定漏洞检测工具为 ASAN(AddressSanitizer,内存越界/泄漏检测),可选值还有undefined(UBSAN,未定义行为检测)、memory(MSAN,内存初始化检测)等;tinyxml2_local:项目名称;/home/jerry/Desktop/tinyxml2:本地 tinyxml2 源码目录(OSS-Fuzz 会将该目录挂载到容器内的$SRC/tinyxml2_local目录)。
编译结果验证:
3.5.3 验证构建结果
python3 infra/helper.py check_build tinyxml2_local参数解释:
check_build:子命令,验证模糊测试二进制文件是否符合 OSS-Fuzz 规范(如是否包含 ASAN 检测能力、是否放入 $OUT 目录等);tinyxml2_local:项目名称。
输出Check build passed则表示构建正常:
3.5.4 运行模糊测试
python3 infra/helper.py run_fuzzer tinyxml2_local tinyxml2_local_fuzzer>fuzz.log2>&1tail-f fuzz.log# 实时查看模糊测试日志参数解释:
run_fuzzer:子命令,运行指定的模糊测试二进制文件;tinyxml2_local:项目名称;tinyxml2_local_fuzzer:模糊测试二进制文件名称(对应 build.sh 中输出到 $OUT 目录的文件);> fuzz.log 2>&1:将标准输出和标准错误重定向到 fuzz.log 文件(避免日志刷屏);tail -f fuzz.log:实时跟踪日志文件内容。
3.6 模糊测试日志解读
日志核心字段解释:
exec/s: 103159 # 每秒执行模糊测试用例数(数值越高,fuzzer 效率越高) cov: 419 # 代码覆盖率(数值上升表示 fuzzer 覆盖了更多代码分支) REDUCE # 表示 fuzzer 发现了“更小的测试用例但覆盖相同代码”(便于后续漏洞复现) DE: "\017\000" # 自动字典功能:fuzzer 识别出被测函数的关键常量(如 XML 特殊字符),并组合测试关键说明:
- 若
cov长时间(如 1 小时)无增长,说明 fuzzer 已穷尽当前变异路径,可停止测试; - 若 fuzzer 检测到崩溃(如内存越界、空指针解引用),会立即停止并输出崩溃信息(核心漏洞发现逻辑)。
4. 总结
OSS-Fuzz的部署与使用核心分为环境准备、项目配置、编译验证、模糊测试四大阶段:
- 环境准备需安装Git、Python3等基础工具
- 部署并配置Docker(国内需代理解决海外镜像拉取问题),克隆OSS-Fuzz官方仓库验证helper.py脚本可用性
- 项目配置要在OSS-Fuzz的projects目录下创建项目目录,编写Dockerfile(基础镜像+依赖安装)、project.yaml(项目元信息),遵循OSS-Fuzz变量约定编写
build.sh编译脚本,按libFuzzer固定格式编写聚焦被测核心函数的Fuzzer代码; - 编译验证需通过
helper.py依次完成项目镜像构建、模糊测试二进制编译、二进制合规性校验 - 模糊测试则通过
helper.py启动fuzzer,监控执行效率、代码覆盖率,关注崩溃/错误提示以检测漏洞。
OSS-Fuzz通过Docker隔离环境、统一配置规范降低模糊测试门槛,开发者只需聚焦Fuzzer编写即可完成高效漏洞检测,是提升项目代码安全性的重要保障。