Introduction to AWS IAM Privilege Escalation
There are an extensive amount of individual APIs available on AWS, which also means there are many ways to misconfigure permissions to those APIs. These misconfigurations can give attackers the ability to abuse APIs to gain more privileges than what was originally intended by your AWS administrator. We at Rhino Security Labs have demonstrated this in the past with our blog post on 17 different privilege escalation methods in AWS.
Most of these privilege escalation methods rely on the IAM service for abuse. An example of this is the “iam:PutUserPolicy” permission that allows a user to create an administrator-level inline policy on themselves, making themselves an administrator. This blog will outline a new method of abuse for privilege escalation within AWS through CodeStar, an undocumented AWS API, as well as two new privilege escalation checks and auto-exploits added to Pacu’s “iam__privesc_scan” module.
AWS CodeStar is a service that allows you to “quickly develop, build, and deploy applications on AWS”. It integrates a variety of other different AWS services and 3rd party applications (such as Atlassian Jira) to “track progress across your entire software development process”. It is essentially a quick, easy way to get your projects up and running with your team in AWS.
CodeStar Undocumented APIs
Like many AWS services, CodeStar has some public-facing APIs that are not publicly documented. In most cases, these exist for convenience when browsing AWS through the web console. For example, CodeStar supports the following APIs, but they are not documented in the official AWS documentation:
There are more undocumented APIs than on this list–the other non-listed APIs are typically used by your web browser to display and verify information in the AWS web console.
I discovered these undocumented APIs by simply setting up Burp Suite to intercept my HTTP traffic while browsing the AWS web console and seeing what showed up. Here is an example of some requests Burp Suite picked up while browsing CodeStar in the AWS web console:
One of the undocumented APIs that we discovered was the codestar:CreateProjectFromTemplate API. This API was created for the web console to allow you to create sample (templated) projects to try out CodeStar. If you look at the documented APIs for CodeStar, you’ll only see codestar:CreateProject, but this page references project templates as well.
As long as the CodeStar service role exists in the target account, this single undocumented API allows us to escalate our privileges in AWS. Because this is an undocumented API and people typically don’t know it exists, it’s likely not granted to any users in AWS directly. This means that although you only need this single permission to escalate privileges, it will likely be granted with a broader set of permissions, such as “codestar:Create*” or “codestar:*” in your IAM permissions. Because those are using the wildcard character “*”, it expands out and includes codestar:CreateProjectFromTemplate. If you needed another reason to stop using wildcards in your IAM policies, this is it.
The following AWS-managed IAM policies grant access to codestar:CreateProjectFromTemplate, but there are likely many more customer-managed IAM policies out there that grant it as well.
- arn:aws:iam::aws:policy/AdministratorAccess (obviously)
Undocumented CodeStar API to Privilege Escalation
The codestar:CreateProjectFromTemplate permission was the only permission needed to create a project from the variety of templates offered in the AWS web console. The trick here is that these templates are “managed” by AWS, so when you choose one to launch, it will use the CodeStar service role to launch the project and not your own permissions. That means that you are essentially instructing the CodeStar service role to act on your behalf, and because that service role likely has more permissions than you do, you can utilize them for malicious activity.
As part of these templates, an IAM policy is created in your account named “CodeStarWorker-<project name>-Owner”, where <project name> is the name you give the CodeStar project. The CodeStar service role then attaches that policy to your user because you are the owner of that project. Just by doing that, we have already escalated our permissions, because the “CodeStarWorker-<project name>-Owner” policy grants a lot of access. Most permissions are restricted to the resources that the project created, but some are more general (like a few IAM permissions on your own user). There are also other policies and roles that get created as part of this process–some important and some not–so we’ll touch on those as we go.
The above screenshot shows some of the available templates when creating a CodeStar project through the web console.
Prior to AWS’s Fix
When this vulnerability was originally discovered, the permissions that the “CodeStarWorker-<project name>-Owner” policy granted were slightly different than they are now. Originally, as long as the CodeStar service role existed in the account, an IAM user with only the codestar:CreateProjectFromTemplate permission could escalate their permissions to a full administrator of the AWS account.
This was because one of the resources that was created was an IAM role named “CodeStarWorker-<project name>-CloudFormation” and it was used to create a CloudFormation stack to build the project that you chose. It was originally granted full access to 50+ AWS services, including a variety of IAM permissions. A few of the important IAM permissions included:
If you have read our blog on AWS privilege escalation, then you already know these permissions can be used to quickly escalate a user or role to a full administrator.
For a copy of the old policy that was attached to the “CodeStarWorker-<project name>-CloudFormation” IAM role, visit this link.
With that unrestricted access to so many services, you could almost certainly compromise most of your target’s resources in AWS, spin up cryptominers, or just delete everything.
To use these permissions, we needed to gain access to the “CodeStarWorker-<project name>-CloudFormation” IAM role. This wasn’t difficult because it was already passed to a CloudFormation stack that the “CodeStarWorker-<project name>-Owner” IAM policy granted us access to. This meant we just needed to update the CloudFormation stack and pass in a template that would use the role’s permissions to do something on our behalf. Due to CloudFormation’s limitations, this “something” needed to be an inline policy to make that same CloudFormation role an administrator, then a second UpdateStack call would need to be made to also make your original user an administrator. There were many reasons for this, but essentially it was because you couldn’t instruct CloudFormation to attach an existing managed IAM policy to an existing user.
Disclosure and How AWS Fixed the Privilege Escalation
We disclosed this vulnerability to AWS Security on March 19th, 2019, and worked with them to resolve the risk of this attack. Over the next few months, multiple fixes were implemented because a few bypasses were discovered the first few times. Those bypasses still allowed for full administrator privilege escalation, even after their initial fixes, but by working with them, we were able to get that resolved. By mid-May 2019, we had the go-ahead that the vulnerability had been remediated.
Overall, this vulnerability was fixed by limiting the permissions granted to the “CodeStarWorker-<project name>-Owner” IAM policy and the “CodeStartWorker-<project name>-CloudFormation” IAM role. The role was restricted by requiring the use of an IAM permissions boundary in its IAM permissions, which is effective in preventing privilege escalation to a full administrator. Depending on what other resources/misconfigurations exist in the environment, it might still be possible to escalate to full admin access (through a service such as Lambda or EC2) after exploiting this method.
They also introduced another fix, where the AWS web console now uses “codestar:CreateProject” and “iam:PassRole” to create projects from templates, but the “codestar:CreateProjectFromTemplate” API is still publicly accessible and enabled, so it can still be abused for privilege escalation (just to a lesser extent than before).
The Attack Vector After the Fix
While the AWS CodeStar team was responsive & implemented several fixes, we were still able to identify a way to use the undocumented API for privilege escalation. This wasn’t as severe as before AWS implemented their fixes, but still noteworthy.
The new attack path looks like this:
- Use codestar:CreateProjectFromTemplate to create a new project.
- You will be granted access to “cloudformation:UpdateStack” on a stack that has the “CodeStarWorker-<project name>-CloudFormation” IAM role passed to it.
- Use the CloudFormation permissions to update the target stack with a CloudFormation template of your choice.
- The name of the stack that needs to be updated will be “awscodestar-<project name>-infrastructure” or “awscodestar-<project name>-lambda”, depending on what template is used (in the example exploit script, at least).
At this point, you would now have full access to the permissions granted to the CloudFormation IAM role. You won’t be able to get full administrator with this alone; you’ll need other misconfigured resources in the environment to help you do that.
Automation and Exploitation with Pacu
This privilege escalation method has been integrated into Pacu’s “iam__privesc_scan”, so you can check what users/roles are vulnerable within your account. To check your account for privilege escalation (all 17+ methods we have blogged about, including this one) from a fresh Pacu session, you can run the following commands from the Pacu CLI:
1. import_keys default: Import the “default” profile from the AWS credentials file (~/.aws/credentials) 2. run iam__enum_users_roles_policies_groups --users: Enumerate IAM users 3. run iam__enum_permissions --all-users: Enumerate their permissions 4. run iam__privesc_scan --offline: Check for privilege escalation methods
As you can see, two IAM users were found and had their permissions enumerated. One of them was already an administrator, and the other user, “VulnerableUser”, is vulnerable to the “CodeStarCreateProjectFromTemplate” privilege escalation method.
Two Bonus Privilege Escalations Added to Pacu
With this blog release and Pacu update, we also added two more checks to the “iam__privesc_scan” module, both with auto-exploitation available. The first method is “PassExistingRoleToNewCodeStarProject” which uses “codestar:CreateProject” and “iam:PassRole” to escalate an IAM user or role to a full administrator. The second method is “CodeStarCreateProjectThenAssociateTeamMember” which uses “codestar:CreateProject” and “codestar:AssociateTeamMember” to make an IAM user the owner of a new CodeStar project, which will grant them a new policy with a few extra permissions.
Pacu can be found on our GitHub with the latest updates pushed, so we suggest using it to check your own environment for any of these new privilege escalations.
CreateProjectFromTemplate Exploit Script
This privilege escalation method did not have auto-exploitation integrated into Pacu because it is an undocumented API, and thus unsupported in the “boto3” Python library. Instead, an exploit script was derived from AWS’s guide on manually signing API requests in Python.
The standalone exploitation script can be found here.
The script has the option of using two different templates, one of which grants more access than the other, but it requires that you know the ID of a VPC, the ID of a subnet in that VPC, and the name of an SSH key pair in the target region. It’s possible to collect some of that information by running the exploit script without that knowledge, then using the escalated permissions to enumerate that information, then re-running the exploit script again with the data you discovered.
Using the Script
The only permission required to run the script is “codestar:CreateProjectFromTemplate”, but you must be a user (not a role) because of how CodeStar works.
Without prior information: you can run the script like this, which will use the default AWS profile:
python3 CodeStarPrivEsc.py --profile default
With the EC2/VPC information: you can run the script like this:
python3 CodeStarPrivEsc.py --profile default --vpc-id vpc-4f1d6h18 --subnet-id subnet-2517b823 --key-pair-name MySSHKey
There should be quite a bit of output, but at this point, you will just be waiting for the CloudFormation stacks to spin up in the environment and create all the necessary resources. Right away, you’ll gain some additional privileges through the “CodeStar_<project name>_Owner” IAM policy, but if you wait, additional versions of that policy will be created as other resources in the environment are created. The script will output the AWS CLI command you need to run to view your own user’s permissions, once the privilege escalation has complete. That command will look something like this (pay attention though, because the version ID will change, depending on the template you are using):
aws iam get-policy-version --profile default --policy-arn arn:aws:iam::ACCOUNT-ID:policy/CodeStar_PROJECTNAME_Owner --version-id v3
It might take some time for that command to execute successfully while everything gets spun up in the environment, but once it is able to execute successfully, that means the privilege escalation process is complete.
Utilizing Your New Permissions
You’ll now have all the permissions that the policy you just viewed grants, and as part of that, you are granted the “cloudformation:UpdateStack” permission on a CloudFormation stack that has already had the “CodeStarWorker-<project name>-CloudFormation” IAM role passed to it. That means you can use that role for what you want, without ever needing the “iam:PassRole” permission. The permissions granted to this role should be the same every time (unless they update the template behind the scenes) and you won’t have permission to view them.
Without prior information: visit this link to see what the access looks like.
With the EC2/VPC information: visit this link to see what the access looks like.
The script will also output the command to use to update the CloudFormation stack that you want to target. That command will look like this:
aws cloudformation update-stack --profile default --region us-east-1 --stack-name awscodestar-PROJECTNAME-lambda --capabilities "CAPABILITY_NAMED_IAM" --template-body file://PATH-TO-CLOUDFORMATION-TEMPLATE
Without prior information: the stack’s name will be “awscodestar-<project name>-lambda”
With the EC2/VPC information: the stack’s name will be “awscodestar-<project name>-infrastructure”.
Just create a CloudFormation template to create/modify the resources that you want and run that UpdateStack command to take control of the CloudFormation role.
The following video shows a user who is only granted the “codestar:CreateProjectFromTemplate” permission escalating their permissions with the exploit script. The video only shows part 1 of 2 of the full attack-process because the next step depends on what your goal is. After the privilege escalation shown in this video is done, the next step would be to take control of the CloudFormation IAM role and abuse its permissions. The first step of the privilege escalation grants you access to a few things, including control over that CloudFormation role. Then, because the CloudFormation role has more access than you do, you can instruct it to perform an action on your behalf, whatever that may be.
Note that around the 1 minute mark we cut out a few minutes of refreshing the browser. It takes time for the resources to deploy and the privilege escalation is not complete until all of them deploy, so there is a bit of waiting required.
Defending Against Privilege Escalation through CodeStar
There are a few key points to defending against this privilege escalation method in an AWS environment.
- If you don’t use CodeStar in your environment, ensure that the CodeStar IAM service role is removed from or never created in your account (the default name is “aws-codestar-service-role”).
- Implement the principle of least-privilege when granting access to your environment. This entails avoiding the use of wildcards in IAM policies where possible so that you can be 100% sure what APIs you are granting your users access to.
- Do not grant CodeStar permissions to your users unless they require it. Be careful granting CodeStar permissions through wildcards when they do require it, so that users aren’t granted the “codestar:CreateProjectFromTemplate” permission. If a user must be granted “codestar:CreateProject” and “iam:PassRole” (and/or “codestar:AssociateTeamMember”), be sure that sufficient monitoring is in place to detect any privilege escalation attempts.
The CodeStar undocumented API vulnerability has for the most part been fixed, but it is still a good idea to implement the defense strategies outlined above. This type of vulnerability might not only be limited to CodeStar, though, because there might be other undocumented APIs for other AWS services that are abusable like this one.
Many undocumented APIs were discovered in just the short amount of time it took to find this vulnerability. Sometimes these undocumented APIs can be beneficial for attackers, while some might be useless. Either way, it is always useful as an attacker to dig deep and figure out what APIs exist and which ones are abusable.
As a defender, it is necessary to keep up with the attackers to defend against unexpected and unknown attack vectors. Following best practice, like not using wildcards when giving permissions, is also a great way to avoid this vulnerability.
We’ll be at re:Inforce next week, with two more big releases coming before the event. We’ll also be teaming up with Protego and handing out copies of our AWS pentesting book to the first 50 people each day of the event.