Find the IAM Privesc: PassRole + Lambda Escalation

Cloud Security Level 4/4 ~7 min August 26, 2026

The challenge

This AWS IAM policy looks routine, but one permission lets the holder hand a powerful role to a Lambda they create and run - escalating from limited access to admin. Read the policy and type the exact permission that enables that escalation.

What you'll learn

  • Recognise iam:PassRole on Resource * as a privilege escalation primitive
  • Trace how CreateFunction + InvokeFunction + PassRole chain into admin access
  • Tell tightly-scoped, benign statements apart from a dangerous one
  • Explain why passing a role is more powerful than it looks
  • Name the correct scoping: narrow Resource ARN plus a PassedToService condition

Skills tested

AWS IAM policy reviewCloud privilege-escalation analysisLeast-privilege auditing

Prerequisites

  • How AWS IAM policies (Statement, Action, Resource) are structured
  • What an IAM role is and how Lambda assumes one
  • Basic JSON reading

How it works

In AWS, a principal's power comes not only from what it can do directly but from what it can make other services do on its behalf. iam:PassRole is the permission to hand an existing IAM role to a service you are configuring. On its own it does nothing, but combined with a service that runs code under a passed role, it becomes one of the best-known cloud privilege-escalation primitives.

The DeployLambdas statement grants lambda:CreateFunction, lambda:InvokeFunction, and iam:PassRole on Resource: "*". That wildcard is the fatal part: it means the user can pass any role in the account. An attacker creates a Lambda, uses iam:PassRole to attach a high-privilege role (say one with AdministratorAccess) as the function's execution role, then invokes the function. The code inside runs with that role's permissions, so the attacker now executes arbitrary actions as an administrator - having started from a limited developer identity.

The other two statements are decoys done right: read-only CloudWatch and Logs metrics, and read/write to a single named S3 bucket. They are scoped and benign. The audit skill is noticing that the privesc is not any single Lambda action but the iam:PassRole that lets a created function inherit a powerful role. The answer is iam:PassRole.

Common mistakes

  • Naming lambda:CreateFunction alone. Creating a function is harmless without the ability to attach a powerful role to it.
  • Picking lambda:InvokeFunction. Running a function you already control is not escalation by itself.
  • Flagging the read-only or S3 statements. They are scoped to specific resources and grant no escalation.
  • Missing the Resource: * on PassRole. The wildcard is what lets the user pass any role; a narrow ARN would close the hole.

How to defend against it

Never grant iam:PassRole on Resource: "*". Scope exactly which roles can be passed and to which service, so a created function can only ever run as a least-privilege role.

  • Restrict iam:PassRole to specific role ARNs the user legitimately needs.
  • Add a Condition with iam:PassedToService (for example lambda.amazonaws.com) so the role cannot be diverted elsewhere.
  • Separate the permission to create/invoke functions from the permission to pass roles wherever possible.
  • Run access-analyzer / IAM policy linting in CI to flag PassRole with wildcard resources.

Full solution

Pro and Max members unlock the complete step-by-step walkthrough.

Go Pro

Community stats

146 completions
85% success rate
M2F14M3 First blood

Related Daily Hacks

26,000+ Hackers 100+ Labs & Courses Free
Start Hacking Free