Black Lantern Security is publicly releasing our new Python DNS auditing tool, BadDNS.
It’s primarily a subdomain takeover detection tool but covers other DNS related issues like zone transfers and NSEC walking as well.
Some of the discussion assumes prior knowledge of various DNS record types and of subdomain takeover concepts. Here’s a good primer for those who need it.
Introduction
Let’s jump into the obvious question first: Why another subdomain takeover tool?
There are lots of subdomain takeover tools already, including some we really like. But, we wanted to pair solid subdomain takeover detection with exceptional domain discovery, so as to be able to look for these issues at massive scale, and against the hardest to find domains. That is why although BadDNS is a standalone command line tool, it is built from the ground up to integrate into BBOT with its own BBOT module.
We are simultaneously releasing BadDNS and also upgrading our existing subdomain takeover capabilities in BBOT to use BadDNS.
Integrating an existing tool into BBOT in this case wasn’t straightforward, and would have required us to make a lot of compromises that would have introduced significant performance issues and limited some of our detection methodology.
We are also doing a few unique things that most other tools aren’t, such as with our references and txt modules. Before we talk about those, let’s start by going though all of the modules, beginning with those that may be the most familiar.
BadDNS Modules
cname - Check for dangling CNAME records and interrogate them for subdomain takeover opportunities
ns - Check for dangling NS records and interrogate them for takeover opportunities
mx - Check for dangling MX records and assess their base domains for availability
nsec - Enumerate subdomains by NSEC-walking
references - Check HTML content for links or other references that contain a hijackable domain
txt - Check TXT record contents for hijackable domains
zonetransfer - Attempt a DNS zone transfer
cname
Dangling CNAMEs are the most common type of subdomain takeover; this module detects several types of takeovers associated with them. This can include service-specific takeovers, like those pointing to Azure or AWS assets, for example. The logic for this type of takeover is usually wrapped up in signatures, which we will discuss more later.
It will also look at the parent domain, to see if it’s unregistered or expired (using WHOIS data). If you can takeover the parent domain, you obviously control all it’s subdomains as well.
ns
Dangling NS records are also fairly common, although it’s getting harder to find exploitable ones recently. AWS’s route53 service used to be one of the more reliably exploitable types of dangling NS records. We aren’t exactly sure what AWS is doing behind the scenes to protect their customers (if anyone knows, please share!), but they are definitely doing something. However, we have confirmed that it is still at least sometimes possible to successfully perform a takeover with them.
Like CNAME takeovers, NS takeovers are also based on signatures because exploitation depends on the particular service they are associated with.
mx
A takeover based on a dangling MX record can be accomplished if the base domain is available for registration. BadDNS will use WHOIS data to attempt to detect this condition.
Taking over a dangling MX record allows attackers to intercept and potentially manipulate email communications, leading to data breaches, loss of confidentiality, and compromised email functionality. The severity of the impact depends on the priority settings of the MX records.
references
The references module starts to cover some ground most tools don’t. This detects takeovers in JavaScript or CSS includes present in the HTTP content of the target. Another way to think of this kind of takeover is as a “second-order” subdomain takeover. Control of the domain where JavaScript is loaded from has roughly the same consequences as a stored cross-site scripting vulnerability, for example. Behind the scenes, the cname module is being called against the domains found to be hosting JS/CSS content.
In the future, we plan to also look at domains found in CORS/CSP headers vulnerable to takeovers.
txt
The txt modules looks at DNS txt records for domain names. If it finds one, it runs the cname module against them. A hit here might not be significant at all – it completely depends on how the organization is using the txt record, which is probably all over the map.
This type of detection is the least likely to be exploitable - but if it is, it could be very interesting. If you get a detection here, it's worth doing the takeover and just spinning up a server and seeing what requests get sent to it.
The previous BBOT subdomain_hijack module introduced this concept, and we expand on it with BadDNS.
zonetransfer
The zonetransfer module in BadDNS specifically targets the potential vulnerability associated with DNS zone transfers, a critical process for synchronizing record information between a primary DNS server and its secondary servers. While zone transfers are vital for DNS operation, they can expose an organization's full DNS records if not properly secured.
The zonetransfer module attempts to perform a zone transfer on the authoritative name servers for a target domain. If the attempt is successful, it not only completes the zone transfer but also compiles and presents all harvested records, potentially unveiling a detailed map of the organization's DNS infrastructure.
nsec
The nsec module in BadDNS utilizes “NSEC walking” to enumerate DNS zones by exploiting the way NSEC records function within DNSSEC. NSEC records, intended to secure DNS by confirming the absence of specific DNS entries, inadvertently disclose the name of the next domain in the zone sequence. The module leverages this feature to make sequential queries, effectively mapping the entire domain structure within a DNS zone, including subdomains and entries that may be sensitive or intended to remain private. This enumeration can reveal a comprehensive view of the DNS zone's structure, including details not intended for public access.
With both zonetransfer and nsec, when used with BBOT, any discovered domains are automatically fed back into the scan.
Generic Detections
Another important concept with BadDNS are “generic” detections. This occurs when a dangling CNAME or NS record is found, but there is no signature match indicating the possibility for exploitation. Alerting on these are important for the discovery of new subdomain takeover signatures, as they will essentially point out which services are frequently producing dangling records and therefore need to be researched. In BBOT, these will be emitted as FINDING events (whereas signature detections will be VULNERABILITY events).
Signatures
That brings us to the other big reason for creating BadDNS – the issue of takeover signatures.
Currently, there isn’t a single source of signatures or research into takeovers. However, we have found the most useful signatures are those in Nuclei Templates, and within the tool dnsReaper. For discussions and research, the community has coalesced around the GitHub repository can-i-take-over-xyz. Its issues page has become a common location for discussions about takeover techniques.
We have observed a hesitancy in the community for any one entity to become the ‘authority’ on takeover signatures, which we completely understand and share ourselves. This directed our approach of ingesting the best sources of signatures already present and converting them automatically into our format. Currently, we ‘absorb’ signatures from Nuclei and dnsReaper using automated GitHub actions. These are then generated into pull requests we can quickly and easily review, complete with automatic testing of the generated signatures. This allows us to utilize whatever the community comes up with in terms of new signatures, while not making ourselves the direct maintainers of them, and also allowing us the room to create our own signatures or modify existing ones if needed.
Usage
Here’s some basic usage information to get you started:
CLI
First of all, the standalone BadDNS CLI is embedded within our pypi package. So all you need to do is install with pip:
pip install baddns
After that, you can run BadDNS by just typing `baddns` in your console.
Usage
Positional arguments:
target subdomain to analyze
options:
-h, --help show this help message and exit
-n CUSTOM_NAMESERVERS, --custom-nameservers CUSTOM_NAMESERVERS
Provide a list of custom nameservers separated by comma.
-c CUSTOM_SIGNATURES, --custom-signatures CUSTOM_SIGNATURES
Use an alternate directory for loading signatures
-l, --list-modules List available modules and their descriptions.
-m MODULES, --modules MODULES
Comma separated list of module names to use. Ex: module1,module2,module3
-d, --debug Enable debug logging
BBOT
Using BadDNS with BBOT allows for checking for DNS related issues at immense scale, taking advantage of its cutting-edge DNS recon capabilities.
For information on using BBOT, please refer to the BBOT Documentation.
To do so, just run bbot with -m baddns(
the baddns package will automatically be install by BBOT). To combine with subdomain enumeration, run it along with the subdomain-enum flag, as shown below:
bbot –f subdomain-enum –m baddns –t <targetdomain>
Research
One goal for BadDNS is that it can be used as a starting point for research into novel DNS-related vulnerabilities. Its modular design and import-friendly architecture facilitate rapid prototyping of new detection code.
We have already encountered instances of DNS behaving in bizarre and unexpected ways. For example, during the course of creating the ns module, we discovered that many DNS servers were essentially lying to us about NS records. If the NS record was present, but there was no associated SOA record (basically the definition of a dangling NS record) all but a small percentage of servers would happily report back that there were no NS records at all.
We wondered how much this behavior may have affected other tools’ ability to detect dangling NS records. The solution isn’t too complicated - we just need to perform a fully recursive lookup for these records, ignoring any caching, starting at the root DNS servers and moving forward. This was so important for detecting dangling NS records that we built our own recursive resolving class from scratch.
The weirdest thing was actually that something like 5% of DNS servers would always tell us the truth and report the dangling NS records. We briefly considered using this handful of servers as a shortcut, but ultimately decided that was not sustainable and wrote the recursive lookup code instead.
We are also looking forward to exploring more unusual behavior in newer DNS components like NSEC3 and other parts of DNSSEC. The added complexity that comes along with the added security potentially creates more opportunities for abuse.