A structure-aware HTTP fuzzing library

Overview


๐Ÿš€ FeroxFuzz ๐Ÿš€

A structure-aware HTTP fuzzing library


๐Ÿค” Another ferox? why? ๐Ÿค”

Chill, it's not another command-line tool, this one's a library! ๐Ÿ˜

More specifically, FeroxFuzz is a structure-aware HTTP fuzzing library.

The primary goal in writing FeroxFuzz was to move some core pieces out of feroxbuster and into a place where they could be generally useful for other folks. In so doing, my hope is that anyone who wants to write web tooling and/or one-off web fuzzers in Rust, can do so with minimal effort.

Design

FeroxFuzz's overall design is derived from LibAFL. FeroxFuzz implements most of the components listed in LibAFL: A Framework to Build Modular and Reusable Fuzzers (pre-print). When FeroxFuzz deviates, it's typically due to supporting async code.

Similar to LibAFL, FeroxFuzz is a composable fuzzing library. However, unlike LibAFL, FeroxFuzz is solely focused on black box HTTP fuzzing.

Fuzz-loop execution flow

Below is a visual depiction of the different components, hooks, and control flow employed by FeroxFuzz.

fuzz-flow

๐Ÿšง Warning: Under Construction ๐Ÿšง

FeroxFuzz is very capable, and was made to suit all of my planned needs for a new feroxbuster. However, I still expect FeroxFuzz's API to change, at least slightly, as work on the new version of feroxbuster begins.

Until the API solidifies, breaking changes may will occur.

Getting Started

The easiest way to get started is to include FeroxFuzz in your project's Cargo.toml.

[dependencies]
feroxfuzz = { version = "1.0.0-rc.2" }

Docs

In addition to the examples/ folder, the API docs have extensive documentation of components along with examples of their use.

  • FeroxFuzz API Docs: FeroxFuzz's API docs, which are automatically generated from the doc comments in this repo.
  • Official Examples: FeroxFuzz's dedicated, runnable examples, which are great for digging into specific concepts and are heavily commented.

Example

The example below (examples/async-simple.rs) shows the bare minimum to write a fuzzer using FeroxFuzz.

If using the source, the example can be run from the feroxfuzz/ directory using the following command:

note: unless you have a webserver running on your machine @ port 8000, you'll need to change the target passed in Request::from_url

cargo run --example async-simple
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // create a new corpus from the given list of words
    let words = Wordlist::from_file("./examples/words")?
        .name("words")
        .build();

    // pass the corpus to the state object, which will be shared between all of the fuzzers and processors
    let mut state = SharedState::with_corpus(words);

    // bring-your-own client, this example uses the reqwest library
    let req_client = reqwest::Client::builder().build()?;

    // with some client that can handle the actual http request/response stuff
    // we can build a feroxfuzz client, specifically an asynchronous client in this
    // instance.
    //
    // feroxfuzz provides both a blocking and an asynchronous client implementation
    // using reqwest. 
    let client = AsyncClient::with_client(req_client);

    // ReplaceKeyword mutators operate similar to how ffuf/wfuzz work, in that they'll
    // put the current corpus item wherever the keyword is found, as long as its found
    // in data marked fuzzable (see ShouldFuzz directives below)
    let mutator = ReplaceKeyword::new(&"FUZZ", "words");

    // fuzz directives control which parts of the request should be fuzzed
    // anything not marked fuzzable is considered to be static and won't be mutated
    //
    // ShouldFuzz directives map to the various components of an HTTP request
    let request = Request::from_url(
        "http://localhost:8000/?admin=FUZZ",
        Some(&[ShouldFuzz::URLParameterValues]),
    )?;

    // a `StatusCodeDecider` provides a way to inspect each response's status code and decide upon some Action
    // based on the result of whatever comparison function (closure) is passed to the StatusCodeDecider's
    // constructor
    //
    // in plain english, the `StatusCodeDecider` below will check to see if the request's http response code
    // received is equal to 200/OK. If the response code is 200, then the decider will recommend the `Keep`
    // action be performed. If the response code is anything other than 200, then the recommendation will
    // be to `Discard` the response.
    //
    // `Keep`ing the response means that the response will be allowed to continue on for further processing
    // later in the fuzz loop.
    let decider = StatusCodeDecider::new(200, |status, observed, _state| {
        if status == observed {
            Action::Keep
        } else {
            Action::Discard
        }
    });

    // a `ResponseObserver` is responsible for gathering information from each response and providing
    // that information to later fuzzing components, like Processors. It knows things like the response's
    // status code, content length, the time it took to receive the response, and a bunch of other stuff.
    let response_observer: ResponseObserver<AsyncResponse> = ResponseObserver::new();

    // a `ResponseProcessor` provides access to the fuzzer's instance of `ResponseObserver`
    // as well as the `Action` returned from calling `Deciders` (like the `StatusCodeDecider` above).
    // Those two objects may be used to produce side-effects, such as printing, logging, calling out to
    // some other service, or whatever else you can think of.
    let response_printer = ResponseProcessor::new(
        |response_observer: &ResponseObserver<AsyncResponse>, action, _state| {
            if let Some(Action::Keep) = action {
                println!(
                    "[{}] {} - {} - {:?}",
                    response_observer.status_code(),
                    response_observer.content_length(),
                    response_observer.url(),
                    response_observer.elapsed()
                );
            }
        },
    );

    // `Scheduler`s manage how the fuzzer gets entries from the corpus. The `OrderedScheduler` provides
    // in-order access of the associated `Corpus` (`Wordlist` in this example's case)
    let scheduler = OrderedScheduler::new(state.clone())?;

    // the macro calls below are essentially boilerplate. Whatever observers, deciders, mutators,
    // and processors you want to use, you simply pass them to the appropriate macro call and
    // eventually to the Fuzzer constructor.
    let deciders = build_deciders!(decider);
    let mutators = build_mutators!(mutator);
    let observers = build_observers!(response_observer);
    let processors = build_processors!(response_printer);

    let threads = 40;  // number of threads to use for the fuzzing process

    // the `Fuzzer` is the main component of the feroxfuzz library. It wraps most of the other components 
    // and takes care of the actual fuzzing process.
    let mut fuzzer = AsyncFuzzer::new(
        threads, client, request, scheduler, mutators, observers, processors, deciders,
    );

    // the fuzzer will run until it iterates over the entire corpus once
    fuzzer.fuzz_once(&mut state).await?;

    println!("{state:#}");

    Ok(())
}

The fuzzer above would produce something similar to what's shown below.

[200] 815 - http://localhost:8000/?admin=Ajax - 840.985ยตs
[200] 206 - http://localhost:8000/?admin=Al - 4.092037ms
----8<----
SharedState::{
  Seed=24301
  Rng=RomuDuoJrRand { x_state: 97704, y_state: 403063 }
  Corpus[words]=Wordlist::{len=102774, top-3=[Static("A"), Static("A's"), Static("AMD")]},
  Statistics={"timeouts":0,"requests":102774.0,"errors":44208,"informatives":3626,"successes":29231,"redirects":25709,"client_errors":18195,"server_errors":26013,"redirection_errors":0,"connection_errors":0,"request_errors":0,"start_time":{"secs":1662124648,"nanos":810398280},"avg_reqs_per_sec":5946.646301595066,"statuses":{"500":14890,"201":3641,"307":3656,"203":3562,"101":3626,"401":3625,"207":3711,"308":3578,"300":3724,"404":3705,"301":3707,"302":3651,"304":3706,"502":3682,"402":3636,"200":3718,"503":3762,"400":3585,"501":3679,"202":3659,"205":3680,"206":3676,"204":3584,"403":3644,"303":3687}}
}

๐Ÿค“ Projects using FeroxFuzz ๐Ÿค“


chameleon

Contributors โœจ

Thanks goes to these wonderful people (emoji key):


iustin24

๐Ÿ’ป

andreademurtas

๐Ÿ’ป

This project follows the all-contributors specification. Contributions of any kind welcome!

You might also like...
HTTP mocking for Rust!
HTTP mocking for Rust!

HTTP mocking for Rust! Get it on crates.io

Verdun is a HTTP stress-test/benchmark tool written in Rust.
Verdun is a HTTP stress-test/benchmark tool written in Rust.

Verdun is a HTTP stress-test/benchmark tool written in Rust. ๐Ÿฆ€ It supports testing a single URL, loading multiples URLs from a file or automatically navigating a website (auto discovery)

hb is an endpoint focused HTTP load testing / benchmark tool.

hb hb is an endpoint focused HTTP load testing / benchmark tool. Description The goal of hb is to provide a simple, robust tool to apply load against

Playwright is a rust library to automate Chromium, Firefox and WebKit built on top of Node.js library.

๐ŸŽญ Playwright for Rust Playwright is a rust library to automate Chromium, Firefox and WebKit built on top of Node.js library. Installation [dependenci

A library for generating fake data in Rust.

Fake A Rust library for generating fake data. Installation Default (rand is required): [dependencies] fake = "2.4" rand = "0.8" If you want to use #[d

QuickCheck bug hunting in Rust standard library data structures

BugHunt, Rust This project is aiming to provide "stateful" QuickCheck models for Rust's standard library. That is, we build up a random list of operat

Simple assertion library for unit testing in python with a fluent API

Simple assertions library for unit testing in Python with a nice fluent API. Supports both Python 2 and 3.

A tiny, super simple and portable benchmarking library.

benchmark-simple A tiny benchmarking library for Rust. Trivial to use Works pretty much everywhere, including WebAssembly (WASI, but also in-browser)

This is a tiny (but delightful!) utility library for exhaustive testing.

Exhaustigen This is a tiny (but delightful!) utility library for exhaustive testing. It is based (directly) on the idea and code in the following blog

Comments
  • allow for an explicitly empty corpus

    allow for an explicitly empty corpus

    capturing an old TODO as an issue

        // todo should probably allow for an explicitly empty corpus that can be used as a solutions corpus...
        // rn, it limits the number of iterations to the length of the corpus and the typestate build won't allow
        // it to be empty
    
    opened by epi052 0
Releases(v1.0.0-rc.6)
  • v1.0.0-rc.6(Dec 1, 2022)

    What's Changed

    • fixed up type oversight in request processor

    Full Changelog: https://github.com/epi052/feroxfuzz/compare/v1.0.0-rc.5...v1.0.0-rc.6

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-rc.5(Dec 1, 2022)

    What's Changed

    • added dynamic dispatch to Processors by @epi052 in https://github.com/epi052/feroxfuzz/pull/16
    • added typesafe builder pattern for fuzzer construction by @epi052 in https://github.com/epi052/feroxfuzz/pull/16
    • added pre-loop / post-loop hooks to fuzzers by @epi052 in https://github.com/epi052/feroxfuzz/pull/16
    • implemented Named for most components by @epi052 in https://github.com/epi052/feroxfuzz/pull/16
    • RandomScheduler can operate on a subset of corpora, instead of only all corpora by @epi052 in https://github.com/epi052/feroxfuzz/pull/16
    • SharedState can add a Corpus after being instantiated by @epi052 in https://github.com/epi052/feroxfuzz/pull/16

    Full Changelog: https://github.com/epi052/feroxfuzz/compare/v1.0.0-rc.4...v1.0.0-rc.5

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-rc.4(Nov 24, 2022)

    What's Changed

    • added action traking in stats by @epi052 in https://github.com/epi052/feroxfuzz/pull/15

    Full Changelog: https://github.com/epi052/feroxfuzz/compare/v1.0.0-rc.3...v1.0.0-rc.4

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-rc.3(Nov 23, 2022)

    What's Changed

    • fixed http method builder return type by @epi052 in https://github.com/epi052/feroxfuzz/pull/12
    • added api calls for multiple methods during HttpMethodsCorpus build by @epi052 in https://github.com/epi052/feroxfuzz/pull/13
    • added pub/sub event system by @epi052 in https://github.com/epi052/feroxfuzz/pull/14

    Full Changelog: https://github.com/epi052/feroxfuzz/compare/v1.0.0-rc.2...v1.0.0-rc.3

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-rc.2(Oct 14, 2022)

    What's Changed

    • improved api for malformed urls by @epi052 in https://github.com/epi052/feroxfuzz/pull/11

    Full Changelog: https://github.com/epi052/feroxfuzz/compare/v1.0.0-rc.1...v1.0.0-rc.2

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-rc.1(Oct 10, 2022)

    What's Changed

    • added a Content Length Decider by @iustin24 in https://github.com/epi052/feroxfuzz/pull/5
    • added ability to do dynamic dispatch with Deciders by @epi052 in https://github.com/epi052/feroxfuzz/pull/3
    • added ability to do dynamic dispatch with Mutators by @epi052 in https://github.com/epi052/feroxfuzz/pull/7
    • added ability to use an explicitly empty corpus by @andreademurtas in https://github.com/epi052/feroxfuzz/pull/8
    • added an Action to stop fuzzing by @epi052 in https://github.com/epi052/feroxfuzz/pull/10
    • fixed version from 0.1.0 to 1.0.0 as when the rc status is removed, we'll be at 1.0.0

    New Contributors

    • @iustin24 made their first contribution in https://github.com/epi052/feroxfuzz/pull/5
    • @andreademurtas made their first contribution in https://github.com/epi052/feroxfuzz/pull/8

    Full Changelog: https://github.com/epi052/feroxfuzz/compare/v0.1.0-rc.0...1.0.0-rc.1

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0-rc.0(Sep 3, 2022)

Owner
epi
epi
Hopper is a tool for generating fuzzing test cases for libraries automatically using interpretative fuzzing.

Hopper Hopper is an tool for generating fuzzing test cases for libraries automatically using interpretative fuzzing. It transforms the problem of libr

FuzzAnything 118 Nov 15, 2023
Hopper is a tool for generating fuzzing test cases for libraries automatically using interpretative fuzzing.

Hopper Hopper is an tool for generating fuzzing test cases for libraries automatically using interpretative fuzzing. It transforms the problem of libr

FuzzAnything 124 Nov 24, 2023
Advanced Fuzzing Library - Slot your Fuzzer together in Rust! Scales across cores and machines. For Windows, Android, MacOS, Linux, no_std, ...

LibAFL, the fuzzer library. Advanced Fuzzing Library - Slot your own fuzzers together and extend their features using Rust. LibAFL is written and main

Advanced Fuzzing League ++ 1.2k Dec 29, 2022
๐Ÿ‡ Fuzzing Rust code with American Fuzzy Lop

afl.rs Fuzzing Rust code with AFLplusplus What is it? Fuzz testing is a software testing technique used to find security and stability issues by provi

Rust Fuzzing Authority 1.3k Jan 5, 2023
A self-hosted Fuzzing-As-A-Service platform

OneFuzz A self-hosted Fuzzing-As-A-Service platform Project OneFuzz enables continuous developer-driven fuzzing to proactively harden software prior t

Microsoft 2.6k Dec 30, 2022
An example fuzzer about how to fuzz a JS engine combinign Nautilus with Token-level fuzzing

LibAFL QuickJS Fuzzing Example An example fuzzer about how to fuzz a JS engine combinign Nautilus with Token-level fuzzing. Prepare Make sure to have

Andrea Fioraldi 32 Dec 21, 2022
Pre-Silicon Hardware Fuzzing Toolkit

Disclaimer All components are provided for research and validation purposes only. Use at your own risk. Pre-Silicon Hardware Fuzzing Toolkit From CPU

Intel Labs 12 Dec 13, 2022
ยตFUZZ: Redesign of Parallel Fuzzing using Microservice Architecture

mufuzz, a parallel fuzzing framework TODO: Add reference Build Install cargo and protoc curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Software Systems Security Team at Penn State University 7 May 15, 2023
HTTP mocking library for Rust.

httpmock HTTP mocking library for Rust. Documentation ยท Crate ยท Report Bug ยท Request Feature ยท Changelog Features Simple, expressive, fluent API. Many

Alexander Liesenfeld 320 Dec 21, 2022
Drill is an HTTP load testing application written in Rust inspired by Ansible syntax

Drill is an HTTP load testing application written in Rust inspired by Ansible syntax

Ferran Basora 1.5k Jan 1, 2023