mcpField
I
implementing-fuzz-testing-in-cicd-with-aflplusplus

implementing-fuzz-testing-in-cicd-with-aflplusplus

github.com/mukul975测试与质量35.2k42 次安装8 周前更新
代码仓库

关于 implementing-fuzz-testing-in-cicd-with-aflplusplus

介绍如何将 AFL++ 覆盖引导模糊测试集成到编译应用的 CI/CD 中。内容包括测试 harness、插桩、语料准备、并行测试和崩溃分析。

主要功能

  1. 01覆盖引导的输入变异测试
  2. 02源码和二进制插桩模式
  3. 03用于加速模糊测试的持久模式
  4. 04种子语料最小化
  5. 05CI/CD 与夜间测试配置
  6. 06崩溃复现与分类分析

适用场景

  1. 01测试处理不可信输入的解析器
  2. 02在 CI/CD 中定期运行模糊测试
  3. 03对无源码二进制进行模糊测试
  4. 04复现并整理发现的崩溃

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill implementing-fuzz-testing-in-cicd-with-aflplusplus

安装后在 Claude Code 中输入/implementing-fuzz-testing-in-cicd-with-aflplusplus确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE
assets/
template.md
references/
api-reference.md
standards.md
workflows.md
scripts/
agent.py
process.py

详细介绍

在 CI/CD 中使用 AFL++ 实施模糊测试

概述

AFL++(American Fuzzy Lop Plus Plus)是 AFL 的社区维护分支,提供先进的覆盖率引导模糊测试,用于发现编译型应用程序中的漏洞。AFL++ 使用遗传算法变异输入,跟踪代码覆盖率以发现触发崩溃、挂起和未定义行为的新执行路径。在 CI/CD 环境中,可以集成 AFL++ 来持续测试解析器、协议处理器、文件格式处理器以及任何处理不受信任输入的代码。AFL++ 支持持久模式以实现高速模糊测试(每秒高达 100,000+ 次执行)、自定义变异器、用于仅二进制模糊测试的 QEMU 模式,以及用于自动字典提取的 CmpLog/RedQueen。

何时使用

  • 在你的环境中部署或配置使用 aflplusplus 在 CI/CD 中实施模糊测试的能力时
  • 建立符合合规要求的安全控制时
  • 为该领域构建或改进安全架构时
  • 执行需要此实施的安全评估时

前提条件

  • 基于 Linux 的 CI 运行器(AFL++ 不原生支持 Windows)
  • GCC 或 Clang 编译器工具链
  • 已安装 AFL++(apt install aflplusplus 或从源码构建)
  • 目标应用程序具有隔离输入处理的 harness 函数
  • 有效输入样本的种子语料库

核心概念

覆盖率引导模糊测试

AFL++ 在编译时(或对于仅二进制目标通过 QEMU/Frida)对目标二进制文件进行插桩,以跟踪每个输入所执行的代码路径。当变异输入触发新代码路径时,它会被保存到语料库中以供进一步变异。这种反馈循环使 AFL++ 能够系统地探索程序状态空间。

插桩模式
模式使用场景性能
afl-clang-fast (LTO)有源码,最佳性能最高
afl-clang-fast有源码,标准高
afl-gcc-fast基于 GCC 的项目高
QEMU mode仅二进制,无源码中
Frida mode仅二进制,跨平台中
Unicorn mode固件,嵌入式低
持久模式

持久模式通过在循环内进行模糊测试来避免 fork 开销:

#include <unistd.h>

__AFL_FUZZ_INIT();

int main() {
    __AFL_INIT();
    unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;

    while (__AFL_LOOP(10000)) {
        int len = __AFL_FUZZ_TESTCASE_LEN;
        // Process buf[0..len-1]
        parse_input(buf, len);
    }
    return 0;
}

工作流

步骤 1 --- 构建模糊测试 Harness

创建一个将 AFL++ 输入提供给目标函数的 harness:

// fuzz_harness.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "target_parser.h"

__AFL_FUZZ_INIT();

int main() {
    __AFL_INIT();
    unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;

    while (__AFL_LOOP(10000)) {
        int len = __AFL_FUZZ_TESTCASE_LEN;
        if (len < 4) continue;

        // Reset state between iterations
        parser_context_t ctx;
        parser_init(&ctx);
        parser_process(&ctx, buf, len);
        parser_cleanup(&ctx);
    }
    return 0;
}
步骤 2 --- 使用 AFL++ 插桩进行编译
# Standard instrumentation
export CC=afl-clang-fast
export CXX=afl-clang-fast++

# Enable AddressSanitizer for better crash detection
export AFL_USE_ASAN=1

# Build the target with instrumentation
$CC -o fuzz_harness fuzz_harness.c -ltarget_parser -fsanitize=address

# Build a CmpLog binary for better coverage
$CC -o fuzz_harness_cmplog fuzz_harness.c -ltarget_parser \
  -fsanitize=address -DCMPLOG
步骤 3 --- 准备种子语料库
mkdir -p corpus/
# Add valid input samples
cp test_inputs/* corpus/
# Minimize the corpus
afl-cmin -i corpus/ -o corpus_min/ -- ./fuzz_harness @@
# Further minimize individual inputs
mkdir -p corpus_tmin/
for f in corpus_min/*; do
    afl-tmin -i "$f" -o "corpus_tmin/$(basename $f)" -- ./fuzz_harness @@
done
步骤 4 --- 配置 CI/CD 集成

GitHub Actions:

name: Fuzz Testing
on:
  push:
    branches: [main]
  schedule:
    - cron: '0 2 * * *'  # Nightly fuzzing

jobs:
  fuzz:
    runs-on: ubuntu-latest
    timeout-minutes: 120
    steps:
      - uses: actions/checkout@v4

      - name: Install AFL++
        run: |
          sudo apt-get update
          sudo apt-get install -y aflplusplus

      - name: Restore corpus cache
        uses: actions/cache@v4
        with:
          path: corpus/
          key: fuzz-corpus-${{ github.sha }}
          restore-keys: fuzz-corpus-

      - name: Build fuzzing harness
        run: |
          export CC=afl-clang-fast
          export AFL_USE_ASAN=1
          make fuzz_harness

      - name: Run AFL++ fuzzing (CI mode)
        env:
          AFL_CMPLOG_ONLY_NEW: 1
          AFL_FAST_CAL: 1
          AFL_NO_STARTUP_CALIBRATION: 1
        run: |
          mkdir -p findings/
          timeout 7200 afl-fuzz \
            -S ci_fuzzer \
            -i corpus/ \
            -o findings/ \
            -t 5000 \
            -- ./fuzz_harness @@ || true

      - name: Check for crashes
        run: |
          CRASHES=$(find findings/ -path "*/crashes/*" -not -name "README.txt" | wc -l)
          echo "Found $CRASHES unique crashes"
          if [ "$CRASHES" -gt 0 ]; then
            echo "::error::AFL++ found $CRASHES crashes"
            for crash in findings/*/crashes/*; do
              [ -f "$crash" ] && echo "Crash: $crash ($(wc -c < $crash) bytes)"
            done
            exit 1
          fi

      - name: Update corpus cache
        if: always()
        run: |
          afl-cmin -i findings/ci_fuzzer/queue/ -o corpus/ -- ./fuzz_harness @@
步骤 5 --- 用于夜间运行的并行模糊测试
# Launch multiple secondary instances for better coverage
for i in $(seq 1 $(nproc)); do
    afl-fuzz -S fuzzer_$i \
      -i corpus/ \
      -o findings/ \
      -- ./fuzz_harness @@ &
done

# Wait for all fuzzers
wait

# Merge and minimize corpus
afl-cmin -i findings/*/queue/ -o corpus_merged/ -- ./fuzz_harness @@
步骤 6 --- 崩溃分类
# Reproduce and categorize crashes
for crash in findings/*/crashes/*; do
    echo "=== Testing: $crash ==="
    timeout 5 ./fuzz_harness_asan "$crash" 2>&1 | head -20
    echo "---"
done

# Deduplicate crashes by stack trace
afl-collect findings/ crashes_deduped/ -- ./fuzz_harness @@

AFL++ 的 CI/CD 最佳实践

设置CI 短时运行夜间长时运行
持续时间30-60 分钟4-24 小时
模式-S(仅 secondary)-S(CI 不使用 -M)
AFL_CMPLOG_ONLY_NEW11
AFL_FAST_CAL10
AFL_NO_STARTUP_CALIBRATION10
语料库缓存必需必需
并行实例1-2nproc

监控模糊测试活动

# View fuzzing statistics
afl-whatsup findings/

# Key metrics to track:
# - Total paths found (code coverage indicator)
# - Unique crashes / unique hangs
# - Stability percentage (should be >90%)
# - Exec speed (execs/sec)
# - Cycles done (full corpus cycles completed)

参考资料

评论

支持 Markdown