Subdomain enumeration is usually the first real step of recon on a wildcard target. If a program says *.example.com is in scope, the main website is only one door. Staging servers, old admin panels, forgotten marketing sites and internal tools often live on subdomains, and these get much less attention than the main app. In this post I’ll show you how I approach subdomain enumeration in two stages: passive collection first, then active discovery, and finally how to turn a big list of names into a short list of live hosts worth testing.
Before you run anything, confirm the target is in scope and that subdomains are covered. A wildcard entry means subdomains are allowed. A single domain like www.example.com does not. Everything below assumes you are testing a program you are allowed to test, and that you follow its rate limits.
Why subdomain enumeration matters
Most hunters test the same main application. That is where the competition is. Subdomains change the picture because each one can run different software, be managed by a different team, or be left behind after a project ends. If you want the wider context of why recon pays off, I have written about why recon is so important in bug bounty hunting.
A good subdomain list helps you:
- Find assets that other hunters missed
- Spot development, staging and test environments
- Understand which technologies and vendors the company uses
- Build input for the next steps: port scanning, content discovery and JavaScript recon
Passive subdomain enumeration
Passive means you collect names from third-party sources without sending traffic to the target’s servers. It is fast, quiet and safe to start with. Sources include certificate transparency logs, search engines, DNS datasets and public archives.
subfinder
subfinder from ProjectDiscovery queries many passive sources at once. Some sources work without keys, but adding free API keys in its provider config file gives you far better results.
subfinder -d example.com -all -silent -o subfinder.txtThe -all flag tells it to use all sources, not only the default set. For several root domains, put them in a file and use -dL domains.txt instead of -d.
assetfinder and amass
Different tools use different sources, so running more than one usually adds new names.
assetfinder --subs-only example.com > assetfinder.txt
amass enum -d example.com -o amass.txtamass is slower but thorough. Give it time on large targets.
Certificate transparency with crt.sh
Every public TLS certificate is logged, and certificates often list subdomain names. crt.sh lets you search these logs directly:
curl -s "https://crt.sh/?q=%25.example.com&output=json" \
| jq -r '.[].name_value' \
| sed 's/\*\.//g' \
| sort -u > crtsh.txtThe %25 is a URL-encoded % wildcard. The sed step removes the *. prefix from wildcard certificates. crt.sh can be slow or time out on big domains, so try again later if it fails.
Merge everything
cat subfinder.txt assetfinder.txt amass.txt crtsh.txt | sort -u > passive.txtActive subdomain enumeration
Passive sources only know names that have appeared somewhere public. Active techniques find names that were never published. The main method is DNS brute forcing: you try many possible names and see which ones resolve.
Get good resolvers
Brute forcing sends a lot of DNS queries. Use a list of trusted public resolvers, not your home router. Bad resolvers return wrong answers and fill your results with false positives. Keep the rate reasonable so you do not abuse the resolvers or create noise.
Brute force with puredns
puredns is built on massdns and handles wildcard DNS filtering for you, which saves a lot of cleanup.
puredns bruteforce wordlist.txt example.com -r resolvers.txt -w brute.txtThe wordlist matters more than the tool. A huge list is not always better. Start with a medium-sized list of common subdomain words, then add words that fit the target, such as product names, regions or team names you saw during passive recon.
Permutations
Once you know names like api.example.com and dev.example.com, there is a good chance that api-dev.example.com or dev2.example.com also exist. Permutation tools such as alterx generate these variations from your known list. You then resolve the output with puredns. This step often finds the most interesting hosts, because they follow the company’s own naming habits.
Resolving and finding live hosts
A list of names is not a list of targets. Many names from passive sources are old and no longer resolve. First, check which names still have DNS records:
cat passive.txt brute.txt | sort -u > all.txt
dnsx -l all.txt -silent -o resolved.txtThen check which of these run a web server. httpx probes common HTTP and HTTPS ports and can show useful details in one pass:
httpx -l resolved.txt -silent -status-code -title -tech-detect -o live.txtNow you have a file you can actually read. The status code, page title and detected technology help you sort hosts quickly. A title like “Jenkins” or “Grafana”, or a 401 on a host called internal-tools, deserves a closer look than another copy of the marketing site.
If you also want to check non-web ports, naabu can scan the resolved hosts. Keep port scans light and only do them where the program allows it.
Common mistakes in subdomain enumeration
- Relying on one tool. Every tool has gaps. Combine at least two passive sources plus crt.sh.
- Skipping API keys. subfinder without keys misses a lot. The free keys are worth the ten minutes of setup.
- Ignoring wildcard DNS. Some domains answer for any name. Without filtering, you get thousands of fake subdomains. puredns handles this, but always spot check.
- Testing out-of-scope hosts. A subdomain may belong to a third-party vendor or be listed as out of scope. Check before you test.
- Running once and forgetting. Companies add new subdomains all the time. Re-run your enumeration regularly and compare with your old results to see what is new.
- Using too much speed. High rates cause missed results, angry resolvers and sometimes blocks from the target. Slower and accurate beats fast and noisy.
Tips for a simple workflow
- Create one folder per target and keep each tool’s output in its own file.
- Run passive tools first and merge with
sort -u. - Brute force and generate permutations with target-specific words.
- Resolve with dnsx, then probe with httpx.
- Read the httpx output by hand and mark the hosts that look unusual.
- Save the date of each run so you can compare later.
How far you go depends on the size of the target. A single-domain program needs a different plan from a company with hundreds of root domains. My guide to recon for small, medium and large scope targets explains how to adjust your approach for each.
Conclusion
Subdomain enumeration is not about running every tool you can find. It is about collecting names from good passive sources, finding hidden names with careful brute forcing and permutations, and then filtering down to live hosts you can study. Do it well and the rest of your recon gets easier, because you are working from a complete map instead of a guess.
If you want to automate this pipeline, take a look at my small scope reconnaissance automation script. For wildcard programs with many assets, you can also join the waitlist for the Large Scope Reconnaissance Guide course.
