Subdomain Enumeration Techniques for SaaS Attack Surfaces
Discover forgotten subdomains before attackers find them.

Subdomain enumeration exposes the gap between the systems a SaaS company thinks it owns and the hostnames it actually exposes. To close that gap, teams need both public records and active discovery, then validation and triage. Attackers use the same methods before exploitation. Security teams need the same methods to find assets that have been neglected before someone else does.
Why SaaS attack surfaces are structurally over-exposed at the subdomain level
An engineer creates dev.example.com for a sprint demo, then leaves the company. The hostname stays in DNS without an owner or patch cycle. At the same time, the parent domain gets hardened and penetration tested. Its forgotten child gets neither. The weakness starts with how work gets done.
Developers, marketing teams, and contractors can create subdomains without adding them to the central asset register. That makes the exposure gap an organizational problem. MITRE ATT&CK catalogs DNS reconnaissance, including subdomain records, as adversary sub-technique T1590.002. What an attacker runs as reconnaissance, a defender must run as asset discovery.
What subdomain enumeration actually is and the two fundamentally different ways it works
Subdomain enumeration discovers hostnames under a parent domain, such as api.example.com and staging.example.com. Passive enumeration searches third-party records without sending traffic to the target’s infrastructure. It is quiet, but backward-looking. Active enumeration generates candidate names and queries DNS to learn which resolve now, including names that public datasets never recorded.
Passive discovery misses names that never appeared in its sources, while active discovery misses names it does not guess. Teams can therefore use passive results as the starting list and as clues to names for an active pass.
Before trusting active results, a team must account for wildcard DNS. A wildcard zone can resolve made-up names, filling the results with phantom hosts. Resolving a random, implausible hostname establishes a baseline for filtering. Without that check, a large result set may say more about the zone’s configuration than the company’s infrastructure.
Passive enumeration: the five public sources and what each one uniquely contributes
Certificate transparency logs yield the most names at the start. Chrome’s CT policy applies to publicly trusted TLS certificates issued after April 30, 2018, and began to be enforced in May 2018. Apple later extended CT requirements, as did Mozilla with Firefox 135 in 2025. The crt.sh service aggregates logs and lets a query for %.example.com reveal recorded certificate names, including expired certificates and decommissioned assets. Wildcard certificate names show how hosts are named, with gaps in this source’s coverage for names that use only self-signed certificates, internal certificate authorities, or no HTTPS.
Passive DNS fills part of that gap. Its past records show which names were seen to resolve, including hosts that never used publicly trusted certificates and how their destination IPs changed. DNSDumpster, Shodan’s DNS-by-hostname endpoint, VirusTotal Passive DNS, and CIRCL’s passive DNS service provide access, subject to their limits. Subfinder consolidates results from configured sources using available API keys. What these sources can find still depends on what they have seen.
Shodan and Censys expose certificate names and help find hosts sharing an IP with a known asset. This can reveal virtual-host deployments that a DNS-only search misses, as well as shadow IT on personal cloud accounts. These datasets widen the search beyond managed DNS zones. They are records of scanned infrastructure.
Public source code and configuration repositories show names that developers made public by accident. JavaScript endpoints, README environment examples, Terraform files, CloudFormation configurations, and CI/CD files can all contain useful hostnames. Search-engine queries aimed at public repositories catch references that certificate and DNS datasets miss. Decompiled mobile app binaries can reveal hardcoded API endpoints too. A reference supplies a candidate whose deployment status still needs verification.
HTTP response headers provide the fifth source. Content-Security-Policy headers list where resources are allowed to come from and may show names such as cdn.example.com, api.example.com, and analytics.internal.example.com. Inspecting headers already captured in public datasets or existing responses requires no new probing. Fetching fresh headers from the target does produce traffic, so it falls outside the strict passive definition. A thorough passive pass combines all five sources and merges their results.
Active enumeration: DNS brute-forcing, permutation scanning, and virtual-host discovery
Wordlist quality determines how far DNS brute-forcing reaches. The method combines candidate labels with the parent domain and records which resolve through public resolvers such as 8.8.8.8 or 1.1.1.1. A generic list finds api, admin, staging, and dev. Larger lists built from CT data cover patterns that are harder to guess, while names found through passive discovery give clues to how the organization names its hosts. A fast resolver cannot compensate for missing guesses.
Puredns and shuffledns combine wordlist-driven discovery with wildcard detection on top of massdns, while dnsx handles resolution and record-type filtering. Permutation tools then expand the known names. Dnsgen and gotator can use api.example.com to make names to try, such as api-dev.example.com, api2.example.com, and api-internal.example.com, which puredns can resolve. A varied seed list gives these mutations more useful patterns to work with.
Virtual-host discovery tests a different boundary altogether. Multiple applications can share an IP address, with the HTTP Host header determining which site responds. Sending hostnames to try in that header and comparing the responses can show applications that DNS results missed. FFUF, gobuster, and wfuzz support this approach. It is particularly useful when internal tooling shares a load balancer with a public product.
Zone walking has a narrower place in discovery. DNSSEC zones using NSEC records can expose their signed names through the records’ canonical ordering. NSEC3 was introduced to stop this simple walk, so the older configuration is now a rare chance to use it. AXFR requests against authoritative nameservers are also worth attempting within the test’s scope. A misconfigured server may still disclose its whole zone.
The four-phase production pipeline: how these techniques chain together
A team can adapt this workflow without treating it as a rigid script. The first phase runs passive collection in parallel through Subfinder, Amass in passive mode, crt.sh, and the Wayback Machine, then merges and deduplicates the results. The names found also serve as seeds for recursive searches. For example, dev.example.com may have a child such as jenkins.dev.example.com that the first pass missed.
The second phase uses puredns for active brute-forcing with wildcard detection enabled and a wordlist scaled to the organization. Tool boundaries are important at this stage. Subfinder has been passive-only since v2.0, when its brute-force module was removed. Its -all flag enables passive sources, so its output must feed a separate active tool.
The third phase generates permutations from the combined passive and brute-force results, then resolves them. This gives dnsgen and gotator more seeds to work with than either of the earlier phases alone. The fourth phase validates and enriches the resulting hosts with httpx, collecting status codes, page titles, redirects, and technology fingerprints. DNS history, hosting context, and reputation signals add the context needed for triage. Subzy and Nuclei takeover templates fit into this validation phase to flag takeover candidates, rather than leaving automated detection as an unrelated afterthought.
What enumeration consistently finds: the high-risk subdomain patterns that appear in almost every engagement
Forgotten development and staging environments are a recurring finding. They may run older software, show debug output or internal API endpoints, and have weaker credentials than the main application. A legacy-api.example.com host running an old Express application can escape the scrutiny given to the product. Exposed internal tools create a related problem. Jenkins, Grafana, or Kibana may receive a public hostname during setup and never move behind a VPN.
Orphaned marketing sites fall out of routine maintenance. Their campaigns end, but their subdomains remain unpatched, unmonitored, or pointed at third-party hosting no longer clearly under company control. Inherited domains and subdomains may never enter the parent company’s asset register or security lifecycle.
Dangling CNAMEs deserve closer attention than ordinary stale pages. A hostname can still point to an S3 bucket, Heroku app, or GitHub Pages site after that resource has been removed. Cancelling the service does not remove the DNS record. Where the provider allows the abandoned resource name to be claimed, another party may take control of content served through the company’s hostname.
Subdomain takeover: why dangling CNAMEs are more than a hygiene issue
A dangling CNAME can become a trust transfer. In the example blog.example.com pointing to example.github.io, deleting or renaming the destination leaves the original DNS relationship behind. If an attacker can claim that destination through GitHub Pages, the company’s hostname can lead to attacker-controlled content. The mechanism exploits the mismatch between the resource lifecycle and the DNS lifecycle.
The consequences extend beyond a defaced blog page. An attacker can serve content under a hostname users recognize, set cookies scoped to the parent domain, and potentially harvest session tokens, depending on the application’s trust and session configuration. AWS S3, GitHub Pages, Heroku, Azure Web Apps, Shopify, and Netlify are among the platforms involved in this risk. A dangling record is still a candidate until claimability and impact are established.
Enumeration can also expose targets for an adjacent risk. Server-side request forgery, or SSRF, can let requests from the application layer reach internal services. Discovered subdomains can supply a map of those services. A hostname can be useful to an attacker through SSRF even without direct public access.
Turning a raw subdomain list into a prioritized work queue
DNS history provides the strongest initial triage signal. A hostname that once pointed into known company infrastructure and now points elsewhere warrants immediate investigation for a dangling entry or hijack. Hosting ASN context and known cloud-account information help distinguish forgotten company resources from destinations nobody on the team provisioned.
An httpx result showing 200 OK and a Jenkins login page calls for different attention from a 404 on a parked marketing site. Redirect chains and technology fingerprints help identify what is actually running. Cross-referencing destination IPs with blocklists and threat-intelligence feeds can also reveal infrastructure already flagged for abuse.
The queue should put takeover candidates, exposed internal tooling, and authentication-adjacent assets at the top of the list. Stale marketing pages and parked domains belong in a separate cleanup stream. This is where enumeration becomes useful security work. Because infrastructure keeps changing, the queue also needs fresh discovery results. A hostname that was safe last quarter may become dangling after a SaaS cancellation or app deletion.
How a professional pen test uses these techniques differently than a one-off script
Automated enumeration maps candidates. A penetration test establishes exploitability. A dangling CNAME does not prove that a provider will allow a claim or that the application’s users face the assumed impact. In an authorized test, claiming the abandoned resource and showing what happens gives the team evidence of what it had only suspected. Human review then connects that evidence to the application’s architecture and trust model. An OSCP-certified reviewer can distinguish a credible exploit from an automated false positive.
Whitebox access also changes what discovery can reach. Source code, cloud configurations, and infrastructure-as-code show names that never appeared in CT logs or passive DNS and that a generic wordlist would miss. Distinguishing names that may be internal-only from those that exist in Terraform awaiting deployment prevents a planned resource from being mistaken for a current internet exposure.
SOC 2 Type II auditors commonly expect evidence of testing across in-scope systems, although no Trust Services Criterion explicitly mandates penetration testing. An automated hostname inventory does not provide the same evidence as a penetration test report with a certified attestation. Continuous pull-request scanning addresses an earlier point in the lifecycle by catching new subdomain configurations before they ship.


