← Back to blog
Cloud SecuritySep 15, 2026· 9 min

AWS IAM Privilege Escalation: How It Happens

How attackers turn a low-privilege AWS user into an admin - the exact IAM permissions that make it possible, and how to find and stop them.

AWS IAM Privilege Escalation: How It Happens

What it is: IAM privilege escalation is when someone who starts with limited access in your AWS account uses a weak permission to give themselves more access - often all the way to full admin. Why it matters: attackers rarely land as admin. They phish a developer, find a leaked access key, or pop one app, then look for a single over-broad IAM permission that lets them climb. When to care: any AWS account where humans or apps have permissions that were granted broadly and never tightened - which is almost every account.

IAM (Identity and Access Management) is the service that decides who can do what in AWS. A privilege-escalation path is a chain of allowed actions that ends with more power than you were meant to have. Below are the paths attackers actually use, in plain terms, and what to do about them.

The permissions that let someone rewrite their own access

The most direct paths let an identity edit policies attached to itself. If a user can attach a managed policy, add an inline policy, or create a new version of an existing policy, they can simply grant themselves AdministratorAccess.

  • iam:AttachUserPolicy / iam:AttachRolePolicy - attach AdministratorAccess to yourself in one call.
  • iam:PutUserPolicy / iam:PutRolePolicy - write an inline policy that allows everything.
  • iam:CreatePolicyVersion + iam:SetDefaultPolicyVersion - quietly publish a new, wide-open version of a policy the identity already uses, then make it the default.
  • iam:CreateAccessKey (on another user) - mint API keys for a higher-privileged user and log in as them.

The tell for all of these: an identity that is allowed to call iam:* actions on itself or on other identities. IAM write permissions are admin permissions in disguise - treat them that way.

The PassRole trap

iam:PassRole lets you hand an existing IAM role to an AWS service - for example, giving a role to a new EC2 instance or Lambda function so it can run with that role's permissions. On its own it sounds harmless. The danger is the combination: if an identity can pass a powerful role AND create the thing that runs it, it inherits that role's power.

  • iam:PassRole + lambda:CreateFunction + lambda:InvokeFunction - create a function that runs as an admin role, then invoke it.
  • iam:PassRole + ec2:RunInstances - launch an instance with an admin instance profile, then read its credentials from inside.
  • iam:PassRole + glue:CreateDevEndpoint or similar - same idea through data services.

The fix is to scope PassRole tightly. Never write "Resource": "*" on an iam:PassRole statement. List the exact role ARNs a service is allowed to receive, and add a condition on iam:PassedToService so a role meant for Lambda cannot be passed to EC2.

{
  "Effect": "Allow",
  "Action": "iam:PassRole",
  "Resource": "arn:aws:iam::123456789012:role/app-lambda-exec",
  "Condition": {
    "StringEquals": { "iam:PassedToService": "lambda.amazonaws.com" }
  }
}

Trust-policy and assume-role paths

A role's trust policy says who is allowed to assume it. If an identity can edit that, it can add itself as a trusted principal and then assume the role.

  • iam:UpdateAssumeRolePolicy + sts:AssumeRole - rewrite a powerful role's trust policy to trust you, then assume it.
  • iam:CreateLoginProfile / iam:UpdateLoginProfile - set or change a console password for a user who has no password yet, then sign in as them.
  • sts:AssumeRole on an over-permissive role - sometimes no editing is needed; a role simply trusts too much already.

How to find these paths before an attacker does

You do not have to guess. AWS can show you where over-broad access lives.

  • IAM Access Analyzer - review 'unused access' findings and generate least-privilege policies from real CloudTrail activity, so a policy grants only what an identity actually used.
  • Check for the dangerous actions directly - search your policies for iam:*, a PassRole with Resource "*", CreatePolicyVersion, AttachUserPolicy, and UpdateAssumeRolePolicy on non-admin identities.
  • Permission boundaries - set a ceiling on what any role your developers create can do, so a self-service role can never exceed the boundary.
  • Service Control Policies (SCPs) - at the AWS Organizations level, deny the risky IAM write actions for everyone except a small break-glass admin role.

Detect the escalation in real time

Every one of these paths is an API call, and every API call is in CloudTrail (AWS's audit log). Alert on the specific events that signal someone climbing, and you catch it while it is happening rather than in the post-incident review.

# High-signal CloudTrail eventNames to alert on:
AttachUserPolicy        AttachRolePolicy
PutUserPolicy           PutRolePolicy
CreatePolicyVersion     SetDefaultPolicyVersion
UpdateAssumeRolePolicy  CreateLoginProfile
CreateAccessKey         PassRole (in RunInstances / CreateFunction)

Wire these into your SIEM or a simple EventBridge rule that pages on-call. A brand-new access key for a user who has not made an API call in months, or an AttachUserPolicy that adds AdministratorAccess, should never pass silently.

Prove it in your own account: run IAM Access Analyzer's unused-access analyzer, then grep your customer-managed policies for iam:PassRole with Resource "*". Most teams find at least one path on the first pass.

IAM privilege escalation is not an exotic exploit - it is over-broad permissions plus one attacker who reads policy JSON carefully. Tighten IAM write and PassRole permissions, cap them with boundaries and SCPs, and alert on the CloudTrail events above, and the climb from low-privilege to admin stops being available.

Learn it by doing

Pick your track and launch a hands-on lab in a real, isolated environment.

24 people viewing now