Hardening AWS IAM Trust Policies: Blue Team Defense Guide
Overview & Defensive Context#
In this morning's offensive breakdown, we analyzed how cross-account AWS IAM role trust policies become critical attack vectors when configured with overly permissive account-root principals (arn:aws:iam::<AccountID>:root). Because AWS delegates trust evaluation entirely to the external account's administrators, any compromised entity possessing sts:AssumeRole rights in the trusted account can assume the role and inherit production administrative permissions.
Standard perimeter network defenses and web application firewalls remain blind to this exploit path because the entire transaction occurs over legitimate AWS Security Token Service (STS) control-plane API calls. Furthermore, conventional security monitoring often treats sts:AssumeRole operations as normal infrastructure automation, allowing adversaries to move laterally between accounts without generating high-severity alarms.
[!IMPORTANT] Securing cross-account trust boundaries requires eliminating account-root wildcards, enforcing cryptographic external identifiers (
sts:ExternalId), constraining role assumption through Attribute-Based Access Control (ABAC) condition keys, and establishing continuous automated policy validation via AWS IAM Access Analyzer and Service Control Policies (SCPs).
Architecture Hardening: Multi-Tiered Trust Verification Gate#
Hardening IAM trust relationships demands that role assumption requests pass through multiple defensive evaluation layers before temporary security credentials can be generated by STS.
flowchart TD
subgraph ExternalCaller [External Caller - Account 444455556666]
CallerIdentity["Caller Identity: CI/CD Runner / Third Party"]
AssumeReq["sts:AssumeRole API Request"]
end
subgraph STSVerificationEngine [AWS STS Evaluation Engine]
SCPEval{"Organization SCP Check: Allowed Role Assumption?"}
TrustPolicyCheck{"Trust Policy Verification Gate"}
ConditionCheck{"Condition Keys: ExternalId & PrincipalArn & MFA"}
DropUnauthorized["Deny: Unauthorized Principal / Missing External ID"]
end
subgraph ProductionBoundary [Production Account 111122223333]
TargetRole["Target IAM Role: Restricted Session Scope"]
SessionTokens["Issue Scoped Temporary Credentials (Max 1 Hour)"]
CloudTrailStream["CloudTrail Real-Time Event Stream"]
end
CallerIdentity --> AssumeReq
AssumeReq --> SCPEval
SCPEval -->|Blocked by SCP| DropUnauthorized
SCPEval -->|Allowed by Org| TrustPolicyCheck
TrustPolicyCheck --> ConditionCheck
ConditionCheck -->|Failed Evaluation| DropUnauthorized
ConditionCheck -->|Verified Match| TargetRole
TargetRole --> SessionTokens
SessionTokens --> CloudTrailStreamHardened Policy Implementations#
To remediate vulnerable trust policies, organizations must replace open account-root delegation with explicit principal constraints and mandatory external IDs.
1. Hardened Cross-Account Trust Policy#
The following trust policy enforces specific role scoping, strict external ID matching, and session duration limits:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EnforceExplicitPrincipalAndExternalId",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::444455556666:role/AuthorizedDeployerRole"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "7f8b9a12-c4d3-4e5f-9a8b-1c2d3e4f5a6b",
"aws:PrincipalOrgID": "o-a1b2c3d4e5"
},
"NumericLessThanEquals": {
"sts:DurationSeconds": 3600
}
}
}
]
}
[!TIP] Use
aws:PrincipalOrgIDin the condition block to ensure that even if an account ID changes or gets reused, the assuming principal must reside inside your AWS Organization.
Production Detection Queries#
Security Operations Centers (SOC) must monitor CloudTrail logs for anomalous cross-account role assumption activity, especially attempts originating from unexpected source IPs or unapproved AWS accounts.
1. Production Sigma Rule: Unauthorized Cross-Account AssumeRole Activity#
The following Sigma rule detects cross-account sts:AssumeRole API calls executed against high-privilege administrative roles:
title: Suspicious Cross-Account STS AssumeRole to Sensitive Role
id: 8f2a1b9c-4e3d-4c12-9a8b-7c6d5e4f3a21
status: production
description: Detects cross-account sts:AssumeRole API calls targeting administrative or deployment roles from unauthorized external AWS accounts.
references:
- https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html
- https://attack.mitre.org/techniques/T1078/004/
logsource:
category: cloudtrail
service: sts
detection:
selection_action:
eventName: 'AssumeRole'
eventSource: 'sts.amazonaws.com'
selection_target_role:
requestParameters.roleArn|contains:
- ':role/Admin'
- ':role/Administrator'
- ':role/Deployer'
- ':role/AppDeployerRole'
filter_internal_accounts:
recipientAccountId:
- '111122223333' # Production Account
userIdentity.accountId:
- '111122223333' # Same account self-assumption
- '222233334444' # Known Central Identity Account
condition: selection_action and selection_target_role and not filter_internal_accounts
falsepositives:
- Legitimate cross-account deployments authorized in change-management windows
level: high
tags:
- attack.initial_access
- attack.privilege_escalation
- attack.t1078.004
Enterprise Mitigation Matrix#
Securing enterprise cloud architectures requires selecting controls that remediate trust weaknesses across accounts without breaking automated CI/CD pipelines:
| Remediation Strategy | Technical Implementation | Operational Blast Radius | Performance Overhead | Security Guarantee |
|---|---|---|---|---|
| Mandatory sts:ExternalId | Add cryptographically random GUID conditions to all third-party trust policies | Low (requires updating vendor configurations) | Zero runtime impact | Completely eliminates Confused Deputy attack vectors |
| Principal Scoping | Replace account-root ARNs with specific role ARNs (arn:aws:iam::ACC:role/ROLE) |
Moderate (requires explicit role provisioning in external accounts) | Zero | Prevents arbitrary identities in trusted accounts from assuming role |
| Organization SCP Guardrail | Deploy AWS Organizations SCP denying sts:AssumeRolewithoutaws:PrincipalOrgID |
High (blocks all non-organization accounts unless exempted) | Zero | Prevents accidental exposure to external third-party AWS accounts |
| IAM Access Analyzer | Automated continuous scanning of all IAM roles for external public/cross-account access | Low (passive audit and alerting tool) | Zero | Surfaces newly introduced misconfigured trust relationships in near real-time |
Incident Response & Verification Playbook#
When an alert fires for an unauthorized cross-account role assumption, incident response teams must follow this structured verification playbook:
Phase 1: Rapid Triage & Session Invalidation#
- Extract Assumed Session Details from CloudTrail: Query CloudTrail events to identify the compromised role, caller IP, and session name:
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole \
--max-results 20 \
--query 'Events[].{Time:EventTime,User:Username,Source:CloudTrailEvent}' \
--output json
- Revoke Active Role Sessions Immediately:
Attach an inline policy to the compromised role setting
aws:TokenIssueTimeto reject all sessions issued before the current timestamp:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"DateLessThan": {
"aws:TokenIssueTime": "2026-09-08T15:00:00Z"
}
}
}
]
}
Apply via AWS CLI:
aws iam put-role-policy \
--role-name AppDeployerRole \
--policy-name EmergencySessionRevocation \
--policy-document file://revoke_sessions.json
Phase 2: Trust Relationship Remediation#
- Audit All Attached Policies on the Role: Verify if the attacker established persistence by creating new access keys, backdoored policies, or additional trust relationships:
aws iam list-attached-role-policies --role-name AppDeployerRole
aws iam get-role --role-name AppDeployerRole --query 'Role.AssumeRolePolicyDocument'
- Re-baseline Trust Policy Conditions:
Update the trust policy to require explicit principal ARNs and an updated
sts:ExternalId.
[!CAUTION] Revoking sessions via
aws:TokenIssueTimeimmediately severs active API credentials across all workloads utilizing the role. Coordinate rapid redeployment of authorized automated tasks after invalidation.
Authoritative Technical References#
- AWS IAM Documentation: How to Use Trust Policies with IAM Roles
- AWS IAM User Guide: How to Use an External ID When Granting Access to Your AWS Resources
- Cloud Security Alliance (CSA): 2026 Cloud Security Index - IAM Vulnerability Patterns
- MITRE ATT&CK Technique T1078.004: Valid Accounts - Cloud Accounts
Comments
Post a Comment