aws-ec2-run-instances-as-role
RunInstances + PassRole -> launch an instance running as a chosen role, then read IMDS.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
?principal has EFFECTIVE ec2:RunInstances (+ iam:AddRoleToInstanceProfile / iam:CreateInstanceProfile if no profile exists)
?role trust policy allows Principal Service ec2.amazonaws.com
iam:PassRole iam:PassedToService condition (if any) includes ec2.amazonaws.com
emit
| source type | Identity |
|---|---|
| target type | Identity |
| source | <principal> |
| target | <IAM role> |
| permissions | iam:PassRole ec2:RunInstances iam:AddRoleToInstanceProfile |
| conditions | role_compatibility iam_permission condition_expression |
| state logic | ACTIVE if role trusts ec2.amazonaws.com and PassedToService includes ec2 else POTENTIAL(role_compatibility) |
Narrative
{principal.name} can pass {role.name} to EC2 and run a new instance (iam:PassRole + ec2:RunInstances), executing code as {role.name} and reading its credentials from IMDS.
Raw rule rules/derived/aws/ec2.yaml
id: aws-ec2-run-instances-as-role
emits: CanCreateWorkloadAs
description: RunInstances + PassRole -> launch an instance running as a chosen role, then read IMDS.
match:
- - principal: null
- CanPassIdentity
- role: null
where:
- ?principal has EFFECTIVE ec2:RunInstances (+ iam:AddRoleToInstanceProfile / iam:CreateInstanceProfile
if no profile exists)
- ?role trust policy allows Principal Service ec2.amazonaws.com
- iam:PassRole iam:PassedToService condition (if any) includes ec2.amazonaws.com
emit:
source_type: Identity
target_type: Identity
source: <principal>
target: <IAM role>
permissions:
- iam:PassRole
- ec2:RunInstances
- iam:AddRoleToInstanceProfile
conditions:
- role_compatibility
- iam_permission
- condition_expression
escalation: Launch an attacker-controlled instance bound to a privileged role; UserData runs as root
and IMDS vends the role's STS credentials.
state_logic: ACTIVE if role trusts ec2.amazonaws.com and PassedToService includes ec2 else POTENTIAL(role_compatibility)
false_positive_note: Only ACTIVE when the role trust allows ec2.amazonaws.com AND iam:PassRole is not
scoped away from ec2 via iam:PassedToService. A role passable only to lambda/ecs does NOT yield EC2
execution.
narrative: '{principal.name} can pass {role.name} to EC2 and run a new instance (iam:PassRole + ec2:RunInstances),
executing code as {role.name} and reading its credentials from IMDS.'