Subdomain Enumeration Tools and Examples on Kali Linux

Tested on Kali GNU/Linux Rolling 2026.2 (kali-rolling)
Package amass 5.1.1-0kali1
subfinder 2.15.0-0kali1
assetfinder 0.1.1-1+b12
sublist3r 1.1-5
massdns 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
Short on time?Beta Get the gist of this 13-minute read in seconds, then ask follow-up questions

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.

IMPORTANT
Enumerate subdomains only on domains you own or have explicit permission to test. Passive APIs still describe your target to third-party datasets. Confirm scope in your penetration testing rules of engagement before you brute-force or scrape production zones.

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.

bash
export DOMAIN=zonetransfer.me
export BRUTE_NS=nsztm1.digi.ninja
export LAB=/tmp/subdomain-lab
mkdir -p "$LAB"
NOTE
Keyless Amass is normal: Without provider API keys in ~/.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:

bash
subfinder -silent -d zonetransfer.me
output
staging.zonetransfer.me
www.zonetransfer.me

For 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:

bash
assetfinder --subs-only zonetransfer.me
output
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.me

zonetransfer.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-brute in the DNS enumeration guide)
  • Zone transfers — AXFR when a nameserver leaks the full zone (zonetransfer.me demos)

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 in datasources.yaml; if you use -dir, pass -config ~/.config/amass/config.yaml or place config where that enumeration expects it)
  • Zone-transfer or other active Amass checks → Amass -active on 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-brute with BRUTE_NS in 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:

bash
sudo apt update

Install Amass, Subfinder, Assetfinder, Sublist3r, and massdns in one pass:

bash
sudo apt install -y amass subfinder assetfinder sublist3r massdns

Build a short wordlist and resolver file for the active DNS sections later:

bash
mkdir -p "$LAB"

Seed the wordlist with common hostname labels from the training zone:

bash
printf 'www\nmail\nftp\nowa\nstaging\nvpn\n' > "$LAB/words.txt"

Add public resolver addresses massdns will query:

bash
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:

bash
/usr/lib/amass/amass -version
output
v5.1.1

Amass 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:

bash
/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:

bash
/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:

bash
subfinder -version 2>&1 | head -2
output
[INF] Current Version: v2.15.0
[INF] Subfinder Config Directory: /home/kali/.config/subfinder

Your 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:

bash
subfinder -silent -d "$DOMAIN"
output
staging.zonetransfer.me
www.zonetransfer.me

Each 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:

bash
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:

bash
wc -l "$LAB/subfinder.txt"

Subfinder JSON output and source attribution

For reporting, write JSONL with the passive sources that contributed each hostname:

bash
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.

output
{"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:

bash
assetfinder --subs-only "$DOMAIN"
output
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.me

Assetfinder 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:

bash
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:

bash
sed 's/$/.'"$DOMAIN"'/' "$LAB/words.txt" > "$LAB/fqdns.txt"

Resolve those names through the resolver file:

bash
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:

bash
cat "$LAB/massdns-out.txt"
output
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:

bash
subfinder -silent -d "$DOMAIN" -o "$LAB/subfinder.txt"

Save the broader Assetfinder pass to a separate file:

bash
assetfinder --subs-only "$DOMAIN" > "$LAB/assetfinder.txt"

Merge and deduplicate the hostname candidates:

bash
cat "$LAB"/subfinder.txt "$LAB"/assetfinder.txt | sort -u > "$LAB/all-hosts.txt"

Resolve the merged list through your resolver file:

bash
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:

bash
sort "$LAB/resolved.txt"
output
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.14

The 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:

bash
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.

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.

Finished reading?Beta Get the key takeaways in seconds, then ask follow-up questions
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with 15+ years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)