One Cloud Please

S3 Bucket Namesquatting - Abusing predictable S3 bucket names

31 July 2019

Abuse of permissions in S3 buckets is one of the more common security issues companies face but this post addresses a different issue, S3 Bucket Namesquatting. This post outlines a security issue I’ve been working on for over a year that may affect your deployment and provides some quick fixes to avoid being vulnerable.

The Issue

A common practice in AWS is to use files in an S3 bucket that is also located in the region. Sometimes this is for latency reasons and sometimes you don’t have a choice in the matter. The S3Bucket property of a Lambda function in a CloudFormation template for example requires the bucket be in the same region as the function.

S3 also has a global namespace which means bucket names cannot be reused in other regions or by other accounts. This means that services which are deployed in many regions generally have a standard way of naming their buckets, usually by using the region name as a prefix or suffix to another string. When setting these up, a developer will generally register all buckets which match the pattern in their respective regions and make a note to additionally register new buckets as new regions are launched.

If someone has both prior knowledge of both the pattern being used for the bucket registration and of an upcoming region name, they could claim that bucket as their own before the owner of the other buckets has a chance to.

AWS region names aren’t generally publicized but you will see the region names in Certificate Transparency logs fairly early, or you could simply take an educated guess. For example, Cape Town which is near the southern-most point of Africa was announced last year and is the first region in that geographical area (hint hint).

Throughout the last year I registered many buckets that had this issue, both from AWS service teams and from external vendors and subsequently worked with them on this issue - in particular when the new regions were released.

The Response

The first time the AWS team and I communicated regarding the registration of an S3 bucket was early last year. I worked with a senior product manager of CloudFormation on the return of a bucket I registered. The bucket had a name in the form prefix-ap-northeast-3-suffix which was needed for the CloudFormation Specification in the new Osaka region at the time. We coordinated the handover of the bucket and that was all that was needed to resolve the issue for that particular bucket.

Although I would work with the CloudFormation team a few times on this issue, it wasn’t limited only to that service. Throughout the last year I worked with some other service team members and also had buckets relating to services such as SSM, VPC, Lambda, Control Tower and Solutions Architecture.

Recently, the AWS security team reached out and have started addressing the issue across all services within AWS. We got on a conference call and worked through the issue and the effective remediation strategies. The security team agreed with the remediation efforts, discussed their future plans and we coordinated the handover of all buckets of affected AWS services that I still had in my control - 52 buckets in total.

The Resolution

Many ISVs had related issues with their buckets and one which had a fantastic security response was Sumo Logic. The Sumo Logic service deals with log analysis and a big component to that is log ingestion. To make this easier, they provide a quick-start in the form of a CloudFormation template which deploys a Lambda in your account which CloudWatch Log Subscriptions can fire messages at, which will then ship the logs to your Sumo Logic account.

In order to specify the source for the Lambda function, they previously used an intrinsic function in the form:

"Code": {
  "S3Bucket": {"Fn::Join": ["", ["appdevzipfiles-", { "Ref" : "AWS::Region" }] ] },
  "S3Key": "cloudwatchlogs-with-dlq.zip"
}

Seeing this, I was able to register the bucket appdevzipfiles-eu-north-1 for the then unreleased Stockholm region. I reached out to the Sumo Logic security team which has a security program with HackerOne and they promptly assisted with onboarding me in order to coordinate disclosure. Their templates now utilize a CloudFormation mapping and their source specification now looks like this:

"Code": {
  "S3Bucket": { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "bucketname"]},
  "S3Key": "cloudwatchlogs-with-dlq.zip"
}

With the above, even if I were to register a bucket which followed a common format, they could simply map to a different bucket name at their own convenience.

tl;dr

If you use bucket names with region substitution in your templates, you may be affected by this issue and should take steps to ensure you are protected when the next region comes online. Use a region mapping or a process which allows a single bucket to be used in your solution. Now is also a good time to remind you to do a quick check of infrastructure-as-code templates and associated source code from third parties before inserting it into your environment, particularly if that template requires the construction of IAM resources.

I also wanted to say thanks to the service teams and security team at AWS for working with me on this issue, to the team at Sumo Logic for their quick response on the issue and to the other unnamed vendors who I’ve managed worked with to resolve related issues. Having an open dialog greatly helps the community get involved when they see issues that may affect you and are genuinely trying to help.