| Tested on | Kali GNU/Linux Rolling 2026.2 (kali-rolling) |
|---|---|
| Package | amass 5.1.1-0kali1subfinder 2.15.0-0kali1assetfinder 0.1.1-1+b12sublist3r 1.1-5massdns 1.1.0-0kali2 |
| Lab environment | Pentest lab |
| Cert prep | CompTIA PenTest+ PT0-003 — Domain 2 (Reconnaissance and Enumeration) |
| Privilege | Normal user for enumeration commands; sudo for apt install |
| Scope | Passive subdomain discovery with Amass, Subfinder, Assetfinder, and Sublist3r; active DNS resolution and wordlist-based validation with massdns against the authorized training zone zonetransfer.me. Merge and deduplicate hostname lists for reporting. Does not cover subdomain takeover exploitation, puredns installs, or scanning domains without authorization. |
| Related guides | OSINT tools for pentesters |
Subdomain enumeration expands one apex domain into hostnames you might scan next. After DNS enumeration maps nameservers and record types, passive OSINT tools pull historical certificate and threat-intel data while active resolvers confirm which guesses answer in DNS today.
Here, subdomain enumeration means discovering hostname candidates and resolving them. Port or vulnerability scanning begins only after those names are confirmed and in scope. Scheduled subdomain monitoring or change detection is a separate workflow — this guide focuses on one-time discovery and DNS validation.
This guide runs every command against zonetransfer.me, a domain maintained for DNS and zone-transfer training. Commands need outbound Internet access from Kali.
Export these variables once per shell before the quick start commands. These exports last for the current shell only — re-run the block in a new terminal.
export DOMAIN=zonetransfer.me
export BRUTE_NS=nsztm1.digi.ninja
export LAB=/tmp/subdomain-lab
mkdir -p "$LAB"~/.config/amass/datasources.yaml, passive Amass often returns only the apex domain. Start with Subfinder and Assetfinder in the quick start below; add Amass keys when you need deeper passive coverage on real engagements.
Subdomain enumeration quick start on Kali
The fastest way to get subdomains on an authorized domain is Subfinder:
subfinder -silent -d zonetransfer.mestaging.zonetransfer.me
www.zonetransfer.meFor broader passive coverage, merge Subfinder with Assetfinder. For DNS validation — confirming which names answer today — use massdns on the merged list (see Passive enumeration pipeline).
In this test, Assetfinder returned more names from its source set, including training-zone noise you should scope-check before scanning:
assetfinder --subs-only zonetransfer.meemail.zonetransfer.me
office.zonetransfer.me
owa.zonetransfer.me
staging.zonetransfer.me
vpn.zonetransfer.me
www.zonetransfer.me
alltcpportsopen.firewall.test.zonetransfer.me
canberra-office.zonetransfer.me
dc-office.zonetransfer.me
testing.zonetransfer.mezonetransfer.me is maintained for DNS labs, so Assetfinder may also return the apex domain or odd test hostnames. Treat every row as a lead, not an automatic in-scope asset.
The sections below add Subfinder JSON output with source attribution, Amass for deeper mapping, massdns for resolver-backed checks, and Sublist3r as a legacy supplemental pass.
What is subdomain enumeration in ethical hacking?
A subdomain is a hostname under a registered domain, such as www.example.com or vpn.example.com. Subdomain enumeration collects those names so you can feed them into Nmap, Burp Suite, or manual browsing during an engagement.
Common discovery methods overlap:
- Passive OSINT — certificate transparency, search engines, and threat-intel APIs (Amass, Subfinder, Assetfinder)
- Active DNS — wordlist guesses resolved through public or target resolvers (massdns; Nmap
dns-brutein the DNS enumeration guide) - Zone transfers — AXFR when a nameserver leaks the full zone (
zonetransfer.medemos)
Passive tools query third-party datasets about your target namespace. They do not always contact the target authoritative nameserver for every source, but they still disclose the domain to external services. Active brute force and resolver lookups generate DNS traffic that nameservers and resolvers can log.
Subdomain enumeration tools on Kali
| Tool | Mode | Best use |
|---|---|---|
| Amass | Passive or active | Deep attack-surface mapping; optional zone-transfer checks |
| Subfinder | Passive OSINT | Fast ProjectDiscovery passive pass |
| Assetfinder | Passive OSINT | Broad third-party source merge in one command |
| massdns | Active DNS | High-speed resolution of candidate hostname lists through chosen resolvers |
| Sublist3r | Passive scrape | Legacy search-engine OSINT (supplemental only) |
Which subdomain enumeration tool should I use?
- Fast passive list for a spreadsheet → Subfinder plus Assetfinder
- Deeper passive attack-surface mapping → Amass
-passive(configure provider keys indatasources.yaml; if you use-dir, pass-config ~/.config/amass/config.yamlor place config where that enumeration expects it) - Zone-transfer or other active Amass checks → Amass
-activeon authorized zones only - Confirm which guessed hostnames answer in DNS today → massdns with a wordlist and resolver file
- Authoritative brute force against a known nameserver → Nmap
dns-brutewithBRUTE_NSin DNS enumeration - Certificate transparency only, no extra packages → theHarvester with
-b crtsh,certspotter - Legacy search-engine scrape → Sublist3r as a supplemental pass only
Start with Subfinder and Assetfinder for a quick passive merge, then add Amass when you need deeper indexing or massdns when you need resolver-backed confirmation.
The export block at the top of this guide sets DOMAIN, BRUTE_NS, and LAB. Install the enumeration packages if they are missing:
sudo apt updateInstall Amass, Subfinder, Assetfinder, Sublist3r, and massdns in one pass:
sudo apt install -y amass subfinder assetfinder sublist3r massdnsBuild a short wordlist and resolver file for the active DNS sections later:
mkdir -p "$LAB"Seed the wordlist with common hostname labels from the training zone:
printf 'www\nmail\nftp\nowa\nstaging\nvpn\n' > "$LAB/words.txt"Add public resolver addresses massdns will query:
printf '8.8.8.8\n1.1.1.1\n' > "$LAB/resolvers.txt"Enumerate subdomains with Amass
OWASP Amass maps attack surface through passive indexes and optional active checks. Kali ships Amass 5.x; call /usr/lib/amass/amass when /usr/bin/amass fails with a libpostal_data wrapper error.
Check the installed build:
/usr/lib/amass/amass -versionv5.1.1Amass 5.x groups work into enumeration modes you combine with flags:
| Flag | Mode | Purpose |
|---|---|---|
-passive |
Purely passive | Restrict enumeration to passive methods |
-active |
Active reconnaissance | Enables Amass active reconnaissance methods, including zone-transfer attempts |
-passive limits the run to passive collection. A plain enum without -passive is not the same mode. -active generates DNS activity against the namespace you name; use it only on authorized zones.
Passive Amass enumeration
Run a passive pass and write results under "$LAB". Because -dir changes where Amass looks for configuration, pass your home config explicitly:
/usr/lib/amass/amass enum -passive -d "$DOMAIN" -config ~/.config/amass/config.yaml -dir "$LAB/amass-passive" -oA "$LAB/amass-passive/out"Passive Amass can take a minute while it queries configured sources. Without provider keys in ~/.config/amass/datasources.yaml, the session summary may list only the apex domain while Subfinder and Assetfinder still return hostnames from their own source lists. Add credentials per the Amass documentation when you need deeper passive coverage on real engagements.
Active Amass checks
-active enables Amass active reconnaissance methods, including zone-transfer attempts:
/usr/lib/amass/amass enum -active -d "$DOMAIN" -config ~/.config/amass/config.yaml -dir "$LAB/amass-active" -oA "$LAB/amass-active/out"Use this on authorized zones only. For dedicated AXFR walkthroughs and dig examples, see DNS enumeration. For DNS wordlist brute force on Kali, use massdns or Nmap dns-brute in that guide rather than Amass -brute on 5.1.1 builds where the wordlist may not be consumed.
Enumerate subdomains with Subfinder
Subfinder queries configured passive sources and prints one hostname per line. Confirm the package version before you query APIs:
subfinder -version 2>&1 | head -2[INF] Current Version: v2.15.0
[INF] Subfinder Config Directory: /home/kali/.config/subfinderYour path may differ; Subfinder prints the active config directory in this banner. Add API keys in provider-config.yaml when a source requires credentials — run subfinder -ls to list available sources.
Run a silent pass against the lab domain:
subfinder -silent -d "$DOMAIN"staging.zonetransfer.me
www.zonetransfer.meEach line is a candidate hostname for your target spreadsheet. Subfinder reports names seen in passive datasets; it does not prove the host is live today. Follow with DNS resolution or HTTP probes on authorized targets.
Save results when you need a file for diffing or reporting:
subfinder -silent -d "$DOMAIN" -o "$LAB/subfinder.txt"Subfinder exits quietly on success when -silent is set. Count saved lines before you merge into a master list:
wc -l "$LAB/subfinder.txt"Subfinder JSON output and source attribution
For reporting, write JSONL with the passive sources that contributed each hostname:
subfinder -d "$DOMAIN" -oJ -cs -o "$LAB/subfinder.jsonl"-oJ writes one JSON object per line. -cs (collect sources) records which indexes reported each name — useful when you need corroboration before you add a row to a client report.
{"host":"www.zonetransfer.me","input":"zonetransfer.me","sources":["shodanct","hackertarget","submd","thc"]}
{"host":"staging.zonetransfer.me","input":"zonetransfer.me","sources":["submd","thc"]}www.zonetransfer.me appeared in four source lists; staging.zonetransfer.me in two. That does not prove either host is live today, but it helps you prioritize names with multi-source corroboration. Run subfinder -ls to see available sources; add API keys in provider-config.yaml when a source requires credentials.
Enumerate subdomains with Assetfinder
Assetfinder aggregates several public indexes in one command. The --subs-only flag focuses on hostnames under the target, though the apex domain may still appear depending on the index.
List subdomains for the training zone:
assetfinder --subs-only "$DOMAIN"email.zonetransfer.me
office.zonetransfer.me
owa.zonetransfer.me
staging.zonetransfer.me
vpn.zonetransfer.me
www.zonetransfer.me
alltcpportsopen.firewall.test.zonetransfer.me
canberra-office.zonetransfer.me
dc-office.zonetransfer.me
testing.zonetransfer.meAssetfinder returned more names than Subfinder in this lab run, including training-zone hostnames you should validate against scope. Different tools query different source sets and can therefore return different results. Merge unique lines from both tools before you declare passive enumeration complete.
Write the list to disk for later diffing:
assetfinder --subs-only "$DOMAIN" | tee "$LAB/assetfinder.txt"Enumerate subdomains with Sublist3r (supplemental)
Sublist3r remains on Kali as a legacy search-engine scraper. Many modules fail when sites block bots or change HTML, and on Python 3.14 /usr/bin/sublist3r may crash with cannot pickle '_thread.lock' object before engines finish. Run python3.13 /usr/bin/sublist3r -d "$DOMAIN" -t 10 when needed; in this lab it returned only owa.zonetransfer.me while VirusTotal and DNSDumpster failed. Treat Sublist3r as optional, not a primary passive source.
Resolve subdomains with massdns
massdns resolves large hostname lists quickly through public or custom resolvers. It complements passive tools by confirming which guessed names answer in DNS today.
Build fully qualified names from the short wordlist:
sed 's/$/.'"$DOMAIN"'/' "$LAB/words.txt" > "$LAB/fqdns.txt"Resolve those names through the resolver file:
massdns -r "$LAB/resolvers.txt" -t A -o S -w "$LAB/massdns-out.txt" "$LAB/fqdns.txt"massdns prints a progress bar on stderr and finishes when every line in fqdns.txt is processed. Read the answers from the output file:
cat "$LAB/massdns-out.txt"www.zonetransfer.me. A 5.196.105.14
vpn.zonetransfer.me. A 174.36.59.154
owa.zonetransfer.me. A 207.46.197.32
staging.zonetransfer.me. CNAME www.sydneyoperahouse.com.mail and ftp produced no lines because those names did not resolve during this run. The staging CNAME shows why you should follow aliases before you port-scan.
For brute-force against the training nameserver specifically, use Nmap dns-brute with BRUTE_NS as documented in DNS enumeration. massdns with public resolvers is enough for this walkthrough.
Passive enumeration pipeline: discover, merge, resolve
Readers searching get subdomains or subdomain scanning usually want one flow: enumerate passively, deduplicate, then resolve. This pipeline stops at DNS answers — network reconnaissance using Nmap or web testing comes only after scope confirmation.
Collect passive lists from Subfinder and Assetfinder:
subfinder -silent -d "$DOMAIN" -o "$LAB/subfinder.txt"Save the broader Assetfinder pass to a separate file:
assetfinder --subs-only "$DOMAIN" > "$LAB/assetfinder.txt"Merge and deduplicate the hostname candidates:
cat "$LAB"/subfinder.txt "$LAB"/assetfinder.txt | sort -u > "$LAB/all-hosts.txt"Resolve the merged list through your resolver file:
massdns -r "$LAB/resolvers.txt" -t A -o S -w "$LAB/resolved.txt" "$LAB/all-hosts.txt"massdns prints a progress bar on stderr. Read the DNS answers from the output file:
sort "$LAB/resolved.txt"owa.zonetransfer.me. A 207.46.197.32
staging.zonetransfer.me. CNAME www.sydneyoperahouse.com.
vpn.zonetransfer.me. A 174.36.59.154
www.zonetransfer.me. A 5.196.105.14The full resolved.txt from this lab run included additional training-zone names and CNAME chains. Names with no current DNS answer produce no line in the output file. Follow CNAME targets before you treat a hostname as a scan target.
Review the merged count before you import anything into a scanner:
wc -l "$LAB/all-hosts.txt"Treat every hostname as a candidate until DNS checks confirm it is in scope and reachable. Feed confirmed names into network reconnaissance and banner grabbing on authorized targets only.
When you need larger brute lists, build custom wordlists with a wordlist generator after you learn naming patterns from passive output.
What to do after subdomain enumeration
Hostname lists are leads, not a finished attack surface. Map each confirmed name to the next authorized step:
| Finding | Next step (when in scope) |
|---|---|
| New subdomain from passive OSINT | Resolve with dig or massdns → confirm it answers today |
| CNAME to a third-party host | Follow the alias chain before you scan — staging in this lab pointed at an external opera-house domain |
| Wildcard or odd training hostname | Scope-check against the SoW — zonetransfer.me includes deliberate lab noise |
| Merged passive list | Dedupe with sort -u, drop out-of-scope rows, then hand off to web testing or reporting |
Export only in-scope hostnames into your penetration test report. Pair DNS findings with DNS enumeration when you also need AXFR or record-type context.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
command not found for Subfinder or Assetfinder |
Package not installed | sudo apt install -y subfinder assetfinder sublist3r massdns amass |
amass: libpostal_data: command not found |
Broken /usr/bin/amass wrapper |
Use /usr/lib/amass/amass for enum and intel subcommands |
| Passive Amass returns only the apex | No provider keys in datasources.yaml, or -dir without -config |
Add keys under ~/.config/amass/datasources.yaml; pass -config ~/.config/amass/config.yaml when using -dir; run Subfinder and Assetfinder in parallel |
Sublist3r crashes with cannot pickle '_thread.lock' |
Python 3.14 multiprocessing incompatibility | Run python3.13 /usr/bin/sublist3r … until the package updates |
| Sublist3r VirusTotal or DNSDumpster errors | Site blocking or HTML changes | Expect partial results; rely on Subfinder, Assetfinder, and Amass |
| massdns empty output file | All guesses returned no answers, resolver list failed, or queries were rate-limited | Verify "$LAB/resolvers.txt" and FQDN formatting in "$LAB/fqdns.txt"; try a smaller wordlist or Nmap dns-brute against BRUTE_NS |
| Duplicate hostnames across tools | Normal overlap | sort -u merged lists before scanning |
| Resolver rate limiting during massdns | High query volume | Use a smaller wordlist in labs; tune massdns rate flags on authorized tests |
Summary
You installed Amass, Subfinder, Assetfinder, Sublist3r, and massdns on Kali and enumerated the authorized training zone zonetransfer.me. Subfinder reported www and staging; Assetfinder returned a longer passive list including owa, vpn, and training-zone test names; Sublist3r remains a supplemental legacy source only. The passive pipeline — Subfinder plus Assetfinder, sort -u, then massdns — answers get-subdomains intent in one workflow; Subfinder -oJ -cs adds source attribution for reporting.
Passive OSINT tools disagree because they query different third-party datasets, and passive Amass coverage improves when you add provider keys to ~/.config/amass/datasources.yaml and pass -config ~/.config/amass/config.yaml when enumerations use -dir. Merge and deduplicate hostname lists before port scans or web tests. Use massdns or Nmap DNS scripts when you need resolver-backed confirmation on nameservers you are allowed to query. When /usr/bin/amass fails with libpostal_data: command not found, call /usr/lib/amass/amass instead — that wrapper error occurred on the Kali build tested for this guide.
Run these workflows only on domains under authorization. Pair subdomain lists with DNS enumeration for AXFR context, theHarvester for certificate-transparency-only passes, and network reconnaissance using Nmap on the hosts you confirm in scope.
References
- OWASP Amass
- ProjectDiscovery Subfinder
- tomnomnom Assetfinder
- Sublist3r
- massdns
- ZoneTransfer.me training zone (DigiNinja)
Frequently Asked Questions
What is subdomain enumeration in ethical hacking?
Subdomain enumeration discovers hostnames under a registered domain such as api.example.com or mail.example.com. Pentesters use those names to widen the attack surface before port scanning, web testing, or phishing simulations on systems they are authorized to assess.
Is subdomain enumeration legal?
Subdomain discovery is appropriate on domains you own or are explicitly authorized to test. Passive OSINT and DNS brute force can still violate provider terms or local law when aimed at third-party zones, so obtain written permission before running these tools against customer or competitor domains.
Amass vs Subfinder on Kali?
Amass maps attack surface through many OSINT sources and optional active modes such as zone-transfer checks. Subfinder is a focused ProjectDiscovery passive enumeration tool with a smaller CLI surface. Run Subfinder and Assetfinder for quick lists, then Amass when you need deeper passive indexing on authorized zones. Use massdns or Nmap dns-brute for active DNS brute force rather than relying on Amass -brute on current 5.1.1 builds.
Why does Sublist3r return fewer names than Assetfinder?
Sublist3r scrapes search engines and legacy APIs that often block automated requests. VirusTotal and DNSDumpster integrations failed in the tested Kali run for this guide. On Python 3.14 the default launcher may crash before modules finish. Treat Sublist3r as a supplemental pass, not your only passive tool.
Do I need massdns if I already use Amass or Subfinder?
Subfinder, Assetfinder, and passive Amass read third-party datasets. massdns actively resolves large candidate hostname lists through resolvers you choose. Use massdns when you need to validate a wordlist against public resolvers or confirm which guessed hostnames answer today.

