Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
feroxfuzz — 합성 가능한 뮤테이터, 스케줄러, 옵저버, 디사이더, 프로세서를 통해 맞춤형 웹 및 API 테스트를 위한 구조 인식 블랙박스 HTTP 퍼저를 Rust로 구축하세요. | Kitploit
도구/GitHubGitHub/epi052/feroxfuzz
API Security TestingWeb SecurityFuzzingUtilities & Frameworks
GitHubepi052/feroxfuzz

feroxfuzz

합성 가능한 뮤테이터, 스케줄러, 옵저버, 디사이더, 프로세서를 통해 맞춤형 웹 및 API 테스트를 위한 구조 인식 블랙박스 HTTP 퍼저를 Rust로 구축하세요.

저장소 보기
223197개월 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유


🚀 FeroxFuzz 🚀

구조를 인식하는 HTTP 퍼징 라이브러리


🤔 또 다른 ferox? 왜? 🤔

진정하세요, 또 다른 커맨드라인 도구가 아니라 라이브러리입니다! 😁

보다 정확히 말하면, FeroxFuzz는 구조를 인식하는 HTTP 퍼징 라이브러리입니다.

FeroxFuzz를 작성한 주요 목표는 feroxbuster의 핵심 요소 일부를 분리하여 다른 사람들에게도 일반적으로 유용한 곳으로 옮기는 것이었습니다. 그렇게 함으로써 Rust로 웹 도구 및/또는 일회성 웹 퍼저를 작성하려는 사람이라면 누구나 최소한의 노력으로 작성할 수 있기를 바랍니다.

설계

FeroxFuzz의 전반적인 설계는 LibAFL에서 파생되었습니다. FeroxFuzz는 LibAFL: A Framework to Build Modular and Reusable Fuzzers (pre-print)에 나열된 대부분의 구성 요소를 구현합니다. FeroxFuzz가 해당 설계에서 벗어나는 경우는 일반적으로 비동기 코드를 지원하기 위해서입니다.

LibAFL과 유사하게, FeroxFuzz는 구성 가능한(composable) 퍼징 라이브러리입니다. 그러나 LibAFL과 달리 FeroxFuzz는 블랙박스 HTTP 퍼징에만 전적으로 초점을 맞추고 있습니다.

퍼즈 루프 실행 흐름

다음은 FeroxFuzz에서 사용하는 다양한 구성 요소, 훅, 그리고 제어 흐름을 시각적으로 나타낸 것입니다.

fuzz-flow

🚧 경고: 공사 중 🚧

FeroxFuzz는 매우 강력하며, 새로운 feroxbuster를 위해 제가 계획한 모든 요구 사항을 충족하도록 만들어졌습니다. 하지만 새 버전의 feroxbuster 작업이 시작되면서 FeroxFuzz의 API가 최소한 약간은 변경될 것으로 예상합니다.

API가 확정될 때까지 호환성을 깨뜨리는 변경(breaking change)이 발생할 수도 발생할 것입니다.

시작하기

가장 쉽게 시작하는 방법은 프로젝트의 Cargo.toml에 FeroxFuzz를 포함시키는 것입니다.

root@kitploit:~
[dependencies]
feroxfuzz = { version = "1.0.0-rc.13" }

문서

examples/ 폴더 외에도 API 문서에는 구성 요소에 대한 광범위한 문서와 사용 예제가 포함되어 있습니다.

  • FeroxFuzz API 문서: 이 저장소의 doc 주석에서 자동으로 생성된 FeroxFuzz의 API 문서.
  • 공식 예제: 특정 개념을 깊이 파고들기에 좋고 주석이 많이 달려 있는, FeroxFuzz 전용 실행 가능한 예제들.

예제

아래 예제(examples/async-simple.rs)는 FeroxFuzz를 사용하여 퍼저를 작성하는 데 필요한 최소한의 코드를 보여줍니다.

소스를 사용하는 경우, 다음 명령어를 사용하여 feroxfuzz/ 디렉터리에서 예제를 실행할 수 있습니다:

참고: 포트 8000에서 실행 중인 웹 서버가 없다면 Request::from_url에 전달된 대상을 변경해야 합니다.

root@kitploit:~
cargo run --example async-simple
root@kitploit:~
#[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(client)
        .request(request)
        .scheduler(scheduler)
        .mutators(mutators)
        .observers(observers)
        .processors(processors)
        .deciders(deciders)
        .post_loop_hook(|state| {
            // this closure is called after each fuzzing loop iteration completes.
            // it's a good place to do things like print out stats
            // or do other things that you want to happen after each
            // full iteration over the corpus
            println!("\n•*´¨`*•.¸¸.•* Finished fuzzing loop •*´¨`*•.¸¸.•*\n");
            println!("{state:#}");
        })
        .build();

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

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

    Ok(())
}

위의 퍼저는 아래와 유사한 결과를 생성합니다.

root@kitploit:~
[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}}
}

🤓 FeroxFuzz를 사용하는 프로젝트 🤓


chameleon

기여자 ✨

이 멋진 분들에게 감사드립니다 (이모지 키):

이 프로젝트는 all-contributors 사양을 따릅니다. 어떤 종류의 기여든 환영합니다!

도구 다운로드
iustin24
iustin24

💻
andreademurtas
andreademurtas

💻
Mieszko Grodzicki
Mieszko Grodzicki

💻 🚇