跳到主要内容
知仓学习社ZHICANG

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

Integrates AFL++ coverage-guided fuzzing into CI/CD pipelines, covering harness construction, AFL++/AddressSanitizer/CmpLog instrumentation builds, …

读凭据执行命令读文件写文件严重 0 · 高危 8mukul975/Anthropic-Cybersecurity-Skills

它会碰到什么

扫了多少8 个文本文件,38 KB
它会碰到什么读凭据执行命令读文件写文件
命中总数10 处
命中统计严重 0 · 高 8 · 中 2 · 低 0
逐条看命中(8 条严重或高危)
  • scripts/agent.py:15cred-envread
    env["AFL_HARDEN"] = "1"
  • scripts/agent.py:16exec-spawn
    result = subprocess.run(cmd, capture_output=True, text=True, env=env, timeout=120)
  • scripts/agent.py:49exec-spawn
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
  • scripts/agent.py:62cred-envread
    env["AFL_SKIP_CPUFREQ"] = "1"
  • scripts/agent.py:63cred-envread
    env["AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES"] = "1"
  • scripts/agent.py:64cred-envread
    env["AFL_NO_UI"] = "1"
  • scripts/agent.py:73exec-spawn
    result = subprocess.run(cmd, capture_output=True, text=True, env=env, timeout=duration_seconds + 60)
  • scripts/agent.py:117exec-spawn
    proc = subprocess.run(

这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。

技能内容

Implementing Fuzz Testing in CI/CD with AFL++

Overview

AFL++ (American Fuzzy Lop Plus Plus) is a community-maintained fork of AFL that provides state-of-the-art coverage-guided fuzz testing for discovering vulnerabilities in compiled applications. AFL++ uses genetic algorithms to mutate inputs, tracking code coverage to find new execution paths that trigger crashes, hangs, and undefined behavior. In CI/CD environments, AFL++ can be integrated to continuously test parsers, protocol handlers, file format processors, and any code that handles untrusted input. AFL++ supports persistent mode for high-speed fuzzing (up to 100,000+ executions per second), custom mutators, QEMU mode for binary-only fuzzing, and CmpLog/RedQueen for automatic dictionary extraction.

When to Use

  • When deploying or configuring implementing fuzz testing in cicd with aflplusplus capabilities in your environment
  • When establishing security controls aligned to compliance requirements
  • When building or improving security architecture for this domain
  • When conducting security assessments that require this implementation

Prerequisites

  • Linux-based CI runners (AFL++ does not support Windows natively)
  • GCC or Clang compiler toolchain
  • AFL++ installed (apt install aflplusplus or built from source)
  • Target application with harness functions isolating input processing
  • Seed corpus of valid input samples

Core Concepts

Coverage-Guided Fuzzing

AFL++ instruments the target binary at compile time (or via QEMU/Frida for binary-only targets) to track which code paths each input exercises. When a mutated input triggers a new code path, it is saved to the corpus for further mutation. This feedback loop enables AFL++ to systematically explore program state space.

Instrumentation Modes

| Mode | Use Case | Performance |

|------|----------|-------------|

| afl-clang-fast (LTO) | Source available, best performance | Highest |

| afl-clang-fast | Source available, standard | High |

| afl-gcc-fast | GCC-based projects | High |

| QEMU mode | Binary-only, no source | Medium |

| Frida mode | Binary-only, cross-platform | Medium |

| Unicorn mode | Firmware, embedded | Low |

Persistent Mode

Persistent mode avoids fork overhead by fuzzing within a loop:

#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;
}

Workflow

Step 1 --- Build the Fuzzing Harness

Create a harness that feeds AFL++ input to the target function:

// 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;
}

Step 2 --- Compile with AFL++ Instrumentation

# 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

Step 3 --- Prepare Seed Corpus

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

Step 4 --- Configure CI/CD Integration

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 @@

Step 5 --- Parallel Fuzzing for Nightly Runs

# 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 @@

Step 6 --- Crash Triage

# 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 @@

CI/CD Best Practices for AFL++

| Setting | CI Short Run | Nightly Long Run |

|---------|-------------|-----------------|

| Duration | 30-60 min | 4-24 hours |

| Mode | -S (secondary only) | -S (no -M for CI) |

| AFL_CMPLOG_ONLY_NEW | 1 | 1 |

| AFL_FAST_CAL | 1 | 0 |

| AFL_NO_STARTUP_CALIBRATION | 1 | 0 |

| Corpus caching | Required | Required |

| Parallel instances | 1-2 | nproc |

Monitoring Fuzzing Campaigns

# 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)

References

想直接用这个技能?

本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。