The Anatomy of an IAM Trust Escalation

During recent cloud penetration tests across fintech and banking infrastructures, one misconfiguration pattern appeared repeatedly: over-permissive IAM trust relationships chained across multi-account AWS Organizations.

When organisations scale out multiple AWS accounts (e.g. Development, Staging, Shared-Services, and Production), security boundaries are assumed to be naturally enforced by account borders. However, automated CI/CD runners or operational roles frequently pierce these boundaries with wide assumptions.

The Attack Vector: Trust Policy with Wildcard Principals

Consider an internal audit or deployment role in the primary account:

json code
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}

When :root is specified as the principal without an ExternalId or explicit role/user restriction, any principal in account 111122223333 that possesses sts:AssumeRole permissions can assume this role, regardless of their intended blast radius.

Step-by-Step Chain:

  1. Initial Access: Attacker gains execution inside an ECS task in the development account through a dependency injection bug.
  2. Instance Profile Exfiltration: The metadata service (http://169.254.169.254/latest/meta-data/iam/security-credentials/) yields temporary credentials.
  3. Cross-Account Discovery: Enumerating attached policies reveals permission to assume deployment roles in production.
  4. AssumeRole Execution:

bash code
aws sts assume-role \
  --role-arn arn:aws:iam::444455556666:role/ProductionDeployer \
  --role-session-name devwalls-audit

  1. Persistence & Pivot: Production access granted with administrative read/write privileges over database snapshots and KMS keys.

Defensive Remediation & Detection Rules

  • Enforce ExternalId: For all cross-account roles, require a cryptographically random, non-guessable ExternalId.
  • Scope Down Principals: Never specify :root in trust documents; explicitly name the exact role ARN authorized to assume.
  • Service Control Policies (SCPs): Deny role creation without boundary permissions at the AWS Organizations root level.
  • Continuous Monitoring: Configure CloudTrail alarms alerting whenever cross-account sts:AssumeRole calls originate from unexpected VPC subnets.