From 55c67358d66fff7bb360974923198a71a97f6a7e Mon Sep 17 00:00:00 2001 From: epi <43392618+epi052@users.noreply.github.com> Date: Wed, 8 Nov 2023 21:18:53 -0500 Subject: [PATCH] allow --json in conjunction with --silent (#1022) * updated parser to allow --silent with --json * updated config parsing with new silentjson output variant * added new silentjson output variant * updated outputlevel usage to include new variant --- shell_completions/_feroxbuster | 2 +- shell_completions/_feroxbuster.ps1 | 2 +- shell_completions/feroxbuster.elv | 2 +- src/config/container.rs | 10 +++++--- src/config/utils.rs | 37 ++++++++++++++++++++++++------ src/parser.rs | 4 ++-- src/response.rs | 22 ++++++++++-------- src/scan_manager/scan.rs | 4 ++-- src/scan_manager/scan_container.rs | 4 ++-- 9 files changed, 59 insertions(+), 28 deletions(-) diff --git a/shell_completions/_feroxbuster b/shell_completions/_feroxbuster index ec8c2340..61a2a5b6 100644 --- a/shell_completions/_feroxbuster +++ b/shell_completions/_feroxbuster @@ -103,7 +103,7 @@ _feroxbuster() { '--collect-words[Automatically discover important words from within responses and add them to the wordlist]' \ '(--silent)*-v[Increase verbosity level (use -vv or more for greater effect. \[CAUTION\] 4 -v'\''s is probably too much)]' \ '(--silent)*--verbosity[Increase verbosity level (use -vv or more for greater effect. \[CAUTION\] 4 -v'\''s is probably too much)]' \ -'(-q --quiet)--silent[Only print URLs + turn off logging (good for piping a list of urls to other commands)]' \ +'(-q --quiet)--silent[Only print URLs (or JSON w/ --json) + turn off logging (good for piping a list of urls to other commands)]' \ '-q[Hide progress bars and banner (good for tmux windows w/ notifications)]' \ '--quiet[Hide progress bars and banner (good for tmux windows w/ notifications)]' \ '--json[Emit JSON logs to --output and --debug-log instead of normal text]' \ diff --git a/shell_completions/_feroxbuster.ps1 b/shell_completions/_feroxbuster.ps1 index 250581eb..9be27d4a 100644 --- a/shell_completions/_feroxbuster.ps1 +++ b/shell_completions/_feroxbuster.ps1 @@ -109,7 +109,7 @@ Register-ArgumentCompleter -Native -CommandName 'feroxbuster' -ScriptBlock { [CompletionResult]::new('--collect-words', 'collect-words', [CompletionResultType]::ParameterName, 'Automatically discover important words from within responses and add them to the wordlist') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Increase verbosity level (use -vv or more for greater effect. [CAUTION] 4 -v''s is probably too much)') [CompletionResult]::new('--verbosity', 'verbosity', [CompletionResultType]::ParameterName, 'Increase verbosity level (use -vv or more for greater effect. [CAUTION] 4 -v''s is probably too much)') - [CompletionResult]::new('--silent', 'silent', [CompletionResultType]::ParameterName, 'Only print URLs + turn off logging (good for piping a list of urls to other commands)') + [CompletionResult]::new('--silent', 'silent', [CompletionResultType]::ParameterName, 'Only print URLs (or JSON w/ --json) + turn off logging (good for piping a list of urls to other commands)') [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Hide progress bars and banner (good for tmux windows w/ notifications)') [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Hide progress bars and banner (good for tmux windows w/ notifications)') [CompletionResult]::new('--json', 'json', [CompletionResultType]::ParameterName, 'Emit JSON logs to --output and --debug-log instead of normal text') diff --git a/shell_completions/feroxbuster.elv b/shell_completions/feroxbuster.elv index 5cd98d30..1cf4240e 100644 --- a/shell_completions/feroxbuster.elv +++ b/shell_completions/feroxbuster.elv @@ -106,7 +106,7 @@ set edit:completion:arg-completer[feroxbuster] = {|@words| cand --collect-words 'Automatically discover important words from within responses and add them to the wordlist' cand -v 'Increase verbosity level (use -vv or more for greater effect. [CAUTION] 4 -v''s is probably too much)' cand --verbosity 'Increase verbosity level (use -vv or more for greater effect. [CAUTION] 4 -v''s is probably too much)' - cand --silent 'Only print URLs + turn off logging (good for piping a list of urls to other commands)' + cand --silent 'Only print URLs (or JSON w/ --json) + turn off logging (good for piping a list of urls to other commands)' cand -q 'Hide progress bars and banner (good for tmux windows w/ notifications)' cand --quiet 'Hide progress bars and banner (good for tmux windows w/ notifications)' cand --json 'Emit JSON logs to --output and --debug-log instead of normal text' diff --git a/src/config/container.rs b/src/config/container.rs index 9ec13bcc..886b0d3c 100644 --- a/src/config/container.rs +++ b/src/config/container.rs @@ -794,7 +794,11 @@ impl Configuration { // if the line below is outside of the if, we'd overwrite true with // false if no --silent is used on the command line config.silent = true; - config.output_level = OutputLevel::Silent; + config.output_level = if config.json { + OutputLevel::SilentJSON + } else { + OutputLevel::Silent + }; } if came_from_cli!(args, "quiet") { @@ -1061,6 +1065,7 @@ impl Configuration { new.server_certs, Vec::::new() ); + update_if_not_default!(&mut conf.json, new.json, false); update_if_not_default!(&mut conf.client_cert, new.client_cert, ""); update_if_not_default!(&mut conf.client_key, new.client_key, ""); update_if_not_default!(&mut conf.verbosity, new.verbosity, 0); @@ -1072,7 +1077,7 @@ impl Configuration { update_if_not_default!(&mut conf.collect_backups, new.collect_backups, false); update_if_not_default!(&mut conf.collect_words, new.collect_words, false); // use updated quiet/silent values to determine output level; same for requester policy - conf.output_level = determine_output_level(conf.quiet, conf.silent); + conf.output_level = determine_output_level(conf.quiet, conf.silent, conf.json); conf.requester_policy = determine_requester_policy(conf.auto_tune, conf.auto_bail); update_if_not_default!(&mut conf.output, new.output, ""); update_if_not_default!(&mut conf.redirects, new.redirects, false); @@ -1130,7 +1135,6 @@ impl Configuration { update_if_not_default!(&mut conf.replay_proxy, new.replay_proxy, ""); update_if_not_default!(&mut conf.debug_log, new.debug_log, ""); update_if_not_default!(&mut conf.resume_from, new.resume_from, ""); - update_if_not_default!(&mut conf.json, new.json, false); update_if_not_default!(&mut conf.timeout, new.timeout, timeout()); update_if_not_default!(&mut conf.user_agent, new.user_agent, user_agent()); diff --git a/src/config/utils.rs b/src/config/utils.rs index e45c0ea6..1d1e30b2 100644 --- a/src/config/utils.rs +++ b/src/config/utils.rs @@ -100,6 +100,9 @@ pub enum OutputLevel { /// silent scan, only print urls (used to be --quiet in versions 1.x.x) Silent, + + /// silent scan, but with JSON output + SilentJSON, } /// implement a default for OutputLevel @@ -111,14 +114,22 @@ impl Default for OutputLevel { } /// given the current settings for quiet and silent, determine output_level (DRY helper) -pub fn determine_output_level(quiet: bool, silent: bool) -> OutputLevel { +pub fn determine_output_level(quiet: bool, silent: bool, json: bool) -> OutputLevel { if quiet && silent { // user COULD have both as true in config file, take the more quiet of the two - OutputLevel::Silent + if json { + OutputLevel::SilentJSON + } else { + OutputLevel::Silent + } } else if quiet { OutputLevel::Quiet } else if silent { - OutputLevel::Silent + if json { + OutputLevel::SilentJSON + } else { + OutputLevel::Silent + } } else { OutputLevel::Default } @@ -166,16 +177,28 @@ mod tests { #[test] /// test determine_output_level returns higher of the two levels if both given values are true fn determine_output_level_returns_correct_results() { - let mut level = determine_output_level(true, true); + let mut level = determine_output_level(true, true, false); assert_eq!(level, OutputLevel::Silent); - level = determine_output_level(false, true); + level = determine_output_level(false, true, false); assert_eq!(level, OutputLevel::Silent); - level = determine_output_level(false, false); + let mut level = determine_output_level(true, true, true); + assert_eq!(level, OutputLevel::SilentJSON); + + level = determine_output_level(false, true, true); + assert_eq!(level, OutputLevel::SilentJSON); + + level = determine_output_level(false, false, false); + assert_eq!(level, OutputLevel::Default); + + level = determine_output_level(true, false, false); + assert_eq!(level, OutputLevel::Quiet); + + level = determine_output_level(false, false, true); assert_eq!(level, OutputLevel::Default); - level = determine_output_level(true, false); + level = determine_output_level(true, false, true); assert_eq!(level, OutputLevel::Quiet); } diff --git a/src/parser.rs b/src/parser.rs index 05687dfd..c40cab67 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -594,7 +594,7 @@ pub fn initialize() -> Command { .num_args(0) .conflicts_with("quiet") .help_heading("Output settings") - .help("Only print URLs + turn off logging (good for piping a list of urls to other commands)") + .help("Only print URLs (or JSON w/ --json) + turn off logging (good for piping a list of urls to other commands)") ) .arg( Arg::new("quiet") @@ -645,7 +645,7 @@ pub fn initialize() -> Command { let mut app = app .group( ArgGroup::new("output_files") - .args(["debug_log", "output"]) + .args(["debug_log", "output", "silent"]) .multiple(true), ) .arg( diff --git a/src/response.rs b/src/response.rs index 2fb73437..ae7ddcc6 100644 --- a/src/response.rs +++ b/src/response.rs @@ -485,15 +485,19 @@ impl FeroxSerialize for FeroxResponse { message } else { // not a wildcard, just create a normal entry - utils::create_report_string( - self.status.as_str(), - method, - &lines, - &words, - &chars, - &url_with_redirect, - self.output_level, - ) + if matches!(self.output_level, OutputLevel::SilentJSON) { + self.as_json().unwrap_or_default() + } else { + utils::create_report_string( + self.status.as_str(), + method, + &lines, + &words, + &chars, + &url_with_redirect, + self.output_level, + ) + } } } diff --git a/src/scan_manager/scan.rs b/src/scan_manager/scan.rs index 3de12b79..f2798169 100644 --- a/src/scan_manager/scan.rs +++ b/src/scan_manager/scan.rs @@ -175,7 +175,7 @@ impl FeroxScan { let bar_type = match self.output_level { OutputLevel::Default => BarType::Default, OutputLevel::Quiet => BarType::Quiet, - OutputLevel::Silent => BarType::Hidden, + OutputLevel::Silent | OutputLevel::SilentJSON => BarType::Hidden, }; let pb = add_bar(&self.url, self.num_requests, bar_type); @@ -194,7 +194,7 @@ impl FeroxScan { let bar_type = match self.output_level { OutputLevel::Default => BarType::Default, OutputLevel::Quiet => BarType::Quiet, - OutputLevel::Silent => BarType::Hidden, + OutputLevel::Silent | OutputLevel::SilentJSON => BarType::Hidden, }; let pb = add_bar(&self.url, self.num_requests, bar_type); diff --git a/src/scan_manager/scan_container.rs b/src/scan_manager/scan_container.rs index 080d9dc7..fc985b55 100644 --- a/src/scan_manager/scan_container.rs +++ b/src/scan_manager/scan_container.rs @@ -516,7 +516,7 @@ impl FeroxScans { let bar_type = match self.output_level { OutputLevel::Default => BarType::Message, OutputLevel::Quiet => BarType::Quiet, - OutputLevel::Silent => return Ok(()), // fast exit when --silent was used + OutputLevel::Silent | OutputLevel::SilentJSON => return Ok(()), // fast exit when --silent was used }; if let Ok(scans) = self.scans.read() { @@ -609,7 +609,7 @@ impl FeroxScans { let bar_type = match self.output_level { OutputLevel::Default => BarType::Default, OutputLevel::Quiet => BarType::Quiet, - OutputLevel::Silent => BarType::Hidden, + OutputLevel::Silent | OutputLevel::SilentJSON => BarType::Hidden, }; let progress_bar = add_bar(url, bar_length, bar_type);