🛡️ Methodology Checklist
- Passive first: crt.sh, VirusTotal, SecurityTrails
- Active brute-force:
gobuster dns -d [DOMAIN] -w [WORDLIST] -t 50 - Resolver-based:
dnsx -d [DOMAIN] -w [WORDLIST] -resp - Permutation:
altdns -i subdomains.txt -o permuted.txt -w words.txt - Check for wildcard DNS before brute-force:
dig DOESNOTEXIST.[DOMAIN] - Resolve all discovered subdomains and remove dead ones
- Add live subdomains to Nmap target list
🎯 Operational Context
Use when: Passive CT log enumeration returns few subdomains; active brute needed to discover internal staging/dev/admin subdomains.
Think Dumber First: Run dnsx resolution check on passive results first — many CT log entries are dead. Only brute-force after passive sources are exhausted. Use dns.wordlists from SecLists subdomains-top1million-5000.txt before the full 110k list.
Skip when: DNS rate-limiting is detected (high NXDOMAIN rate) — slow down or switch resolvers.
⚡ Tactical Cheatsheet
| Command | Tactical Outcome |
|---|---|
dnsenum --enum [DOMAIN] -f [WORDLIST] -r | Comprehensive DNS brute-force with recursion |
dnsenum --dnsserver [TARGET_IP] --enum -p 0 -s 0 -o subdomains.txt -f [WORDLIST] [DOMAIN] | Targeted DNS server enumeration |
curl -s "https://crt.sh/?q=[DOMAIN]&output=json" | jq -r '.[] | .name_value' | sed 's/\*\.//g' | sort -u > crt_sh_results.txt | CT log extraction (run first!) |
sed -i 's/\*\.//g' crt_sh_results.txt | Remove wildcards from CT results |
sort -u crt_sh_results.txt -o crt_sh_results.txt | Remove duplicates |
cewl -d 2 -m 5 https://[DOMAIN] -w keywords.txt | Scrape target site for custom wordlist |
echo prefix-{1..20}.[DOMAIN] | tr ' ' '\n' > list.txt | Generate numbered pattern list |
echo {dev,test,prod}-{api,web,mail}.[DOMAIN] | tr ' ' '\n' > list.txt | Generate environment+service patterns |
cat crt_sh_results.txt > master_list.txt && cat cewl_output.txt >> master_list.txt && sort -u master_list.txt -o master_list.txt | Build master subdomain list |
🔬 Deep Dive & Workflow
Brute-Force Process
- Wordlist selection — general, targeted, or custom
- Iteration — tool appends each word:
dev+example.com=dev.example.com - DNS lookup — A/AAAA query for each candidate
- Validation — successful resolutions = valid subdomains
Tool Comparison
| Tool | Key Feature |
|---|---|
| dnsenum | Comprehensive — brute-force + zone transfers + Google scraping |
| fierce | Recursive + wildcard detection |
| amass | Extensive data source integration |
| puredns | Best for large result set filtering |
| assetfinder | Lightweight, quick scans |
dnsenum Flags
--enum— shortcut for common enumeration options-f [wordlist]— subdomain wordlist path-r— recursive brute-forcing (finds sub-subdomains)--dnsserver [IP]— target specific DNS server
Wordlist Paths (Kali/Parrot)
/usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt
/usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
Custom Wordlist Generation
# Naming convention patterns
echo prefix-{1..20}.[DOMAIN] | tr ' ' '\n' > list.txt
echo {dev,test,prod}-{api,web,mail}.[DOMAIN] | tr ' ' '\n' > list.txt
# Scrape target site for keywords
cewl -d 2 -m 5 https://[DOMAIN] -w keywords.txtTactic: If you find internal-v1, immediately create a list for v2 through v10.
Master List Strategy (Exam)
cat crt_sh_results.txt > master_list.txt # Start with passive
cat cewl_output.txt >> master_list.txt # Add scraped keywords
echo dev-0{1..9}.[DOMAIN] | tr ' ' '\n' >> master_list.txt # Add patterns
sort -u master_list.txt -o master_list.txt # DeduplicateLinux Redirection
>— overwrite/create new file>>— append to existing file
🛠️ Troubleshooting & Edge Cases
| Problem | Cause | Fix |
|---|---|---|
| All results return NXDOMAIN | Wrong base domain | Verify apex domain resolves; try with and without www |
| ffuf subdomain brute hits rate limit | Target DNS throttling | Add -rate 100 or use external resolvers with --resolver-list |
| Wildcard DNS returns everything as valid | Wildcard record configured | Run host randomstring123.target.com — if it resolves, wildcard is set; filter with --fw in ffuf |
| gobuster dns mode fails on VPN | Resolver mismatch | Force resolver: gobuster dns -r 8.8.8.8 -d target.com -w wordlist.txt |
| Subdomains resolve but return empty/403 | Internal vhost only | Fuzz Host header against IP: these are vhosts not subdomain records |
📝 Reporting Trigger
Finding Title: Unenumerated Subdomains Expose Additional Attack Surface Impact: Hidden subdomains (dev, staging, admin, api) frequently run older software versions or lack security controls applied to production, providing low-resistance entry points. Root Cause: No subdomain inventory management; development and staging subdomains left publicly accessible without network segmentation or authentication. Recommendation: Maintain a subdomain inventory and conduct periodic active enumeration. Place non-production environments behind VPN or IP allowlisting. Implement wildcard TLS certificates only where necessary.