Skip to content

Article by Houston Hopkins.

Simple Route53/Cloudfront/S3 Subdomain Takeover

Utilizing various enumeration techniques for recon and enumeration, an attacker can discover orphaned Cloudfront distributions and/or DNS Records that are attempting to serve content from an S3 bucket that no longer exists. There are numerous tools to do this, but I have been using dwatch combined with CTFR.

Essentially you need a list of domains to check. Create a domain list using CTFR or amass or the like, and then utilize a tool like dwatch to test each host to look for a specific error page that contains the text "NoSuchBucket".

<Error>
<Code>NoSuchBucket</Code>
<Message>The specified bucket does not exist</Message>
<BucketName>hackingthe.cloud</BucketName>
<RequestId>68M9C1KTARF9FBYN</RequestId>
<HostId>RpbdvVU9AXidVVI/1zD+WTwYdVI5YMqQNJShmf6zJlztBVyINq8TtqbzWpThdi/LivlOWRVCPVs=</HostId>
</Error>

The simple next step is to go create a bucket with this name in S3.

This alone can be enough to stop the bucket from being taken over by anyone else. However, you may want to place some POC code in an index.html or any html file in the root directory of the bucket file.

<h1> Simple PoC for Subdomain Takeover,</h1>
<button onclick=alert(document.domain)> XSS Alert for PoC </button>
<h2> demo purposes only. </h2> 

Root Causes of this issue are typically due to a hygiene related issues where an S3 bucket was deleted while content was still being served by Cloudfront or by a DNS Record CNAME (Route53 or otherwise).

There are other nuanced conditions with Cloudfront, although rare, that can cause the similar takeover susceptibility.

To protect against this type of attack utilize robust hygiene practices:

Always create in this order S3 -> Cloudfront -> DNS

Always Sunset/Delete in this order DNS -> Cloudfront-> S3

Likewise, if you are testing, and something doesn't work, dont forget to clean up!

I highly recommend looking at OWASP's domain-protect as a framework for detection and event driven mitigation.