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 realted 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!