Black-box fuzzer that fuzzes APIs based on OpenAPI specification. Find bugs for free!

Overview

OpenAPI fuzzer

ci

Black-box fuzzer that fuzzes APIs based on OpenAPI specification. All you need to do is to supply URL of the API and its specification. Find bugs for free!

demo

Findings

The fuzzer has been used to find bugs in numerous software. Some of the well-known fuzzed software include1:

The category of bugs differ, but some of the common are parsing bugs, invalid format bugs and querying non-existent entities. If you have found bugs with this fuzzer, please reach out to me. I would love to hear from you. Feel free to submit a PR and add your finding to the list above.

Building & installing

To build the fuzzer, you will need to have rust installed.

# Install from crates.io
cargo install openapi-fuzzer

# Or download the repo and build locally
git clone [email protected]:matusf/openapi-fuzzer.git
cd openapi-fuzzer

# Install to the $PATH
cargo install --path .

# Or build (add --releade to build optimized binary) inside the repo
cargo build

Usage

After installation you will have two binaries, openapi-fuzzer and openapi-fuzzer-resender. The openapi-fuzzer will fuzz the API according to the specification and report any findings. All findings will be located in a results directory in a JSON format. After you are done with fuzzing, you can use openapi-fuzzer-resender to resend payloads that triggered a bugs and examine the cause in depth.

Tips

  • When the fuzzer receives an unexpected status code, it will report is as a finding. However, many APIs do not specify client error status codes in the specification. To minimize false positive findings ignore status codes that you are not interested in with -i flag. It is adviced to fuzz it two stages. Firstly, run the fuzzer without -i flag for a minute. Then check results folder for the reported findings. If there are reports from status codes you do not care about, add them via -i flag and rerun the fuzzer.
  • Most APIs use some base prefix for endpoints like /v1 or /api, however, the specifications are sometimes writen without it. Do not forget to include the path prefix in the url.
  • You may add an extra header with -H flag. It may be useful when you would like to increase coverage by providing some sort of authorization.
$ openapi-fuzzer --help
Usage: openapi-fuzzer -s <spec> -u <url> [-i <ignore-status-code>] [-H <header>]

OpenAPI fuzzer

Options:
  -s, --spec        path to OpenAPI specification
  -u, --url         url of api to fuzz
  -i, --ignore-status-code
                    status codes that will not be considered as finding
  -H, --header      additional header to send
  --help            display usage information


$ openapi-fuzzer -s spec.yaml -u http://127.0.0.1:8200/v1/ -i 404

Replaying findings

When you are done fuzzing you can replay the findings. All findings are stored in the results folder in path according to finding's endpoint and method. To resend the same payload to API, you simply run openapi-fuzzer-resender with path to the finding file as an argument. You can overwrite the headers with -H flag as well, which is useful for example, when the authorization token expired.

$ tree -L 3 results/
results/
├── sys-leases-renew
│   └── POST
│       └── 500
└── sys-seal
    └── POST
        └── 500

$ openapi-fuzzer-resender --help
Usage: openapi-fuzzer-resender <file> [-H <header>]

Resender of openapi-fuzzer results

Options:
  -H, --header      extra header
  --help            display usage information

$ openapi-fuzzer-resender results/sys-seal/POST/500/1b4e8a77.json
Response[status: 500, status_text: Internal Server Error, url: http://127.0.0.1:8200/v1/sys/seal]
{"errors":["1 error occurred: * missing client token"]}

Future plans

  • Add script for minimization of the findings

Footnotes

  1. not all found bugs are linked

Comments
  • compile errors when installing from crates.io

    compile errors when installing from crates.io

    I'm trying to install this from crates.io with Cargo. When building however it exits with the following error lines:

    [...]
       Compiling rustls v0.20.1
       Compiling webpki-roots v0.22.1
       Compiling url v2.2.2
       Compiling serde_yaml v0.8.21
       Compiling ureq v2.3.1
       Compiling openapiv3 v0.5.0
       Compiling openapiv3 v0.3.2
       Compiling openapi_utils v0.2.2
       Compiling openapi-fuzzer v0.1.1
    error[E0599]: no method named `to_item_ref` found for reference `&ReferenceOr<PathItem>` in the current scope
      --> /Users/xvilo/.cargo/registry/src/github.com-1ecc6299db9ec823/openapi-fuzzer-0.1.1/src/fuzzer.rs:96:40
       |
    96 |                 let item = ref_or_item.to_item_ref();
       |                                        ^^^^^^^^^^^ method not found in `&ReferenceOr<PathItem>`
    
    error[E0599]: no method named `to_item_ref` found for reference `&ReferenceOr<Box<openapiv3::Schema>>` in the current scope
      --> /Users/xvilo/.cargo/registry/src/github.com-1ecc6299db9ec823/openapi-fuzzer-0.1.1/src/payload.rs:29:35
       |
    29 |         let schema_kind = &schema.to_item_ref().schema_kind;
       |                                   ^^^^^^^^^^^ method not found in `&ReferenceOr<Box<openapiv3::Schema>>`
    
    error[E0599]: no method named `to_item_ref` found for enum `ReferenceOr` in the current scope
      --> /Users/xvilo/.cargo/registry/src/github.com-1ecc6299db9ec823/openapi-fuzzer-0.1.1/src/payload.rs:36:29
       |
    36 |     let items = array.items.to_item_ref();
       |                             ^^^^^^^^^^^ method not found in `ReferenceOr<Box<openapiv3::Schema>>`
    
    error[E0599]: no method named `to_item_ref` found for reference `&ReferenceOr<Parameter>` in the current scope
      --> /Users/xvilo/.cargo/registry/src/github.com-1ecc6299db9ec823/openapi-fuzzer-0.1.1/src/payload.rs:89:32
       |
    89 |             match ref_or_param.to_item_ref() {
       |                                ^^^^^^^^^^^ method not found in `&ReferenceOr<Parameter>`
    
    error[E0599]: no method named `to_item_ref` found for reference `&ReferenceOr<RequestBody>` in the current scope
       --> /Users/xvilo/.cargo/registry/src/github.com-1ecc6299db9ec823/openapi-fuzzer-0.1.1/src/payload.rs:106:44
        |
    106 |             let request_body = ref_or_body.to_item_ref();
        |                                            ^^^^^^^^^^^ method not found in `&ReferenceOr<RequestBody>`
    
    error[E0599]: no method named `deref_all` found for struct `OpenAPI` in the current scope
      --> /Users/xvilo/.cargo/registry/src/github.com-1ecc6299db9ec823/openapi-fuzzer-0.1.1/src/main.rs:83:41
       |
    83 |     let openapi_schema = openapi_schema.deref_all();
       |                                         ^^^^^^^^^ method not found in `OpenAPI`
    
    For more information about this error, try `rustc --explain E0599`.
    error: could not compile `openapi-fuzzer` due to 6 previous errors
    warning: build failed, waiting for other jobs to finish...
    error: failed to compile `openapi-fuzzer v0.1.1`, intermediate artifacts can be found at `/var/folders/0y/42sfx52d50d3g62rxgf9rsxm0000gn/T/cargo-installEUuSl7`
    
    Caused by:
      build failed
    Error: `cargo install` didn't work either. Looks like you're on your own.
    

    I have no experience with this, so I would appreciate some help. I noticed there are no tagged versions, so could it be the case that the current version on master is broken?

    Environment

    • Intel MacBook Pro (2020)
    • macOS Monterey (build 21A559)
    • Cargo version 1.56.0
    • Rustc version 1.56.1
    opened by xvilo 7
  • Error: No such file or directory (os error 2)

    Error: No such file or directory (os error 2)

    I tried running docker run --rm -it rust

    Then running cargo install openapi-fuzzer

    Then running openapi-fuzzer --url http://localhost/swagger --spec http://localhost/swagger/v1/swagger.json

    But I just get back Error: No such file or directory (os error 2)

    ...Not particularly helpful, but I'm not sure where to go from here. As far as I can tell I'm doing what the docs said to do.

    opened by snow-jallen 3
  • Allow multiple HTTP codes to be ignored

    Allow multiple HTTP codes to be ignored

    Currently, it looks like only one can be ignored per run

    $ ./openapi-fuzzer --spec spec.json -u http://127.0.0.1/ -i 403,404
    Error parsing option '-i' with value '403,404': invalid digit found in string
    
    opened by opsdisk 2
  • Mention OpenAPI specification version in README

    Mention OpenAPI specification version in README

    Hi,

    Not much of an issue really, but it would be helpful I think. My webservers generate OpenAPI v2 specifications, which I tried feeding into this program, which didn't go too well. After some thinking I converted it to an OpenAPPI v3 spec, which did work.

    It might be worth to mention the following in the README:

    • OpenAPI v3 is required
    • Whether JSON or YAML should be used, I only tried YAML thusfar

    If wanted, I can open a PR for this. Thanks!

    opened by TobiasDeBruijn 2
  • Report errors based on status codes defined in OpenAPI

    Report errors based on status codes defined in OpenAPI

    Most of the existing fuzzers consider only 500 status codes as a failure. However, given the OpenAPI schema we can check the expected status codes and thus report any unexpected one.

    opened by matusf 0
  • rtls 'Failed to add native certificate too root store: UnsupportedCriticalExtension' main thread panic

    rtls 'Failed to add native certificate too root store: UnsupportedCriticalExtension' main thread panic

    Hi!

    I'm trying to fuzz a public yaml: https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.0/petstore.yaml with endpoint here https://petstore.swagger.io/v2

    however, it fails with message (running with RUST_BACKTRACE=1)

    $ openapi-fuzzer -s petstore.yaml -u https://petstore.swagger.io/v2/
    
    thread 'main' panicked at 'Failed to add native certificate too root store: UnsupportedCriticalExtension', C:\Users\Finicu\.cargo\registry\src\github.com-1ecc6299db9ec823\ureq-2.5.0\src\rtls.rs:74:14
    stack backtrace:
       0:     0x7ff71a9da9ef - <unknown>
         ... (other <unknown> threads) ...
      22:     0x7ff71aa0515c - <unknown>
      23:     0x7ffaece27034 - BaseThreadInitThunk
      24:     0x7ffaeec82651 - RtlUserThreadStart
    

    Any idea what could be causing this? Thanks!

    openapi-fuzzer was installed via cargo $ cargo install openapi-fuzzer ( openapi-fuzzer v0.1.3 )

    opened by finicu212 0
  • Feature request: Fetch spec from URL

    Feature request: Fetch spec from URL

    Hi, awesome tool :+1:

    Would it be possible to implement a feature where the OpenApi spec where fetched from URL?

    For example; I'm using FastAPI for my API, which has an integrated spec generator that is served at /openapi.json. It's easy enough to curl this url, save to a file, and run the tool as usual. But just being able to do; openapi-fuzzer --spec http://localhost/openapi.json would be nice.

    opened by soofstad 0
  • Automatic payload generation from responses

    Automatic payload generation from responses

    I was wondering if the fuzzer was only generating random payloads from the spec, or was it able to reuse responses from the easy requests (ones that don't require a parameter) This would really improve the drilling in complex paths, otherwise it will only hit 404 or 403 for non-existing/non-authorized resources (unless there is an IDOR vulnerability or the authentication allows you to get any value)

    It's less like raw fuzzing, but smarter and maybe more efficient. I built something similar in python so maybe I could try in rust

    opened by Gby56 2
  • Feature Request: Store all Request

    Feature Request: Store all Request

    In some cases i`m interested in 404 or 200 responses. A flag would be great to tell the fuzzer to store all requests or (like the -i flag) to specify the response code which should be stored.

    Is this an edge case, or could this be beneficial to bigger a audience?

    opened by tandarim 2
  • thread 'main' panicked at 'called `Option::unwrap()` on a `None` value'

    thread 'main' panicked at 'called `Option::unwrap()` on a `None` value'

    Hello! I tried to use this project to fuzz my API and it crashed. Here is the backtrace:

    $ RUST_BACKTRACE=1 openapi-fuzzer -s spec-api.yaml -u https://test.local/api/v1
    thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', /home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/openapi_utils-0.2.2/src/dereferer.rs:82:56
    stack backtrace:
       0: rust_begin_unwind
                 at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:493:5
       1: core::panicking::panic_fmt
                 at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/panicking.rs:92:14
       2: core::panicking::panic
                 at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/panicking.rs:50:5
       3: openapi_utils::dereferer::deref_everything_in_path
       4: <openapiv3::openapi::OpenAPI as openapi_utils::dereferer::SpecExt>::deref_all
       5: openapi_fuzzer::main
    note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
    
    opened by xmunoz 3
  • Panic on main thread (`No Reference found`)

    Panic on main thread (`No Reference found`)

    When trying to run the fuzzer with the following options:

    RUST_BACKTRACE=1 openapi-fuzzer -s dist/bundled.json -u https://api.somehost.com
    

    I will get the following output

    thread 'main' panicked at 'No Reference found!: ReferenceError { name: "400" }', /Users/xvilo/.cargo/registry/src/github.com-1ecc6299db9ec823/openapi_utils-0.2.2/src/dereferer.rs:161:63
    stack backtrace:
       0: _rust_begin_unwind
       1: core::panicking::panic_fmt
       2: core::result::unwrap_failed
       3: openapi_utils::dereferer::deref_everything_in_path
       4: <openapiv3::openapi::OpenAPI as openapi_utils::dereferer::SpecExt>::deref_all
       5: openapi_fuzzer::main
    note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
    

    Full backtrace

    thread 'main' panicked at 'No Reference found!: ReferenceError { name: "400" }', /Users/xvilo/.cargo/registry/src/github.com-1ecc6299db9ec823/openapi_utils-0.2.2/src/dereferer.rs:161:63
    stack backtrace:
       0:        0x103a8530a - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h269eb561a1b20dd5
       1:        0x103ab311b - core::fmt::write::h7b05e3902e6336ad
       2:        0x103a7a8ba - std::io::Write::write_fmt::h842f6e8e90a0f75d
       3:        0x103a7b955 - std::panicking::default_hook::{{closure}}::h29848b594b0f958e
       4:        0x103a7b52e - std::panicking::default_hook::h8d763c56718ff5ea
       5:        0x103a7c002 - std::panicking::rust_panic_with_hook::hcaf53ab3fe2e7772
       6:        0x103a8590e - std::panicking::begin_panic_handler::{{closure}}::hd3ae1107ade7d1ce
       7:        0x103a85467 - std::sys_common::backtrace::__rust_end_short_backtrace::hdd495b645c18f633
       8:        0x103a7ba43 - _rust_begin_unwind
       9:        0x103acb70f - core::panicking::panic_fmt::hc3d172c021afebe6
      10:        0x103acbdf5 - core::result::unwrap_failed::h5047fe6f720b213d
      11:        0x103a5192a - openapi_utils::dereferer::deref_everything_in_path::h72e7296ee79b38a7
      12:        0x103a5f73f - <openapiv3::openapi::OpenAPI as openapi_utils::dereferer::SpecExt>::deref_all::h181a287db7120bd6
      13:        0x1038d180b - openapi_fuzzer::main::h52c229988ee7a094
      14:        0x103900ae6 - std::sys_common::backtrace::__rust_begin_short_backtrace::he28581362e115688
      15:        0x1038c52c1 - std::rt::lang_start::{{closure}}::h69a42237a09c6143
      16:        0x103a85985 - std::rt::lang_start_internal::hfb267ddb37513000
      17:        0x1038d4f89 - _main
    

    Environment

    • Intel MacBook Pro (2020)
    • macOS Monterey (build 21A559)
    • Cargo version 1.56.0
    • Rustc version 1.56.1
    opened by xvilo 1
Owner
Matúš Ferech
I fold pancakes in O(log(n))
Matúš Ferech
Fuzzer to automatically find side-channel (timing) vulnerabilities

SideFuzz: Fuzzing for side-channel vulnerabilities SideFuzz is an adaptive fuzzer that uses a genetic-algorithm optimizer in combination with t-statis

PHAYES 94 Sep 29, 2022
a grammar based feedback fuzzer

Nautilus NOTE: THIS IS AN OUTDATE REPOSITORY, THE CURRENT RELEASE IS AVAILABLE HERE. THIS REPO ONLY SERVES AS A REFERENCE FOR THE PAPER Nautilus is a

Chair for Sys­tems Se­cu­ri­ty 157 Oct 26, 2022
Rewind is a snapshot-based coverage-guided fuzzer targeting Windows kernel components.

Rewind is a snapshot-based coverage-guided fuzzer targeting Windows kernel components.

Quarkslab 259 Dec 26, 2022
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
A fuzzer framework built in Rust

lain This crate provides functionality one may find useful while developing a fuzzer. A recent nightly Rust build is required for the specialization f

Microsoft 469 Dec 9, 2022
A symbolic-model-guided fuzzer for TLS

tlspuffin TLS Protocol Under FuzzINg A symbolic-model-guided fuzzer for TLS Master Thesis | Thesis Presentation | Documentation Description Fuzzing im

null 69 Dec 20, 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
StdFuzzer - StdFuzzer is the reference implementation of a generic bit-level fuzzer with LibAFL

StdFuzzer StdFuzzer is the reference implementation of a generic bit-level fuzzer with LibAFL Building Build with $ cargo build --release Compiling a

Advanced Fuzzing League ++ 41 Sep 7, 2022
A fuzzer setup to fuzz libc functions.

libc-fuzzer This does what it sounds like! It attempts to, as automatically as possible, generate and run fuzzers for up to the entire set of libc (in

null 9 Nov 30, 2022
A snapshotting, coverage-guided fuzzer for software (UEFI, Kernel, firmware, BIOS) built on SIMICS

TSFFS: Target Software Fuzzer For SIMICS TSFFS is a snapshotting, coverage-guided fuzzer built on the SIMICS full system simulator. TSFFS makes it eas

Intel Corporation 194 Oct 9, 2023
A fast Rust-based safe and thead-friendly grammar-based fuzz generator

Intro fzero is a grammar-based fuzzer that generates a Rust application inspired by the paper "Building Fast Fuzzers" by Rahul Gopinath and Andreas Ze

null 203 Nov 9, 2022
A minimalist property-based testing library based on the arbitrary crate.

A minimalist property-based testing library based on the arbitrary crate.

Aleksey Kladov 61 Dec 21, 2022
ArchTest is a rule based architecture testing tool for rust

ArchTest is a rule based architecture testing tool. It applies static analyses on the specified rust project to extract use relationships.

Tom Dymel 7 Sep 26, 2021
Automated property based testing for Rust (with shrinking).

quickcheck QuickCheck is a way to do property based testing using randomly generated input. This crate comes with the ability to randomly generate and

Andrew Gallant 2k Jan 2, 2023
Test for rust-based plugin system for swc

rust-dylib-test Steps Run cargo build in plugin_a Ensure that plugin_a dynamically links to runtime/common by otool -L plugin_a/target/debug/libplugin

Donny/강동윤 1 Apr 6, 2022
Fixture-based test framework for Rust

Fixture-based test framework for Rust Introduction rstest uses procedural macros to help you on writing fixtures and table-based tests. To use it, add

Michele d'Amico 567 Dec 24, 2022
Easy-to-use grammar-based black-box fuzzer. Has found dozens of bugs in important targets like Clang, Deno, and rustc.

tree-crasher tree-crasher is an easy-to-use grammar-based black-box fuzzer. It parses a number of input files using tree-sitter grammars, and produces

Langston Barrett 5 Mar 28, 2023
Black-box integration tests for your REST API using the Rust and its test framework

restest Black-box integration test for REST APIs in Rust. This crate provides the [assert_api] macro that allows to declaratively test, given a certai

IOmentum 10 Nov 23, 2022
A black-box raw calldata decoder using only calldata to guess types and parse parameters.

Calldata Decoder A black-box raw calldata decoder using only calldata. Based off the topics discussed in DeGatchi's article, Reverse The EVM: Raw Call

DeGatchi 78 Jan 24, 2023
🦀 REST API client implementation for freee, auto-generated from OpenAPI specification.

freee-rs REST API client implementation for freee, auto-generated from OpenAPI specification. Getting Started Add to your Cargo.toml as follows: [depe

Naoki Ikeguchi 3 Jul 14, 2022