mirror of
https://github.com/epi052/feroxbuster.git
synced 2026-06-01 21:21:12 -03:00
key requires cert; accept multiple server certs
This commit is contained in:
@@ -53,9 +53,9 @@ _feroxbuster() {
|
||||
'*--status-codes=[Status Codes to include (allow list) (default\: All Status Codes)]:STATUS_CODE: ' \
|
||||
'-T+[Number of seconds before a client'\''s request times out (default\: 7)]:SECONDS: ' \
|
||||
'--timeout=[Number of seconds before a client'\''s request times out (default\: 7)]:SECONDS: ' \
|
||||
'--server-cert=[Add a custom root certificate to connect to servers with a self-signed certificate]:PEM/DER:_files' \
|
||||
'--client-cert=[Use a custom client SSL certificate for mutual authentication]:PEM:_files' \
|
||||
'--client-key=[Use a custom client SSL key file for mutual authentication]:PEM:_files' \
|
||||
'--server-certs=[Add custom root certificate(s) for servers with unknown certificates]:PEM|DER:_files' \
|
||||
'--client-cert=[Add a PEM encoded certificate for mutual authentication (mTLS)]:PEM:_files' \
|
||||
'--client-key=[Add a PEM encoded private key for mutual authentication (mTLS)]:PEM:_files' \
|
||||
'-t+[Number of concurrent threads (default\: 50)]:THREADS: ' \
|
||||
'--threads=[Number of concurrent threads (default\: 50)]:THREADS: ' \
|
||||
'-d+[Maximum recursion depth, a depth of 0 is infinite recursion (default\: 4)]:RECURSION_DEPTH: ' \
|
||||
|
||||
@@ -59,9 +59,9 @@ Register-ArgumentCompleter -Native -CommandName 'feroxbuster' -ScriptBlock {
|
||||
[CompletionResult]::new('--status-codes', 'status-codes', [CompletionResultType]::ParameterName, 'Status Codes to include (allow list) (default: All Status Codes)')
|
||||
[CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Number of seconds before a client''s request times out (default: 7)')
|
||||
[CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Number of seconds before a client''s request times out (default: 7)')
|
||||
[CompletionResult]::new('--server-cert', 'server-cert', [CompletionResultType]::ParameterName, 'Add a custom root certificate to connect to servers with a self-signed certificate')
|
||||
[CompletionResult]::new('--client-cert', 'client-cert', [CompletionResultType]::ParameterName, 'Use a custom client SSL certificate for mutual authentication')
|
||||
[CompletionResult]::new('--client-key', 'client-key', [CompletionResultType]::ParameterName, 'Use a custom client SSL key file for mutual authentication')
|
||||
[CompletionResult]::new('--server-certs', 'server-certs', [CompletionResultType]::ParameterName, 'Add custom root certificate(s) for servers with unknown certificates')
|
||||
[CompletionResult]::new('--client-cert', 'client-cert', [CompletionResultType]::ParameterName, 'Add a PEM encoded certificate for mutual authentication (mTLS)')
|
||||
[CompletionResult]::new('--client-key', 'client-key', [CompletionResultType]::ParameterName, 'Add a PEM encoded private key for mutual authentication (mTLS)')
|
||||
[CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Number of concurrent threads (default: 50)')
|
||||
[CompletionResult]::new('--threads', 'threads', [CompletionResultType]::ParameterName, 'Number of concurrent threads (default: 50)')
|
||||
[CompletionResult]::new('-d', 'd', [CompletionResultType]::ParameterName, 'Maximum recursion depth, a depth of 0 is infinite recursion (default: 4)')
|
||||
|
||||
@@ -19,7 +19,7 @@ _feroxbuster() {
|
||||
|
||||
case "${cmd}" in
|
||||
feroxbuster)
|
||||
opts="-u -p -P -R -a -A -x -m -H -b -Q -f -S -X -W -N -C -s -T -r -k -t -n -d -e -L -w -D -E -B -g -I -v -q -o -U -h -V --url --stdin --resume-from --burp --burp-replay --smart --thorough --proxy --replay-proxy --replay-codes --user-agent --random-agent --extensions --methods --data --headers --cookies --query --add-slash --dont-scan --filter-size --filter-regex --filter-words --filter-lines --filter-status --filter-similar-to --status-codes --timeout --redirects --insecure --server-cert --client-cert --client-key --threads --no-recursion --depth --force-recursion --extract-links --dont-extract-links --scan-limit --parallel --rate-limit --time-limit --wordlist --auto-tune --auto-bail --dont-filter --collect-extensions --collect-backups --collect-words --dont-collect --verbosity --silent --quiet --json --output --debug-log --no-state --update --help --version"
|
||||
opts="-u -p -P -R -a -A -x -m -H -b -Q -f -S -X -W -N -C -s -T -r -k -t -n -d -e -L -w -D -E -B -g -I -v -q -o -U -h -V --url --stdin --resume-from --burp --burp-replay --smart --thorough --proxy --replay-proxy --replay-codes --user-agent --random-agent --extensions --methods --data --headers --cookies --query --add-slash --dont-scan --filter-size --filter-regex --filter-words --filter-lines --filter-status --filter-similar-to --status-codes --timeout --redirects --insecure --server-certs --client-cert --client-key --threads --no-recursion --depth --force-recursion --extract-links --dont-extract-links --scan-limit --parallel --rate-limit --time-limit --wordlist --auto-tune --auto-bail --dont-filter --collect-extensions --collect-backups --collect-words --dont-collect --verbosity --silent --quiet --json --output --debug-log --no-state --update --help --version"
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
@@ -177,7 +177,7 @@ _feroxbuster() {
|
||||
COMPREPLY=($(compgen -f "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
--server-cert)
|
||||
--server-certs)
|
||||
COMPREPLY=($(compgen -f "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
|
||||
@@ -56,9 +56,9 @@ set edit:completion:arg-completer[feroxbuster] = {|@words|
|
||||
cand --status-codes 'Status Codes to include (allow list) (default: All Status Codes)'
|
||||
cand -T 'Number of seconds before a client''s request times out (default: 7)'
|
||||
cand --timeout 'Number of seconds before a client''s request times out (default: 7)'
|
||||
cand --server-cert 'Add a custom root certificate to connect to servers with a self-signed certificate'
|
||||
cand --client-cert 'Use a custom client SSL certificate for mutual authentication'
|
||||
cand --client-key 'Use a custom client SSL key file for mutual authentication'
|
||||
cand --server-certs 'Add custom root certificate(s) for servers with unknown certificates'
|
||||
cand --client-cert 'Add a PEM encoded certificate for mutual authentication (mTLS)'
|
||||
cand --client-key 'Add a PEM encoded private key for mutual authentication (mTLS)'
|
||||
cand -t 'Number of concurrent threads (default: 50)'
|
||||
cand --threads 'Number of concurrent threads (default: 50)'
|
||||
cand -d 'Maximum recursion depth, a depth of 0 is infinite recursion (default: 4)'
|
||||
|
||||
@@ -65,7 +65,7 @@ pub struct Banner {
|
||||
client_cert: BannerEntry,
|
||||
|
||||
/// represents Configuration.server_cert
|
||||
server_cert: BannerEntry,
|
||||
server_certs: BannerEntry,
|
||||
|
||||
/// represents Configuration.replay_proxy
|
||||
replay_proxy: BannerEntry,
|
||||
@@ -331,7 +331,7 @@ impl Banner {
|
||||
let auto_bail = BannerEntry::new("🙅", "Auto Bail", &config.auto_bail.to_string());
|
||||
let cfg = BannerEntry::new("💉", "Config File", &config.config);
|
||||
let proxy = BannerEntry::new("💎", "Proxy", &config.proxy);
|
||||
let server_cert = BannerEntry::new("🏅", "Server Certificate", &config.server_cert);
|
||||
let server_certs = BannerEntry::new("🏅", "Server Certificates", &format!("[{}]", config.server_certs.join(", ")));
|
||||
let client_cert = BannerEntry::new("🏅", "Client Certificate", &config.client_cert);
|
||||
let client_key = BannerEntry::new("🔑", "Client Key", &config.client_key);
|
||||
let threads = BannerEntry::new("🚀", "Threads", &config.threads.to_string());
|
||||
@@ -415,7 +415,7 @@ impl Banner {
|
||||
proxy,
|
||||
client_cert,
|
||||
client_key,
|
||||
server_cert,
|
||||
server_certs,
|
||||
replay_codes,
|
||||
replay_proxy,
|
||||
headers,
|
||||
@@ -578,8 +578,8 @@ by Ben "epi" Risher {} ver: {}"#,
|
||||
writeln!(&mut writer, "{}", self.client_key)?;
|
||||
}
|
||||
|
||||
if !config.server_cert.is_empty() {
|
||||
writeln!(&mut writer, "{}", self.server_cert)?;
|
||||
if !config.server_certs.is_empty() {
|
||||
writeln!(&mut writer, "{}", self.server_certs)?;
|
||||
}
|
||||
|
||||
if !config.replay_proxy.is_empty() {
|
||||
|
||||
@@ -9,17 +9,21 @@ use std::time::Duration;
|
||||
/// Create and return an instance of [reqwest::Client](https://docs.rs/reqwest/latest/reqwest/struct.Client.html)
|
||||
/// For now, silence clippy for this one
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn initialize(
|
||||
pub fn initialize<I>(
|
||||
timeout: u64,
|
||||
user_agent: &str,
|
||||
redirects: bool,
|
||||
insecure: bool,
|
||||
headers: &HashMap<String, String>,
|
||||
proxy: Option<&str>,
|
||||
server_cert: Option<&str>,
|
||||
server_certs: Option<I>,
|
||||
client_cert: Option<&str>,
|
||||
client_key: Option<&str>,
|
||||
) -> Result<Client> {
|
||||
) -> Result<Client>
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: AsRef<std::ffi::OsStr>,
|
||||
{
|
||||
let policy = if redirects {
|
||||
Policy::limited(10)
|
||||
} else {
|
||||
@@ -46,33 +50,35 @@ pub fn initialize(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(cert_path) = server_cert {
|
||||
let cert_path = Path::new(cert_path);
|
||||
if let Some(cert_paths) = server_certs {
|
||||
for cert_path in cert_paths {
|
||||
let cert_path = Path::new(&cert_path);
|
||||
|
||||
// if the root certificate path is not empty, open it
|
||||
// and read it into a buffer
|
||||
// if the root certificate path is not empty, open it
|
||||
// and read it into a buffer
|
||||
|
||||
let buf = std::fs::read(cert_path)?;
|
||||
let cert = match cert_path
|
||||
.extension()
|
||||
.map(|s| s.to_str().unwrap_or_default())
|
||||
{
|
||||
// depending upon the extension of the file, create a
|
||||
// certificate object from it using either the "pem" or "der" parser
|
||||
Some("pem") => reqwest::Certificate::from_pem(&buf)?,
|
||||
Some("der") => reqwest::Certificate::from_der(&buf)?,
|
||||
let buf = std::fs::read(cert_path)?;
|
||||
let cert = match cert_path
|
||||
.extension()
|
||||
.map(|s| s.to_str().unwrap_or_default())
|
||||
{
|
||||
// depending upon the extension of the file, create a
|
||||
// certificate object from it using either the "pem" or "der" parser
|
||||
Some("pem") => reqwest::Certificate::from_pem(&buf)?,
|
||||
Some("der") => reqwest::Certificate::from_der(&buf)?,
|
||||
|
||||
// if we cannot determine the extension, do nothing
|
||||
_ => {
|
||||
log::warn!(
|
||||
"unable to determine extension: assuming PEM format for root certificate"
|
||||
);
|
||||
reqwest::Certificate::from_pem(&buf)?
|
||||
}
|
||||
};
|
||||
// if we cannot determine the extension, do nothing
|
||||
_ => {
|
||||
log::warn!(
|
||||
"unable to determine extension: assuming PEM format for root certificate"
|
||||
);
|
||||
reqwest::Certificate::from_pem(&buf)?
|
||||
}
|
||||
};
|
||||
|
||||
// in either case, add the root certificate to the client
|
||||
client = client.add_root_certificate(cert);
|
||||
// in either case, add the root certificate to the client
|
||||
client = client.add_root_certificate(cert);
|
||||
}
|
||||
}
|
||||
|
||||
if let (Some(cert_path), Some(key_path)) = (client_cert, client_key) {
|
||||
|
||||
@@ -106,9 +106,9 @@ pub struct Configuration {
|
||||
|
||||
/// Path to a custom root certificate for connecting to servers with a self-signed certificate
|
||||
#[serde(default)]
|
||||
pub server_cert: String,
|
||||
pub server_certs: Vec<String>,
|
||||
|
||||
/// Path to a client's PEM encoded X509 certificate(s) used during mutual authentication
|
||||
/// Path to a client's PEM encoded X509 certificate used during mutual authentication
|
||||
#[serde(default)]
|
||||
pub client_cert: String,
|
||||
|
||||
@@ -336,7 +336,7 @@ impl Default for Configuration {
|
||||
fn default() -> Self {
|
||||
let timeout = timeout();
|
||||
let user_agent = user_agent();
|
||||
let client = client::initialize(
|
||||
let client = client::initialize::<Vec<String>>(
|
||||
timeout,
|
||||
&user_agent,
|
||||
false,
|
||||
@@ -391,7 +391,6 @@ impl Default for Configuration {
|
||||
force_recursion: false,
|
||||
update_app: false,
|
||||
proxy: String::new(),
|
||||
server_cert: String::new(),
|
||||
client_cert: String::new(),
|
||||
client_key: String::new(),
|
||||
config: String::new(),
|
||||
@@ -401,6 +400,7 @@ impl Default for Configuration {
|
||||
time_limit: String::new(),
|
||||
resume_from: String::new(),
|
||||
replay_proxy: String::new(),
|
||||
server_certs: Vec::new(),
|
||||
queries: Vec::new(),
|
||||
extensions: Vec::new(),
|
||||
methods: methods(),
|
||||
@@ -857,7 +857,6 @@ impl Configuration {
|
||||
// organizational breakpoint; all options below alter the Client configuration
|
||||
////
|
||||
update_config_if_present!(&mut config.proxy, args, "proxy", String);
|
||||
update_config_if_present!(&mut config.server_cert, args, "server_cert", String);
|
||||
update_config_if_present!(&mut config.client_cert, args, "client_cert", String);
|
||||
update_config_if_present!(&mut config.client_key, args, "client_key", String);
|
||||
update_config_if_present!(&mut config.replay_proxy, args, "replay_proxy", String);
|
||||
@@ -930,6 +929,12 @@ impl Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(certs) = args.get_many::<String>("server_certs") {
|
||||
for val in certs {
|
||||
config.server_certs.push(val.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
@@ -947,10 +952,10 @@ impl Configuration {
|
||||
Some(configuration.proxy.as_str())
|
||||
};
|
||||
|
||||
let server_cert = if configuration.server_cert.is_empty() {
|
||||
let server_certs = if configuration.server_certs.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(configuration.server_cert.as_str())
|
||||
Some(&configuration.server_certs)
|
||||
};
|
||||
|
||||
let client_cert = if configuration.client_cert.is_empty() {
|
||||
@@ -972,7 +977,7 @@ impl Configuration {
|
||||
|| configuration.insecure
|
||||
|| !configuration.headers.is_empty()
|
||||
|| configuration.resumed
|
||||
|| server_cert.is_some()
|
||||
|| server_certs.is_some()
|
||||
|| client_cert.is_some()
|
||||
|| client_key.is_some()
|
||||
{
|
||||
@@ -983,7 +988,7 @@ impl Configuration {
|
||||
configuration.insecure,
|
||||
&configuration.headers,
|
||||
proxy,
|
||||
server_cert,
|
||||
server_certs,
|
||||
client_cert,
|
||||
client_key,
|
||||
)
|
||||
@@ -1000,7 +1005,7 @@ impl Configuration {
|
||||
configuration.insecure,
|
||||
&configuration.headers,
|
||||
Some(&configuration.replay_proxy),
|
||||
server_cert,
|
||||
server_certs,
|
||||
client_cert,
|
||||
client_key,
|
||||
)
|
||||
@@ -1037,7 +1042,11 @@ impl Configuration {
|
||||
update_if_not_default!(&mut conf.target_url, new.target_url, "");
|
||||
update_if_not_default!(&mut conf.time_limit, new.time_limit, "");
|
||||
update_if_not_default!(&mut conf.proxy, new.proxy, "");
|
||||
update_if_not_default!(&mut conf.server_cert, new.server_cert, "");
|
||||
update_if_not_default!(
|
||||
&mut conf.server_certs,
|
||||
new.server_certs,
|
||||
Vec::<String>::new()
|
||||
);
|
||||
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);
|
||||
|
||||
@@ -641,10 +641,10 @@ impl<'a> Extractor<'a> {
|
||||
Some(self.handles.config.proxy.as_str())
|
||||
};
|
||||
|
||||
let server_cert = if self.handles.config.server_cert.is_empty() {
|
||||
let server_certs = if self.handles.config.server_certs.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(self.handles.config.server_cert.as_str())
|
||||
Some(&self.handles.config.server_certs)
|
||||
};
|
||||
|
||||
let client_cert = if self.handles.config.client_cert.is_empty() {
|
||||
@@ -666,7 +666,7 @@ impl<'a> Extractor<'a> {
|
||||
self.handles.config.insecure,
|
||||
&self.handles.config.headers,
|
||||
proxy,
|
||||
server_cert,
|
||||
server_certs,
|
||||
client_cert,
|
||||
client_key,
|
||||
)?;
|
||||
|
||||
@@ -392,35 +392,33 @@ pub fn initialize() -> Command {
|
||||
.help("Disables TLS certificate validation in the client"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("server_cert")
|
||||
.long("server-cert")
|
||||
.value_name("PEM/DER")
|
||||
Arg::new("server_certs")
|
||||
.long("server-certs")
|
||||
.value_name("PEM|DER")
|
||||
.value_hint(ValueHint::FilePath)
|
||||
.num_args(1)
|
||||
.num_args(1..)
|
||||
.help_heading("Client settings")
|
||||
.help(
|
||||
"Add a custom root certificate to connect to servers with a self-signed certificate",
|
||||
),
|
||||
).arg(
|
||||
.help("Add custom root certificate(s) for servers with unknown certificates"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("client_cert")
|
||||
.long("client-cert")
|
||||
.value_name("PEM")
|
||||
.value_hint(ValueHint::FilePath)
|
||||
.num_args(1)
|
||||
.requires("client_key")
|
||||
.help_heading("Client settings")
|
||||
.help(
|
||||
"Use a custom client SSL certificate for mutual authentication",
|
||||
),
|
||||
).arg(
|
||||
.help("Add a PEM encoded certificate for mutual authentication (mTLS)"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("client_key")
|
||||
.long("client-key")
|
||||
.value_name("PEM")
|
||||
.value_hint(ValueHint::FilePath)
|
||||
.num_args(1)
|
||||
.requires("client_cert")
|
||||
.help_heading("Client settings")
|
||||
.help(
|
||||
"Use a custom client SSL key file for mutual authentication",
|
||||
),
|
||||
.help("Add a PEM encoded private key for mutual authentication (mTLS)"),
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user