Five Subdomains, Five Takeovers, One Afternoon
The scope for this assessment covered the entire external attack surface of a media infrastructure company — a platform powering broadcast workflows for television networks and content distributors across multiple continents. The company operated thousands of subdomains spread across AWS, Azure, and several legacy hosting providers.
I started, as I often do, with DNS. Not because DNS is exotic or complicated, but because it is the skeletal structure of everything else. Before looking at applications, APIs, or network services, understanding what is reachable and what it points to provides the map.
It took approximately two hours to discover five CloudFront subdomain takeovers. All five were confirmed by end of day. The root cause was identical in each case.
The Pattern That Repeats
CloudFront distributions use randomly assigned domains in the format d[identifier].cloudfront.net. When an organization wants a subdomain like assets.example.com to serve content through CloudFront, they create a CNAME record:
assets.example.com → d3k7xhqxchqfma.cloudfront.net
They configure the distribution with assets.example.com as an alternate domain name and provision a TLS certificate through ACM. Traffic flows from the user, through the CNAME, to the CloudFront distribution, to the origin.
When the project that needed assets.example.com is decommissioned, the team deletes the CloudFront distribution. The d3k7xhqxchqfma.cloudfront.net endpoint is released back into the pool. But the CNAME record in DNS — assets.example.com → d3k7xhqxchqfma.cloudfront.net — is still there.
Now anyone can create a new CloudFront distribution in their own AWS account, add assets.example.com as an alternate domain name, and serve arbitrary content under that subdomain. The CNAME does the rest.
Finding the First One
My DNS enumeration produced a list of several hundred subdomains. After resolving each one, I filtered for CNAMEs terminating in *.cloudfront.net. There were dozens. The next step was checking which of those CloudFront distributions were still active.
The signature of a dangling CloudFront CNAME is a specific error response. A live, properly configured distribution returns the application's content — or a 403 from CloudFront's access control if the request doesn't match the distribution's configuration. A distribution that no longer exists produces a distinct response:
HTTP/1.1 403 Forbidden
Server: CloudFront
X-Cache: Error from cloudfront
<html>
<head><title>403 Forbidden</title></head>
<body>
<h1>403 ERROR</h1>
<p>The request could not be satisfied.</p>
<hr>
<p>Generated by cloudfront (CloudFront)</p>
</body>
</html>
The critical indicator is the error message. CloudFront's 403 for missing distributions says "The request could not be satisfied" and does not include a distribution ID in the response headers. Compare this to a valid distribution that returns a 403 due to geo-restriction or WAF rules — those responses include a X-Amz-Cf-Id header identifying the active distribution.
The first subdomain that matched this pattern was a media asset delivery endpoint. The CNAME resolved to a cloudfront.net domain that returned this exact error signature. The distribution was gone.
Confirming Claimability
Finding the error signature is evidence of a dangling record, not proof of a claimable takeover. The next step is confirming that the CloudFront distribution domain is actually available to register.
I opened my AWS console and attempted to create a new CloudFront distribution. In the alternate domain names configuration, I added the victim's subdomain. CloudFront requires that you demonstrate ownership of the domain before it will associate it with a distribution — or it requires that the CNAME already point to CloudFront infrastructure (which, in this case, it does).
The distribution accepted the alternate domain name. I provisioned a TLS certificate through ACM for the subdomain, validated it through the existing CNAME chain, and deployed the distribution with an S3 origin containing a single HTML file:
html
<html>
<head><title>Security Assessment - Subdomain Takeover</title></head>
<body>
<p>This subdomain is now serving content from an external security researcher's CloudFront distribution.</p>
<p>This is a proof-of-concept demonstrating a subdomain takeover vulnerability.</p>
<p>The subdomain assets.redacted.example is controlled by: [contact details]</p>
</body>
</html>Within minutes of the distribution propagating, assets.redacted.example was serving my proof-of-concept. The browser displayed a valid TLS certificate. The subdomain was the company's. The content was mine.
The Other Four
The first takeover confirmed the pattern. I went back through the rest of the CloudFront CNAMEs and applied the same check to each one that returned the missing distribution error.
Four more matched.
Each one followed the same lifecycle: a CloudFront distribution had been created for a specific project or service, configured with the subdomain as an alternate domain name, and later deleted. The DNS record remained in every case.
The five affected subdomains served different functions in the company's infrastructure:
- A media asset delivery endpoint used for large file transfers to broadcast partners
- A developer documentation portal that had been migrated to a different host
- A staging environment for a streaming platform that had been decommissioned
- An API endpoint for a deprecated version of their content management interface
- A support portal that had been consolidated into the main website
Each was distinct. Each pointed to a different deleted distribution with a different cloudfront.net domain. Each was independently claimable. And each carried its own threat profile based on what it had previously been used for — the API endpoint, for example, may have been registered as an OAuth redirect URI, and the staging environment may have had access to production session cookies depending on the cookie scope configured during its operation.
What Five Takeovers Means in Practice
A single subdomain takeover is a serious finding. Five of them at the same organization points to a systemic process failure.
The root cause is not that engineers deleted CloudFront distributions. It is that deleting a distribution and removing its associated DNS record are separate actions, performed by different people using different systems, with no enforced coupling between them.
The engineer who decommissions a project knows to delete the CloudFront distribution. They may not manage the DNS zone — that might be owned by a central infrastructure team. Or they plan to file a ticket to have the DNS record removed and the ticket falls through. Or they simply do not know the DNS record exists, because it was created months earlier by someone who has since left the team.
At the scale of an organization with hundreds of subdomains across multiple cloud providers, this gap is not the exception. It is the structural default.
The Impact Assessment
When reporting five simultaneous takeovers, it helps to be specific about what each one enables, because the severity varies by subdomain. For these five:
Cookie scope was the most consistent concern. Session cookies for the main application were scoped to .redacted.example, which means they were transmitted to every subdomain — including the five dangling ones. An attacker who controls a subdomain can set new cookies with the parent domain scope, enabling session fixation. They can also read cookies sent in requests to the subdomain if the application uses wildcard cookie scopes without the HttpOnly attribute.
CSP bypass was relevant for at least two of the subdomains. The company's main application included a Content Security Policy that allowed content from *.redacted.example. Any of the hijacked subdomains could host malicious scripts that the application would load and execute without violating its own CSP.
Phishing legitimacy applied to all five. Each subdomain was familiar to some segment of the company's users — partners, developers, customers, or internal employees. A login page or a malware-hosting page served from a known, trusted subdomain would face far less skepticism than the same content on an unknown domain.
TLS legitimacy was automatic. Because I controlled the CNAME destination, ACM domain validation succeeded for each subdomain, and CloudFront issued valid TLS certificates without requiring any interaction with the company's certificate authority or DNS control panel.
Remediation
The company's security team received the report and remediated all five within 24 hours. The immediate fix was removing the five CNAME records. But the conversation that followed the immediate fix was more important: how did five of these accumulate, and how do you prevent the next five from appearing?
The longer-term remediation involved two changes:
Decommissioning checklists. Any process that involves deleting a CloudFront distribution must now include a DNS cleanup step. The checklist is enforced through the infrastructure-as-code tooling — when a Terraform resource for a CloudFront distribution is destroyed, the pipeline flags any DNS records that reference the distribution's domain for review before the deletion is executed.
Automated DNS auditing. A scheduled scanner now resolves every CNAME record in the company's DNS zones and checks for the CloudFront missing-distribution error signature. Any match creates a ticket automatically. The scanner runs daily and feeds into the security team's backlog.
Both changes address the structural gap: one prevents new dangling records from forming, the other catches any that slip through.
The Takeaway
CloudFront subdomain takeovers are straightforward to find and exploit. The technical complexity is low — resolve a CNAME, check for the error signature, create a distribution, prove control. What makes them significant is not the technique but the consequence: an attacker operating under your domain, with your certificate, serving your users.
Five of them in a single afternoon is not unusual for organizations that have been operating at scale for several years. The attack surface for subdomain takeovers grows with every project that launches and then quietly shuts down, every migration that moves content from CloudFront to another provider without cleaning up the DNS, every developer who deletes the resource and assumes someone else handles the record.
Subdomain hygiene is infrastructure hygiene. The DNS record does not expire when the service does.
For a broader look at how subdomain takeovers work across different cloud providers and hosting platforms, see the subdomain takeover knowledge article.