文章目录
- [1. 简介](#1. 简介)
- [2. 环境部署](#2. 环境部署)
-
- [2.1 系统前置准备](#2.1 系统前置准备)
- [2.2 Docker 安装与配置](#2.2 Docker 安装与配置)
-
- [2.2.1 安装 Docker](#2.2.1 安装 Docker)
- [2.2.2 配置 Docker 加速(可选,根据网络情况)](#2.2.2 配置 Docker 加速(可选,根据网络情况))
- [2.2.3 配置 Docker 权限](#2.2.3 配置 Docker 权限)
- [2.3 克隆 OSS-Fuzz 仓库并验证基础工具](#2.3 克隆 OSS-Fuzz 仓库并验证基础工具)
-
- [2.3.1 克隆官方仓库](#2.3.1 克隆官方仓库)
- [2.3.2 验证 OSS-Fuzz 核心辅助脚本](#2.3.2 验证 OSS-Fuzz 核心辅助脚本)
- [2.4 配置代理(国内必配)](#2.4 配置代理(国内必配))
- [2.5 拉取 OSS-Fuzz 基础镜像](#2.5 拉取 OSS-Fuzz 基础镜像)
- [2.6 环境完整校验](#2.6 环境完整校验)
- [3. 项目示例](#3. 项目示例)
-
- [3.1 示例项目准备](#3.1 示例项目准备)
- [3.2 项目配置文件编写](#3.2 项目配置文件编写)
-
- [3.2.1 Dockerfile 编写与参数解释](#3.2.1 Dockerfile 编写与参数解释)
- [3.2.2 project.yaml 编写与参数解释](#3.2.2 project.yaml 编写与参数解释)
- [3.3 编译脚本 build.sh 编写与参数解释](#3.3 编译脚本 build.sh 编写与参数解释)
- [3.4 模糊测试代码编写与规范说明](#3.4 模糊测试代码编写与规范说明)
-
- [3.4.1 libFuzzer 固定格式](#3.4.1 libFuzzer 固定格式)
- [3.4.2 fuzzer 编写重点](#3.4.2 fuzzer 编写重点)
- [3.5 测试步骤与参数解释](#3.5 测试步骤与参数解释)
-
- [3.5.1 构建项目镜像](#3.5.1 构建项目镜像)
- [3.5.2 构建模糊测试用例](#3.5.2 构建模糊测试用例)
- [3.5.3 验证构建结果](#3.5.3 验证构建结果)
- [3.5.4 运行模糊测试](#3.5.4 运行模糊测试)
- [3.6 模糊测试日志解读](#3.6 模糊测试日志解读)
- [4. 总结](#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 用于克隆仓库):
bash
sudo apt update && sudo apt upgrade -y
sudo apt install -y git python3 python3-pip curl wget build-essential
git --version
python3 --version

2.2 Docker 安装与配置
OSS-Fuzz 完全基于 Docker 运行(核心优势是环境隔离),需安装官方稳定版 Docker 并完成权限、加速配置。
2.2.1 安装 Docker
bash
# 安装证书、GPG 密钥相关依赖,确保软件源验证合法
sudo apt install -y ca-certificates curl gnupg lsb-release
# 创建 Docker 软件源密钥目录并设置权限
sudo install -m 0755 -d /etc/apt/keyrings
# 下载阿里云 Docker 源的 GPG 密钥并写入密钥文件
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 赋予密钥文件全局可读权限,确保 apt 能读取验证
sudo chmod a+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" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker 全套组件
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
2.2.2 配置 Docker 加速(可选,根据网络情况)
国内访问 Docker 官方镜像源速度较慢,可配置国内镜像加速:
shell
sudo mkdir -p /etc/docker
sudo apt-get install vim -y
sudo vim /etc/docker/daemon.json
# 写入国内镜像加速地址(DaoCloud 镜像,国内可用性高)
{
"registry-mirrors": [
"https://docker.m.daocloud.io"
]
}
# 重新加载系统服务配置并重启 Docker 服务,使加速配置生效
sudo systemctl daemon-reload && sudo systemctl restart docker
sudo systemctl status docker
2.2.3 配置 Docker 权限
默认情况下 Docker 命令需 sudo 执行,配置普通用户权限可简化后续操作:
bash
sudo groupadd -f docker
sudo usermod -aG docker $USER
newgrp docker

2.3 克隆 OSS-Fuzz 仓库并验证基础工具
2.3.1 克隆官方仓库
OSS-Fuzz 的核心脚本和配置都在官方仓库中,需先克隆到本地(国内慢可导入 Gitee 后克隆):
bash
git clone https://github.com/google/oss-fuzz.git
cd oss-fuzz
2.3.2 验证 OSS-Fuzz 核心辅助脚本
infra/helper.py 是 OSS-Fuzz 最核心的辅助脚本,负责镜像构建、模糊测试编译/运行等全流程,需验证其可用性:
bash
python3 infra/helper.py --help

2.4 配置代理(国内必配)
国内直接拉取 OSS-Fuzz 的海外 Docker 镜像(gcr.io 源)会超时,仅靠镜像加速无法解决,需配置代理:
shell
# 创建 Docker 服务的代理配置目录
sudo mkdir -p /etc/systemd/system/docker.service.d
# 编辑 HTTP/HTTPS 代理配置文件
sudo vim /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,使代理生效
sudo systemctl daemon-reload
sudo systemctl restart docker
2.5 拉取 OSS-Fuzz 基础镜像
OSS-Fuzz 为不同编程语言提供了预构建的基础镜像,首次拉取较慢,建议提前拉取:
bash
# 拉取 C/C++ 项目基础构建镜像
docker pull gcr.io/oss-fuzz-base/base-builder
# 拉取 Java/Go 项目基础构建镜像(按需选择)
docker pull gcr.io/oss-fuzz-base/base-builder-jvm
docker pull gcr.io/oss-fuzz-base/base-builder-go

2.6 环境完整校验
运行以下命令验证整个环境是否满足 OSS-Fuzz 运行要求:
bash
# 验证 Docker 服务状态
sudo systemctl status docker --no-pager
# 验证 helper.py 能否识别基础镜像
python3 infra/helper.py build_image --help

3. 项目示例
3.1 示例项目准备
tinyxml2 是轻量级 C++ XML 解析库,也是 OSS-Fuzz 官方内置的测试项目,但是官方的配置是拉取在线的 tinyxml2 源码进行测试,本次演示本地源码测试(而非官方在线拉取),先明确目录结构:
shell
/home/xxx/Desktop/
├── oss-fuzz/ # OSS-Fuzz 根目录(所有操作的核心目录)
└── tinyxml2/ # tinyxml2 源码目录(与 oss-fuzz 同级,本地测试用)
克隆 tinyxml2 源码:
bash
git clone https://github.com/leethomason/tinyxml2.git
3.2 项目配置文件编写
进入 OSS-Fuzz 的 projects 目录,创建本地测试配置目录:
shell
cd oss-fuzz/projects
mkdir -p tinyxml2_local # 创建 tinyxml2 本地测试配置目录
cd tinyxml2_local
目录结构如下:

3.2.1 Dockerfile 编写与参数解释
shell
vim Dockerfile
文件内容:
dockerfile
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 编写与参数解释
shell
vim project.yaml # 创建项目元信息配置文件
文件内容:
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 编写与参数解释
shell
vim build.sh # 创建编译脚本(OSS-Fuzz 核心脚本,负责编译项目和模糊测试用例)
# 保持后添加文件权限
chmod 755 build.sh
文件内容:
bash
#!/bin/bash -eu
cd $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 模糊测试代码编写与规范说明
shell
vim tinyxml2_local_fuzzer.cpp
文件内容:
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 size
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size == 0) return 0;
// 初始化模糊数据解析器:将原始字节数据转换为可按需提取的结构化数据
FuzzedDataProvider provider(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();
}
return 0; // 函数必须 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 构建项目镜像
bash
python3 infra/helper.py build_image tinyxml2_local
参数解释:
infra/helper.py:OSS-Fuzz 核心辅助脚本;build_image:子命令,用于构建指定项目的 Docker 镜像;tinyxml2_local:项目名称(对应 projects 目录下的 tinyxml2_local 目录)。

3.5.2 构建模糊测试用例
bash
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 验证构建结果
bash
python3 infra/helper.py check_build tinyxml2_local
参数解释:
check_build:子命令,验证模糊测试二进制文件是否符合 OSS-Fuzz 规范(如是否包含 ASAN 检测能力、是否放入 $OUT 目录等);tinyxml2_local:项目名称。
输出 Check build passed 则表示构建正常:

3.5.4 运行模糊测试
bash
python3 infra/helper.py run_fuzzer tinyxml2_local tinyxml2_local_fuzzer > fuzz.log 2>&1
tail -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编写即可完成高效漏洞检测,是提升项目代码安全性的重要保障。