Satellite view of the Earth at night showing lights from cities around the world.

Now, the fun begins. If you followed my last post about the basics of DNS, you should be armed and ready to tackle the subject of this post: DNS enumeration.

DNS enumeration is the process of obtaining as much information about a target as possible by pulling from publicly available DNS records. This can expand the attack surface of a target by revealing their internet facing servers, email addresses, and more depending on how extensively you enumerate.

The keyword in this definition is “publicly“. That means that all of the methods I’m about to show you in the next section you can try on your own (and I encourage you to do so).

However, it’s important to note that some automated scripts brute-force subdomains by default, which may overload some older servers. This is unlikely though, but just make sure you know what the tool is going to do before you fire it off.

With that being said, let’s get into enumerating DNS!

Manual Techniques

There are several scripts out there that allow you to automatically scrape tons of DNS information in a point and click fashion. However, it’s important to know how to manually enumerate DNS in order to modularize enumeration and adapt it to more specific situations.

Don’t let the term “manual” scare you though. I’m going to go over a few tools that will make this process a snap.


Using the Whois service is a great starting point in your quest for information. With just the domain name of a target’s website, you can pull it’s registrar information, geographic location of its servers, name servers associated with it, and contact information system admins and technical support.

The whois command is built into most UNIX based operating systems. So, if you’re running one of it’s variants like a Linux distro or MacOS, you can run:

whois <domain name>

You’ll quickly be overwhelmed with a bunch of information about that domain name. For this reason, I recommend using an online tool like They organize data a bit more graphically than the plain terminal-based whois command does.


If there’s one manual tool you need to know, it’s the dig command. Like whois, it comes prepackaged with many UNIX variants. Unlike whois, it’s much more powerful.

To use dig, follow this format:

dig @<name server> <domain name> <record type>

The name server and record type positional arguments are optional. You can use dig in the same way as you would whois:

[~]$ dig

; <<>> DiG 9.16.1-Ubuntu <<>>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4266
;; flags: qr ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;                    IN      A

;; ANSWER SECTION:             60      IN      A

;; Query time: 115 msec
;; WHEN: Tue Feb 28 19:17:22 PST 2023
;; MSG SIZE  rcvd: 44

By default, dig pulls A records and uses whatever nameserver it can access from my /etc/resolv.conf file. As you can see, it decided to use Google’s nameserver at

Of course, dig can be used for so much more. Let’s try pulling the nameservers of

[~]$ dig NS +short

In this example, I told dig to grab me the NS records associated with and keep the output short and sweet with the +short query modifier. I like to use +short with dig because the output can be pretty cluttered.

Another useful query type is the ANY query, which pulls all available records associated with a domain:

[~]$ dig ANY +noall +answer             60      IN      A             900     IN      NS             900     IN      NS             900     IN      NS             900     IN      NS             900     IN      NS             900     IN      NS             900     IN      NS             900     IN      NS             900     IN      SOA 1 7200 900 1209600 86400             3600    IN      MX      1             3600    IN      MX      10             3600    IN      MX      10             3600    IN      MX      5             3600    IN      MX      5

As you can see, dig was able to pull a variety of records, including SOA and MX. I also used the +noall combined with +answer query modifiers to single out the responses in the output. This is useful if you just want to see the results of a query (no annoying header messages) but want a little more info than what’s provided with +short.

Additionally, dig can initiate zone transfer. A zone transfer is the process DNS servers use to transfer copies of records of a particular zone to another server. This is primarily used for redunancy–if one server goes down, another server with copies of all the records will be able to resume operation in its place.

Misconfigured servers allow zone transfers to occur between anyone that requests it (including you). This can potentially leak private records.

With dig it’s as simple as:

[~]$ dig AXFR +noall +answer
; Transfer failed.

I used the AXFR query type to initiate a zone transfer with one of‘s nameservers. It didn’t let me. Good job GitHub.

This is usually the case as zone transfers are a well-known vulnerability. However, never rule them out. Company nameservers usually have multiple nameservers for redundancy. In some cases, backups might be overlooked in terms of hardening. So, try zone transfers against all of a target’s nameservers. You might get lucky.


Another tool worth mentioning that is very similar to dig and is bundled with most UNIX-based OS’s is host. Keep in mind this is not the same host command that is available on Windows by default.

Just typing host and supplying it a domain name can reveal some useful information:

[~]$ host has address has address has address has address has IPv6 address 2a04:4e42::396 has IPv6 address 2a04:4e42:600::396 has IPv6 address 2a04:4e42:400::396 has IPv6 address 2a04:4e42:200::396 mail is handled by 5 mail is handled by 1 mail is handled by 10 mail is handled by 10 mail is handled by 5

With just one argument, host was able to pull‘s A, AAAA, and MX records in an arguably cleaner fashion than dig.

A useful argument I like using when running host is a:

[~]$ host -a
Trying ""
Trying ""
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12601
;; flags: qr rd ra; QUERY: 1, ANSWER: 34, AUTHORITY: 0, ADDITIONAL: 0

;                    IN      ANY

;; ANSWER SECTION:             278     IN      A             278     IN      A             278     IN      A             278     IN      A             86378   IN      NS             86378   IN      NS             86378   IN      NS             86378   IN      NS             878     IN      SOA 1 7200 900 1209600 86400             278     IN      MX      5             278     IN      MX      1             278     IN      MX      10             278     IN      MX      10             278     IN      MX      5             3578    IN      TXT     "google-site-verification=zZHozYbAJmSLOMG4OjQFoHiVqkxtdgvyBzsE7wUGFiw"             3578    IN      TXT     "logmein-verification-code=1e307fc8-361a-4e39-8012-ed0873b06668"             3578    IN      TXT     "onetrust-domain-verification=6b98ba3dd087405399bbf45b6cbdcd37"             3578    IN      TXT     "stripe-verification=9bd70dd1884421b47f596fea301e14838c9825cdba5b209990968fdc6f8010c7"             3578    IN      TXT     "twilio-domain-verification=5e37855d7c9445e967b31c5e0371ebb5"             3578    IN      TXT     "v=spf1 ip4: ip4: ip4: ~all"             3578    IN      TXT     "614ac4be-8664-4cea-8e29-f84d08ad875c"             3578    IN      TXT     "MS=ms71041902"             3578    IN      TXT     "apple-domain-verification=qC3rSSKrh10DoMI7"             3578    IN      TXT     "atlassian-domain-verification=aGWDxGvt+oY3p7qTWt5v2uJDVJkoJAeHxwGqKmGQLMEsUXUJJe/Pm/k+GGNPpn6M"             3578    IN      TXT     "atlassian-domain-verification=vBaV6PXyyu4OAPLiQFbxFMCboSTjoR/qxKJ2OlpI46ZEpZL/FVTIfMlgoM5Hy9eY"             3578    IN      TXT     "box-domain-verification=95c33f4ee4b11d8827190dbc5371ca7df25b961019116e5565ce4aa36de9be3a"             3578    IN      TXT     "docusign=6ba0c5a9-5a5e-41f8-a7c8-8b4c6e35c10c"             3578    IN      TXT     "google-site-verification=0uv13-wxlHK8FFKaUpgzyrVmL1YdNYW6v3PupLdw3JI"             3578    IN      TXT     "google-site-verification=oh_YJE560y0e6FHP1RT7NIjyTlBhACNMvD2EgSss0sc"             278     IN      AAAA    2a04:4e42:200::396             278     IN      AAAA    2a04:4e42:400::396             278     IN      AAAA    2a04:4e42:600::396             278     IN      AAAA    2a04:4e42::396             86378   IN      CAA     0 issue "; cansignhttpexchanges=yes"

Received 1838 bytes from in 15 ms

As you can see, an absolutely enormous amount of information was pulled. That’s because using -a tells host to pull all of the records it can from it’s target.

You can also perform zone transfers:

[~]$ host -l
;; Connection to 123.456.78.9#53(123.456.78.9) for failed: connection refused.
;; Connection to 123.456.78.1#53(123.456.78.1) for failed: connection refused.

And it seems that the default nameserver (123.456.78.9) didn’t allow us to do this.


This tool functions fairly similarly to host and dig but has an optional interactive mode. This is useful for when you want to frequently options such as query types and nameservers without retyping the name of the command all over again.

Here’s a quick example:

[~]$ nslookup
> set type=NS
Server:         123.456.78.9
Address:        123.456.78.9#53

Non-authoritative answer:   nameserver =   nameserver =   nameserver =   nameserver =

Authoritative answers can be found from:
> server
Default server:
Default server:
Address: 2603:1061:0:10::27#53
> set type=MX
Address:   mail exchanger = 10

To access interactive mode, I ran nslookup without any arguments. From there I set the query type to NS to look up‘s nameservers, then used one of their nameservers to look up their mail servers.

As you can see, most of the commands I typed were only one or two words long. For this reason, I like nslookup for poking around if I’m not necessarily sure what I’m looking for and need to frequently update my commands.

It’s important to note that these three tools (dig, host, nslookup) function very similarly. So, I encourage you to try all of them, use them interchangeably, and read the man pages for each one. They each have their strengths and weaknesses. The one you choose depends on your situation and preferences.

Subdomain Enumeration

Subdomain enumeration is the process of finding as many subdomains associated with a domain as possible. This is an important process of DNS enumeration as it expands our attack surface even further. You can also apply the techniques described previously on the subdomains you find to make your enumeration even more effective.

Most modern search engines can be a useful tool for subdomain enumeration. If you read one of my earlier posts about Google Dorking, you may already be familiar with the technique I’m about to describe.

Google makes subdomain enumeration a snap with the inurl parameter:

iRobot’s subdomains provided by Google

Using inurl and the domain name,, I was able to find numerous subdomains. I also used -www to tell Google to exclude search results containing www.

Another powerful tool for subdomain enumeration is the Certificate Search tool: results from the query

The query I used to pull all of these results was, where the % symbol was a wild card. This means that results with anything ending with “” will be a part of the search results.

Combining these techniques is a powerful way of discovering subdomains that give you an edge by providing you with more information.

Automated Techniques

Now that you know some basic (but powerful) techniques for enumerating subdomains, its time to automate the process.

There’s tons of tools out there that do all of these steps (and more) to provide you with as much information associated with a domain name as possible. One popular one is dnsenum. As described in its man pages dnsenum can perform:

nslookup, zonetransfer, google scraping, domain brute force (support also recursion), whois ip and reverse lookups.

Here’s what I was able to pull by pointing this tool at

[~]$ dnsenum
dnsenum VERSION:1.2.6

-----   -----

Host's addresses:
__________________                          37       IN    A                          37       IN    A                          37       IN    A                          37       IN    A

Name Servers:
______________                        28800    IN    A                         13091    IN    A

Mail (MX) Servers:
___________________                   293      IN    A                 293      IN    A                 293      IN    A                      292      IN    A                   293      IN    A

Trying Zone Transfers and getting Bind Versions:

Trying Zone Transfer for on ...
AXFR record query failed: REFUSED

Trying Zone Transfer for on ...
AXFR record query failed: REFUSED

Brute forcing with /usr/share/dnsenum/dns.txt:
_______________________________________________                      86400    IN    CNAME               60       IN    A               60       IN    A               60       IN    A               60       IN    A

I cut the scan short but you can see it was able to pull some useful servers (as well as their IP addresses), find some domains, and attempted to do a zone transfer and figure out the DNS server’s bind version.

Other great tools include fierce, dnsrecon, and sublist3r (for enumerating subdomains). I encourage you to try them all out and see what tools work for you. There are also tons of opensource tools out there that I haven’t mentioned that you should try as well!

Now that you’ve seen a fantastic tool that formats everything you might need beautifully with color-coding, you may be asking yourself: “Why even bother with manual testing in the first place?”

While these tools are extremely efficient, they may not be a one line solution for all of your needs. It’s important when enumerating to supplement your automated information gathering with manual gathering.

Manual enumeration is extremely flexible, allowing you to poke around at every angle you can think of and dig deeper than some automated scripts. It’s also worth noting that these automated scripts generate a ton of traffic. So, in a scenario where stealth is required, it may be more appropriate to manual test to fly under the radar.


DNS enumeration is a critical step in the process of analyzing your target. When executed correctly, it can be used to expose a wealth of information. The more information you have on a target, the more effective your penetration test will be.

I only covered the basics to give you a starting point. I highly encourage you to look at the manual pages (with the man command, arguably the best UNIX command) to learn the ins and outs of these tools so you can make the most out of them. At the end of the day, these tools are simply lines of code–it’s up to you to make them useful.

Remember, this information is all public, so feel free to practice on your own (you definitely should) and see what you can dig up. Just be careful when using the brute-force tools against servers you don’t own (again read the man pages so you know what you’re doing) and don’t use any of the information you gather without permission.

That’s all and happy hunting! In the next post, I’m going to be talking about scanning with nmap so stay tuned for that!


The Cybermentor’s Web Hacking Course