A subdomain takeover happens when a DNS record on a domain you own keeps pointing at a cloud resource that no longer exists, and an attacker registers that same resource name on the provider to serve their own content from your trusted subdomain. The record is still there. The thing it pointed at is gone. Somebody else claims the empty slot, and now status.acmenotes.com answers with a page the attacker wrote, on a name your users already trust. This post walks the mechanism one step at a time: how a DNS record outlives the resource behind it, why the gap is claimable, what control of a trusted subdomain actually unlocks, and how to close the window for good.
The dangling pointer at the heart of a subdomain takeover
A domain name is a tree. acmenotes.com is the apex, and below it you hang names like www, blog, status, and app. Each of those names needs a DNS record to tell the world where it lives. The most common kind for a hosted service is a CNAME, which is an alias. It says, in effect, do not look here, look over there instead.
Say your team puts the marketing status page on a managed host. You create:
status.acmenotes.com. CNAME acme-status.someprovider.io.
Now any browser that asks for status.acmenotes.com is told to go ask acme-status.someprovider.io, and the provider serves the page. This works because you registered the resource name acme-status on that provider, and the provider mapped it back to your content. Two things are now linked: the DNS alias you control, and the resource slot the provider holds for you.
Months later the status page is retired. An engineer deletes the resource on the provider, closes the account, and moves on. The provider releases the name acme-status back into its pool of available names. But the CNAME in your DNS zone is never touched. It still says status.acmenotes.com aliases to acme-status.someprovider.io. The alias now points at a slot that belongs to nobody. That is a dangling DNS record, and OWASP describes the condition plainly: a DNS record, typically a CNAME, points to a cloud resource or third party service that has been deprovisioned or no longer exists.
The trouble is structural, not careless. Cloud resources are short lived and DNS records are persistent. Teams spin up and tear down services constantly, and the records that point at them tend to pile up unless somebody deletes them on purpose. The pointer outlives the thing it pointed at.
Why the empty slot is claimable
An attacker enumerating your subdomains looks for exactly this shape. They resolve status.acmenotes.com, follow the alias to acme-status.someprovider.io, and ask for the page. Instead of your content they get a provider error that says the resource is not configured. Each provider has a recognizable fingerprint for that state. On Amazon S3 the bucket returns The specified bucket does not exist. On GitHub Pages the response reads There isn't a GitHub Pages site here. On Heroku it is No such app. On some Azure endpoints the name simply fails to resolve at all and the DNS layer returns NXDOMAIN. That distinctive error is the signal that the alias is dangling and the slot is open.
From there the takeover is just a registration. The attacker creates their own account on the provider and registers the resource name your record still points at, acme-status. The provider has no memory that this name was once yours. It hands the name to whoever asks first. The moment the attacker holds acme-status.someprovider.io, your CNAME resolves their content. They did not touch your DNS. They did not breach your account. They claimed the address your own record was still advertising. The can I take over xyz project catalogs which providers leave this door open and the exact error string each one shows when a slot is unclaimed.
Two conditions have to line up for this to work, and both are common. First, your external DNS server has a subdomain record configured to point at a resource or endpoint that is no longer active. Second, the provider hosting that endpoint does not handle ownership verification properly, so it lets a new account register the name without proving any connection to your domain. When a provider does verify ownership, the second condition fails and the slot stays safe even though the record dangles. When it does not, the dangling record is enough on its own.
It is not only CNAME records
The alias case is the most frequent, but the same shape appears across record types, and the impact climbs as you move up the tree. A dangling A record that pins a subdomain to an IP address can be taken over if that address is released back into a cloud provider’s shared pool and the attacker manages to acquire it. A dangling MX record can route mail for the subdomain to a host the attacker controls, which lets them receive password resets and verification mails sent to that name. The worst case is a dangling NS record. Nameserver delegation hands authority for a whole zone to another server. If that server is deprovisioned and the delegation is left in place, an attacker who claims it gains control over the entire DNS zone under that name, not just one page. An NS takeover is less likely but has the highest impact, because it is full control of the subtree rather than a single endpoint.
The attacker never breaks into your domain. Your domain keeps pointing at an address you abandoned, and the attacker simply moves into it.
What control of a trusted subdomain unlocks
Serving a page from status.acmenotes.com sounds like vandalism, a defacement at worst. It is far more than that, because the rest of your application has been built to trust names under acmenotes.com. The browser, your cookies, your login flow, and your content policy all make decisions based on the domain. A taken over subdomain steps inside that trust boundary and quietly inherits a pile of privileges it was never supposed to have.
Phishing that passes every glance test
The simplest payoff is a login page. The attacker serves a pixel perfect copy of your sign in form at status.acmenotes.com and mails the link to your users. Everything a careful user checks holds up. The domain is really yours. The TLS certificate is valid, because the attacker controls the subdomain and can request one from any certificate authority on the spot. There is no typosquatting tell, no lookalike character, no foreign domain. The credentials users type go straight to the attacker. This is the same trust that makes phishing on a controlled subdomain so much more effective than a random external link.
Cookies scoped to the parent domain
Cookies are where this turns from convincing into mechanical. A cookie set with Domain=.acmenotes.com is sent by the browser to every subdomain under it, including the one the attacker now owns. If a session cookie or a preference cookie is scoped to the parent domain and is not marked HttpOnly, JavaScript running on the attacker’s page can read it directly with document.cookie. The attacker did not need to defeat your login. The browser handed them the session cookie because, as far as it can tell, the request came from a legitimate part of acmenotes.com. Parent domain cookie scoping was a convenience for sharing sessions across app and www. It now shares them with the attacker too.
Even cookies marked HttpOnly are not fully out of reach. The attacker can set their own cookies on the parent domain from the controlled subdomain, which opens session fixation, and they can read any cookie that scripts are allowed to see. The boundary everyone assumed sat at the domain edge actually ran between subdomains, and one of those subdomains just changed hands.
OAuth and SSO redirect abuse
Login flows lean on a list of trusted return addresses. When a user signs in through OAuth or single sign on, the identity provider sends the token or authorization code back to a redirect_uri, and it will only send it to a destination on an approved allowlist. Teams frequently approve patterns rather than exact addresses, allowlisting anything under *.acmenotes.com so they do not have to update the list every time they add a subdomain. A taken over subdomain matches that wildcard. The attacker starts an authentication flow with redirect_uri=https://status.acmenotes.com/callback, the identity provider sees a host that passes the allowlist, and it delivers the authorization code or token to a page the attacker controls. The fix the standards push is exact match redirect URIs precisely because wildcard allowlists turn any one weak subdomain into a token leak.
Bypassing a Content Security Policy allowlist
A Content Security Policy is a list of sources a browser is allowed to load scripts and other content from. Many policies list a wildcard like script-src https://*.acmenotes.com so that internal subdomains can host assets. The policy is meant to be a wall against injected scripts from anywhere else. A taken over subdomain sits inside the wildcard, so a script served from status.acmenotes.com satisfies the policy. If the attacker also has an HTML injection or cross site scripting foothold on the main app, the CSP that should have blocked their payload now waves it through, because the source is an allowlisted subdomain they happen to own. The same wildcard that bypasses the OAuth allowlist bypasses the script allowlist. To see how a policy like that grades, and to spot a wildcard before an attacker does, paste your response headers into our free security headers and CSP analyzer.
Defeating same site assumptions
A lot of web security quietly rests on the idea that everything under one registrable domain is one trust zone. Same site cookie rules, CORS allowlists that permit any origin under the parent, frames that are trusted because they share the domain, internal tools that skip a permission check for requests coming from a sibling subdomain. Each of those is a reasonable shortcut right up until one subdomain is controlled by someone outside the organization. After the takeover the attacker speaks from inside the same site, and every assumption built on that sameness now works in their favor.
How one weak subdomain chains into a full compromise
The individual effects above are bad, but the real danger is that they combine. Walk a plausible chain on our invented app, Acme Notes. The main app at app.acmenotes.com sets a session cookie scoped to .acmenotes.com so the marketing site and the app can share a login. It also ships a Content Security Policy that allowlists script-src https://*.acmenotes.com for shared widgets, and its single sign on flow approves any redirect_uri under *.acmenotes.com. None of those three choices is reckless on its own. Each one is a normal convenience.
Now the attacker takes over the retired status.acmenotes.com. They host a script there. Because the subdomain matches the CSP wildcard, that script loads inside the main app whenever they find a place to reference it, and it reads the parent domain session cookie that the browser cheerfully attaches to the controlled subdomain. If a cookie is marked HttpOnly and stays out of reach, they pivot to the login flow instead, starting an authentication request with redirect_uri=https://status.acmenotes.com/callback, which the wildcard allowlist accepts, and the identity provider delivers the authorization code to their page. Three separate trust shortcuts, each defensible alone, become one path from a forgotten DNS record to a stolen session. That is why a single dangling subdomain rarely stays a small problem.
How attackers find a dangling record before you do
None of this requires luck. The reconnaissance is routine. An attacker collects the subdomains of a target from certificate transparency logs, which publicly record every TLS certificate ever issued for a name, from passive DNS datasets, and from brute forcing common names. Then they resolve each one and check where the alias lands. Any subdomain whose CNAME points at a provider and returns one of the known not configured fingerprints is a candidate. Tooling automates the whole sweep, matching responses against the same fingerprint list that the can I take over xyz project maintains. The economics favor the attacker. They scan thousands of names cheaply, and they only need one forgotten record. You have to remember all of them.
It is worth naming where this sits relative to neighboring bugs. A subdomain takeover is not server side request forgery, where a server is tricked into making a request on the attacker’s behalf, and it is not the credential theft path from a cloud instance metadata service. But it rhymes with both. All three come from a component trusting a name or a location more than the situation deserves. Here the trusted thing is the domain label, and the betrayal is that the label kept its meaning after the resource behind it disappeared.
Preventing a subdomain takeover
The good news is that this class of bug has a clean root cause, which means it has a clean fix. The window only exists because of an ordering mistake during decommissioning. Close that ordering and the window never opens.
Deprovision in the right order
The single most important habit is sequencing. When you retire a service, the order is fixed:
- First serve a maintenance page or redirect from the subdomain, so nothing breaks abruptly.
- Then update or remove the DNS record so the name no longer points at the provider slot.
- Allow time for DNS to propagate so caches expire.
- Only then decommission the cloud resource.
The common mistake is doing these steps in reverse, deleting the cloud resource first. That creates an immediate window for takeover that persists until someone notices the dangling record. Delete the pointer before you release the thing it points at, and there is never an empty slot for anyone to claim.
Inventory every record and tie it to an owner
You cannot protect records you do not know you have. Keep a live inventory of every DNS record in every zone, and link each one to the resource and the team that owns it. When a resource is torn down, that link is what tells you which record has to go with it. Records without a known owner are exactly the ones that rot into dangling aliases, so treat an unowned record as a finding, not a footnote.
Claim and verify the resource you point at
Wherever a provider offers domain verification, use it. A claimed and verified resource cannot be silently re registered by a stranger, because the provider checks ownership before handing the name out. This shrinks the set of providers where a free registration is enough to steal the slot, and it is the difference between an alias that is merely unused and one that is actually open for the taking.
Monitor for the dangling state continuously
Treat detection as ongoing, not a one time audit. For every CNAME in your zone, resolve the target on a schedule and check that it still exists and returns the content you expect, rather than a provider error page. Watch for two signals in particular. The first is NXDOMAIN, where the aliased target no longer resolves at all. The second is a known service fingerprint in the response body, one of those distinctive not configured error strings that says the resource has been removed. A weekly automated scan that flags either condition turns a silent dangling record into an alert before an attacker finds it. If you already have a CNAME target and the error page it serves, our free subdomain takeover fingerprint checker matches them against the known service fingerprints so you can confirm a dangling slot fast. Certificate transparency logs help here too, since they reveal subdomains you may have forgotten you ever created.
The assumption that breaks
Step back from the records and the fingerprints and one assumption is left holding everything up. DNS assumes that the record still points at something you own. A CNAME is a promise about a relationship between two names, and the relationship is only safe while you control both ends. The system has no way to notice when one end quietly slips away. The provider forgets you the instant you delete the resource. Your zone keeps advertising the alias as if nothing changed. Nothing in the protocol reconciles those two views, so the gap between them sits open, advertised to the whole internet, waiting.
The bug is not a broken DNS server or a sloppy provider. The bug is a pointer that outlived the resource it pointed at, and a trust boundary that everyone drew at the domain edge when it actually ran between the subdomains. That gap between what a system assumes about a name and what an attacker can actually arrange is the kind of flaw you find by asking what each component trusts and why it still trusts it, rather than by scanning for a known bad string. It is exactly the kind of assumption an autonomous researcher built to test assumptions is meant to catch. Delete the record before you release the resource, verify what you point at, and watch your aliases for the day one of them stops pointing home. Learn more about that approach on our about page.
Frequently asked questions
What causes a subdomain takeover?
It is caused by a dangling DNS record. A subdomain has a CNAME aliasing it to a cloud resource, and when that resource is deleted or the account is closed, the provider releases the name but the DNS record is never removed. The alias now points at an empty slot anyone can register. The OWASP Subdomain Takeover Prevention Cheat Sheet describes this dangling record as the core condition.
How does an attacker claim the dangling subdomain?
They enumerate your subdomains, follow each alias to its provider target, and look for a not configured error such as The specified bucket does not exist on S3 or There isn't a GitHub Pages site here. on GitHub Pages. That error means the slot is free. The attacker then registers the same resource name on the provider, and your unchanged CNAME immediately serves their content. The can I take over xyz project catalogs the vulnerable providers and their exact fingerprints.
Why is a taken over subdomain so dangerous?
Because the subdomain sits inside the trust boundary of your domain. The attacker can host a convincing phishing login on a real name with a valid certificate, read cookies scoped to the parent domain, match wildcard OAuth redirect allowlists to steal tokens, and satisfy a Content Security Policy that allowlists *.yourdomain.com. Every assumption built on names being under one trusted domain now works in the attacker’s favor.
How do you prevent a subdomain takeover?
Deprovision in the right order: remove or update the DNS record before you delete the cloud resource, never the reverse. Keep an inventory of every DNS record tied to its owner, use provider domain verification to claim the resources you point at, and monitor every CNAME on a schedule for NXDOMAIN or a known service fingerprint. This maps to the weakness MITRE tracks as CWE-350, relying on a name resolving to something you still control.
