Socials
Twitter: https://twitter.com/Mako_Sec GitHub: https://github.com/MakoSec
Materials Used
- Pacu
- List of AWS privilege escalation methods
https://github.com/RhinoSecurityLabs/AWS-IAM-Privilege-Escalation
Introduction
Recently, I wrote a blog post on a simple method of privilege escalation in AWS. While writing that blog post I became curious of AWS managed policies and wanted to know which of them can be leveraged for privilege escalation. The reason I wanted to look into AWS managed policies in particular, is because customers have no control over managed policies. If they are being used, permissions cannot be added or removed from the policy by the customer. This can be dangerous, because if an account with a managed policy is compromised, privilege escalation can potentially occur by no fault of the customer. The results of this analysis into managed policies was not very shocking. I figured that most of the managed policies would be pretty safe and that the policies that allowed for privilege escalation would be the inherently permissive ones such as the full access policies.
Results
As previously mentioned the results of this research were not very shocking and pretty much fit into what was expected. There are 743 managed policies offered in AWS, out of that 743 only 36 allowed for privilege escalation, meaning that only 4.8% of the available managed polices allowed for privilege escalation. Most of the policies that allowed for privilege escalation were the inherently permissive policies. For example, most of the policies that gave a user full access to a particular service allowed for the potential of privilege escalation. Another important thing to understand about privilege escalation in AWS in general is that just because a policy allows for privilege escalation in theory does not mean it is possible in a given AWS environment. There are multiple methods of privilege escalation that involve the starting of a service and using the iam:PassRole call to pass a more permissive role to that service and then stealing the access keys, or performing an action such as adding a policy to your current account using that role. This is best shown by the following example.
I created a new user in AWS and attached the AWSMarketPlaceFullAccess policy to the user. I also attached a policy that I created named “Test” to it, this policy only has list access to IAM. I did this because not all of the policies below had access to list their own permissions using the IAM API. Not giving my test user list access to IAM would have made it more difficult to use Pacu to verify if a policy did in fact allow for privilege escalation. From an actual assessment standpoint, if permissions could not be enumerated they can be brute forced or discovered via other methods.
In the following set of screenshots, you will be able to see me run the Pacu module iam__privesc_scan. This module will enumerate an accounts permissions and attempt to escalate privileges. The module confirmed that the AWSMarketPlaceFullAccess policy was potentially able to escalate privileges by passing a more permissive role to an EC2 instance or to a new CloudFormation stack. In this example, I went with passing an instance profile to EC2. The role that I ran the EC2 instance was named “TestDeleteLater” and had the AdministratorAccess managed policy attached to it. To escalate privileges and obtain Administrator access, I added a call to IAM in the user data of the instance that will attach the AdministratorAccess policy to my test user. It is important to understand that if a role with an elevated set of permissions did not exist, privilege escalation would not have been possible in this scenario.
Running iam__privesc_scan
Escalating privileges
Administrator Access Achieved
The full list of AWS managed policies that allow for privilege escalation can be seen below.
AWSMarketplaceFullAccess
- PassingRoleToEC2
- PassingRoleToCloudFormation
AWSLambdaFullAccess
- PassExistingRoleToNewLambdaThenInvoke
- PassExistingRoleToNewLambdaThenTriggerWithExistingDynamo
- EditExistingLambdaFunctionWithRole
IAMFullAccess
- CreateNewPolicyVersion
- SetExistingDefaultPolicyVersion
- CreateAccessKey
- CreateLoginProfile
- UpdateLoginProfile
- AttachUserPolicy
- AttachGroupPolicy
- PutUserPolicy
- PutGroupPolicy
- AddUserToGroup
DatabaseAdministrator
- PassingRoleToNewLambdaFunctionAndTriggeringWithDynamo
- PassingRoleToDataPipeline
- PassExistingRoleToNewLambdaThenTriggerWithExistingDynamo
AWSSSOServiceRolePolicy
- AttachPolicyToRole
- CreateOrUpdateInlinePolicyForRole
AWSGlueServiceNotebookRole
- UpdatingExistingGlueDevEndpoint
AWSDataPipeline_PowerUser
- PassExistingRoleToNewDataPipeline
AWSCodeStarServiceRole
- CreateNewPolicyVersion
- SetDefaultPolicyVersion
- AttachPolicyToUser
- AttachPolicyToRole
- CreateOrUpdateInlinePolicyForRole
- CreateEC2WithExistingIP
- PassExistingRoleToNewCloudFormation
- PassExistingRoleToNewCodeStarProject
- CodeStarCreateProjectFromTemplate
- CodeStarCreateProjectThenAssociateTeamMember
AmazonDynamoDBFullAccess
- PassingRoleToNewLambdaFunctionAndTriggeringWithDynamo
- PassingRoleToDataPipeline
- PassExistingRoleToNewLambdaThenTriggerWithExistingDynamo
AWSRoboMakerServiceRolePolicy
- UpdatingCodeOfExistingLambdaFunction
AWSGlueServiceRole
- UpdateExistingGlueDevEndpoint
AWSBatchServiceRole
- CreateECSTaskWithRole
- CreateEC2WithExistingIP
AWSCodeStarFullAccess
- CodeStarCreateProjectFromTemplate
- CodeStarCreateProjectThenAssociateTeamMember
AWSDataPipeline_FullAccess
- PassExistingRoleToNewDataPipeline
AmazonElasticMapReduceFullAccess
- PassingRoleToCloudFormation
- CreateEC2WithExistingIP
AWSElasticBeanstalkFullAccess
- CreateEC2WithExistingIP
- RunECSTaskWithRole
- PassExistingRoleToNewCloudFormation
AmazonDynamoDBFullAccesswithDataPipeline
- CreateEC2WithExistingIP
- PassExistingRoleToNewLambdaThenInvoke
- PassExistingRoleToNewLambdaThenTriggerWithNewDynamo
- PassExistingRoleToNewLambdaThenTriggerWithExistingDynamo
- PassExistingRoleToNewDataPipeline
- EditExistingLambdaFunctionWithRole
DataScientist
- PassingRoleToCloudFormation
AWSOpsWorksCMServiceRole
- PassingRoleToCloudFormation
- CreateEC2WithExistingIP
AmazonECS_FullAccess
- PassingRoleToCloudFormation
- CreateTaskWIthTaskRole
- CreateEC2WithExistingIP
AmazonEC2ContainerServiceFullAccess
- PassingRoleToCloudFormation
- CreateEC2WithExistingIP
- CreateTaskWIthTaskRole
AWSGlueConsoleSageMakerNotebookFullAccess
- CreateEC2WithExistingIP
- PassingRoleToCloudFormation
- PassExistingRoleToNewGlueDevEndpoint
- UpdateExistingGlueDevEndpoint
AWSDeepLensServiceRolePolicy
- UpdatingCodeOfExistingLambdaFunction
AWSElasticBeanstalkService
- PassExistingRoleToNewCloudFormation
- CreateEC2WithExistingIP
AWSGlueConsoleFullAccess
- PassingRoleToCloudFormation
- PassExistingRoleToNewGlueDevEndpoint
- UpdateExistingGlueDevEndpoint
- CreateEC2WithExistingIP
AWSDeepRacerServiceRolePolicy
- PassingRoleToNewLambdaFunctionAndInvoking
- UpdatingCodeOfExistingLambdaFunction
- PassingRoleToCloudFormation
AWSServiceCatalogAdminFullAccess
- PassingRoleToCloudFormation
AWSDeepRacerCloudFormationAccessPolicy
- UpdatingCodeOfExistingLambdaFunction
- PassExistingRoleToNewCloudFormation
AmazonLaunchWizard_Fullaccess
- PassingRoleToNewLambdaFunctionAndInvoking
- PassingRoleToCloudFormation
AWSThinkboxAWSPortalAdminPolicy
- PassingRoleToCloudFormation
- CreateEC2WithExistingIP
AWSOpsWorksRegisterCLI_OnPremises
- CreateNewUserAccessKey
- AttachPolicyToUser
- AddUserToGroup
AWSThinkboxDeadlineResourceTrackerAdminPolicy
- PassingRoleToNewLambdaFunctionAndTriggeringWithDynamo
- PassingRoleToCloudFormation
AWSControlTowerServiceRolePolicy
- PassingRoleToCloudFormation
ServerMigration_ServiceRole
- PassingRoleToCloudFormation
AWSElasticBeanstalkRoleCore
- PassingRoleToCloudFormation
- CreateEC2WithExistingIP
AWSLambda_FullAccess
- PassExistingRoleToNewLambdaThenInvoke
- PassExistingRoleToNewLambdaThenTriggerWithExistingDynamo
- EditExistingLambdaFunctionWithRole