IAM Privilege Escalation in AWS: The Paths Ira Maps Automatically
Each step in an IAM privilege escalation chain looks like a routine API call. The attack only becomes visible when you trace the full sequence. Ira does that automatically.
MITRE ATT&CK T1078.004 — Valid Accounts: Cloud Accounts — is the most common privilege escalation technique seen in AWS environments. The reason it works so well is the same reason it is hard to detect: every step in the escalation chain is a legitimate API call, issued with valid credentials, that AWS will execute without complaint.
The challenge for detection is not identifying individual API calls. It is recognising the sequence.
What a typical escalation chain looks like
A well-documented path starts with iam:CreatePolicy. An attacker with an underprivileged identity creates a new IAM policy with the permissions they want — s3:*, ec2:*, or iam:* for maximum flexibility. Creating a policy does not grant any permissions by itself, so this step often passes unnoticed.
The next call is iam:AttachUserPolicy, targeting either the attacker’s own identity or a separate identity they control. This call attaches the newly created policy, granting the permissions it defines. At this point the escalation is complete, but the two events — create, then attach — may be separated by minutes or hours, and will appear in CloudTrail under the same principal identity that started with limited permissions.
A second common path uses iam:PassRole. The PassRole permission allows an identity to pass an IAM role to an AWS service. If the role being passed has more permissions than the calling identity, this is a privilege escalation — the identity can now launch an EC2 instance with the high-privilege role attached, then connect to that instance and issue API calls as the role. The sequence: iam:PassRole → ec2:RunInstances → SSH/SSM access → high-privilege API calls from inside the instance.
A third path targets the console: iam:UpdateLoginProfile allows an identity with no console access to set a password on another IAM user, then log in as that user. If the target user has AdministratorAccess, the escalation is complete in a single API call.
Why single-event alerting misses this
iam:CreatePolicy fires thousands of times per day in active AWS environments. Infrastructure-as-code pipelines create, update, and delete IAM policies on every deployment. Alerting on CreatePolicy in isolation would produce noise too high to act on.
iam:AttachUserPolicy is less common but still routine — new team members, new services, new roles being configured. An alert on this event needs context to be actionable: who issued it, what policy was attached, to which identity, and what sequence of events preceded it in the same session.
That context is available in CloudTrail. The problem is that assembling it manually, per incident, in real time, is not operationally feasible.
How Ira maps escalation chains
Ira’s IAM sub-agent monitors for a set of high-signal IAM events: CreatePolicy, AttachUserPolicy, AttachRolePolicy, PutUserPolicy, PutRolePolicy, UpdateLoginProfile, CreateLoginProfile, PassRole, CreateAccessKey.
For each of these events, the sub-agent pulls the full session context: the principal ARN, the source IP, the user agent, and the temporal window. It then queries backwards — what other IAM events did this principal issue in the preceding 60 minutes? — and forwards — what did this principal do in the 30 minutes following this event?
The result is a session graph. Nodes are API calls. Edges are temporal sequence relationships. An escalation pattern is a path through the graph from a low-privilege starting point to a high-privilege outcome.
Ira scores these graphs against known escalation paths. The scoring considers:
- Permission delta: the effective permissions of the principal before and after the sequence. A sequence that grants
iam:*scores higher than one that grantss3:GetObject. - Velocity: how quickly the steps occurred. A human with legitimate business need may take hours to configure a policy and attach it. An attacker typically does it in seconds.
- Source context: API calls from a CI/CD system user agent score lower than the same calls from an interactive session or an unfamiliar IP.
- Target identity: escalating to an existing high-privilege identity scores higher than creating a new one (existing identity is immediately usable; new identity may be noticed in an audit).
A worked example
Consider this sequence, extracted from a real escalation scenario:
18:04:11 iam:GetUserPolicy — attacker audits own permissions
18:04:23 iam:CreatePolicy — policy created: allows iam:*, s3:*, ec2:*
18:04:31 iam:AttachUserPolicy — policy attached to attacker's own user
18:04:45 iam:GetUser — attacker confirms new effective permissions
18:05:02 sts:GetCallerIdentity — identity confirmed
18:05:08 iam:CreateAccessKey — new access key created for persistence
Each of these events is individually unremarkable. The iam:GetUserPolicy at the start might be legitimate curiosity. The CreatePolicy might be legitimate IaC. The AttachUserPolicy might be legitimate onboarding.
The sequence, completed in 57 seconds by a single principal from a non-corporate IP, is not. Ira surfaces this as a high-severity privilege escalation with a containment recommendation to revoke the new access key, detach the escalated policy, and log the incident for forensic review.
The broader point
IAM is the control plane of AWS. Whoever controls IAM controls everything in the account. Escalation paths through IAM are not obscure edge cases — they are the primary mechanism by which compromised credentials become full account compromises.
Detecting them requires cross-event correlation at session scope, not single-event alerting. That correlation has to happen fast enough to be relevant — a full-account compromise can be completed in under five minutes by a capable attacker who already has initial access.
Ira’s IAM sub-agent runs this analysis in seconds, not minutes. The gap between initial access and full compromise is where containment has to happen.