This case study documents a controlled AWS lab exercise demonstrating how IAM misconfigurations involving iam:PassRole can lead to privilege escalation, even when traditional console‑based protections are in place.
The lab highlights a realistic attacker progression:
A key outcome is the distinction between browser‑based security controls and programmatic/API threat models — console guardrails alone are insufficient when automation permissions are misaligned.
iam:PassRole can be abused without IAM visibility| User | Intended Role |
|---|---|
| ops-junior | Junior operations, EC2 via console |
| ci-helper | CI / automation user (CLI access) |
| dev-automation | Lambda automation experiments |
| dev-readonly / security-auditor | IAM read-only visibility |
| guest-contractor | Minimal / no permissions |
ec2.amazonaws.com, Policy AdministratorAccess — high-risk roleec2.amazonaws.com, lambda.amazonaws.com, Policy EC2 + SSM — orphaned / over-trustedSecurityAuditLAB 2 focused on human trust boundaries, not technical exploitation. Key observations:
This laid the groundwork for LAB 3.
The attacker (ci-helper) did not possess full automation credentials or independent infrastructure design capability. Instead, the attacker relied on social engineering of a junior operations user to obtain a valid EC2 launch blueprint, including the AMI ID, instance type, region, and knowledge of a privileged IAM role.
While console-based IAM controls prevented role discovery and selection, this human trust boundary bridged the remaining gaps. Once the attacker obtained a known-good configuration, iam:PassRole enabled privilege escalation through the AWS CLI without requiring any IAM visibility or administrative permissions.
Observed behavior:
iam:ListRoles, iam:ListPolicies → AccessDeniediam:CreateRole) deniedPrivilege escalation via PassRole was blocked at the console layer due to missing role enumeration permissions, demonstrating effective IAM hardening against browser‑based abuse.
ops-junior launched EC2 instances via consoleAdminEC2RoleWith console escalation blocked, ci-helper pivoted to AWS CLI (PowerShell) using existing automation access keys.
The attacker did not need role listing, IAM visibility, or role creation — only the name of a privileged role, iam:PassRole, and ec2:RunInstances.
Command Executed (AWS CLI):
aws ec2 run-instances \
--image-id ami-0c02fb55956c7d316 \
--instance-type t3.micro \
--iam-instance-profile Name=AdminEC2Role \
--region us-east-1 \
--profile ci-helper
Result:
AdminEC2Role attached"IamInstanceProfile": { "Arn": "arn:aws:iam::7xxxxxxxxxx5:instance-profile/AdminEC2Role" }This proves that ci-helper, a non‑privileged user, socially engineered information to launch persistent administrator‑privileged EC2 infrastructure.
Despite creating the instance, ci-helper could NOT:
All lifecycle actions failed with AccessDenied.
ci-helper, a non‑privileged user, socially engineered information to launch persistent administrator‑privileged infrastructure, which they could not later manage. This is a serious operational and security risk.
CloudTrail RunInstances events confirmed:
ci-helperami-0c02fbxxxxxx7d316 is a public Amazon Linux 2 AMIPrivilege escalation occurred via role attachment, not AMI reuse.
iam:PassRole granted without sufficient constraintsiam:PassedToService restrictioniam:PassRole is privilege escalation when combined with computeiam:PassRole with explicit role ARNs and iam:PassedToServiceRunInstances with TerminateInstancesPassRole + RunInstances
Even when IAM role visibility, listing, and creation are restricted, a user with iam:PassRole and workload execution permissions can escalate privileges through automation interfaces. Console‑based guardrails do not prevent CLI‑based role abuse.
This lab demonstrates a realistic, defensible, and commonly overlooked AWS privilege escalation path, combining technical misconfiguration with human trust failures — exactly how real incidents occur.