For the complete documentation index, see llms.txt. This page is also available as Markdown.

Roles & AssumeRole

AWS IAM Roles & AssumeRole

Theory

IAM Roles are AWS identities with specific permissions that can be assumed by entities such as users, services, or other roles. Unlike users, roles don't have permanent credentials—instead, they provide temporary security credentials when assumed.

Every role has two essential components: a trust policy that defines who can assume the role, and permissions policies that define what the role can do once assumed. When you assume a role, you receive temporary credentials consisting of an access key, secret key, and session token that expire after a duration between 1 and 12 hours. This creates a role session during which the temporary credentials remain valid.

AssumeRole Mechanism

┌─────────────┐           ┌─────────────┐           ┌─────────────┐
│   Caller    │──Request──│  STS Service│──Validate─│ Target Role │
│ (Principal) │           │             │  Trust    │             │
└─────────────┘           └─────────────┘           └─────────────┘
       │                         │                          │
       │   Temporary Credentials │                          │
       │←────────────────────────┤                          │
       │                                                    │
       │   Access AWS Resources with Role Permissions       │
       └────────────────────────────────────────────────────┘

The AssumeRole workflow begins when a caller sends a request to assume a role via the sts:AssumeRole API call. AWS Security Token Service (STS) receives this request and validates the caller's identity against the target role's trust policy. If the trust policy allows the caller to assume the role, STS issues temporary credentials valid for 15 minutes to 12 hours. The caller then uses these credentials to access AWS resources with the role's permissions. When the credentials expire, the process can be repeated if continued access is needed.

Trust Policy Structure

Trust policies are resource-based policies attached to roles that determine who can assume them. These policies include a Principal element specifying the trusted entities, an Action element typically set to sts:AssumeRole, and optional Condition elements to add requirements like external IDs or source IP restrictions.

Trust policies can specify different types of principals. AWS account principals like "AWS": "arn:aws:iam::123456789012:root" trust all identities in an account, while IAM user principals like "AWS": "arn:aws:iam::123456789012:user/alice" trust specific users. You can also trust IAM roles, AWS services like "Service": "ec2.amazonaws.com", or federated users via SAML providers.

Security Mechanisms

Several security mechanisms can protect role assumption. External IDs mitigate the "confused deputy" problem by requiring a secret value known only to trusted parties, commonly used for third-party cross-account access. The external ID acts as an additional authentication factor beyond the principal's identity.

MFA requirements force multi-factor authentication before role assumption by using the condition "aws:MultiFactorAuthPresent": "true" in the trust policy. This ensures that even if credentials are compromised, attackers cannot assume the role without the MFA device.

Source IP restrictions limit role assumption to specific networks using conditions like "aws:SourceIp": ["203.0.113.0/24"]. This prevents role assumption from untrusted locations even with valid credentials.

Session duration controls how long temporary credentials remain valid. The default session duration is 1 hour, with a maximum of 12 hours configurable via the role's MaxSessionDuration property. The actual duration is specified during the AssumeRole call using the --duration-seconds parameter.

Practice

Reconaissance

Before you can exploit roles, you need to discover which roles exist in the environment and which ones you can assume. Roles are defined by their trust policies, which specify exactly who can assume them. Enumerating roles and analyzing their trust policies reveals potential privilege escalation paths through role assumption.

Enumerate roles in account can be perfomed using awscli and following commands.

After identifying roles, you need to examine their trust policies to determine which ones you can actually assume. This script automates the process of checking each role's trust policy for references to your current identity or account.

Pacu's IAM enumeration module automates the discovery of all roles in the account and analyzes their trust policies to identify which ones you can potentially assume.

CloudFox specializes in analyzing role trust relationships, especially for cross-account scenarios. It visualizes trust paths and identifies pivot opportunities.

ScoutSuite performs comprehensive role security analysis, identifying misconfigurations in trust policies, missing MFA requirements, and privilege escalation paths through role assumption.

For more sophisticated enumeration, this Python script uses boto3 to programmatically analyze all role trust policies.

Testing AssumeRole Permission

Once you've identified potentially assumable roles through trust policy analysis, you need to verify that you can actually assume them. The trust policy might allow you, but you also need the sts:AssumeRole permission in your own identity policies. Testing assumption attempts will confirm whether both conditions are met.

The simplest way to test role assumption is directly calling the AssumeRole API. A successful call returns temporary credentials, while a failure indicates either the trust policy denies you or you lack the necessary permissions.

When you have multiple potential roles to test, automating the process saves time. This script attempts to assume each role and handles errors gracefully, giving you a clear picture of which roles you can successfully assume. Use this to quickly validate enumeration results.

Direct Role Assumption

The most straightforward exploitation is assuming a role that has higher privileges than your current identity. Once you've identified an assumable role with elevated permissions, you assume it to receive temporary credentials with those permissions, then use those credentials to perform privileged actions.

You identify your current low-privilege identity, discover a high-privilege role you can assume, assume it to get temporary credentials, export those credentials to your environment, and then use them to execute privileged commands.

Some roles require MFA for assumption, adding an extra security layer. If you have access to the MFA device (physical token or virtual authenticator app), you can provide the MFA code during assumption.

External IDs are used for third-party access scenarios to prevent the confused deputy problem. If you've discovered or guessed the external ID (perhaps through documentation, configuration files, or social engineering), you can provide it during role assumption to satisfy the trust policy requirement.

UpdateAssumeRolePolicy

The iam:UpdateAssumeRolePolicy permission allows you to modify the trust policy of any role. This provides a direct privilege escalation path since you can add your own identity to the trust policy of high-privilege roles, then assume those roles to gain elevated permissions.

The basic exploitation approach is straightforward:

  • create a new trust policy that trusts your current identity,

  • replace the role's existing trust policy with your malicious one,

  • then assume the role.

This works on any role you have UpdateAssumeRolePolicy permissions for, regardless of who the role currently trusts.

A stealthier approach preserves the original trust policy principals while adding your own identity. This reduces the chance of detection since legitimate users can still assume the role normally.

You can optionally restore the original policy after completing your actions to further cover your tracks.

Cross-Account Role Assumption

Cross-account roles enable access between different AWS accounts, commonly used for multi-account organizations or third-party integrations. If you've compromised credentials in one account, you can pivot to other accounts by assuming cross-account roles that trust your account.

First, identify which roles in the current account trust external accounts. These roles represent potential pivoting opportunities to other AWS accounts. The trust policies will reveal the account IDs you can potentially access.

CloudFox excels at mapping cross-account trust relationships and identifying pivot opportunities across AWS accounts in an organization.

With credentials from one account and a role ARN from another account, you can assume the cross-account role if its trust policy permits. This switches your identity to the target account, giving you whatever permissions that role has. You're now operating in a completely different AWS account.

Role Chaining

Role chaining involves assuming multiple roles in sequence to reach a target role with elevated privileges. This technique exploits trust relationships between roles where you might not be able to directly assume the final target role, but you can assume an intermediate role that has permission to assume the target.

Each assumption provides new temporary credentials that are used for the next step in the chain.

Manual chaining involves sequentially assuming each role in the path, exporting the credentials from each assumption before moving to the next. This creates a chain of role sessions, with each link providing access to assume the next role until you reach your target privileged role.

Automating role chaining with a script makes it easier to traverse long chains and reduces manual errors. This Python script iterates through a predefined chain of roles, assuming each one and using the resulting credentials for the next assumption, ultimately returning a session with the final role's permissions.

Confused Deputy Attack

The Confused Deputy problem occurs when trust policies are overly permissive, trusting entire AWS accounts rather than specific principals. When a trust policy specifies an AWS account root (arn:aws:iam::123456789012:root) as the principal, any identity in that account with the sts:AssumeRole permission can assume the role.

This trust policy trusts the entire account, not just specific identities within it:

The problem is that any principal in account 123456789012 with the sts:AssumeRole permission can assume this role, not just the intended trusted principals.

To exploit this misconfiguration, you just need any compromised credentials from the trusted account,even a low-privilege intern account works.

Because the trust policy checks the account rather than the specific principal, any identity in that account with basic AssumeRole permissions can assume the vulnerable role.

Resources

Last updated