-
Notifications
You must be signed in to change notification settings - Fork 562
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1037 from blacklanternsecurity/baddns_module
Add Baddns Module
- Loading branch information
Showing
28 changed files
with
429 additions
and
464 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
from baddns.base import get_all_modules | ||
from baddns.lib.loader import load_signatures | ||
from .base import BaseModule | ||
|
||
import asyncio | ||
import logging | ||
from bbot.core.logger.logger import include_logger | ||
|
||
include_logger(logging.getLogger("baddns")) | ||
|
||
|
||
class baddns(BaseModule): | ||
watched_events = ["DNS_NAME", "DNS_NAME_UNRESOLVED"] | ||
produced_events = ["FINDING", "VULNERABILITY"] | ||
flags = ["active", "safe", "web-basic", "baddns", "cloud-enum", "subdomain-hijack"] | ||
meta = {"description": "Check hosts for domain/subdomain takeovers"} | ||
options = {"custom_nameservers": [], "only_high_confidence": False} | ||
options_desc = { | ||
"custom_nameservers": "Force BadDNS to use a list of custom nameservers", | ||
"only_high_confidence": "Do not emit low-confidence or generic detections", | ||
} | ||
max_event_handlers = 8 | ||
deps_pip = ["baddns~=1.1.0"] | ||
|
||
def select_modules(self): | ||
selected_modules = [] | ||
for m in get_all_modules(): | ||
if m.name in ["CNAME", "NS", "MX", "references", "TXT"]: | ||
selected_modules.append(m) | ||
return selected_modules | ||
|
||
async def setup(self): | ||
self.custom_nameservers = self.config.get("custom_nameservers", []) or None | ||
if self.custom_nameservers: | ||
self.custom_nameservers = self.helpers.chain_lists(self.custom_nameservers) | ||
self.only_high_confidence = self.config.get("only_high_confidence", False) | ||
self.signatures = load_signatures() | ||
return True | ||
|
||
async def handle_event(self, event): | ||
|
||
tasks = [] | ||
for ModuleClass in self.select_modules(): | ||
module_instance = ModuleClass( | ||
event.data, | ||
http_client_class=self.scan.helpers.web.AsyncClient, | ||
dns_client=self.scan.helpers.dns.resolver, | ||
custom_nameservers=self.custom_nameservers, | ||
signatures=self.signatures, | ||
) | ||
tasks.append((module_instance, asyncio.create_task(module_instance.dispatch()))) | ||
|
||
for module_instance, task in tasks: | ||
if await task: | ||
results = module_instance.analyze() | ||
if results and len(results) > 0: | ||
for r in results: | ||
r_dict = r.to_dict() | ||
|
||
if r_dict["confidence"] in ["CONFIRMED", "PROBABLE"]: | ||
data = { | ||
"severity": "MEDIUM", | ||
"description": f"{r_dict['description']}. Confidence: [{r_dict['confidence']}] Signature: [{r_dict['signature']}] Indicator: [{r_dict['indicator']}] Trigger: [{r_dict['trigger']}] baddns Module: [{r_dict['module']}]", | ||
"host": str(event.host), | ||
} | ||
await self.emit_event( | ||
data, "VULNERABILITY", event, tags=[f"baddns-{module_instance.name.lower()}"] | ||
) | ||
|
||
elif r_dict["confidence"] in ["UNLIKELY", "POSSIBLE"] and not self.only_high_confidence: | ||
data = { | ||
"description": f"{r_dict['description']} Confidence: [{r_dict['confidence']}] Signature: [{r_dict['signature']}] Indicator: [{r_dict['indicator']}] Trigger: [{r_dict['trigger']}] baddns Module: [{r_dict['module']}]", | ||
"host": str(event.host), | ||
} | ||
await self.emit_event( | ||
data, "FINDING", event, tags=[f"baddns-{module_instance.name.lower()}"] | ||
) | ||
else: | ||
self.warning(f"Got unrecognized confidence level: {r['confidence']}") | ||
|
||
found_domains = r_dict.get("found_domains", None) | ||
if found_domains: | ||
for found_domain in found_domains: | ||
await self.emit_event( | ||
found_domain, "DNS_NAME", event, tags=[f"baddns-{module_instance.name.lower()}"] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from baddns.base import get_all_modules | ||
from .baddns import baddns as baddns_module | ||
|
||
import logging | ||
from bbot.core.logger.logger import include_logger | ||
|
||
include_logger(logging.getLogger("baddns_zone")) | ||
|
||
|
||
class baddns_zone(baddns_module): | ||
watched_events = ["DNS_NAME"] | ||
produced_events = ["FINDING", "VULNERABILITY"] | ||
flags = ["active", "safe", "subdomain-enum", "baddns", "cloud-enum"] | ||
meta = {"description": "Check hosts for DNS zone transfers and NSEC walks"} | ||
options = {"custom_nameservers": [], "only_high_confidence": False} | ||
options_desc = { | ||
"custom_nameservers": "Force BadDNS to use a list of custom nameservers", | ||
"only_high_confidence": "Do not emit low-confidence or generic detections", | ||
} | ||
max_event_handlers = 8 | ||
deps_pip = ["baddns~=1.1.0"] | ||
|
||
def select_modules(self): | ||
selected_modules = [] | ||
for m in get_all_modules(): | ||
if m.name in ["NSEC", "zonetransfer"]: | ||
selected_modules.append(m) | ||
return selected_modules | ||
|
||
# minimize nsec records feeding back into themselves | ||
async def filter_event(self, event): | ||
if "baddns-nsec" in event.tags or "baddns-nsec" in event.source.tags: | ||
return False | ||
return True |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.