From 6d7d6c4e7b1c308e7684f900f532270f91bdd816 Mon Sep 17 00:00:00 2001 From: epi Date: Mon, 11 Apr 2022 20:14:41 -0500 Subject: [PATCH] added tests for --force-recursion --- src/response.rs | 2 -- tests/test_banner.rs | 28 +++++++++++++++++++- tests/test_scanner.rs | 59 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/src/response.rs b/src/response.rs index f56035d..bdfe816 100644 --- a/src/response.rs +++ b/src/response.rs @@ -339,8 +339,6 @@ impl FeroxResponse { pub fn is_directory(&self) -> bool { log::trace!("enter: is_directory({})", self); - - if self.status().is_redirection() { // status code is 3xx match self.headers().get("Location") { diff --git a/tests/test_banner.rs b/tests/test_banner.rs index b6e0df8..0dd669f 100644 --- a/tests/test_banner.rs +++ b/tests/test_banner.rs @@ -784,7 +784,6 @@ fn banner_prints_filter_status() { .and(predicate::str::contains("http://localhost")) .and(predicate::str::contains("Threads")) .and(predicate::str::contains("Wordlist")) - .and(predicate::str::contains("Status Codes")) .and(predicate::str::contains("Timeout (secs)")) .and(predicate::str::contains("User-Agent")) .and(predicate::str::contains("Status Code Filters")) @@ -1394,3 +1393,30 @@ fn banner_prints_all_composite_settings_burp_replay() { .and(predicate::str::contains("─┴─")), ); } + +#[test] +/// test allows non-existent wordlist to trigger the banner printing to stderr +/// expect to see all mandatory prints + force recursion +fn banner_prints_force_recursion() { + Command::cargo_bin("feroxbuster") + .unwrap() + .arg("--url") + .arg("http://localhost") + .arg("--force-recursion") + .arg("--wordlist") + .arg("/definitely/doesnt/exist/0cd7fed0-47f4-4b18-a1b0-ac39708c1676") + .assert() + .success() + .stderr( + predicate::str::contains("─┬─") + .and(predicate::str::contains("Target Url")) + .and(predicate::str::contains("http://localhost")) + .and(predicate::str::contains("Threads")) + .and(predicate::str::contains("Wordlist")) + .and(predicate::str::contains("Status Codes")) + .and(predicate::str::contains("Timeout (secs)")) + .and(predicate::str::contains("User-Agent")) + .and(predicate::str::contains("Force Recursion")) + .and(predicate::str::contains("─┴─")), + ); +} diff --git a/tests/test_scanner.rs b/tests/test_scanner.rs index 4ec3caa..9d3f459 100644 --- a/tests/test_scanner.rs +++ b/tests/test_scanner.rs @@ -852,3 +852,62 @@ fn collect_words_makes_appropriate_requests() { teardown_tmp_directory(tmp_dir); } + +#[test] +/// send a request to an endpoint that has abnormal redirect logic, ala fast-api +fn scanner_forced_recursion_ignores_normal_redirect_logic() -> Result<(), Box> +{ + let srv = MockServer::start(); + let (tmp_dir, file) = setup_tmp_directory(&["LICENSE".to_string()], "wordlist")?; + + let mock1 = srv.mock(|when, then| { + when.method(GET).path("/LICENSE"); + then.status(301) + .body("this is a test") + .header("Location", &srv.url("/LICENSE")); + }); + + let mock2 = srv.mock(|when, then| { + when.method(GET).path("/LICENSE/LICENSE"); + then.status(404); + }); + + let mock3 = srv.mock(|when, then| { + when.method(GET).path("/LICENSE/LICENSE/LICENSE"); + then.status(404); + }); + + let mock4 = srv.mock(|when, then| { + when.method(GET).path("/LICENSE/LICENSE/LICENSE/LICENSE"); + then.status(404); + }); + + let outfile = tmp_dir.path().join("output"); + + Command::cargo_bin("feroxbuster") + .unwrap() + .arg("--url") + .arg(srv.url("/")) + .arg("--wordlist") + .arg(file.as_os_str()) + .arg("--force-recursion") + .arg("-o") + .arg(outfile.as_os_str()) + .unwrap(); + + let contents = std::fs::read_to_string(outfile)?; + println!("{}", contents); + + assert!(contents.contains("/LICENSE")); + assert!(contents.contains("301")); + assert!(contents.contains("14")); + + assert_eq!(mock1.hits(), 2); + assert_eq!(mock2.hits(), 2); + assert_eq!(mock3.hits(), 2); + assert_eq!(mock4.hits(), 1); + + teardown_tmp_directory(tmp_dir); + + Ok(()) +}