← back to lessons

META - Subdomain-Takeover Triage Playbook (transferable)

Consolidates the 2026-06-12 passive-Web2 session's takeover lessons into ONE reusable methodology. Run this against any program with a broad wildcard scope. Source lessons: web2-firebase-hosting-dangling-domain-fingerprint, web2-statuspage-custom-domain-host-header-discriminator, web2-vercel-deployment-not-found-vs-claimability, web2-takeover-claimed-vs-claimable-distinction, web2-cname-empty-field-vs-dangling-distinction, web2-ct-source-failover-and-claimed-cname-fingerprint, 2026-06-11-web2-fresh-program-claimed-cname-takeover-triage.

Target selection (the EV driver)

Takeover EV is highest on LARGE, SPRAWLING, MULTI-ACQUISITION orgs (forgotten subdomains from M&A / many brands / old products), NOT small/fresh targets. Session evidence: Playtika + Spotify + Elastic (sprawling, multi-brand) each yielded a candidate; Sentry/Moov/Taiko/Doppler (small/clean) yielded none; Yahoo (sprawling BUT well-managed) yielded none. So: sprawl raises PROBABILITY, management-quality lowers it. Pick big multi-brand wildcard scopes; expect hundreds of hosts.

Enumeration (with failover - CT sources are flaky)

  1. certspotter FIRST: curl "https://api.certspotter.com/v1/issuances?domain=DOMAIN&include_subdomains=true&expand=dns_names" (rate-limits 429 without a key).
  2. crt.sh is a flaky single-point-of-failure (frequent 404/502/empty) - do NOT rely on it; FAIL OVER to: hackertarget https://api.hackertarget.com/hostsearch/?q=DOMAIN, rapiddns, certspotter.
  3. (subfinder/amass/dnsx NOT installed on the box - only httpx; installing subfinder would deepen enum. Banked infra ask.)
  4. Filter raw results to in-scope suffixes (multi-SAN certs add noise).

The two-stage filter

Stage 1 - DANGLING? (the CNAME column is the filter)

Stage 2 - CLAIMABLE? ("dangling != claimable" - the decisive distinction)

A dangling pointer is only a finding if an attacker can actually BIND it. Two sub-checks: (a) Provider serves the UNCLAIMED fingerprint (not the org's real content), AND (b) The provider's custom-domain VERIFICATION GATE does not block re-binding. Most modern providers have a gate (TXT record / team-verification / account-binding) that PREVENTS takeover even when the pointer dangles - which downgrades the candidate to informational. You CANNOT confirm (b) passively; it requires an authorized active claim-test. So passive output = "candidate, claimability UNCONFIRMED."

Per-provider fingerprint + gate table

Provider Unclaimed fingerprint Claimability gate (blocks takeover if present)
Firebase Hosting Anycast A (151.101.x.x) + generic "Site Not Found" page Project must add the custom domain; modern Firebase may require ownership proof
Atlassian Statuspage CNAME *.stspg-customer.com; real-Host fetch 302s to statuspage.io with NO x-statuspage-version (claimed sibling HAS it) Free-tier custom-domain bind WITHOUT TXT verification = claimable; if TXT enforced = informational
Vercel x-vercel-error: DEPLOYMENT_NOT_FOUND (+ often an expired cert) Apex/team domain-verification gate; if enforced = not claimable
GitHub Pages "There isn't a GitHub Pages site here" Repo must add the CNAME; org-owned verification can block
AWS S3-website NoSuchBucket Bucket name globally re-creatable = claimable (no gate) - higher confidence
CloudFront distribution-not-found (NOT an origin 4xx - distinguish) re-pointable only if the distribution alias is free

FALSE-POSITIVE classes (banked - do NOT stage these)

  1. WAF / anti-bot challenge wall (Cloudflare/DataDome/Tumblr) returning a generic page - NOT a provider unclaimed-page. Check baseline server: / cf-mitigated: / x-datadome:.
  2. Portal-OWNED 404 (HubSpot serves a 404 but the portal id is owned by the org) - not claimable.
  3. Account-GATED 404 (WP-VIP / go-vip nginx-404 where the account owns the slug) - not claimable.
  4. SPA catch-all: .git/.env/random-path all return 200 with the SAME body = Vercel/Netlify SPA shell, NOT a real file/deployment. Diff a random path to confirm.
  5. "resolves != claimed": a host that resolves and serves SOMETHING is usually claimed; only the provider-specific unclaimed fingerprint counts.
  6. Raw-IP dangle / dead-ELB / Google-ghs hosts: often not externally re-claimable.

Output discipline

Session scoreboard (calibration)

4 sprawl lanes -> 3 candidates (Playtika/Firebase, Spotify/Statuspage, Elastic/Vercel), all Medium + claimability-pending; 1 clean (Yahoo). 4 small-target lanes -> 0. Bottleneck after staging: operator authorization for the active claim-test (one decision covers all candidates).

Generated 2026-07-02 13:15:04 UTC | auto-sync /15min