Hardening AWS IAM: Blue Team PassRole Defense Guide
Overview & Defensive Context: AWS IAM Privilege Escalation & iam:PassRole (T1078.004)#
Harden AWS IAM against PassRole privilege escalation: scope Resource ARNs, enforce iam:PassedToService, and deploy permission boundaries.
In our morning threat architecture analysis, we deconstructed the offensive mechanics of AWS IAM Privilege Escalation via iam:PassRole (mapped to MITRE ATT&CK T1078.004: Cloud Accounts and T1098: Account Manipulation). We analyzed how an adversary with restricted developer or DevOps access exploits an over-permissive iam:PassRole grant ("Resource": "*") to pass an administrative service role to a serverless compute service (AWS Lambda, EC2, AWS Glue, or CloudFormation). When invoked, the compute resource assumes the elevated role via the AWS Security Token Service (STS) and attaches the managed AdministratorAccess policy directly to the attacker's user, resulting in total cloud account takeover.
For cloud security architects, IAM engineers, and blue teams, defending enterprise AWS environments against iam:PassRole abuse exposes critical structural challenges unique to the AWS identity delegation model:
- The Inherent Misunderstanding of PassRole:
iam:PassRoleis not an API that performs a standalone action; it is a permission evaluated when passing a role to an execution service. Developers and platform teams routinely configureiam:PassRolewith wildcard resources (Resource: "*") because restricting ARNs requires anticipating every future application role name, inadvertently granting permission to pass high-privilege account roles. - The Inefficacy of Standard Perimeter & Network Defenses: Cloud control plane privilege escalations occur entirely over authenticated HTTPS requests to the AWS IAM and Lambda API endpoints (
iam.amazonaws.com,lambda.amazonaws.com). Perimeter firewalls, VPC security groups, and Network Access Control Lists (NACLs) have zero visibility into internal IAM policy semantics or role delegation handshakes. - Ambient Compute Trust Policies: Many enterprise organizations create administrative roles (such as automated patching roles or cross-account deployment roles) whose trust policies allow broad assumption by
lambda.amazonaws.comorec2.amazonaws.com. If any low-privilege user in the account possesses unrestrictediam:PassRole, those administrative roles become immediate privilege escalation bridges. - The Additive Nature of IAM Policies: In AWS IAM, permissions are evaluated additively. If a developer creates a role and attaches policies without an administrative ceiling, the newly created role can assume privileges greater than the creator's own identity. Preventing this requires enforcing IAM Permission Boundaries.
An IAM policy that pairs iam:PassRole on wildcard resources ("*") with resource creation permissions (lambda:CreateFunction, ec2:RunInstances, or cloudformation:CreateStack) is functionally identical to granting full AdministratorAccess. Blue teams must strictly constrain iam:PassRole to designated role ARN paths and enforce iam:PassedToService condition keys.
⚔️ Exploitation Mechanics: For root-cause memory corruption analysis and attack flow, see our deep-dive: Deconstructing Breakdown.
Architecture Hardening: Multi-Layered IAM Defense-in-Depth#
Securing enterprise AWS environments against iam:PassRole privilege escalation demands a comprehensive four-tier defense-in-depth architecture: Strictly Scoped Resource ARNs and Condition Keys, Mandatory IAM Permission Boundaries, Organization-Wide Service Control Policies (SCPs), and Least-Privilege Service Trust Policies.
Defense Architecture Flowchart#
flowchart TD
classDef client fill:#1e293b,stroke:#ef4444,stroke-width:2px,color:#f8fafc
classDef gate fill:#0f172a,stroke:#3b82f6,stroke-width:2px,color:#93c5fd
classDef iam fill:#064e3b,stroke:#10b981,stroke-width:2px,color:#6ee7b7
classDef audit fill:#4c1d95,stroke:#8b5cf6,stroke-width:2px,color:#ddd6fe
classDef drop fill:#450a0a,stroke:#dc2626,stroke-width:2px,color:#fca5a5
classDef pass fill:#065f46,stroke:#34d399,stroke-width:2px,color:#a7f3d0
CallerReq[Developer / User Invokes API: lambda:CreateFunction --role ARN]:::client --> SCPCheck{Tier 1: Organization Service Control Policy Gate}:::gate
SCPCheck -- Attempting to Pass Restricted Admin / Core Role --> DropSCP[Action: Deny by SCP Organization Rule]:::drop
SCPCheck -- Complies with SCP Boundaries --> PassRolePolicy{Tier 2: Caller Identity PassRole Evaluation}:::gate
PassRolePolicy -- Wildcard or Unscoped Role ARN Attempted --> DropUnscoped[Action: Deny PassRole on Unauthorized ARN]:::drop
PassRolePolicy -- Role ARN Matches Designated App Path --> ConditionCheck{Tier 3: iam:PassedToService Condition Gate}:::iam
ConditionCheck -- Service Does Not Match Configured Target --> DropService[Action: Deny Service Delegation Mismatch]:::drop
ConditionCheck -- Target Service Matches lambda.amazonaws.com --> BoundaryCheck{Tier 4: Mandatory IAM Permission Boundary}:::iam
BoundaryCheck -- Target Role Missing Permission Boundary Ceiling --> DropBoundary[Action: Deny by Boundary Enforcement Policy]:::drop
BoundaryCheck -- Role Constrained by Boundary Ceiling --> AllowDelegation[AWS Control Plane Attaches Role to Lambda]:::pass
AllowDelegation --> SafeExecution[Lambda Executes within Hardened Boundary Ceiling]:::pass
DropSCP -.-> TelemetryStream[Tier 5: CloudTrail & GuardDuty Telemetry Stream]:::audit
DropUnscoped -.-> TelemetryPipeline
DropBoundary -.-> TelemetryPipeline
TelemetryPipeline --> SOCAlert[SOC Incident Triage Triggered]:::passLayer 1: Strictly Scoping iam:PassRole with Resource ARNs and Condition Keys#
The most direct remediation for iam:PassRole abuse is eliminating wildcard resources and enforcing the iam:PassedToService condition key. This ensures that the caller can only pass specific, application-tier roles to explicitly approved AWS services.
Deploy the following least-privilege IAM policy template across developer roles:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowScopedPassRoleToLambdaOnly",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::123456789012:role/application-roles/*",
"Condition": {
"StringEquals": {
"iam:PassedToService": "lambda.amazonaws.com"
}
}
},
{
"Sid": "AllowLambdaManagementWithinAppNamespace",
"Effect": "Allow",
"Action": [
"lambda:CreateFunction",
"lambda:UpdateFunctionCode",
"lambda:UpdateFunctionConfiguration",
"lambda:InvokeFunction"
],
"Resource": "arn:aws:lambda:*:123456789012:function:app-*"
}
]
}
By enforcing arn:aws:iam::123456789012:role/application-roles/* and "iam:PassedToService": "lambda.amazonaws.com":
- The caller cannot pass any role outside the
/application-roles/IAM path (preventing delegation of account-level administrative roles). - The caller cannot pass the role to unintended compute services (such as EC2 or Glue).
Layer 2: Mandatory IAM Permission Boundaries#
An IAM Permission Boundary is an advanced authorization control that sets the maximum permissions an identity-based policy can grant to an IAM entity. Even if a role has the AdministratorAccess policy attached, its effective permissions can never exceed the ceiling defined by its permission boundary.
To prevent developers from creating roles with elevated privileges or passing unconstrained roles, enforce a policy that requires all created or passed roles to have a designated permission boundary attached:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EnforcePermissionBoundaryOnRoleCreation",
"Effect": "Allow",
"Action": [
"iam:CreateRole",
"iam:AttachRolePolicy",
"iam:PutRolePolicy"
],
"Resource": "arn:aws:iam::123456789012:role/application-roles/*",
"Condition": {
"StringEquals": {
"iam:PermissionsBoundary": "arn:aws:iam::123456789012:policy/DeveloperBoundaryPolicy"
}
}
},
{
"Sid": "DenyBoundaryTampering",
"Effect": "Deny",
"Action": [
"iam:DeleteRolePermissionsBoundary",
"iam:DeletePolicyVersion",
"iam:CreatePolicyVersion"
],
"Resource": [
"arn:aws:iam::123456789012:policy/DeveloperBoundaryPolicy",
"arn:aws:iam::123456789012:role/application-roles/*"
]
}
]
}
Layer 3: Organization-Wide Service Control Policies (SCPs)#
At the AWS Organizations management root, deploy Service Control Policies (SCPs) to prevent any member account principal from passing administrative roles or tampering with central security controls:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyPassingAdminAndSecurityRoles",
"Effect": "Deny",
"Action": "iam:PassRole",
"Resource": [
"arn:aws:iam::*:role/*Admin*",
"arn:aws:iam::*:role/*Administrator*",
"arn:aws:iam::*:role/*Security*",
"arn:aws:iam::*:role/*OrganizationAccountAccessRole*"
],
"Condition": {
"ArnNotLike": {
"aws:PrincipalARN": [
"arn:aws:iam::*:role/CentralSecurityAdminRole",
"arn:aws:iam::*:role/aws-reserved/sso.amazonaws.com/*"
]
}
}
}
]
}
Layer 4: Hardening Service Trust Policies (AssumeRolePolicyDocument)#
A role cannot be passed to a service unless its trust policy explicitly permits that service to assume it. Perform a fleet-wide audit of all role trust policies in your AWS account:
- Remove
lambda.amazonaws.com,ec2.amazonaws.com, or other service principals from any role containingAdministratorAccessor broad IAM manipulation permissions. - If an administrative role must be assumed by automation, restrict assumption to dedicated cross-account CI/CD role ARNs or require MFA (
"aws:MultiFactorAuthPresent": "true").
Production Detection Queries: Sigma Rule, CloudTrail & EventBridge#
Detecting iam:PassRole abuse requires monitoring CloudTrail for role delegation events combined with resource creation, as well as alerting on anomalous IAM privilege modifications.
1. Production Sigma Rule: Suspicious iam:PassRole to AWS Compute Service#
The following production-validated Sigma rule monitors AWS CloudTrail management events, alerting when an IAM user passes a role containing administrative naming patterns to a compute service:
title: AWS IAM PassRole to Privileged Compute Service
id: 5a91f82c-4c3a-49a1-b841-8e9c9e012078
status: production
description: |
Detects instances where an IAM user passes an administrative or privileged IAM role
to an AWS compute resource (such as Lambda, EC2, Glue, or CloudFormation) via iam:PassRole,
indicative of cloud privilege escalation (MITRE T1078.004).
references:
- https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/
- https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_passrole.html
tags:
- attack.privilege_escalation
- attack.persistence
- attack.t1078.004
- attack.t1098
logsource:
service: cloudtrail
product: aws
detection:
selection_compute_events:
eventName:
- 'CreateFunction20150331' # Lambda CreateFunction
- 'UpdateFunctionCode20150331'
- 'RunInstances'
- 'CreateDevEndpoint'
- 'CreateStack'
- 'CreateProject' # CodeBuild
selection_privileged_roles:
requestParameters.role|contains:
- 'admin'
- 'Admin'
- 'FullAccess'
- 'PowerUser'
- 'OrganizationAccountAccessRole'
filter_approved_automation:
userIdentity.type: 'AssumedRole'
userIdentity.sessionContext.sessionIssuer.userName|startswith:
- 'AWSServiceRole'
- 'TerraformPipeline'
- 'AWSControlTower'
condition: selection_compute_events and selection_privileged_roles and not filter_approved_automation
fields:
- eventTime
- userIdentity.userName
- eventName
- requestParameters.role
- requestParameters.functionName
- sourceIPAddress
falsepositives:
- Legitimate infrastructure-as-code automation pipelines deploying approved services.
level: high
2. Automated Remediation via Amazon EventBridge & Lambda#
Deploy an EventBridge rule that detects unauthorized AttachUserPolicy calls granting AdministratorAccess and immediately revokes the policy:
{
"source": ["aws.iam"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventSource": ["iam.amazonaws.com"],
"eventName": ["AttachUserPolicy", "AttachRolePolicy"],
"requestParameters": {
"policyArn": ["arn:aws:iam::aws:policy/AdministratorAccess"]
}
}
}
When triggered, an automated security Lambda function inspects the caller; if the caller is not the designated root deployment pipeline, it detaches the policy immediately, deactivates the caller's access keys, and emits a high-priority alert to the SOC.
Enterprise Mitigation Matrix: Workarounds, Hotfixes & Architecture#
When prioritizing defensive engineering against iam:PassRole privilege escalation, cloud security teams must balance operational agility against isolation boundaries:
| Remediation Strategy | Implementation Effort | Blast Radius & Operational Risk | Detection & Prevention Efficacy | Performance Overhead | Architectural Longevity |
|---|---|---|---|---|---|
| Workaround: Eliminate Wildcard Resources on PassRole | 2 - 4 Hours (Audit all identity policies and replace Resource: "*" with specific ARNs) |
Low - Moderate May require updating CI/CD policies that dynamically provision role names. |
High (85%) Blocks passing unapproved roles; restricts escalation targets. |
Zero Native IAM policy evaluation. |
Tactical Baseline Immediate mitigation while designing permission boundaries. |
| Operational Control: Enforce iam:PassedToService Condition Key | 1 - 2 Days (Attach iam:PassedToService condition to all PassRole statements) |
Low Ensures roles meant for Lambda cannot be passed to EC2 or Glue. |
High (90%) Eliminates cross-service confused deputy exploitation paths. |
Zero Native IAM policy evaluation. |
Core Policy Standard Essential CIS AWS Benchmark compliance requirement. |
| Architecture Fix: Mandatory IAM Permission Boundaries | 1 - 2 Weeks (Deploy boundary policies across all developer and service role pipelines) |
Moderate Requires updating role creation scripts to include boundary parameters. |
Absolute Against Escalation (100%) Enforces an immutable permission ceiling regardless of attached policies. |
Zero Native IAM policy evaluation. |
Mandatory Standard Permanently neutralizes role-based privilege escalation. |
| Organization Fix: Service Control Policies (SCPs) & Automated IR | 2 - 4 Weeks (Deploy organization-wide SCPs blocking admin role delegation) |
Substantial Requires testing across non-production accounts to avoid deployment drops. |
Comprehensive (100%) Enforces immutable organizational boundaries across all AWS accounts. |
Zero AWS Organizations control plane. |
Permanent State Zero-trust cloud architecture fully immune to PassRole takeover. |
Merely restricting iam:PassRole on IAM Users is insufficient if developers possess permissions to create or modify IAM roles (iam:CreateRole, iam:PutRolePolicy). A developer with iam:CreateRole can create a brand new role with administrative privileges unless restrained by an IAM Permission Boundary. Both controls must be deployed in tandem.
Incident Response & Verification Playbook: PassRole Escalation Triage#
If unauthorized iam:PassRole usage or an anomalous privilege escalation event is detected in your AWS account, execute the following four-phase incident response playbook immediately:
flowchart TD
classDef alert fill:#450a0a,stroke:#dc2626,stroke-width:2px,color:#fca5a5
classDef check fill:#1e293b,stroke:#f59e0b,stroke-width:2px,color:#fef3c7
classDef triage fill:#0f172a,stroke:#3b82f6,stroke-width:2px,color:#93c5fd
classDef clean fill:#064e3b,stroke:#10b981,stroke-width:2px,color:#6ee7b7
Triage[Phase 1: CloudTrail Triage & Session Audit]:::triage --> CorrelateLogs{Check CloudTrail for PassRole + CreateFunction Calls}:::check
CorrelateLogs -- Unauthorized Role Passed to Compute Service --> IsolateCaller[Phase 2: Immediate Containment & Principal Quarantine]:::alert
CorrelateLogs -- Clean CloudTrail Activity --> CheckGuardDuty{Check GuardDuty for PrivilegeEscalation Alerts}:::check
CheckGuardDuty -- Anomalous API Calls Detected --> IsolateCaller
CheckGuardDuty -- False Positive Confirmed --> CloseIncident[Close Incident as Clean / Low Risk]:::clean
IsolateCaller --> DetachPolicies[Phase 3: Detach Unauthorized Admin Policies]:::alert
DetachPolicies --> DeleteBackdoors[Delete Rogue Lambda Functions & EC2 Instances]:::alert
DeleteBackdoors --> RevokeSTSTokens[Revoke Active STS Temporary Credentials]:::alert
RevokeSTSTokens --> Phase4[Phase 4: Post-Remediation Hardening & Verification]:::cleanPhase 1: Live Triage & Forensic CloudTrail Audit#
- Query CloudTrail for Recent Compute Resource Creations: Inspect CloudTrail logs over the past 24 hours for instances where non-administrative users invoked compute creation APIs passing IAM roles:
# Search CloudTrail for Lambda CreateFunction events
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=CreateFunction20150331 --start-time $(date -u -d '24 hours ago' +%s) --query "Events[].[EventTime,Username,Resources[0].ResourceName]" --output table
- Inspect Attached IAM Policies on the Calling Principal: Verify whether the user has been recently granted administrative policies:
# Inspect policies attached to suspect user
aws iam list-attached-user-policies --user-name <SUSPECT_USER>
aws iam list-user-policies --user-name <SUSPECT_USER>
Phase 2: Immediate Containment & Principal Quarantine#
- Quarantine the Compromised Calling Principal: Immediately attach an explicit inline Deny policy to the suspected IAM user or role to terminate all access:
# Attach emergency quarantine policy denying all actions
aws iam put-user-policy --user-name <SUSPECT_USER> --policy-name EmergencyQuarantine --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Action":"*","Resource":"*"}]}'
# Deactivate all active access keys for the user
for key in $(aws iam list-access-keys --user-name <SUSPECT_USER> --query "AccessKeyMetadata[].AccessKeyId" --output text); do
aws iam update-access-key --user-name <SUSPECT_USER> --access-key-id $key --status Inactive
done
- Revoke Active Temporary STS Sessions: Invalidate any temporary credentials generated by the assumed role prior to containment:
# Invalidate temporary STS credentials issued for the compromised role
aws iam put-role-policy --role-name <COMPROMISED_ROLE_NAME> --policy-name RevokeOldSessions --policy-document "{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Action":"*","Resource":"*","Condition":{"DateLessThan":{"aws:TokenIssueTime":"$(date -u +%Y-%m-%dT%H:%M:%SZ)"}}}]}"
Phase 3: Eradication & Artifact Clean-Up#
- Delete Rogue Compute Resources: Delete the malicious Lambda function, terminate the EC2 instance, or delete the CloudFormation stack created during exploitation:
# Delete the malicious Lambda function
aws lambda delete-function --function-name <ROGUE_FUNCTION_NAME> --region <REGION>
- Detach Unauthorized IAM Policies: Remove any elevated policies attached by the exploit:
# Detach unauthorized AdministratorAccess policy
aws iam detach-user-policy --user-name <SUSPECT_USER> --policy-arn "arn:aws:iam::aws:policy/AdministratorAccess"
Phase 4: Post-Remediation Verification & Hardening Checklist#
Before concluding incident response and restoring development operations:
- Verify that all access keys for the compromised user have been deactivated and deleted.
- Confirm that
Resource: "*"oniam:PassRolehas been eliminated from all identity policies. - Verify that the
iam:PassedToServicecondition key is enforced on all active PassRole statements. - Confirm that IAM Permission Boundaries are attached to all developer and automation roles.
- Deploy the production Sigma rule
5a91f82c-4c3a-49a1-b841-8e9c9e012078into your cloud SIEM. - Verify that the Amazon EventBridge automated policy detachment rule is active across the organization.
Executive Takeaway Table#
| Attack Vector / Phase | Forensic Detection Signal | Primary Defensive Mitigation |
|---|---|---|
| IAM Policy Enumeration | Spike in iam:ListRoles and iam:GetUserPolicy API calls in CloudTrail. |
Enforce least-privilege IAM read policies; alert on rapid IAM discovery. |
| Unscoped PassRole Delegation | IAM policies contain Action: iam:PassRole with wildcard "Resource": "*". |
Scope Resource strictly to /application-roles/*; enforce iam:PassedToService. |
| Malicious Function Creation | CloudTrail event CreateFunction20150331 passing administrative role ARN. |
Enforce mandatory IAM Permission Boundaries on all created roles. |
| Compute Privilege Escalation | CloudTrail event AttachUserPolicy originating from internal Lambda IP address. |
Deploy Service Control Policies (SCPs) denying admin role delegation across accounts. |
| Account-Wide Persistence | Non-admin user account assigned AdministratorAccess or custom admin policies. |
Deploy Amazon EventBridge automated remediation to revoke unauthorized policy attachments. |
Authoritative References#
- AWS Identity and Access Management Documentation: Granting a User Permissions to Pass a Role to an AWS Service — AWS Documentation
- AWS Security Guidance: Permissions boundaries for IAM entities — AWS Documentation
- Rhino Security Labs Research: AWS IAM Privilege Escalation: Methods and Mitigation by Spencer Gietzen — Rhino Security Labs
- Bishop Fox Research: Investigating Privilege Escalation Methods in AWS — Bishop Fox Cybersecurity
- MITRE ATT&CK Framework: Technique T1078.004: Valid Accounts - Cloud Accounts — MITRE ATT&CK
Comments
Post a Comment