Skip to content
Breachfolio
Domains vs subdomains: how to enumerate them.
CYBERSECURITY · OSINT

Domains vs subdomains: how to enumerate them.

What a domain is made of, why subdomains are an attack surface, and how to enumerate them – passive and active – with crt.sh, Amass, subfinder and more.

July 18, 202613 min readDaniel A. & Óscar S.

Every investigation, every bug-bounty engagement, and every attacker's reconnaissance phase starts in the same place: a name. Before anyone touches a service, they want to know how big the target actually is, and the honest answer is almost always "bigger than the marketing site suggests." That gap between example.com and the dozens of forgotten hostnames hanging off it is where a huge amount of real-world risk lives. This article takes the name apart, explains where subdomains come from, and walks through how to enumerate them properly – the passive way, the active way, and the responsible way.

example.comwwwmaildevapishop
One domain, many subdomains – each a separate attack surface.

Anatomy of a domain name

A domain name looks like one thing but is really a stack of labels read right to left, each one a level of delegation in a global hierarchy. Take a fully-qualified name like api.staging.example.com and pull it apart:

PartExampleWhat it is
Root. (implicit)The unnamed top of the tree. It is really there – example.com. with a trailing dot is the true FQDN.
TLDcomTop-Level Domain. Managed by a registry (Verisign for .com) under ICANN. Could be a gTLD (.com, .io) or ccTLD (.uk, .es).
Second-level domainexampleThe label you register and pay for. example + .com is the registrable domain: the unit WHOIS knows about.
Subdomainstaging, apiAny label to the left of the registrable domain. You create these yourself, for free, as many as you like.
FQDNapi.staging.example.comThe Fully-Qualified Domain Name: the complete, unambiguous path from host to root.

Two subtleties trip people up. First, "www" is not special – www.example.com is just a subdomain named www, no different in kind from api or vpn. Second, the boundary between "registrable domain" and "subdomain" is not always two labels from the right. Under example.co.uk, the registrable domain is three labels deep because co.uk is an effective TLD. The Public Suffix List is the authoritative map of where that line falls, and every serious enumeration tool consults it so it does not mistake co.uk for someone's subdomain.

What a subdomain is, and why security cares

A subdomain is simply a DNS entry the domain owner created under a name they control. There is no registrar, no fee, and no approval step: whoever controls the DNS zone for example.com can conjure internal.example.com into existence in seconds. That convenience is exactly why subdomains matter so much to a defender or an investigator.

  • They are the attack surface. The registrable domain is a brand; the subdomains are the actual machines, apps, and APIs. Mapping them is mapping the target. Ten subdomains you did not know about are ten services nobody is patching, monitoring, or thinking about.
  • They leak environments. Names like dev., staging., uat., test., jenkins., or vpn. advertise non-production systems that are often built for convenience, not hardening – default credentials, verbose errors, no WAF, stale software. An attacker who cannot get through the front door will happily walk in through staging.
  • They enable subdomain takeover. A subdomain that points (via CNAME) at a cloud service that no longer exists can be silently claimed by an attacker – more on this below.

This is why subdomain enumeration is a foundational OSINT and reconnaissance skill. If you are new to the broader discipline, our guide to what OSINT is and the workflow around it puts this step in context: enumeration is the "pivot outward" phase, where one artefact (a domain) is used to discover the next (its hosts).

The DNS records that make subdomains real

A subdomain only "exists" on the internet because a DNS record answers for it. Understanding the record types is what separates a list of names from an understanding of the infrastructure behind them. We cover the resolution process itself in how networks work; here is the working subset that matters for enumeration:

RecordAnswers the questionWhy it matters in enumeration
AWhat IPv4 address is this host at?Confirms a name is live and points somewhere. Reverse the IP to find neighbours.
AAAAWhat IPv6 address is this host at?Increasingly common; hosts sometimes expose IPv6 without the same firewalling as IPv4.
CNAMEThis name is an alias for which other name?The key record for takeover hunting – a CNAME pointing at an unclaimed service is the vulnerability.
MXWhich servers handle mail for this domain?Reveals the mail provider and often internal gateway naming.
TXTArbitrary text – SPF, DKIM, verification tokens.SPF records list sending IPs and third-party services; verification tokens fingerprint the SaaS a company uses.
NSWhich nameservers are authoritative for this zone?Identifies the DNS provider and can reveal delegated sub-zones run by other teams.

You can pull any of these with dig. A quick look at the records for a name you are investigating tells you whether it is a real host, an alias, or a mail endpoint:

$ dig +short A api.example.com
203.0.113.42

$ dig +short CNAME assets.example.com
example-cdn.s3.amazonaws.com.

$ dig +short TXT example.com
"v=spf1 include:_spf.google.com include:mailgun.org ~all"

That single SPF line already tells you the organisation uses Google Workspace and Mailgun – infrastructure intelligence, straight from a public record, without touching the target once.

Passive vs active enumeration

There are two fundamentally different ways to discover subdomains, and knowing which mode you are in at every step is both an operational-security decision and, sometimes, a legal one.

Passive enumeration reads subdomain data from third parties – certificate logs, search-engine indexes, passive-DNS databases – and never sends a packet to the target. The target has no way to know you looked. Active enumeration resolves or requests names against the target's own infrastructure: it queries their DNS resolvers, connects to their servers, and can be logged. Brute-forcing subdomains is active by definition. As a rule, start passive, and only go active inside an authorised scope.

TechniqueModeToolWhen to use it
Certificate Transparency searchPassivecrt.shAlways: the fastest, quietest first pass. CT logs leak names nobody meant to publish.
Aggregated passive sourcesPassivesubfinder, Amass (passive), assetfinderBroad first sweep pulling from dozens of datasets at once.
Passive-DNS / historical DNSPassiveSecurityTrails, VirusTotal, NetcraftWhen you want history – names that resolved in the past but were removed.
DNS resolution / validationActivednsxTo confirm which discovered names are actually live before you act on them.
DNS brute-forceActivegobuster, ffuf, Amass (active)Only on authorised targets – to find names that appear in no public dataset.
Takeover detectionActivesubjack, nucleiAfter enumeration, to test dangling CNAMEs for claimability.

Passive enumeration, with commands

Certificate Transparency (crt.sh)

Every publicly-trusted TLS certificate is logged in append-only Certificate Transparency logs – the mechanism we explain in TLS certificates and Certificate Transparency. Because a certificate names the hosts it covers, those logs are an accidental, authoritative list of an organisation's subdomains. The easiest way in is crt.sh, which is queryable from the browser or the command line:

# Every name ever certified under example.com, de-duplicated
$ curl -s "https://crt.sh/?q=%25.example.com&output=json" \
    | jq -r '.[].name_value' \
    | sed 's/\*\.//g' \
    | sort -u
api.example.com
dev.example.com
mail.example.com
vpn.example.com
...

The %25 is a URL-encoded %, the SQL wildcard crt.sh understands. This one request, sent to a third party and never to the target, often returns more real hostnames than any other single technique.

Aggregators: subfinder, Amass, assetfinder

subfinder (from ProjectDiscovery) queries dozens of passive sources at once and is the fast default:

$ subfinder -d example.com -silent
api.example.com
blog.example.com
cdn.example.com
staging.example.com

Amass, the OWASP project, is the most thorough. Run it in passive mode to stay entirely off the target while pulling from its large source list:

$ amass enum -passive -d example.com

assetfinder is a tiny, fast tool that scrapes a handful of the highest-value sources – perfect for piping into other tools:

$ assetfinder --subs-only example.com | sort -u

In practice you run several and merge the results, because no single source is complete:

$ { subfinder -d example.com -silent; assetfinder --subs-only example.com; } \
    | sort -u > subs-passive.txt

Active enumeration, with commands

Authorization first

Everything in this section sends traffic to infrastructure you are enumerating. Only run it against domains you own or have explicit, written authorization to test (your own assets, a signed pentest scope, or a bug-bounty program's in-scope list). Brute-forcing and resolving names against a target you have no permission to test can constitute unauthorised activity. Observe, do not intrude.

Validating what you found (dnsx)

A passive list is full of dead names – hosts that were decommissioned or never went live. dnsx resolves the list against DNS and keeps only the ones that answer, optionally showing the record data:

$ cat subs-passive.txt | dnsx -silent -a -resp
api.example.com    [203.0.113.42]
cdn.example.com    [198.51.100.10]
vpn.example.com    [203.0.113.77]

DNS brute-force (gobuster, ffuf, Amass active)

Some subdomains appear in no public dataset. The only way to find them is to guess candidate names from a wordlist and check which resolve. gobuster in dns mode is the classic:

$ gobuster dns -d example.com \
    -w subdomains-top1million-5000.txt
Found: grafana.example.com
Found: git.example.com
Found: backup.example.com

Good wordlists come from SecLists (the Discovery/DNS folder). To find virtual hosts – different sites served from the same IP by the Host header – ffuf fuzzes that header and filters out the default-response size:

$ ffuf -w subdomains.txt \
    -u https://example.com \
    -H "Host: FUZZ.example.com" \
    -fs 4242

Amass can also do active resolution and brute-forcing when you drop the -passive flag and add -brute – powerful, and firmly in "authorised targets only" territory.

Wildcard DNS and false positives

Before you trust a brute-force result, check for a wildcard record. A *.example.com entry makes every possible subdomain resolve to the same address, so a naive brute-forcer will report thousands of "found" hosts that do not really exist. The test is one query for a name no sane admin would create:

$ dig +short definitely-not-real-8f3a9.example.com
198.51.100.200   <- an answer means a wildcard is in play

If a random garbage name resolves, the zone has a wildcard, and you must filter accordingly: note the wildcard IP and discard any brute-forced name that resolves to it, or use a tool that does this automatically. Amass, subfinder's resolver, and dnsx all include wildcard-filtering logic precisely because this is such a common source of noise. The general lesson holds across all of OSINT: a result you have not corroborated is a lead, not a finding.

Subdomain takeover

A subdomain takeover is one of the highest-impact issues enumeration turns up. The setup: a company creates promo.example.com as a CNAME pointing at a third-party service: a cloud bucket, a Heroku app, a GitHub Pages site, a SaaS landing page. Later, they delete the resource on the provider but forget to remove the DNS record. The CNAME is now dangling: it points at a service name that is available for anyone to register.

If an attacker registers that service name, the victim's own DNS now sends visitors to attacker-controlled content on a legitimate-looking hostname. That enables convincing phishing, cookie theft scoped to the parent domain, and bypasses of same-site trust. The tell-tale sign is a CNAME to a known provider combined with that provider's "no such app / bucket not found" error page:

$ dig +short CNAME promo.example.com
example-promo.herokuapp.com.

$ curl -s https://promo.example.com | grep -i "no such app"
<title>No such app</title>   <- dangling CNAME, likely claimable

At scale you automate the detection. subjack checks a list of subdomains against a fingerprint database of vulnerable services:

$ subjack -w subs-live.txt -t 100 -ssl \
    -c fingerprints.json -v

nuclei ships a maintained set of takeover templates and is the more modern choice:

$ nuclei -l subs-live.txt -t http/takeovers/

Finding a takeover is not the same as exploiting one. On an authorised engagement, the responsible move is usually to prove claimability with a harmless marker file and report it – not to serve real content from the hostname.

Tools and websites worth bookmarking

Beyond the command-line tools above, several web services do subdomain and infrastructure discovery from the browser, which is ideal for a quick, entirely passive first look:

  • crt.sh – Certificate Transparency log search. The single best passive source of subdomains.
  • DNSDumpster – free DNS recon that maps a domain's hosts, records, and network relationships in one visual view.
  • SecurityTrails – historical DNS and subdomain data; see what a name used to point to, invaluable for tracking infrastructure over time.
  • VirusTotal – the "Relations" tab on a domain lists observed subdomains it has seen in the wild.
  • Netcraft – long-running site reports and a searchable database of hosts and hosting history.
  • Amass (OWASP) and the ProjectDiscovery suite – subfinder and dnsx – for scripted, repeatable enumeration.

A registration lookup rounds out the picture: pairing enumeration with WHOIS tells you not just what hosts exist but who registered the parent domain and when. Together they turn a single name into a map.

The takeaway

A domain name is a hierarchy, and the subdomains hanging off it are the real, sprawling attack surface most organisations under-count. Enumerating them well means starting passive – Certificate Transparency and aggregators that never touch the target – validating with resolution, and only brute-forcing or testing for takeover where you have explicit authorization. Do it in that order and you will consistently see more of a target than it meant to show, without ever crossing the line from observation into intrusion.

Frequently asked questions

What is the difference between a domain and a subdomain?
A domain (more precisely, a registrable domain like example.com) is the name you register with a registrar, pay for, and that WHOIS knows about: it is your second-level domain plus its top-level domain. A subdomain is any label added to the left of that registrable domain, such as api.example.com or dev.example.com. The crucial practical difference is control and cost: registering a domain involves a registrar and a fee, while the domain owner can create unlimited subdomains for free, instantly, just by adding DNS records to the zone they already control. That is exactly why subdomains proliferate and why they so often become forgotten, unmonitored attack surface.
How do I find all the subdomains of a domain?
Start passively, because it is fast, quiet, and legal against any target. Search Certificate Transparency logs with crt.sh, then run aggregators like subfinder, assetfinder, and Amass in passive mode to pull from dozens of datasets at once, and check passive-DNS services such as SecurityTrails, VirusTotal, and Netcraft for historical names. Merge and de-duplicate the results, then resolve them with dnsx to see which are actually live. To find names that appear in no public dataset you can brute-force candidate names with gobuster or ffuf using a good wordlist, but only against domains you own or are explicitly authorised to test. No single method is complete, so real enumeration combines several.
What is a subdomain takeover?
It happens when a subdomain has a DNS record – usually a CNAME – pointing at a third-party service (a cloud bucket, a Heroku or GitHub Pages app, a SaaS host) that has since been deleted, while the DNS record was left behind. That "dangling" record now points at a service name anyone can register. An attacker who claims it gains control of content served on the victim's own hostname, which enables convincing phishing, theft of cookies scoped to the parent domain, and abuse of same-site trust. You detect it by looking for CNAMEs to known providers that return a "no such app / not found" error, and you automate the check with tools like subjack or nuclei's takeover templates. The fix is simple: delete the stale DNS record.
What is the difference between passive and active subdomain enumeration?
Passive enumeration collects subdomain data from third parties – certificate logs, search indexes, passive-DNS databases – and never sends a single packet to the target, so the target cannot tell you looked. Active enumeration interacts with the target's own infrastructure: resolving names against their DNS, connecting to their servers, or brute-forcing candidate hostnames, all of which can be logged. Passive is the safe default you can run against anyone; active carries operational and sometimes legal weight and should be reserved for assets you own or are authorised to test. The usual workflow is passive first to build a list, then a controlled active pass to validate and extend it.
Is subdomain enumeration legal?
Passive enumeration – reading Certificate Transparency logs, querying passive-DNS services, using aggregators that pull from third-party datasets – is reading already-public information and is legal in most jurisdictions, because you never touch the target's systems. Active techniques are different: brute-forcing subdomains, resolving names directly against a target's DNS, or probing discovered hosts sends traffic to infrastructure you may have no right to test, and at volume it can look like reconnaissance for an attack. Do active enumeration only against domains you own or have explicit, written authorization to test, such as a signed penetration-test scope or a bug-bounty program's in-scope list. Finding a subdomain is not permission to attack what runs on it.
Why do dev and staging subdomains matter so much in security?
Because they concentrate risk. Non-production environments named dev, staging, uat, test, or similar are built for developer convenience, not for hostile internet exposure: they often run outdated software, ship with default or weak credentials, return verbose error messages, and sit behind little or no WAF or monitoring. Yet they frequently connect to the same databases or internal services as production. An attacker who cannot breach the hardened main site will look for exactly these forgotten hostnames, which is why enumerating them and getting them off the public internet (or properly locked down) is one of the highest-value outcomes of a subdomain assessment.
Who writes this

Daniel A. and Óscar S. run Breachfolio, a small independent site about security and AI. This article was drafted with AI assistance and reviewed by a person before it went live. We write from documentation, vendor sources and published research rather than from original lab benchmarks, and we link a source in the sentence that relies on it. How we work · About us