Active Reconnaissance: DNS Enumeration with dig
dig (Domain Information Groper) is a powerful command-line tool for querying DNS servers and gathering information about domains, subdomains, mail servers, name servers, and more. Unlike passive reconnaissance, using dig makes direct queries to DNS servers, leaving traces in logs. It's essential for active reconnaissance and penetration testing.
What You'll Learn
- What dig is and how it works
- DNS record types (A, AAAA, MX, NS, TXT, etc.)
- Basic and advanced dig syntax
- DNS enumeration techniques
- Zone transfer attacks (AXFR)
- Reverse DNS lookups
- DNS cache snooping
- Automating DNS reconnaissance
- Defensive measures
What Is dig?
Overview:
dig = Domain Information Groper
Purpose:
- Query DNS servers
- Retrieve DNS records
- Troubleshoot DNS issues
- Enumerate domains/subdomains
Platform:
- Pre-installed on Linux/macOS
- Windows: Use nslookup or install BIND tools
How It Works:
You → dig → DNS Server → Response
Example:
$ dig example.com
1. dig sends query to DNS server
2. DNS server responds with records
3. dig displays results
Installation
Linux:
# Debian/Ubuntu
sudo apt update
sudo apt install dnsutils
# RHEL/CentOS/Fedora
sudo dnf install bind-utils
# Arch
sudo pacman -S bind-tools
macOS:
# Pre-installed
dig --version
# If not installed (via Homebrew):
brew install bind
Windows:
Option 1: Use nslookup (pre-installed):
nslookup example.com
Option 2: Install BIND tools:
# Download BIND from ISC website
# Or use Windows Subsystem for Linux (WSL)
Basic dig Usage
Simple Query:
dig example.com
Output:
; <<>> DiG 9.18.1 <<>> example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 3600 IN A 93.184.216.34
;; Query time: 45 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Jan 01 12:00:00 PST 2024
;; MSG SIZE rcvd: 56
Short Answer Only:
dig example.com +short
Output:
93.184.216.34
DNS Record Types
A Record (IPv4 Address):
dig example.com A
# Or just:
dig example.com
Returns IPv4 address for domain.
AAAA Record (IPv6 Address):
dig example.com AAAA
Returns IPv6 address for domain.
MX Record (Mail Exchange):
dig example.com MX
Returns mail servers for domain:
example.com. 3600 IN MX 10 mail.example.com.
example.com. 3600 IN MX 20 mail2.example.com.
Priority: Lower number = higher priority
NS Record (Name Servers):
dig example.com NS
Returns authoritative name servers:
example.com. 3600 IN NS ns1.example.com.
example.com. 3600 IN NS ns2.example.com.
TXT Record (Text):
dig example.com TXT
Returns text records (SPF, DMARC, verification, etc.):
example.com. 3600 IN TXT "v=spf1 include:_spf.google.com ~all"
example.com. 3600 IN TXT "google-site-verification=ABC123..."
CNAME Record (Canonical Name):
dig www.example.com CNAME
Returns alias (canonical name):
www.example.com. 3600 IN CNAME example.com.
SOA Record (Start of Authority):
dig example.com SOA
Returns zone authority information:
example.com. 3600 IN SOA ns1.example.com. admin.example.com. (
2024010101 ; serial
3600 ; refresh
1800 ; retry
1209600 ; expire
86400 ) ; minimum TTL
PTR Record (Reverse DNS):
dig -x 93.184.216.34
Returns hostname for IP address.
ANY Record (All Records):
dig example.com ANY
⚠️ Note: Many DNS servers now refuse ANY queries due to DDoS abuse.
Advanced dig Techniques
Specify DNS Server:
# Use Google DNS
dig @8.8.8.8 example.com
# Use Cloudflare DNS
dig @1.1.1.1 example.com
# Use specific name server
dig @ns1.example.com example.com
Query Multiple Records:
dig example.com A MX NS
Trace DNS Resolution Path:
dig +trace example.com
Shows full DNS resolution path from root servers down:
. 518400 IN NS a.root-servers.net.
com. 172800 IN NS a.gtld-servers.net.
example.com. 172800 IN NS ns1.example.com.
example.com. 3600 IN A 93.184.216.34
Reverse DNS Lookup:
# Method 1: -x flag
dig -x 93.184.216.34
# Method 2: Manual PTR query
dig 34.216.184.93.in-addr.arpa PTR
Batch Queries:
# From file
dig -f domains.txt
# domains.txt:
# example.com
# google.com
# github.com
Disable Recursion:
dig +norecurs example.com @ns1.example.com
Only queries specified server, doesn't recurse.
DNS Enumeration for Penetration Testing
1. Basic Domain Information:
# Get A record
dig example.com +short
# Get all name servers
dig example.com NS +short
# Get mail servers
dig example.com MX +short
# Get TXT records (SPF, DMARC, etc.)
dig example.com TXT +short
2. Subdomain Enumeration:
Brute Force with Wordlist:
#!/bin/bash
DOMAIN="example.com"
WORDLIST="subdomains.txt"
while read subdomain; do
result=$(dig ${subdomain}.${DOMAIN} +short)
if [ -n "$result" ]; then
echo "[+] ${subdomain}.${DOMAIN} -> $result"
fi
done < $WORDLIST
Common Subdomains to Test:
www
mail
ftp
admin
dev
staging
test
api
vpn
remote
portal
blog
shop
3. Zone Transfer Attack (AXFR):
What is it?
Zone transfer = Copy entire DNS zone
Originally for:
- Replicating zones between name servers
Security issue:
- If misconfigured, anyone can request
- Reveals ALL subdomains
- Massive information disclosure
Attempt Zone Transfer:
# Get name servers first
dig example.com NS +short
# Try zone transfer on each NS
dig @ns1.example.com example.com AXFR
dig @ns2.example.com example.com AXFR
If successful:
example.com. 3600 IN SOA ...
example.com. 3600 IN NS ns1.example.com.
www.example.com. 3600 IN A 93.184.216.34
mail.example.com. 3600 IN A 93.184.216.35
ftp.example.com. 3600 IN A 93.184.216.36
admin.example.com. 3600 IN A 192.168.1.10
dev.example.com. 3600 IN A 10.0.0.5
...
Jackpot! All subdomains revealed including internal IPs!
If denied (properly configured):
; Transfer failed.
4. Reverse DNS Enumeration:
# Get IP range for target
whois example.com | grep CIDR
# Reverse lookup each IP in range
for ip in 93.184.216.{1..255}; do
dig -x $ip +short
done
# Find other domains on same network
5. Cache Snooping:
# Check if domain is cached (no recursion)
dig @8.8.8.8 example.com +norecurs
# If cached, server has recently resolved it
# Can reveal what domains an organization queries
Automating DNS Reconnaissance
Bash Script - Comprehensive DNS Enum:
#!/bin/bash
DOMAIN=$1
if [ -z "$DOMAIN" ]; then
echo "Usage: $0 <domain>"
exit 1
fi
echo "[*] DNS Enumeration for: $DOMAIN"
echo ""
echo "[*] A Records:"
dig $DOMAIN A +short
echo ""
echo "[*] AAAA Records:"
dig $DOMAIN AAAA +short
echo ""
echo "[*] MX Records:"
dig $DOMAIN MX +short
echo ""
echo "[*] NS Records:"
NS_SERVERS=$(dig $DOMAIN NS +short)
echo "$NS_SERVERS"
echo ""
echo "[*] TXT Records:"
dig $DOMAIN TXT +short
echo ""
echo "[*] SOA Record:"
dig $DOMAIN SOA +short
echo ""
echo "[*] Attempting Zone Transfer:"
for ns in $NS_SERVERS; do
echo " [*] Trying $ns"
dig @$ns $DOMAIN AXFR
done
echo ""
echo "[*] Done!"
Usage:
chmod +x dns_enum.sh
./dns_enum.sh example.com
Python Script:
import dns.resolver
import dns.zone
import dns.query
import sys
def dns_enum(domain):
print(f"[*] DNS Enumeration for: {domain}\n")
# A Records
try:
answers = dns.resolver.resolve(domain, 'A')
print("[*] A Records:")
for rdata in answers:
print(f" {rdata}")
except:
print("[*] No A records")
# MX Records
try:
answers = dns.resolver.resolve(domain, 'MX')
print("\n[*] MX Records:")
for rdata in answers:
print(f" {rdata.preference} {rdata.exchange}")
except:
print("[*] No MX records")
# NS Records
try:
answers = dns.resolver.resolve(domain, 'NS')
print("\n[*] NS Records:")
ns_servers = []
for rdata in answers:
print(f" {rdata}")
ns_servers.append(str(rdata))
except:
print("[*] No NS records")
return
# TXT Records
try:
answers = dns.resolver.resolve(domain, 'TXT')
print("\n[*] TXT Records:")
for rdata in answers:
print(f" {rdata}")
except:
print("[*] No TXT records")
# Zone Transfer
print("\n[*] Attempting Zone Transfer:")
for ns in ns_servers:
try:
zone = dns.zone.from_xfr(dns.query.xfr(ns, domain))
print(f" [+] Zone transfer successful from {ns}:")
for name, node in zone.nodes.items():
print(f" {name}.{domain}")
except:
print(f" [-] Zone transfer failed from {ns}")
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python3 dns_enum.py <domain>")
sys.exit(1)
domain = sys.argv[1]
dns_enum(domain)
Installation:
pip install dnspython
Usage:
python3 dns_enum.py example.com
Defensive Measures
For DNS Administrators:
1. Disable Zone Transfers to Unauthorized Hosts:
BIND (named.conf):
zone "example.com" {
type master;
file "/etc/bind/zones/db.example.com";
// Only allow zone transfers to specific IPs
allow-transfer {
192.168.1.10; // Secondary NS
192.168.1.11; // Another secondary
};
};
Windows DNS:
1. Open DNS Manager
2. Right-click zone → Properties
3. Zone Transfers tab
4. Select "Only to the following servers"
5. Add authorized secondary servers only
2. Use DNSSEC:
DNSSEC = DNS Security Extensions
Benefits:
- Authenticates DNS responses
- Prevents cache poisoning
- Verifies data integrity
Implementation:
- Sign DNS zones
- Publish DNSKEY and RRSIG records
- Chain of trust from root
3. Rate Limiting:
Prevent DNS enumeration via rate limiting:
- Limit queries per IP
- Throttle suspicious patterns
- Block after threshold
4. Monitor DNS Logs:
Watch for:
- Zone transfer attempts
- Excessive queries from single IP
- Queries for non-existent subdomains (enumeration)
- Unusual query patterns
Tools:
- dnstop (real-time DNS monitoring)
- DNS logging to SIEM
5. Split-Horizon DNS:
Internal view:
- Full DNS info for internal clients
External view:
- Limited DNS info for internet
- Only public-facing records
- Hide internal infrastructure
dig vs nslookup vs host
Comparison:
dig:
✓ Most detailed output
✓ Best for troubleshooting
✓ Flexible query options
✓ Standard on Linux/macOS
nslookup:
✓ Simple queries
✓ Interactive mode
✓ Cross-platform (Windows!)
✗ Less detailed
host:
✓ Simplest output
✓ Quick lookups
✓ Good for scripts
✗ Fewer options
Examples:
dig:
dig example.com +short
nslookup:
nslookup example.com
host:
host example.com
Try It Yourself
Exercise 1: Basic DNS Queries
# A record
dig google.com +short
# MX records
dig google.com MX
# Name servers
dig google.com NS
# TXT records (SPF, DKIM, etc.)
dig google.com TXT
Exercise 2: Trace DNS Resolution
dig +trace google.com
# Observe path from root servers down
Exercise 3: Zone Transfer
# Find a vulnerable zone (for practice):
# zonetransfer.me is intentionally vulnerable
dig @nsztm1.digi.ninja zonetransfer.me AXFR
# See all subdomains revealed!
Exercise 4: Subdomain Enumeration
# Create wordlist
echo -e "www\nmail\nftp\nadmin\ndev\ntest" > subs.txt
# Test each
while read sub; do
dig ${sub}.example.com +short
done < subs.txt
Quick Reference
Basic Queries:
dig domain.com # A record
dig domain.com MX # Mail servers
dig domain.com NS # Name servers
dig domain.com TXT # TXT records
dig domain.com +short # Short output
Advanced:
dig @8.8.8.8 domain.com # Specific DNS server
dig +trace domain.com # Trace resolution
dig -x IP_ADDRESS # Reverse lookup
dig @ns1.domain.com domain.com AXFR # Zone transfer
Batch:
dig -f domains.txt # Query multiple
Output Control:
dig domain.com +short # Short
dig domain.com +noall +answer # Only answer section
Resources
Documentation:
- dig man page:
man dig - ISC BIND: https://www.isc.org/bind/
Tools:
- dnsutils (Linux):
apt install dnsutils - bind-tools (RHEL):
dnf install bind-utils - dnspython (Python):
pip install dnspython
Practice:
- zonetransfer.me: Intentionally vulnerable for zone transfer practice
- DNS Dumpster: https://dnsdumpster.com (online DNS recon)
Reading:
Next Steps
- Master basic dig queries for all record types
- Practice subdomain enumeration with wordlists
- Attempt zone transfers (authorized targets only!)
- Automate DNS reconnaissance with scripts
- Combine with other tools (nmap, sublist3r, amass)
DNS enumeration is a critical first step in penetration testing. Master dig to uncover target infrastructure!