Subdomain Takeover: The Forgotten DNS Record Attackers Exploit
You pointed blog.yourcompany.com at a third-party service, then tore the service down and left the DNS record behind. An attacker claims the now-unclaimed resource and serves their own content on your subdomain, with a valid TLS certificate.
Watch
How a forgotten dangling DNS record lets an attacker claim your subdomain, and how to prevent it.
TL;DR
- 1 A subdomain takeover happens when a CNAME points at a third-party service whose underlying resource was deleted but the DNS record was left in place.
- 2 An attacker re-registers the unclaimed resource (a new S3 bucket, a new GitHub Pages repo) with the same name and serves content from a subdomain you still own, with a valid certificate for your name.
- 3 Fix it by auditing DNS for dangling records aimed at deprovisioned services, then removing or reclaiming each one.
What it does
A subdomain takeover turns a piece of forgotten DNS into a phishing launchpad on a domain you control. The setup is mundane: you point <code>blog.yourcompany.com</code> at a SaaS host (GitHub Pages, an S3 bucket, Heroku, Netlify) with a CNAME, ship the site, and move on. Months later the service is torn down. The bucket is deleted, the repo is removed, the app is decommissioned. The one thing that does not get cleaned up is the CNAME, which still points at a target that no longer belongs to anyone.
That dangling record is the whole problem. The third-party platform sees an unclaimed name and lets the next person register it. An attacker who notices your CNAME pointing at a deleted resource simply claims that resource: a new bucket with the same name, a new GitHub Pages repo, a new app. Now requests to <code>blog.yourcompany.com</code> resolve to <strong>their</strong> content. Because the request is served over your subdomain, the attacker can obtain a valid TLS certificate for it, so the browser shows a padlock and your real name in the address bar.
From there it is everything a lookalike domain wants to be, except it is not a lookalike. It is your actual domain. Phishing pages look completely legitimate. Cookies scoped to <code>*.yourcompany.com</code> can be read or set. Brand-abuse content sits on infrastructure that search engines and security tools already trust because it is yours. The fix is cheap, but only if you know the dangling record exists.
How it works
-
1
<strong>Resolve the CNAME chain.</strong> The detection starts by walking the subdomain's CNAME chain, following each hop up to a small depth cap (roughly 3 hops). A subdomain with no CNAME does not depend on a third party and is left alone; only subdomains that delegate to an external service are candidates.
-
2
<strong>Match the target against fingerprinted services.</strong> Each hostname in the chain is matched against a catalog of known third-party providers (S3, GitHub Pages, Heroku, Shopify, Netlify, Vercel, Azure, Fastly, Cloudfront, and more). A CNAME ending in <code>.s3.amazonaws.com</code> or <code>.github.io</code> tells you which platform owns the target, and therefore which unclaimed-resource signal to look for.
-
3
<strong>Probe the live page for the unclaimed signal.</strong> If the chain matches a known provider, the page at <code>https://<subdomain>/</code> is fetched and checked for that provider's distinctive unclaimed-resource body text. AWS S3 returns <code>NoSuchBucket</code>; GitHub Pages returns <code>There isn't a GitHub Pages site here</code>; Heroku returns <code>No such app</code>. Only when both the fingerprint and the body signal line up is the subdomain flagged vulnerable.
-
4
<strong>Why a generic 404 is not enough.</strong> A bare <code>404 Not Found</code> is ambiguous: plenty of healthy apps return 404 from their root path during a deploy. The detection deliberately keys on signals a legitimate, claimed resource would never serve, which is what keeps a false <code>your subdomain is hijacked</code> alert from firing on a live site.
-
5
<strong>Errors are not silently passed.</strong> If the CNAME matches a provider but the HTTP probe fails (a timeout, a 5xx, a transport hiccup), the result is recorded as an error and retried on the next run rather than being shadowed as safe. A transient failure on a genuinely takeover-able subdomain would be a costly silent miss.
Common pitfalls
-
<strong>Forgetting to remove DNS on deprovisioning.</strong> The takeover window opens the moment the service is deleted and the CNAME is left behind. Deprovisioning a SaaS resource and removing its DNS record have to be the same checklist item, not two separate ones that drift apart.
-
<strong>Dangling wildcard CNAMEs.</strong> A wildcard like <code>*.yourcompany.com</code> pointed at a third-party host means every unclaimed name under it is takeover-able at once, not just one. Wildcards aimed at external services deserve extra scrutiny because the blast radius is the whole label space.
-
<strong>Assuming "just a subdomain" is low risk.</strong> A subdomain is your real domain. An attacker serving content there inherits your name, your TLS, and any cookie scoped to the parent domain. Treating subdomains as throwaway is exactly the assumption the attack relies on.
-
<strong>Auditing once and calling it done.</strong> New CNAMEs get added and old services get torn down continuously. A one-time DNS audit catches today's dangling records and misses every one created next month. The check has to run on a schedule.