DEV Community

Bala Paranj
Bala Paranj

Posted on

You Don't Own Your CloudFront Subdomain Until You Register the Distribution

✓ Human-authored analysis; AI used for formatting and proofreading.

A researcher checked cdn.grab.com in a browser. The page did not load, because the CloudFront distribution that the CNAME pointed to was not registered in any AWS account. The researcher registered it in their own account. Then cdn.grab.com was serving their content.

This is a gap in how AWS CloudFront distribution ownership works, and it shows up repeatedly across companies that use CloudFront for CDN delivery.

How CloudFront Subdomain Takeover Works

When you create a CloudFront distribution, AWS assigns it a domain name like d1234abcd5678.cloudfront.net. You then create a CNAME in your DNS pointing your branded subdomain to that distribution:

cdn.grab.com  CNAME  d1234abcd5678.cloudfront.net
Enter fullscreen mode Exit fullscreen mode

When you delete the CloudFront distribution for any reasons such as migrating CDN providers, cleaning up old infrastructure, or decommissioning a product the distribution is gone. The CNAME in your DNS is still present.

cdn.grab.com still resolves. It still points to *.cloudfront.net. But the distribution at that endpoint no longer exists in your account.

Anyone can create a new CloudFront distribution. CloudFront distribution domain names follow a predictable format. If an attacker creates a distribution and configures it to respond to cdn.grab.com as an alternate domain name which is a standard CloudFront feature, CloudFront will serve their content when cdn.grab.com is requested.

@todayisnew did this. They registered the distribution, configured it to respond to cdn.grab.com, and served a PoC page at http://cdn.grab.com/index.html. Grab's security team triaged it within hours and confirmed it valid.

Why This is Worse Than Third-Party SaaS Takeover

The previous article in this series covered subdomain takeovers via third-party services such as Vercel, Squarespace, Brandpad, Unbounce. Those services have free tiers. An attacker signs up for free and claims the subdomain.

CloudFront distributions are different in two ways.

First, the trust level is higher. A subdomain like cdn.grab.com is serving static assets such as JavaScript files, images, CSS, potentially SDKs. When an attacker controls cdn.grab.com, they are not just serving a phishing page. They are serving whatever the Grab application loads from that CDN endpoint. If the application loads JavaScript from cdn.grab.com/app.js, that JavaScript now comes from the attacker.

Second, the HTTPS certificate is valid. CloudFront provides SSL certificates via ACM. When an attacker registers a distribution with cdn.grab.com as an alternate domain, they can provision a certificate for cdn.grab.com through CloudFront's certificate management. The browser sees a valid HTTPS connection to cdn.grab.com. There is no certificate warning. The lock icon is green.

The combination of trusted CDN subdomain, valid HTTPS certificate, serving attacker-controlled JavaScript is a supply chain attack vector, not just a phishing risk.

The Attack Path

1. Attacker finds cdn.grab.com CNAME pointing to *.cloudfront.net
2. Attacker verifies the distribution is unclaimed
   (curl -I https://cdn.grab.com → connection error or CloudFront default)
3. Attacker creates CloudFront distribution in their AWS account
4. Attacker adds cdn.grab.com as an alternate domain name
5. CloudFront provisions a certificate for cdn.grab.com
6. cdn.grab.com now serves attacker content over valid HTTPS
7. Any application loading assets from cdn.grab.com
   now loads attacker-controlled content
Enter fullscreen mode Exit fullscreen mode

Step 3 costs money. CloudFront is not free. But the attacker controls a CDN subdomain of a major company with a valid certificate. The economics favor the attacker in any targeted scenario.

The System Invariant

The invariant is the same as every subdomain takeover, stated for CloudFront:

Every DNS CNAME pointing to a CloudFront endpoint must reference a distribution that exists in the same AWS account.

Observable in an infrastructure snapshot: the DNS record points to *.cloudfront.net, and the corresponding CloudFront distribution exists in the account's resource inventory. If the distribution does not exist, it is a violation.

This is detectable without making a live HTTP request to the endpoint. The snapshot contains the DNS records and the CloudFront distribution inventory. Cross-referencing them is a set membership check.

What Stave Detects

CTL.DNS.DANGLING.002    CRITICAL  initial_access
  "DNS CNAME Must Not Point to Unclaimed CloudFront Distribution"

  Fires when: a DNS CNAME record points to *.cloudfront.net
  and no CloudFront distribution in the account inventory
  has a matching alternate domain name or distribution domain.
Enter fullscreen mode Exit fullscreen mode

The control evaluates two fields from the snapshot:

  1. DNS records, any CNAME ending in .cloudfront.net
  2. CloudFront distribution inventory, the list of distributions and their alternate domain names

If a CNAME target has no matching distribution in the account, the control fires. No live HTTP request. No CloudFront API call. Just a cross-reference between two lists in the snapshot.

Running the Grab scenario:

VERDICT: COVERED

CTL.DNS.DANGLING.002    CRITICAL  initial_access
  cdn.grab.com → *.cloudfront.net
  No CloudFront distribution found with alternate domain cdn.grab.com
  or matching distribution domain in account inventory.

Compound chains:
  shadow_api_exposure     confidence: 1.00
Enter fullscreen mode Exit fullscreen mode

The Difference from S3 Subdomain Takeover

S3 subdomain takeover works when a DNS record points to bucket-name.s3-website-region.amazonaws.com and the bucket does not exist. The attacker creates the bucket with the matching name.

CloudFront subdomain takeover works when a DNS record points to a CloudFront distribution domain and the distribution does not exist. The attacker creates a new distribution and adds the victim's subdomain as an alternate domain name.

The detection is slightly different:

  • S3: check if the bucket named in the CNAME endpoint exists in the account
  • CloudFront: check if any distribution in the account has the subdomain as an alternate domain name

Both are cross-reference checks in the snapshot. Neither requires a live request.

CTL.S3.DANGLING.ORIGIN.001 covers S3. CTL.DNS.DANGLING.002 covers CloudFront. The same snapshot assessment catches both.

Remediation

Option A: Delete the DNS record.

The CDN subdomain is no longer needed. Remove the CNAME.

# Route53 — remove the dangling CNAME
aws route53 change-resource-record-sets \
  --hosted-zone-id ZONE_ID \
  --change-batch '{
    "Changes": [{
      "Action": "DELETE",
      "ResourceRecordSet": {
        "Name": "cdn.example.com",
        "Type": "CNAME",
        "TTL": 300,
        "ResourceRecords": [
          {"Value": "d1234abcd.cloudfront.net"}
        ]
      }
    }]
  }'
Enter fullscreen mode Exit fullscreen mode

Option B: Recreate the distribution.

The CDN subdomain is still needed. Create a new CloudFront distribution, add the subdomain as an alternate domain name, provision the certificate, and restore the origin configuration.

Process fix: delete the distribution last.

When decommissioning CDN infrastructure, the order matters:

1. Remove the DNS CNAME record
2. Wait for DNS TTL to expire
3. Delete the CloudFront distribution
Enter fullscreen mode Exit fullscreen mode

Deleting the distribution before removing the DNS record leaves a window, potentially days if the TTL is long where the subdomain points to nothing and is claimable.

Checklist

For any AWS account using CloudFront for CDN delivery:

  • Every DNS CNAME pointing to *.cloudfront.net has a corresponding distribution in the account with a matching alternate domain name
  • CloudFront distribution decommissioning procedure: DNS record removed before distribution deleted
  • CTL.DNS.DANGLING.002 runs against DNS snapshot on each infrastructure change
  • CloudFront distribution inventory audited against DNS records periodically
  • Alternate domain names on all distributions match active DNS records

The distribution you deleted is still in your DNS. Until you remove that CNAME, the subdomain is available.


The Grab cdn.grab.com CloudFront subdomain takeover was reported by @todayisnew and triaged by Grab's security team as valid within hours of submission. Stave detects unclaimed CloudFront distributions via CTL.DNS.DANGLING.002, evaluated from local infrastructure snapshots without AWS credentials or live HTTP requests.

Top comments (0)