Detecting Subdomain Takeover Threats
A subdomain takeover occurs when a DNS record (typically CNAME, sometimes NS/A/MX) points to an external service (e.g., a cloud host, SaaS platform, or third-party CDN) that is no longer provisioned or claimed. An attacker who registers/claims that same resource on the provider side gains full control of content served under the legitimate organization's subdomain — inheriting trust, cookies, and even the parent domain's SSL certificate validity in some configurations.
Minimal detection check:
Bash# 1. Enumerate subdomains subfinder -d target.com -silent -o subs.txt amass enum -passive -d target.com >> subs.txt sort -u subs.txt -o subs.txt # 2. Resolve CNAMEs dnsx -l subs.txt -cname -resp -o cnames.txt # 3. Match CNAME targets against known vulnerable-service fingerprints # (e.g., *.github.io, *.herokuapp.com, *.s3.amazonaws.com, *.azurewebsites.net) grep -f fingerprints.txt cnames.txt > candidates.txt # 4. Confirm by HTTP fingerprint (e.g., "There isn't a GitHub Pages site here") httpx -l candidates.txt -mc 404 -title -match-string "No such app" -o confirmed.txt
Any entry surviving step 4 is a strong takeover candidate requiring manual verification before disclosure.
Progress:
- [ ] Step 1: Enumerate subdomains (passive + active)
- [ ] Step 2: Resolve DNS records (CNAME/A/NS/MX) for each subdomain
- [ ] Step 3: Classify records against a fingerprint database of claimable services
- [ ] Step 4: Query service endpoints to confirm "unclaimed" state
- [ ] Step 5: Score/rank candidates using ML classifier (reduce false positives)
- [ ] Step 6: Validate manually (non-destructive proof-of-concept only)
- [ ] Step 7: Report with evidence, risk level, and remediation guidance
Step 1 — Enumeration. Combine passive sources (certificate transparency logs, public DNS datasets, search engine dorking) with active brute-force (wordlist-based DNS resolution) to maximize subdomain coverage. Coverage gaps here are the primary cause of missed takeovers.
Step 2 — DNS resolution. Bulk-resolve all discovered names; retain CNAME chains, not just final IPs, since the takeover-relevant record is often an intermediate CNAME pointing to a decommissioned third-party resource.
Step 3 — Fingerprint matching. Maintain an updatable table of {CNAME pattern, provider, vulnerable HTTP response signature} (e.g., AWS S3 "NoSuchBucket", GitHub Pages 404 page, Heroku "no such app"). Services change their error signatures over time, so refresh this table periodically.
Step 4 — Active confirmation. Issue an HTTP(S) request to the subdomain and compare response body/title/status code against the known "unclaimed" signature. This distinguishes a genuinely dangling record from one that is merely pointing to a shared/multi-tenant resource still in active use.
Step 5 — ML-based risk scoring. Use historical labeled examples (confirmed takeover vs. benign dangling-looking records) to train a classifier (e.g., gradient boosting or simple logistic regression) on features such as:
- CNAME target entropy / provider category
- HTTP status code and response length
- Time since last successful resolution
- WHOIS/registration age of the target domain in the CNAME
- Presence/absence of valid TLS certificate matching the parent domain
This reduces the manual triage burden on large subdomain sets by prioritizing high-confidence candidates first.
Step 6 — Manual validation. Never register/claim the external resource as "proof" against production targets without explicit authorization. Use provider sandbox/test accounts or clearly scoped bug-bounty rules of engagement.
Step 7 — Reporting. Document: subdomain, DNS record chain, provider, evidence (screenshot/response), risk rationale (e.g., "shares parent SSL cert, zero technical skill to exploit"), and remediation (remove the dangling DNS record or re-claim the resource).
Example 1:
Input: blog.example.com has CNAME → exampleblog.github.io, and GitHub Pages returns "There isn't a GitHub Pages site here."
Output: Confirmed dangling CNAME → high-risk takeover candidate. Remediation: delete the CNAME record or re-register the GitHub Pages site under the organization's account.
Example 2:
Input: shop.example.com has CNAME → cdn.example-shop.s3.amazonaws.com, bucket query returns <Error><Code>NoSuchBucket</Code>.
Output: Confirmed — S3 bucket unclaimed. Attacker can create a bucket with the exact name and serve phishing content under shop.example.com, inheriting trust and, if the parent uses a wildcard certificate, matching TLS validation too.
Example 3:
Input: api.example.com CNAME points to a Heroku app returning HTTP 200 with normal application content.
Output: Not vulnerable — resource is actively claimed; exclude from candidate list.
- Treat subdomain enumeration as continuous monitoring, not a one-time scan — subdomains are added/retired constantly, especially in large or M&A-heavy organizations.
- Prioritize candidates where the CNAME target service is known to allow free/anonymous claiming (GitHub Pages, S3, Heroku, Azure, Shopify, etc.) — these require no "technical skill" and are the highest-volume real-world risk.
- Cross-check TLS certificate scope: a takeover is especially severe when the subdomain inherits a wildcard cert from the parent, since it defeats the usual visual/certificate-based phishing cues.
- Automate fingerprint database updates; provider error messages and takeover feasibility change frequently as vendors patch this issue.
- Use ML scoring as a triage aid, not a final verdict — always confirm with an active, authorized HTTP check before reporting.
- Integrate findings into CI/CD or asset-management pipelines so DNS records are cleaned up when services are decommissioned.
- Relying solely on passive CT-log enumeration and missing subdomains only discoverable via brute force or internal DNS zone data.
- Flagging any CNAME to a third-party provider as vulnerable without confirming the "unclaimed" HTTP signature — causes high false-positive rates.
- Ignoring NS-record takeovers (delegated but unclaimed authoritative nameservers), which are rarer but more severe than CNAME takeovers.
- Performing "proof" by actually claiming the external resource on production targets without written authorization — this can constitute unauthorized access.
- Letting fingerprint signatures go stale; cloud providers periodically change error pages/status codes, silently breaking detection rules.
- Treating this as a one-off audit rather than continuous monitoring — new dangling records appear constantly as infrastructure changes.