IAM PassRole Lambda Escalation
iam:PassRole is the hinge of a large class of AWS privilege escalations. It lets a principal hand an existing IAM role to a service. If you can pass a role more privileged than your own to a service you can also invoke, that service runs with the higher role and you inherit its permissions. Lambda and EC2 are the two most reliable vehicles.
Confirm the Prerequisites
You need three things: iam:PassRole on a target role, a service-creation permission that consumes a role, and a role more privileged than your current identity to pass. Enumerating your own effective permissions is covered in IAM Authenticated Enumeration.
List roles and read their attached policies to pick a target worth passing, for example one with AdministratorAccess or broad iam:*:
Success
The role you pass must trust the service you use. A role for the Lambda path needs lambda.amazonaws.com in its trust policy, the EC2 path needs ec2.amazonaws.com. Check AssumeRolePolicyDocument before spending time on a role the service will refuse.
Lambda Path
With iam:PassRole plus lambda:CreateFunction and lambda:InvokeFunction, create a function that runs under the target role and returns that role's credentials, or performs actions directly. Package a minimal handler:
import os
def handler(event, context):
return {
'AWS_ACCESS_KEY_ID': os.environ['AWS_ACCESS_KEY_ID'],
'AWS_SECRET_ACCESS_KEY': os.environ['AWS_SECRET_ACCESS_KEY'],
'AWS_SESSION_TOKEN': os.environ['AWS_SESSION_TOKEN'],
}
{
"AWS_ACCESS_KEY_ID": "ASIA...",
"AWS_SECRET_ACCESS_KEY": "...",
"AWS_SESSION_TOKEN": "..."
}
Export those and you are operating as the passed role. If you also hold iam:* through it, attach an admin policy to your own user to make the escalation durable.
EC2 Path
With iam:PassRole and ec2:RunInstances, launch an instance with the target role as its instance profile, then read the role's credentials straight from that instance's metadata service. This needs an instance profile that wraps the role, most privileged roles used by EC2 already have one.
Once it boots, if you have SSH or SSM to the box, pull credentials from IMDS as shown in EC2 Instance Metadata Service. No instance profile ready to use? Create one from a role you can pass:
Other PassRole Sinks
The same pattern extends to any service that assumes a passed role and runs your code or exposes its credentials. Worth checking when Lambda and EC2 are locked down:
- Glue development endpoints and jobs
- CloudFormation with a passed service role
- SageMaker notebook instances
- Data Pipeline
- CodeBuild projects
The prerequisite is always iam:PassRole plus a create or run permission on that service.
Warning
Creating functions, launching instances, and attaching policies are all high-signal CloudTrail events (CreateFunction, RunInstances, AttachUserPolicy). Clean up test resources you create, and expect the role assumption chain to be reconstructable after the fact.