Subdomain Takeover: How It Happens and How to Prevent It
A subdomain takeover starts with a DNS record that points at a resource you deleted. How dangling CNAME, NS, A and MX records are abused, found and prevented.
Published: · 7 min read
A subdomain takeover happens when a DNS record in your zone still points at an external resource you no longer control, and somebody else claims that resource. The typical case: shop.example.com is a CNAME to a hosted platform, the shop was cancelled, the record stayed. If the platform lets anyone register the freed name without proving control of the domain, an attacker does so and serves their content on your subdomain, with a valid certificate. The fix is dull and effective: know which records point outside your infrastructure, and remove the DNS record before you delete the thing it points to. This guide covers the variants, the impact, detection with dig and curl, and a prevention checklist.
How a takeover works
Nothing is hacked in the usual sense. Your DNS says, with your authority, "this name is served over there", and "over there" is a namespace shared with every other customer of a provider. The sequence:
- You create a resource at a cloud or SaaS provider (a storage bucket, a platform app, a help-desk or landing-page site) and point a subdomain at it with a CNAME.
- Later the resource is deleted: project over, subscription cancelled, account closed.
- The CNAME stays in the zone. Nobody owns it, nothing reminds anyone. This is a dangling record.
- The provider makes the old resource name available again and does not check who controls the domain pointing at it.
- An attacker registers that name. From that moment your subdomain delivers the attacker's content.
Whether step 4 is possible depends on the provider. Many now require a verification TXT record or reserve released names, but you rarely know the policy of every service ever connected to your domain.
The variants
| Dangling record | What the attacker needs | What they gain |
|---|---|---|
| CNAME to a deleted cloud/SaaS resource | To claim the same resource name at the provider | Web content on the subdomain |
| CNAME to a host whose domain has expired | To register that domain | Everything under that CNAME target |
| NS delegation of a subzone to a DNS provider where the zone was deleted, or to nameservers under an expired domain | To create the zone at that provider, or register the nameserver's domain | Full control of the subzone: every record type, every name below it. The worst case |
| A record to a released cloud IP address | To be assigned the same IP address: a matter of luck and repetition | Web content; opportunistic rather than targeted |
| MX record to a deprovisioned mail service | To claim the domain at that mail service | Incoming mail for the subdomain |
Why it matters more than a defaced page
A subdomain of your domain inherits trust that a look-alike domain never gets:
- Phishing under your real name.
login-help.example.compasses every "check the address bar" training. - Cookies. Cookies set with
Domain=example.comare sent by the browser to every subdomain, including the one the attacker now runs. Depending on the flags, that can include session cookies. - Allowlists that trust
*.example.com. CORS configurations, Content Security Policy sources, OAuth redirect URIs and single-sign-on settings frequently trust the whole domain. A taken-over subdomain is inside that trust. - Publicly trusted certificates. Whoever controls the content of a host name can pass HTTP-based domain validation and obtain a valid certificate for it.
- Mail. With a dangling MX, mail addressed to the subdomain is delivered to the attacker, including password resets for accounts registered with such addresses.
How to find dangling records
Start from your zone, not from the outside (the record types are explained in DNS record types). Export every zone you have and list the records whose target is not your own infrastructure: CNAMEs to other domains, NS delegations, MX records, and A/AAAA records in address ranges of cloud providers.
Then test each one.
CNAMEs. Resolve the target. A target that does not exist is the clearest sign:
$ dig +short CNAME shop.example.com
promo-example.cloudhost.example.
$ dig promo-example.cloudhost.example
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 4711
NXDOMAIN for the target means the record points at nothing. If the target resolves (many platforms answer for every name with a wildcard), look at the HTTP response:
$ curl -sI https://shop.example.com | head -n 1
HTTP/2 404
A provider's generic "no such site", "no such bucket" or "there is nothing here yet" page on your subdomain means the resource behind it is gone. Also check that the domain of each CNAME target is still registered and belongs to the provider you expect.
NS delegations. Ask each delegated nameserver directly, without recursion, whether it is authoritative for the subzone:
$ dig +short NS sub.example.com
ns1.dns-host.example.
ns2.dns-host.example.
$ dig @ns1.dns-host.example sub.example.com SOA +norec
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 1289
REFUSED, SERVFAIL or an answer without the aa flag means that server does not hold your zone. No answer at all may be a network problem: repeat the test before drawing conclusions.
Names you forgot. The zone export finds records; it does not find zones you forgot you have, or names created by another team at another DNS provider. Certificate Transparency logs help here: every publicly trusted certificate is logged, so they reveal host names that once got a certificate. They also reveal certificates you did not request, which is the trace a takeover leaves behind.
Prevention
Order of operations. This one rule prevents most cases:
- Decommissioning: remove the DNS record first, wait for the TTL to pass, then delete the resource.
- Provisioning: create and verify the resource first, add the DNS record last.
Give records owners. Make DNS changes through review, ideally as infrastructure-as-code in the same repository as the resource they point to, so that deleting the resource and deleting the record are one change.
Choose providers that verify domains. A provider that requires a domain-verification TXT record before it serves a custom domain cannot be used for this attack by a stranger.
Avoid wildcard CNAMEs to third parties. *.example.com CNAME something.provider.example makes every possible name a candidate. See wildcard DNS records.
Limit what a subdomain can do. Use host-only cookies (no Domain attribute) for sessions. List exact origins in CORS, CSP and OAuth redirect allowlists instead of *.example.com.
Know what CAA does and does not do. A CAA record restricts which certificate authorities may issue for your names. It does not stop a takeover: the attacker simply uses a CA you allow. Monitoring Certificate Transparency for certificates nobody on your side requested is the useful complement. Details in CAA records explained.
Checklist
- All zones at all DNS providers are known and exported.
- Every CNAME, NS, MX and cloud-IP A/AAAA record has a named owner and purpose.
- Every external CNAME target resolves, and its domain is registered to the expected provider.
- Every delegated subzone is answered authoritatively by all its nameservers.
- The decommissioning procedure says: DNS record first, resource second.
- No wildcard CNAME points at a third party.
- Session cookies are host-only; allowlists name exact hosts.
- CT logs are reviewed for unknown host names and unexpected certificates.
If you find one
- Remove the dangling record immediately (or, if the service is still needed, re-create the resource in your own account first). Removing the record ends the exposure as soon as caches expire.
- Find out whether it was already claimed. What does the subdomain serve right now?
- If it was: treat cookies scoped to the parent domain as exposed, and invalidate sessions. Check allowlists that included the subdomain.
- Review CT logs for certificates issued for that name during the exposure, and ask the issuing CA to revoke those you did not request.
- Fix the process that left the record behind, then audit the rest of the zone: dangling records rarely come alone.
Ethics and law
Test only domains you are responsible for or are authorised in writing to assess. Looking up public DNS is harmless. Claiming the resource behind somebody else's dangling record is a different act: you would be serving content on their name and possibly receiving their users' cookies or mail. That is unauthorised access, even with a harmless "proof" page and good intentions. If you notice a dangling record on a domain that is not yours, report it to the owner through the contact in their security.txt file (the security.txt checker shows whether one is published) and stop there.
Common mistakes
- Deleting the cloud resource first and "cleaning up DNS later".
- Auditing only the main zone and forgetting delegated subzones.
- Trusting
*.example.comin CORS, CSP or OAuth settings. - Believing a CAA record prevents takeovers.
Check it with OrbitProbe
The OrbitProbe subdomain finder lists the host names under a domain that appear in public Certificate Transparency logs, with the most recent certificate date for each. It is a record of certificates, not of DNS: a listed name may no longer exist, and a name that only ever used a wildcard certificate will be missing, so it complements the zone export rather than replacing it. Use it on domains you are responsible for to spot forgotten hosts and certificates nobody remembers ordering, then follow up each unfamiliar name with a DNS query to see where it points today.