From 5f21953bc19082b784d5a0ce26a839b83eebcf70 Mon Sep 17 00:00:00 2001 From: epi Date: Mon, 11 Apr 2022 20:13:10 -0500 Subject: [PATCH] added --force-recursion option --- src/banner/container.rs | 10 ++++++++++ src/config/container.rs | 11 +++++++++++ src/config/tests.rs | 9 +++++++++ src/event_handlers/scans.rs | 4 ++-- src/parser.rs | 5 +++++ src/response.rs | 2 ++ src/scan_manager/tests.rs | 1 + 7 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/banner/container.rs b/src/banner/container.rs index 3ffe6bb..31a8d6e 100644 --- a/src/banner/container.rs +++ b/src/banner/container.rs @@ -163,6 +163,9 @@ pub struct Banner { /// represents Configuration.collect_words collect_words: BannerEntry, + + /// represents Configuration.collect_words + force_recursion: BannerEntry, } /// implementation of Banner @@ -300,6 +303,8 @@ impl Banner { &config.scan_limit.to_string(), ); + let force_recursion = + BannerEntry::new("🤘", "Force Recursion", &config.force_recursion.to_string()); let replay_proxy = BannerEntry::new("🎥", "Replay Proxy", &config.replay_proxy); let auto_tune = BannerEntry::new("🎶", "Auto Tune", &config.auto_tune.to_string()); let auto_bail = BannerEntry::new("🪣", "Auto Bail", &config.auto_bail.to_string()); @@ -409,6 +414,7 @@ impl Banner { no_recursion, rate_limit, scan_limit, + force_recursion, time_limit, url_denylist, collect_extensions, @@ -643,6 +649,10 @@ by Ben "epi" Risher {} ver: {}"#, writeln!(&mut writer, "{}", self.no_recursion)?; + if config.force_recursion { + writeln!(&mut writer, "{}", self.force_recursion)?; + } + if config.scan_limit > 0 { writeln!(&mut writer, "{}", self.scan_limit)?; } diff --git a/src/config/container.rs b/src/config/container.rs index c992e58..9161e77 100644 --- a/src/config/container.rs +++ b/src/config/container.rs @@ -281,6 +281,10 @@ pub struct Configuration { /// Automatically discover important words from within responses and add them to the wordlist #[serde(default)] pub collect_words: bool, + + /// override recursion logic to always attempt recursion, still respects --depth + #[serde(default)] + pub force_recursion: bool, } impl Default for Configuration { @@ -329,6 +333,7 @@ impl Default for Configuration { collect_backups: false, collect_words: false, save_state: true, + force_recursion: false, proxy: String::new(), config: String::new(), output: String::new(), @@ -405,6 +410,7 @@ impl Configuration { /// - **json**: `false` /// - **dont_filter**: `false` (auto filter wildcard responses) /// - **depth**: `4` (maximum recursion depth) + /// - **force_recursion**: `false` (still respects recursion depth) /// - **scan_limit**: `0` (no limit on concurrent scans imposed) /// - **parallel**: `0` (no limit on parallel scans imposed) /// - **rate_limit**: `0` (no limit on requests per second imposed) @@ -774,6 +780,10 @@ impl Configuration { config.json = true; } + if args.is_present("force_recursion") { + config.force_recursion = true; + } + //// // organizational breakpoint; all options below alter the Client configuration //// @@ -942,6 +952,7 @@ impl Configuration { update_if_not_default!(&mut conf.output, new.output, ""); update_if_not_default!(&mut conf.redirects, new.redirects, false); update_if_not_default!(&mut conf.insecure, new.insecure, false); + update_if_not_default!(&mut conf.force_recursion, new.force_recursion, false); update_if_not_default!(&mut conf.extract_links, new.extract_links, false); update_if_not_default!(&mut conf.extensions, new.extensions, Vec::::new()); update_if_not_default!(&mut conf.methods, new.methods, Vec::::new()); diff --git a/src/config/tests.rs b/src/config/tests.rs index 2f1ff1e..6f945a9 100644 --- a/src/config/tests.rs +++ b/src/config/tests.rs @@ -49,6 +49,7 @@ fn setup_config_test() -> Configuration { json = true save_state = false depth = 1 + force_recursion = true filter_size = [4120] filter_regex = ["^ignore me$"] filter_similar = ["https://somesite.com/soft404"] @@ -95,6 +96,7 @@ fn default_configuration() { assert!(config.save_state); assert!(!config.stdin); assert!(!config.add_slash); + assert!(!config.force_recursion); assert!(!config.redirects); assert!(!config.extract_links); assert!(!config.insecure); @@ -208,6 +210,13 @@ fn config_reads_silent() { assert!(config.silent); } +#[test] +/// parse the test config and see that the value parsed is correct +fn config_reads_force_recursion() { + let config = setup_config_test(); + assert!(config.force_recursion); +} + #[test] /// parse the test config and see that the value parsed is correct fn config_reads_quiet() { diff --git a/src/event_handlers/scans.rs b/src/event_handlers/scans.rs index a1705c3..2659a55 100644 --- a/src/event_handlers/scans.rs +++ b/src/event_handlers/scans.rs @@ -368,8 +368,8 @@ impl ScanHandler { async fn try_recursion(&mut self, response: Box) -> Result<()> { log::trace!("enter: try_recursion({:?})", response,); - if !response.is_directory() { - // not a directory, quick exit + if !self.handles.config.force_recursion && !response.is_directory() { + // not a directory and --force-recursion wasn't used, quick exit return Ok(()); } diff --git a/src/parser.rs b/src/parser.rs index 5eb9fa1..df1d9bc 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -427,6 +427,11 @@ pub fn initialize() -> Command<'static> { .takes_value(true) .help_heading("Scan settings") .help("Maximum recursion depth, a depth of 0 is infinite recursion (default: 4)"), + ).arg( + Arg::new("force_recursion") + .long("force-recursion") + .help_heading("Scan settings") + .help("Force recursion attempts on all 'found' endpoints (still respects recursion depth)"), ).arg( Arg::new("extract_links") .short('e') diff --git a/src/response.rs b/src/response.rs index bdfe816..f56035d 100644 --- a/src/response.rs +++ b/src/response.rs @@ -339,6 +339,8 @@ 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/src/scan_manager/tests.rs b/src/scan_manager/tests.rs index 0fd6e5e..c9a0c00 100644 --- a/src/scan_manager/tests.rs +++ b/src/scan_manager/tests.rs @@ -452,6 +452,7 @@ fn feroxstates_feroxserialize_implementation() { r#""quiet":false"#, r#""auto_bail":false"#, r#""auto_tune":false"#, + r#""force_recursion":false"#, r#""json":false"#, r#""output":"""#, r#""debug_log":"""#,