Article by Nick Frichette.
AWS IAM Privilege Escalation Techniques
Original Research: Spencer Gietzen - AWS IAM Privilege Escalation
Further Reading: AWS-IAM-Privilege-Escalation
Further Reading: Investigating PrivEsc Methods in AWS
Note
If you'd like to get hands on experience exploiting these misconfigurations, check out iam-vulnerable by Seth Art.
codestar:CreateProject, codestar:AssociateTeamMember
With access to the codestar:CreateProject and codestar:AssociateTeamMember permissions, an adversary can create a new CodeStar project and associate themselves as an Owner of the project.
This will attach a new policy to the user that provides access to a number of permissions for AWS services. This is most useful for further enumeration as it gives access to lambda:List*, iam:ListRoles, iam:ListUsers, and more.
glue:UpdateDevEndpoint
With access to the glue:UpdateDevEndpoint permission, an adversary can update the existing SSH key associated with the glue endpoint. This will allow the adversary to SSH into the host and gain access to IAM credentials associated with the role attached to the glue endpoint. Though not required, it may be helpful to have the glue:GetDevEndpoint permission as well, if the existing endpoint cannot be identified via other means.
iam:AddUserToGroup
With access to the iam:AddUserToGroup permission, an adversary can add an IAM user they control to an existing group with more privileges. Although this is not required, it may be helpful to have other permissions in the IAM family to identify other groups and their privileges.
iam:AttachGroupPolicy
With access to the iam:AttachGroupPolicy permission, an adversary can attach an IAM policy to a group they are a member of. This potentially includes policies such as AdministratorAccess, which would provide them (surprise) administrator access to the AWS account.
iam:AttachRolePolicy
With access to the iam:AttachRolePolicy permission, an adversary can attach an IAM policy to a role they have access to. This potentially includes policies such as AdministratorAccess, which would provide them administrator access to the AWS account.
iam:AttachUserPolicy
With access to the iam:AttachUserPolicy permission, an adversary can attach an IAM policy to an IAM user they have access to. This potentially includes policies such as AdministratorAccess, which would provide them administrator access to the AWS account.
iam:CreateAccessKey
With access to the iam:CreateAccessKey permission, an adversary can create an IAM Access Key and Secret Access Key for other users. This would allow them to create credentials for more privileged users and have access to their privileges.
iam:CreateLoginProfile
With access to the iam:CreateLoginProfile permission, an adversary can create a password for a more privileged IAM user to login to the console as. Note: if a password is already set, you must use iam:UpdateLoginProfile instead.
iam:CreatePolicyVersion
With access to the iam:CreatePolicyVersion permission, an adversary can create a new version of a existing policy with more privilege. If the adversary has access to the principal that policy is attached to, they can elevate their privileges.
iam:DeleteRolePermissionsBoundary
With access to the iam:DeleteRolePermissionsBoundary permission, an adversary can remove a permissions boundary from a role they have access to. This may increase the role's effective permissions if the permissions boundary was more restrictive than any of the role's identity-based policies.
iam:DeleteRolePolicy
With access to the iam:DeleteRolePolicy permission, an adversary can delete an inline policy from a role they have access to. This may increase the role's effective permissions if the policy contains explicit deny statements that any of the role's other policies allow.
iam:DeleteUserPermissionsBoundary
With access to the iam:DeleteUserPermissionsBoundary permission, an adversary can remove a permissions boundary from a user they have access to. This may increase the user's effective permissions if the permissions boundary was more restrictive than any of the role's identity-based policies.
iam:DeleteUserPolicy
With access to the iam:DeleteUserPolicy permission, an adversary can delete an inline policy from a user they have access to. This may increase the user's effective permissions if the policy contains explicit deny statements that any of the user's other policies allow.
iam:DetachRolePolicy
With access to the iam:DetachRolePolicy permission, an adversary can remove a managed policy from a role they have access to. This may increase the role's effective permissions if the policy contains explicit deny statements that any of the role's other policies allow.
iam:DetachUserPolicy
With access to the iam:DetachUserPolicy permission, an adversary can remove a managed policy from a user they have access to. This may increase the user's effective permissions if the policy contains explicit deny statements that any of the user's other policies allow.
iam:PassRole, autoscaling:CreateAutoScalingGroup or autoscaling:UpdateAutoScalingGroup, autoscaling:CreateLaunchConfiguration,
With access to the iam:PassRole, autoscaling:CreateLaunchConfiguration, autoscaling:CreateAutoScalingGroup, and autoscaling:UpdateAutoScalingGroup permissions, an adversary can create a launch configuration and leverage it in an autoscaling group to pass a more privileged role to it. This would allow an adversary to escalate privileges to that more privileged role.
iam:PassRole, autoscaling:CreateAutoScalingGroup or autoscaling:UpdateAutoScalingGroup, ec2:CreateLaunchTemplate
With access to the iam:PassRole, ec2:CreateLaunchTemplate, autoscaling:CreateAutoScalingGroup, and autoscaling:UpdateAutoScalingGroup permissions, an adversary can create a launch template and leverage it in an autoscaling group to pass a more privileged role to it. This would allow an adversary to escalate privileges to that more privileged role.
iam:PassRole, cloudformation:CreateStack
With access to the iam:PassRole and cloudformation:CreateStack permissions, an adversary can create a new CloudFormation stack and pass a more privileged role to it. This would allow an adversary to escalate privileges to that more privileged role.
iam:PassRole, codestar:CreateProject
With access to the iam:PassRole and codestar:CreateProject permissions, an adversary can create a new CodeStar project and pass a more privileged role to it. This would allow an adversary to escalate privileges to that more privileged role including that of an administrator.
iam:PassRole, datapipeline:ActivatePipeline, datapipeline:CreatePipeline, datapipeline:PutPipelineDefinition
With access to the iam:PassRole, datapipeline:ActivatePipeline, datapipeline:CreatePipeline, and datapipeline:PutPipelineDefinition permissions, an adversary can create a new pipeline and pass in a more privileged role. It is worth noting that to do this the AWS account must already contain a role that can be assumed by DataPipeline and that role must have greater privileges (or at least different ones) than the principal the adversary controls.
iam:PassRole, ec2:RunInstances
With access to the iam:PassRole and ec2:RunInstances permissions, an adversary can create a new EC2 instance and pass a more privileged role to it.
This can be taken advantage of with the following one-liner:
Some things to note: The instance profile must already exist, and (realistically) it must have greater permissions than the role you have access to. If you also have the ability to create a role, this can be leveraged (although you may as well set the trust policy of that role to one you control at that point). The role that is being passed must have a trust policy allowing the EC2 service to assume it. You cannot pass arbitrary roles to an EC2 instance.
A common misconception about this attack is that an adversary must have access to an existing SSH key, or be able to spawn an SSM session. This is not actually true, you can leverage user data to perform an action on the host. One common example is to have the EC2 instance curl the metadata service, retrieve the IAM credentials, and then send them to an attacker controlled machine using curl.
Another (stealthier) example would be to perform all your API operations at once in the user-data script. This way you are not dinged with the IAM credential exfiltration finding (which can be bypassed).
iam:PassRole, glue:CreateDevEndpoint
With access to the iam:PassRole and glue:CreateDevEndpoint permissions, an adversary can create a new Glue development endpoint and pass in a more privileged role. It is worth noting that to do this the AWS account must already contain a role that can be assumed by Glue and that role must have greater privileges (or at least different ones) than the principal the adversary controls.
iam:PassRole, glue:CreateJob
With access to the iam:PassRole and glue:CreateJob permissions, an adversary can create a new Glue job and pass in a more privileged role. The AWS account must already contain a role that can be assumed by Glue and that role must have greater privileges (or at least different ones) than the principal the adversary controls. The glue:StartJobRun privilege would allow for the job to be run.
iam:PassRole, glue:UpdateJob
With access to the iam:PassRole and glue:UpdateJob permissions, an adversary can update the role and command associated with a Glue job. The AWS account must already contain a role that can be assumed by Glue and that role must have greater privileges (or at least different ones) than the principal the adversary controls. The glue:StartJobRun privilege or some pre-existing trigger could cause the job to run.
iam:PassRole, lambda:AddPermission, lambda:CreateFunction
With access to the iam:PassRole, lambda:AddPermission, and lambda:CreateFunction permissions, an adversary can create a Lambda function with an existing role. This function could then by updated with lambda:AddPermission to allow another principal in another AWS account the permission to invoke it. It is worth noting that the AWS account must already contain a role that can be assumed by Lambda.
iam:PassRole, lambda:CreateEventSourceMapping, lambda:CreateFunction
With access to the iam:PassRole, lambda:CreateEventSourceMapping, and lambda:CreateFunction permissions, an adversary can create a Lambda function with an existing privileged role and associating it with a DynamoDB table. Then, when a new record is inserted into the table, the Lambda function will trigger with the privilege of the passed in role.
It is worth noting that the AWS account must already contain a role that can be assumed by Lambda. Additionally, while not required, it may be beneficial to have the dynamodb:CreateTable and dynamodb:PutItem permissions to trigger this yourself.
iam:PassRole, lambda:CreateFunction, lambda:InvokeFunction
With access to the iam:PassRole, lambda:CreateFunction, and lambda:InvokeFunction permissions, an adversary can create a new Lambda function and pass an existing role to it. They can then invoke the function allowing them access to the privileges of the role associated with the function. It is worth noting that unless the adversary can create a role, they must use an already existing role that can be assumed by Lambda.
iam:PutGroupPolicy
With access to the iam:PutGroupPolicy permission, an adversary can create an inline policy for a group they are in and give themselves administrator access to the AWS account.
iam:PutRolePermissionsBoundary
With access to the iam:PutRolePermissionsBoundary permission, an adversary can update a permissions boundary attached to a role they have access to. This may increase the role's effective permissions if the permissions boundary was more restrictive than any of the role's identity-based policies.
iam:PutRolePolicy
With access to the iam:PutRolePolicy permission, an adversary can create an inline policy for a role they have access to and give themselves administrator access to the AWS account.
iam:PutUserPermissionsBoundary
With access to the iam:PutUserPermissionsBoundary permission, an adversary can update a permissions boundary attached to a user they have access to. This may increase the user's effective permissions if the permissions boundary was more restrictive than any of the role's identity-based policies.
iam:PutUserPolicy
With access to the iam:PutUserPolicy permission, an adversary can create an inline policy for a user they have access to and give themselves administrator access to the AWS account.
iam:SetDefaultPolicyVersion
With access to the iam:SetDefaultPolicyVersion permission, an adversary can revert a policy associated with their principal to a previous version. This is useful for scenarios in which a previous version of a policy had more access than the current version.
iam:UpdateAssumeRolePolicy
With access to the iam:UpdateAssumeRolePolicy permission, an adversary can modify the assume-role policy of a role, allowing them to assume it. This is useful to gain access to administrator roles, or other more privileged roles.
iam:UpdateLoginProfile
With access to the iam:UpdateLoginProfile permission, an adversary can change the password of an IAM user. This would allow them to log into the console as that user.
lambda:UpdateFunctionCode
With access to the lambda:UpdateFunctionCode permission, an adversary can modify an existing Lambda function's code. This would allow them to gain access to the privileges of the associated IAM role the next time the function is executed.
lambda:UpdateFunctionConfiguration
With access to the lambda:UpdateFunctionConfiguration permission, an adversary can modify an existing Lambda function's configuration to add a new Lambda Layer. This Layer would then override an existing library and allow an adversary to execute malicious code under the privilege of the role associated with the Lambda function.