OSS-Fuzz 模糊测试使用指南

文章目录

  • [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 固定格式

  1. 入口函数:必须命名为 LLVMFuzzerTestOneInput ,且必须用 extern "C" 修饰(避免 C++ 名字修饰导致 libFuzzer 无法识别);
  2. 函数参数:固定为 const uint8_t* data(模糊测试的原始字节数据)和 size_t size(数据长度),无其他参数;
  3. 返回值:必须为 int 类型,返回 0 表示正常结束(非 0 无特殊意义,libFuzzer 仅关注崩溃/内存错误);
  4. 头文件依赖:必须引入 stdint.hstddef.h(保证 uint8_t/size_t 类型定义),fuzzer/FuzzedDataProvider.h 是 OSS-Fuzz 推荐的辅助工具(可选但建议使用)。

3.4.2 fuzzer 编写重点

  1. 数据解析:避免直接使用原始 data,通过 FuzzedDataProvider 将字节数据转换为被测函数需要的类型(如字符串、整数、数组等),覆盖更多输入场景;
  2. 核心逻辑调用:聚焦被测项目的核心函数(如 tinyxml2 的 Parse 方法),确保模糊测试覆盖核心业务逻辑;
  3. 异常/错误处理:主动调用错误处理函数(如 ErrorStr()/ErrorLineNum()),提升代码覆盖率;
  4. 避免无关逻辑:不添加复杂的日志、休眠等逻辑,避免干扰模糊测试的执行效率;
  5. 边界处理:对空输入、超长输入等边界场景做基础处理(如 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编写即可完成高效漏洞检测,是提升项目代码安全性的重要保障。

相关推荐
llilian_161 天前
信号发生器 多通道多功能脉冲信号发生器应用解决方案 多功能脉冲发生器
功能测试·单片机·嵌入式硬件·测试工具
程序员小远1 天前
使用Postman进行一次完整的接口测试
自动化测试·软件测试·python·测试工具·测试用例·接口测试·postman
我的xiaodoujiao1 天前
使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 44--将自动化测试结果自动推送至钉钉工作群聊
前端·python·测试工具·ui·pytest
生活很暖很治愈1 天前
GUI自动化测试[3]——控件&数鼠标操作
windows·python·功能测试·测试工具
我的xiaodoujiao1 天前
使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 45--生成项目需要的requirements.txt依赖文件
python·学习·测试工具·pytest
@zulnger1 天前
selenium 自动化测试工具实战项目(订单)
selenium·测试工具·自动化
深圳博众测控2 天前
博众测控 | ISO 16750-2:2023汽车电气测试新标准解读:关键变化与测试设备选型
人工智能·测试工具·汽车
国科安芯2 天前
航空级PMSM驱动系统中MCU的故障诊断与容错控制策略研究
单片机·嵌入式硬件·安全·架构·制造·安全性测试
测试界的世清2 天前
金九银十软件测试面试题(800道)
测试工具·面试·职场和发展