Skip to content

Commit

Permalink
Merge pull request #400 from blacklanternsecurity/logging_sync
Browse files Browse the repository at this point in the history
Logging sync
  • Loading branch information
liquidsec authored Jan 17, 2024
2 parents f03e5df + fdb7cd2 commit 92671e4
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 19 deletions.
16 changes: 15 additions & 1 deletion baddns/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@

class BadDNS_base:
def __init__(
self, target, http_client_class=None, dns_client=None, signatures_dir=None, custom_nameservers=None, **kwargs
self,
target,
http_client_class=None,
dns_client=None,
signatures_dir=None,
custom_nameservers=None,
cli=False,
**kwargs,
):
self.http_client_class = http_client_class
self.dns_client = dns_client
Expand All @@ -21,6 +28,13 @@ def __init__(
self.load_signatures(signatures_dir)
self.custom_nameservers = custom_nameservers
self.parent_class = kwargs.get("parent_class", "self")
self.cli = cli

def infomsg(self, msg):
if self.cli:
log.info(msg)
else:
log.debug(msg)

def load_signatures(self, signatures_dir=None):
if signatures_dir:
Expand Down
4 changes: 3 additions & 1 deletion baddns/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ def validate_modules(arg_value, pattern=re.compile(r"^[a-zA-Z0-9_]+(,[a-zA-Z0-9_
async def execute_module(ModuleClass, target, custom_nameservers, signatures_dir):
findings = None
try:
module_instance = ModuleClass(target, custom_nameservers=custom_nameservers, signatures_dir=signatures_dir)
module_instance = ModuleClass(
target, custom_nameservers=custom_nameservers, signatures_dir=signatures_dir, cli=True
)
except BadDNSSignatureException as e:
log.error(f"Error loading signatures: {e}")
raise BadDNSCLIException(f"Error loading signatures: {e}")
Expand Down
6 changes: 3 additions & 3 deletions baddns/lib/findings.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ def __init__(self, finding_dict):
raise BadDNSFindingException("Module was not a valid baddns module")
self.finding_dict["module"] = module.name

data = finding_dict.get("data", None)
if data:
self.finding_dict["data"] = data
found_domains = finding_dict.get("found_domains", None)
if found_domains:
self.finding_dict["found_domains"] = found_domains

def to_dict(self):
return self.finding_dict
Expand Down
6 changes: 3 additions & 3 deletions baddns/modules/cname.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ async def dispatch(self):
await self.target_dnsmanager.dispatchDNS()
if self.direct_mode == False:
if self.target_dnsmanager.answers["CNAME"] != None:
log.info(
self.infomsg(
f"Found CNAME(S) [{' -> '.join([self.target_dnsmanager.target] + self.target_dnsmanager.answers['CNAME'])}]"
)
self.subject = self.target_dnsmanager.answers["CNAME"][-1]
else:
if self.parent_class == "self":
log.info("No CNAME Found :/")
self.infomsg("No CNAME Found :/")
return False
else:
log.debug("Direct mode enabled. Target will be checked for takeover instead of target's CNAME")
Expand Down Expand Up @@ -69,7 +69,7 @@ def analyze(self):
signature_match = False
indicator = None

log.info(f"Got NXDOMAIN for CNAME {self.cname_dnsmanager.target}. Checking against signatures...")
self.infomsg(f"Got NXDOMAIN for CNAME {self.cname_dnsmanager.target}. Checking against signatures...")
for sig in self.signatures:
if sig.signature["mode"] == "dns_nxdomain":
log.debug(f"Trying signature {sig.signature['service_name']}")
Expand Down
2 changes: 1 addition & 1 deletion baddns/modules/ns.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async def dispatch(self):
await self.target_dnsmanager.dispatchDNS(omit_types=[["A", "AAAA", "MX", "NS", "SOA", "TXT", "NSEC"]])

if self.target_dnsmanager.answers["CNAME"] != None:
log.info(
self.infomsg(
f"Detected CNAME(S). Will set target to end of CNAME chain: [{self.target_dnsmanager.answers['CNAME'][-1]}]"
)
self.target_dnsmanager.target = self.target_dnsmanager.answers["CNAME"][-1]
Expand Down
4 changes: 2 additions & 2 deletions baddns/modules/nsec.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async def dispatch(self):
return False

self.nsec_chain.append(self.target)
log.info(f"NSEC Records detected, attempting NSEC walk against domain [{self.target}]")
self.infomsg(f"NSEC Records detected, attempting NSEC walk against domain [{self.target}]")
await self.nsec_walk(self.target_dnsmanager.answers["NSEC"][0])
return True

Expand All @@ -61,7 +61,7 @@ def analyze(self):
"indicator": "NSEC Records",
"trigger": self.target,
"module": type(self),
"data": self.nsec_chain,
"found_domains": self.nsec_chain,
}
)
)
Expand Down
2 changes: 1 addition & 1 deletion baddns/modules/txt.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ async def dispatch(self):
for match in DNSManager.dns_name_regex.finditer(txt_record):
start, end = match.span()
host = txt_record[start:end]
log.info(f"Found host [{host}] in TXT record [{txt_record}] and analyzing with CNAME module")
self.infomsg(f"Found host [{host}] in TXT record [{txt_record}] and analyzing with CNAME module")

cname_instance_direct = BadDNS_cname(
host,
Expand Down
18 changes: 11 additions & 7 deletions baddns/modules/zonetransfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ class BadDNS_zonetransfer(BadDNS_base):

def __init__(self, target, **kwargs):
super().__init__(target, **kwargs)

self.target_dnsmanager = DNSManager(target, dns_client=self.dns_client)

def parse_zone(self, zone):
Expand All @@ -32,16 +31,19 @@ def parse_zone(self, zone):
else:
processed_name = f"{raw_name}.{self.target_dnsmanager.target}"
record = (processed_name, record_type, rdata.to_text())
if record not in self.zone_records:
self.zone_records.append(record)
if record[0] not in self.zone_records:
self.zone_records.append(record[0])

async def zone_transfer(self, nameserver, domain):
ns_ips = await self.target_dnsmanager.do_resolve(nameserver, "A")
ns_ip = ns_ips[0]
try:
zone = await asyncio.to_thread(dns.zone.from_xfr, dns.query.xfr(ns_ip, domain, timeout=10))
except TimeoutError:
log.warning("TimeoutError attempting zone transfer")
except dns.exception.Timeout:
log.debug("TimeoutError attempting zone transfer")
return False
except ConnectionResetError:
log.debug("ConnectionResetError attempting zone transfer")
return False
except dns.xfr.TransferError as e:
log.debug(f"{nameserver} ({ns_ip}): {e}")
Expand All @@ -51,16 +53,18 @@ async def zone_transfer(self, nameserver, domain):
return True

async def dispatch(self):
zone_transfer_detected = False
await self.target_dnsmanager.dispatchDNS(omit_types=["A", "MX", "AAAA", "CNAME", "SOA", "TXT", "NSEC"])
if self.target_dnsmanager.answers["NS"]:
for ns in self.target_dnsmanager.answers["NS"]:
log.debug(f"Attempting Zone Transfer against NS [{ns}] for target [{self.target_dnsmanager.target}]")
r = await self.zone_transfer(ns, self.target_dnsmanager.target)
if r:
zone_transfer_detected = True
log.info(
f"Successful Zone Transfer against NS [{ns}] for target [{self.target_dnsmanager.target}]"
)
return True
return zone_transfer_detected

def analyze(self):
findings = []
Expand All @@ -75,7 +79,7 @@ def analyze(self):
"indicator": "Successful XFR Request",
"trigger": self.zone_nameservers,
"module": type(self),
"data": self.zone_records,
"found_domains": self.zone_records,
}
)
)
Expand Down

0 comments on commit 92671e4

Please sign in to comment.