IAM Role Chaining: How Attackers Use AssumeRole for Lateral Movement
A technical deep-dive into how attackers chain IAM role assumptions across accounts and services to escalate privileges — and the CloudTrail signatures and preventive controls that stop them.
IAM privilege escalation is one of the most consequential techniques in cloud attacker playbooks. Unlike network-based lateral movement, which triggers firewall alerts and anomalous connection logs, IAM-based escalation uses fully legitimate AWS APIs — the same sts:AssumeRole and iam:CreatePolicyVersion calls that developers and automation pipelines make hundreds of times a day. Detection requires understanding what normal looks like and recognizing the specific patterns that indicate abuse.
What role chaining is
When an IAM principal calls sts:AssumeRole, AWS returns a set of temporary credentials scoped to the target role. Those temporary credentials can themselves call sts:AssumeRole on a third role — this is role chaining. There is no AWS-enforced limit on chain depth, and the chain can cross account boundaries if the target role’s trust policy permits.
An attacker who compromises a low-privilege role in a development account can walk this chain: dev role → shared services role → production admin role, provided each role’s trust policy allows the previous one to assume it. The final set of credentials carries the permissions of the last role in the chain, not the initial identity.
The CloudTrail signature for role chaining is distinct from a human or service directly assuming a role. When a role assumes another role, the userIdentity.type field in the CloudTrail event is AssumedRole rather than IAMUser or Root, and the userIdentity.sessionContext.sessionIssuer field traces back to the originating role. Monitoring for AssumeRole events where the caller is already an AssumedRole session — particularly where the source and target account IDs differ — surfaces this pattern.
PassRole privilege escalation
iam:PassRole is a permission that allows an IAM identity to attach an IAM role to an AWS service resource: a Lambda function, an EC2 instance, an ECS task definition, a Glue job, or dozens of other compute services. Its intended use is to grant a developer the ability to specify which execution role a function or instance will use.
The escalation path: an attacker with iam:PassRole and lambda:CreateFunction (or ec2:RunInstances, or ecs:RegisterTaskDefinition) can create a resource that runs with a role they do not themselves possess. They pass a highly privileged role — AdministratorAccess, for example — to the new resource, then invoke it with code that exfiltrates its own credentials or performs privileged actions on the attacker’s behalf.
This escalation requires no direct assumption of the target role. The attacker never calls sts:AssumeRole on the admin role — they simply get a compute resource to run with it. IAM Access Analyzer does not flag this by default because iam:PassRole is a standard permission.
Detect it in CloudTrail by alerting on sessions where iam:PassRole and a resource creation API (lambda:CreateFunction, ec2:RunInstances) occur within a short window, where the passed role ARN has broader permissions than the calling identity’s own policies.
The confused deputy problem
When a third party (such as a SaaS vendor or another AWS account) needs cross-account access to your AWS resources, the standard pattern is to create an IAM role with a trust policy allowing the third party’s account to assume it. The confused deputy vulnerability arises when that trust policy does not require an ExternalId condition.
Without ExternalId, any identity in the trusted account — not just the specific service or principal you intended — can assume your role. If the vendor’s account is ever compromised, or if the vendor’s own permissions are misconfigured, an attacker in that account can assume your role without any additional verification.
Require ExternalId on all cross-account role trust policies. Generate a unique, unguessable ID per customer relationship and include it as a condition:
"Condition": {
"StringEquals": { "sts:ExternalId": "your-unique-external-id" }
}
IAM Access Analyzer surfaces roles that are accessible from outside your AWS Organization — review these findings regularly and confirm that every external trust relationship is intentional and includes ExternalId.
Policy modification escalation paths
Several IAM permissions allow an attacker to modify existing policies in ways that grant themselves or others elevated access:
iam:CreatePolicyVersion allows creating a new version of a managed policy and setting it as the default. An attacker with this permission on a policy that is attached to a privileged role can overwrite its statements with "Action": "*", "Resource": "*" — effectively granting themselves administrator access through the role.
iam:AttachRolePolicy allows attaching any managed policy to any role (subject to resource constraints in the attacker’s own policy). An attacker with unconstrained iam:AttachRolePolicy can attach arn:aws:iam::aws:policy/AdministratorAccess to a role they already possess.
iam:PutRolePolicy allows writing an inline policy directly to a role — functionally equivalent to AttachRolePolicy for escalation purposes.
All three permissions should be treated as equivalent to iam:* in terms of risk. Grant them only to identity governance automation, with strict resource constraints limiting which policies or roles they can modify, and with aws:RequestedRegion and aws:CalledVia conditions where applicable.
Detection and response
The CloudTrail events to alert on:
AssumeRolewhereuserIdentity.type=AssumedRoleand the account inrequestParameters.roleArndiffers from the calling account — cross-account chainingPassRolefollowed within 5 minutes byCreateFunction,RunInstances, orRegisterTaskDefinitionin the same sessionCreatePolicyVersionwithrequestParameters.setAsDefault=trueon any policy attached to roles with high-privilege accessAttachRolePolicyorPutRolePolicywhere the policy being attached isAdministratorAccessor the role being modified has broad permissions
Route these events through EventBridge to a Lambda function that suspends the calling identity’s active sessions via iam:CreateServiceLinkedRole revocation and pages the security team.
Preventive controls
SCPs can restrict sts:AssumeRole to a known set of role ARNs using aws:PrincipalArn conditions, preventing ad-hoc role assumptions from principals outside the approved set. Permission boundaries constrain the maximum effective permissions of roles even if their attached policies are modified — an attacker who overwrites a policy cannot exceed the boundary. IAM Access Analyzer continuously evaluates resource-based policies and trust relationships for external access and surfaces findings that a human review would miss.
Takeaway
IAM privilege escalation paths are well-documented, reliably reproducible, and present in most AWS environments that have grown organically without a defined identity governance model. The techniques — role chaining, PassRole, policy overwrite — all use legitimate AWS APIs, which means prevention must come from policy constraints and detection must come from behavioral analysis of CloudTrail. Neither is optional if you are running privileged workloads in AWS.
CloudDefender
Defend your cloud. Continuously.
CloudDefender Suite gives security teams continuous posture management, threat detection, and compliance automation across AWS, Azure, and GCP — with zero false-positive fatigue.
Try CloudDefender →