Skip to content

Commit

Permalink
new: --dns-ip-lookup option
Browse files Browse the repository at this point in the history
  • Loading branch information
evilsocket committed Jan 31, 2024
1 parent 67070d8 commit c7cea27
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 10 deletions.
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ reqwest = { version = "=0.11.20", features = [
base64 = { version = "0.21.4", optional = true }
ntlmclient = { version = "0.1.0", optional = true }
trust-dns-resolver = { version = "0.23.0", optional = true }
dns-lookup = { version = "2.0.4", optional = true }
async-ssh2-tokio = { version = "0.8.2", optional = true }
sqlx = { version = "0.7.2", features = [
"runtime-tokio",
Expand Down Expand Up @@ -117,7 +118,7 @@ default = [
]
http = ["dep:url", "dep:reqwest", "dep:base64", "dep:ntlmclient"]
http_relative_paths = []
dns = ["dep:trust-dns-resolver"]
dns = ["dep:trust-dns-resolver", "dep:dns-lookup"]
ssh = ["dep:async-ssh2-tokio"]
sql = ["dep:sqlx"]
mssql = []
Expand Down
42 changes: 33 additions & 9 deletions src/plugins/dns/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ fn register() {
#[derive(Clone)]
pub(crate) struct DNS {
resolver: Option<TokioAsyncResolver>,
opts: options::Options,
}

impl DNS {
pub fn new() -> Self {
DNS { resolver: None }
DNS {
resolver: None,
opts: options::Options::default(),
}
}
}

Expand All @@ -40,6 +44,7 @@ impl Plugin for DNS {
}

fn setup(&mut self, opts: &Options) -> Result<(), Error> {
self.opts = opts.dns.clone();
self.resolver = Some(if let Some(resolvers) = opts.dns.dns_resolvers.as_ref() {
let ips: Vec<IpAddr> = resolvers
.split(',')
Expand Down Expand Up @@ -75,20 +80,39 @@ impl Plugin for DNS {

async fn attempt(&self, creds: &Credentials, _: Duration) -> Result<Option<Loot>, Error> {
let subdomain = format!("{}.{}", creds.single(), &creds.target);
// attempt resolving this subdomain to a one or more IP addresses
if let Ok(response) = self.resolver.as_ref().unwrap().lookup_ip(&subdomain).await {
// collect valid IPs
let addresses: Vec<IpAddr> = response.iter().filter(|ip| !ip.is_loopback()).collect();
if !addresses.is_empty() {
let loot_data = if self.opts.dns_ip_lookup {
// perform reverse lookup of the IPs if we have to
let mut parts = vec![];

for ip in &addresses {
if let Ok(hostname) = dns_lookup::lookup_addr(ip) {
if hostname != subdomain {
parts.push(format!("{} ({})", ip.to_string(), hostname));
}
} else {
parts.push(ip.to_string());
}
}

parts.join(", ")
} else {
// just join the IPs
addresses
.iter()
.map(|a| a.to_string())
.collect::<Vec<String>>()
.join(", ")
};

return Ok(Some(Loot::new(
"dns",
&subdomain,
[(
"addresses".to_owned(),
addresses
.iter()
.map(|a| a.to_string())
.collect::<Vec<String>>()
.join(", "),
)],
[("addresses".to_owned(), loot_data)],
)));
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/dns/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ pub(crate) struct Options {
#[clap(long, default_value_t = 1)]
/// Number of retries after lookup failure before giving up.
pub dns_attempts: usize,
#[clap(long)]
/// Perform ip to hostname lookup.
pub dns_ip_lookup: bool,
}

0 comments on commit c7cea27

Please sign in to comment.