The Forgotten CNAME That Became a Phishing Page
An ex-employee spun up a Heroku app three years ago. promo.example.com was a CNAME pointing at example-promo.herokuapp.com. The campaign ended. Someone deleted the Heroku app. Nobody touched DNS. The CNAME still resolves — to nothing. To Heroku, the name example-promo is free. To an attacker watching for exactly this pattern, the next step is simple: claim example-promo on Heroku, deploy a page that looks like your login, and now promo.example.com — a real subdomain on your real domain, with a real TLS certificate via Let's Encrypt — serves their content. Cookies scoped to *.example.com are now in their hands. Customers trust the domain. SSO redirects don't notice.
This is a subdomain takeover. It's not a clever exploit. It's a misalignment between what your DNS zone says exists and what the resource it points at actually has. The vulnerability has been documented for over a decade, and it still ships to production every week because the people writing DNS records and the people deprovisioning cloud resources are rarely the same person on the same day.
How a Takeover Actually Works
The pattern is consistent across providers. A subdomain like shop.example.com has a CNAME record pointing at a cloud-managed hostname — example-shop.myshopify.com, example-prod.azurewebsites.net, ex-cdn.cloudfront.net, example.s3.amazonaws.com. The cloud provider serves whatever resource is registered under that hostname. When the resource is deleted but the CNAME isn't, the hostname becomes unclaimed on the provider's side. Many providers allow anyone to register that exact hostname for their own resource. Whoever does first now controls what shop.example.com serves.
The classic EdOverflow takeover list tracks which providers are vulnerable to this pattern and which have fixed it by requiring domain verification before resource registration. AWS S3, Heroku, GitHub Pages, Azure, Fastly, Shopify, Tumblr, and dozens of SaaS platforms have all had vulnerable windows. Some have closed them. Many haven't, and verification gaps reopen with new product launches.
The mechanic only requires three conditions: a DNS record that points at a third-party hostname, the third-party resource being deleted or never created, and the third-party allowing the next person to claim that hostname. None of those conditions are visible from your DNS console — your DNS record looks the same whether the target resource exists or not.
Why This Isn't 'Just Phishing'
Three things make a successful subdomain takeover qualitatively worse than a typical phishing page.
The domain is real. Browser address bars show promo.example.com. SPF, DMARC, DKIM all pass for mail sent from this subdomain because — from a DNS perspective — it's a legitimate part of your zone. Your customers' email security tools won't flag messages claiming to come from this address as spoofed.
The TLS certificate is real. Let's Encrypt's automated challenge sees that the attacker controls the resource the CNAME points at, so it issues a valid certificate. The padlock shows up. The browser warning doesn't. Every signal a user is trained to check tells them the site is legitimate.
Same-origin trust extends. If you have cookies scoped with Domain=.example.com, they'll be sent to the attacker's page. Many SSO and analytics integrations use wildcard subdomain trust. CORS headers that allow *.example.com origins now allow the attacker. The damage isn't limited to the takeover subdomain — it bleeds into the rest of your brand.
Why It Stays Undetected
Subdomain takeover is the rare class of finding where the attacker has more visibility than the defender. The attacker can systematically enumerate every CNAME in every public DNS zone — Certificate Transparency logs surface the subdomain names, passive DNS aggregators surface the records, and a single HTTP request to the target reveals whether the resource is claimed. The whole pipeline can be automated and run continuously against thousands of domains.
The defender sees: a DNS zone that looks fine. A subdomain that resolves. No log entry for the deleted cloud resource (because it's been deleted from the cloud account, not from DNS). Nothing fails. No alert fires. The only thing that would catch it is the same active enumeration the attacker is running — and most security programs don't run it.
This is exactly why subdomain takeover is a staple finding in bug bounty programs. Researchers find them faster than internal teams do, because researchers have automation pointed outward and internal teams have alerts pointed inward.
What FortWatch's Takeover Scanner Does
Our takeoverScan processor walks the CNAME chain for every subdomain we know about for your asset, identifies which targets resolve to known-vulnerable cloud providers, and fingerprints the response to determine whether the upstream resource is claimed. When a CNAME points at *.herokuapp.com, *.s3.amazonaws.com, *.azurewebsites.net, or any of the dozens of takeover-prone hostnames, we make the same HTTP request an attacker would and look for the provider-specific 'this resource does not exist' fingerprint. A hit creates a critical-severity issue with the exact subdomain, the dangling target, and which provider's claim flow would complete the takeover.
The companion check lives in dnsScan: it flags CNAMEs that resolve to an NXDOMAIN target, which is the broader 'dangling DNS' category. Not every dangling CNAME is a takeover — but every takeover starts as a dangling CNAME, so the noisier signal is worth surfacing even when the cloud provider isn't on our explicit vulnerable list. We rank these as high-severity by default and let the takeover scanner upgrade specific findings to critical when they match a known takeover-prone provider.
Both scanners run automatically on every continuous scan — there's nothing to configure. If you've added a domain to FortWatch, you're already being checked for this.
What to Look for if You're Auditing Manually
If you want to spot-check before automation catches up, the workflow is:
- Pull every subdomain you know about from Certificate Transparency logs (
crt.shagainst your apex domain returns thousands of hostnames for free). - Resolve each one. Note which return CNAMEs and which return A/AAAA records directly. CNAMEs are where takeovers live.
- For each CNAME target, check whether it falls under a cloud or SaaS hostname pattern.
*.herokuapp.com,*.s3.amazonaws.com,*.azurewebsites.net,*.github.io,*.cloudfront.net,*.shopify.com,*.zendesk.comare the high-volume ones. - For each one of those, make an HTTPS request to the original subdomain and inspect the response. Provider-specific fingerprints — Heroku's 'No such app', S3's 'NoSuchBucket', GitHub Pages' 'There isn't a GitHub Pages site here', Azure's '404 Web Site not found' — are the smoking gun.
- For NXDOMAIN CNAMEs (the target hostname itself doesn't resolve), the dangling record is the issue. Even if today's provider doesn't allow takeover, the record is debt waiting for a vulnerable claim window.
You'll be surprised how many records this surfaces on a domain you thought was clean. The first time we ran this against a friend's marketing site, we found a CNAME from a 2019 Tumblr blog campaign still pointing at a deleted Tumblr account. Tumblr's reclaim flow had been closed years ago, but the next provider you don't know about might not have done the same housekeeping.
Remediation Is Boring and Always the Same
Once you find a dangling record, the fix is to either re-claim the upstream resource (if it's something you still need and the provider's hostname is still free) or delete the DNS record entirely. There is no middle ground. A 'dangling CNAME we're keeping for SEO reasons' is a vulnerability disguised as a habit.
The harder problem is preventing the next one. Two practices help:
- DNS records require an owner. If your zone is managed via Terraform or Pulumi, the CNAME and the resource it points at should live in the same module, so deleting one without the other becomes a CI failure rather than an organizational drift.
- Quarterly subdomain inventory. Even if you have continuous monitoring, a manual review of 'what subdomains do we still need' once a quarter catches the records that were correct when created but no longer serve a business purpose.
Neither of these replaces active monitoring. The window between 'cloud resource deleted' and 'attacker claims it' is sometimes hours. The window between 'we run our quarterly review' is months. Both are necessary; only one is sufficient.
What Do I Do With This?
- Audit every CNAME in your DNS zones against the EdOverflow takeover list. Anything pointing at a cloud or SaaS hostname is worth investigating; anything pointing at an NXDOMAIN target is a finding regardless of provider.
- Treat 'we cleaned up the cloud account' as half the work. The other half is removing the DNS records that pointed at those resources. Make this a checklist item, not a memory.
- Run continuous monitoring against your full subdomain inventory. Manual audits miss the records created between audits. FortWatch's takeover scanner runs against every subdomain we discover on every scan — no configuration required.
- Use our free subdomain finder to enumerate what's in CT logs for your apex domain before anyone else does. The list it returns is the list an attacker is also working from.
