Subdomain takeover: how it happens and how to catch it
A subdomain takeover starts with a CNAME pointing to a service you no longer use. How dangling records get exploited, how to audit your zone, and prevention.
A subdomain takeover happens when a DNS record, usually a CNAME, points to an external resource that no longer exists, and someone else re-creates that resource under the same name. From that moment on, your subdomain serves content you do not control. The attacker gets a page that lives under your domain, with your reputation attached: convincing phishing, malware distribution, and in some configurations access to cookies scoped to your parent domain. The DNS itself was never compromised. It kept telling the truth about a target you forgot to clean up. This article covers the mechanism, the services where it typically happens, how to audit your own zone, and how to prevent it.
The mechanism: a dangling record
The vulnerability follows a lifecycle that will feel familiar to anyone who has run a website for a few years:
- You create
blog.example.comas a CNAME pointing to a hosted service, sayyourcompany.some-platform.com. - The service runs for a while. Everything works.
- You cancel the subscription or delete the project. The platform frees up the name
yourcompany. - Nobody deletes the CNAME. It now points at a resource that no longer exists. This is a dangling record.
Here is the before and after:
Before (service active):
blog.example.com. CNAME yourcompany.some-platform.com.
-> the platform serves YOUR content
After cancellation (dangling):
blog.example.com. CNAME yourcompany.some-platform.com.
-> the name is unclaimed on the platform
The DNS resolution still succeeds. The record is syntactically valid and the platform's infrastructure still answers. The only thing missing is the resource behind the name. If the platform lets any customer register that freed name, whoever claims it next receives all traffic sent to blog.example.com. Visitors see your URL in the address bar and a valid page behind it. That is what makes the attack so effective for phishing: nothing looks wrong.
A CNAME is the most common vector because it delegates an entire hostname to a third party, but dangling A records pointing to released cloud IP addresses cause the same problem. If you need a refresher on how these record types behave, see our guide to DNS record types.
Services where this typically happens
Any platform that maps customer-chosen names to hostnames can be affected. When the resource behind a dangling record is gone, the platform usually returns a recognizable error. These signals are what defenders look for during an audit:
| Service | Signal of an orphaned resource |
|---|---|
| GitHub Pages | "There isn't a GitHub Pages site here" |
| AWS S3 | "NoSuchBucket" error page |
| Heroku | "No such app" error page |
| Azure (cloudapp, azurewebsites) | NXDOMAIN or default Azure error |
| Shopify | "Sorry, this shop is currently unavailable" |
| Vercel | 404 with "DEPLOYMENT_NOT_FOUND" |
Many providers have tightened this over the years. GitHub Pages and several others now require domain ownership verification before a custom domain can be attached, which closes the easy path. But the window has narrowed, not disappeared: older platforms, regional providers, and services without verification remain claimable, and verification does not help you if the dangling record points somewhere that never added it.
Auditing your own domain
You do not need special tooling for a first pass. Three steps:
- Export your DNS zone from your provider (Cloudflare, Route 53, OVH, your registrar) and list every CNAME and A record that points outside your own infrastructure.
- For each one, check that the target resource still responds and still belongs to you. Load the hostname in a browser and confirm the content is yours, not a platform error page.
- Delete every record whose target service you have cancelled, migrated away from, or cannot identify.
To inspect a single record from the command line:
dig CNAME store.example.com +short
If the answer points to a SaaS platform, request the page over HTTP and read the response. A branded platform error like the ones in the table above, on a hostname you still publish in DNS, is the exact signal an opportunist looks for. Treat it as urgent: delete the record or reclaim the resource the same day.
Preventing it for good
The core fix is procedural, not technical. When you cancel a service, delete the DNS record in the same ticket, the same pull request, or the same change window. Decommissioning is only finished when both sides are gone. Most takeovers trace back to a cancellation that skipped this step years earlier.
Beyond that single habit, keep a living inventory of every subdomain that points to an external service, along with who owns it internally, and review that list on a schedule. Quarterly works for most teams. Our overview of what DNS monitoring covers explains where record-level checks fit into that routine.
If you use Domain Sentinel, the Extra names field of DNS monitoring lets you add up to ten critical subdomains per domain, each watched as its own hostname. Their CNAME and A records are captured daily, and any change triggers an email alert. Ten is not many, so pick the subdomains that point at an external service. That keeps your inventory honest: a record that changes or appears without a matching change ticket gets noticed. To be clear about the limits, it records what your DNS answers, it does not test whether the target resource still exists on the platform side. Deleting stale records is the defense; monitoring is the safety net that tells you when the record set drifts.
Start today with the export: pull your zone file, list the records pointing at external services, verify each one, and delete the dead ones. Most zones more than a few years old contain at least one surprise. And since dangling records are only one way a subdomain ends up serving someone else's content, read our article on detecting DNS hijacking for the related attack where the zone itself is modified.
Start with a domain you care about
Look it up for free. If you want alerts when status changes or expiry gets close, create an account. Takes about 30 seconds.