> For the complete documentation index, see [llms.txt](https://docs.forestall.io/fsprotect/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.forestall.io/fsprotect/edges/aws/aws_assume_role.md).

# AWS\_ASSUME\_ROLE

## Summary

|                                |                                     |
| ------------------------------ | ----------------------------------- |
| **FSProtect ACL Alias**        | AWS\_ASSUME\_ROLE                   |
| **Edge Type**                  | Attack Path                         |
| **Affected Object Types**      | IAM Users, IAM Roles, AWS Services  |
| **Exploitation Certainty**     | Certain                             |
| **AWS IAM Action / Condition** | `sts:AssumeRole` on the target role |

## Description

`AWS_ASSUME_ROLE` represents the ability to call `sts:AssumeRole` against a target IAM role and obtain temporary security credentials scoped to that role's permissions.

When exploited, the caller receives a set of short-lived credentials — `AccessKeyId`, `SecretAccessKey`, and `SessionToken` — valid for up to 12 hours. These credentials grant the full permission set of the assumed role, which may be far more privileged than the caller's own identity.

This edge requires two conditions to hold simultaneously:

1. The **source identity** must have `sts:AssumeRole` allowed in its own IAM policies.
2. The **target role's trust policy** must explicitly permit the source identity as a principal.

Cross-account role assumption is common in AWS multi-account architectures. In this case, the trust policy of the target role in Account B lists a principal from Account A. An attacker who compromises an identity in Account A may therefore pivot to Account B without any credentials native to that account.

Condition keys frequently used to restrict this path include `aws:MultiFactorAuthPresent`, `sts:ExternalId`, `aws:SourceIp`, and `aws:PrincipalOrgID`. Conditions that are misconfigured or absent are a primary source of over-permissive assume-role chains.

## Identification

### AWS CLI

Retrieve the trust policy of a role to determine who can assume it:

```bash
aws iam get-role --role-name TargetRole \
  --query 'Role.AssumeRolePolicyDocument'
```

Simulate whether the current identity can assume a specific role:

```bash
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::123456789012:user/AnalystUser \
  --action-names sts:AssumeRole \
  --resource-arns arn:aws:iam::123456789012:role/TargetRole
```

Enumerate all roles whose trust policies include a specific principal:

```bash
aws iam list-roles --query 'Roles[*].[RoleName,AssumeRolePolicyDocument]' \
  --output json | python3 -c "
import json, sys
roles = json.load(sys.stdin)
for name, policy in roles:
    doc = policy if isinstance(policy, dict) else json.loads(policy)
    for stmt in doc.get('Statement', []):
        p = stmt.get('Principal', {})
        if 'arn:aws:iam::123456789012:user/AnalystUser' in str(p):
            print(name)
"
```

### AWS Console

1. Open **IAM** → **Roles** → select the target role.
2. Open the **Trust relationships** tab.
3. Review the trust policy JSON — `Principal` defines who can call `AssumeRole`, and `Condition` blocks restrict when it is allowed.
4. To check if a source identity has the permission to call `sts:AssumeRole`, open that user or role and use **Policy Simulator** under **Actions**.

## Exploitation

Assume the target role and retrieve temporary credentials:

```bash
aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/TargetRole \
  --role-session-name AttackerSession
```

Export the returned credentials into the shell environment:

```bash
export AWS_ACCESS_KEY_ID=<AccessKeyId>
export AWS_SECRET_ACCESS_KEY=<SecretAccessKey>
export AWS_SESSION_TOKEN=<SessionToken>
```

Verify the assumed identity:

```bash
aws sts get-caller-identity
```

For cross-account scenarios, the trust policy may require an `ExternalId` condition. If the `ExternalId` value is known or guessable, pass it directly:

```bash
aws sts assume-role \
  --role-arn arn:aws:iam::999999999999:role/CrossAccountRole \
  --role-session-name AttackerSession \
  --external-id KnownExternalId
```

## Mitigation

* Apply least privilege to trust policies — list only the specific principals that genuinely need to assume the role.
* Use `aws:PrincipalOrgID` to restrict cross-account assumptions to accounts within the same organization.
* Require MFA for sensitive role assumptions by adding `aws:MultiFactorAuthPresent: 'true'` as a condition.
* Use `sts:ExternalId` for third-party cross-account access, and treat the external ID as a shared secret — do not expose it.
* Avoid wildcards (`"Principal": "*"`) in trust policies; they allow any authenticated AWS principal to attempt assumption.
* Set `MaxSessionDuration` on roles to the minimum required value to limit credential lifetime.

## Detection

Monitor CloudTrail for AssumeRole activity:

* **Event source**: `sts.amazonaws.com`
* **Event name**: `AssumeRole`

```bash
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole \
  --query 'Events[*].{Time:EventTime,Actor:Username,Role:Resources[0].ResourceName}'
```

High-value signals:

* Cross-account role assumptions where the source account is not a known internal account.
* Session names that do not follow a consistent naming convention (automated or tool-generated sessions often have predictable patterns).
* Repeated assumption attempts that result in `AccessDenied` (trust policy enumeration).
* Assumptions of high-privilege roles (admin roles, deploy roles, break-glass roles) outside normal business hours.

## References

* <https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html>
* <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_permissions-to-switch.html>
* <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_require-mfa.html>
* <https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html>
* <https://cloud.hacktricks.wiki/en/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/index.html>
* <https://ermetic.com/blog/aws/aws-iam-privilege-escalation-methods-mitigation/>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.forestall.io/fsprotect/edges/aws/aws_assume_role.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
