AWS CloudFormation and Resource-Injection Walkthrough
As a process, CloudFormation deployments are modular, with the template upload being a distinct step from the deployment itself. Templates can be made through the web console or through 3rd party tools, but as CloudFormation is an AWS-exclusive service, generally (with some exceptions) it needs to eventually be uploaded to S3 for execution.
One issue with this is the CloudFormation deployment step references the S3 URL, which doesn’t represent the content at a specific point in time. By modifying the CloudFormation template content after it is uploaded to S3 and before it is deployed, an attacker can get significant IAM privilege escalation in the target account.
While this is a new Pacu module, it’s not a new idea and we stand on the shoulders of giants — credit to Matt Fuller (@matthewdfuller), and anyone else we might have missed!
Target AWS Environment (Vulnerable Conditions)
- The CloudFormation deployment step uses the TemplateURL parameter in the CreateStack API call.
- There is at least a one second delay between the template upload step and the deploy step.
- ‘Assumed Breach’ IAM identity that the attacker has access to and can make s3:PutBucketNotification, s3:PutObject, and s3:GetObject calls on the S3 bucket used for uploading templates.
For the sake of demonstration, we’ll use locally-created CloudFormation templates, using the console wizard to upload and execute them. This deployment method uses S3 buckets in the target account prefixed with “s3-templates-“ to store templates. These S3 templates are then referenced during the deployment step. In addition, both the upload and deploy steps are manually triggered as a part of the CloudFormation console wizard stack creation process, leaving plenty of time for an attacker to modify these templates before they are used.
Despite focusing on the CloudFormation console wizard for this attack, any tool or process that leaves enough time for us to update the template prior to deployment will be vulnerable to attack. Currently, the update process takes just under a second, however, it should be possible to improve this and we recommend not ruling out the possibility of this attack for other, faster deployment processes.
In the target account we assume the following. Some of these items are specific to the demo and not a representation of the actual minimal permissions necessary to carry out this attack more generally (which is covered above in the Vulnerable Conditions section).
- An S3 bucket named “cf-templates-nohnwfax6a6i-us-east-1″ exists which is used by the CloudFormation console wizard to store templates.
- The attacker has access to the “S3Access” IAM user.
- The attacker has the ability to list roles in the target account.
The S3Access user has the following policy attached to it:
We also assume we have control over an unrelated AWS account which will be set up with the following.
- A Lambda Function, which will be triggered on s3:PutBucketNotification in the target account’s “cf-templates-*” bucket.
- Includes hard-coded credentials of the S3Access IAM identity in the target account.
When the lambda triggers, it updates the CloudFormation template to add an IAM Role with inlined *:* permissions and a trust role allowing access from a role the attacker specifies. The attack process will look like the following when these resources are set up correctly.
New Pacu Module: cfn_resource_injection
To make the above steps easier, we wrote a new Pacu module available here.
The Pacu module handles setting up notifications on the target bucket, as well as deploying the lambda in the attacker-controlled account, which is triggered on uploads to the target S3 bucket.
For Pacu to deploy the Lambda, credentials need to be set up in Pacu with the “set_keys” command. The name of this key is then referenced when running the cfn_resource_injection module. Several Pacu parameters to the cfn_resource_injection module are optional, however, you will need to specify the “–attacker-key”, which is the name of the credentials in pacu for the attacker account as well as the “–s3-access-key” which is the same but specifies the key used for accessing S3.
You may have noticed that we’ve added the ListBuckets permissions in the S3Access role above which was not included in the initial requirements, this is not strictly needed but allows Pacu to enumerate possible template buckets instead of needing to explicitly specify one. If you do not have this permission on the S3AccessRole you can use the “–bucket” parameter when running the module.
PoC Video: Injecting into a new CloudFormation Template
With the Lambda setup and listening for new S3 notifications in the CF bucket, we’re just waiting for a user to create/upload a new template.
Conclusion: Attack Mitigation Options
Deployment artifact modification isn’t unique to CloudFormation. The reason it is the focus here is because it is a standardized and sensitive deployment which also allows for the possibility of a direct escalation to an Administrator role in a given account.
With any bucket used for deploying artifacts, it’s important to ensure you understand who has permission to use that bucket, as well as what effect modifying these resources can have on your infrastructure. Additionally, when you control the upload and deployment of these artifacts you can also set up an extra layer of protection taking advantage of S3 object versioning to ensure you are always working with the artifact you expect in a CI/CD pipeline.
As always, feel free to open issues and pull requests on GitHub if you’d like and we will try to get to them to support future usage of these tools. Follow us on Twitter for more Pacu releases and blog posts: @RhinoSecurity, @Ryan_Jarv
We’ll have more coming out on related attacks in the coming weeks/months. Stay tuned!