Cognito User Pools
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
Informazioni di base
Un user pool è un directory di utenti in Amazon Cognito. Con un user pool, i tuoi utenti possono accedere alla tua app web o mobile tramite Amazon Cognito, o federarsi tramite un fornitore di identità di terze parti (IdP). Che i tuoi utenti accedano direttamente o tramite un terzo, tutti i membri del user pool hanno un profilo di directory a cui puoi accedere tramite un SDK.
I user pool forniscono:
- Servizi di registrazione e accesso.
- Unâinterfaccia web personalizzabile integrata per accedere agli utenti.
- Accesso sociale con Facebook, Google, Login con Amazon e Accedi con Apple, e tramite fornitori di identitĂ SAML e OIDC dal tuo user pool.
- Gestione della directory degli utenti e profili utente.
- FunzionalitĂ di sicurezza come lâautenticazione a piĂš fattori (MFA), controlli per credenziali compromesse, protezione contro il takeover dellâaccount e verifica di telefono ed email.
- Flussi di lavoro personalizzati e migrazione degli utenti tramite trigger AWS Lambda.
Il codice sorgente delle applicazioni conterrĂ solitamente anche lâID del user pool e lâID dellâapplicazione client, (e a volte il segreto dellâapplicazione?) necessari per un utente per accedere a un Cognito User Pool.
Attacchi potenziali
- Registrazione: Per impostazione predefinita, un utente può registrarsi, quindi potrebbe creare un utente per se stesso.
- Enumerazione degli utenti: La funzionalità di registrazione può essere utilizzata per trovare nomi utente che già esistono. Queste informazioni possono essere utili per un attacco di forza bruta.
- Forza bruta di accesso: Nella sezione Autenticazione hai tutti i metodi che un utente ha per accedere, potresti provare a forzare in modo brutale trovare credenziali valide.
Strumenti per il pentesting
- Pacu, ora include i moduli
cognito__enumecognito__attackche automatizzano lâenumerazione di tutte le risorse Cognito in un account e segnalano configurazioni deboli, attributi utente utilizzati per il controllo degli accessi, ecc., e automatizzano anche la creazione di utenti (incluso il supporto MFA) e lâescalation dei privilegi basata su attributi personalizzati modificabili, credenziali di pool di identitĂ utilizzabili, ruoli assunti nei token id, ecc.
Per una descrizione delle funzioni dei moduli, vedere la parte 2 del post del blog. Per le istruzioni di installazione, vedere la pagina principale di Pacu.
# Run cognito__enum usage to gather all user pools, user pool clients, identity pools, users, etc. visible in the current AWS account
Pacu (new:test) > run cognito__enum
# cognito__attack usage to attempt user creation and all privesc vectors against a given identity pool and user pool client:
Pacu (new:test) > run cognito__attack --username randomuser --email XX+sdfs2@gmail.com --identity_pools
us-east-2:a06XXXXX-c9XX-4aXX-9a33-9ceXXXXXXXXX --user_pool_clients
59f6tuhfXXXXXXXXXXXXXXXXXX@us-east-2_0aXXXXXXX
- Cognito Scanner è uno strumento CLI in python che implementa diversi attacchi su Cognito, inclusa la creazione non desiderata di account e lâoracolo degli account. Controlla this link per ulteriori informazioni.
# Install
pip install cognito-scanner
# Run
cognito-scanner --help
- CognitoAttributeEnum: Questo script consente di enumerare gli attributi validi per gli utenti.
python cognito-attribute-enu.py -client_id 16f1g98bfuj9i0g3f8be36kkrl
Registrazione
User Pools consente per default di registrare nuovi utenti.
aws cognito-idp sign-up --client-id <client-id> \
--username <username> --password <password> \
--region <region> --no-sign-request
Se chiunque può registrarsi
Potresti trovare un errore che indica che devi fornire piĂš dettagli sullâutente:
An error occurred (InvalidParameterException) when calling the SignUp operation: Attributes did not conform to the schema: address: The attribute is required
Puoi fornire i dettagli necessari con un JSON come:
--user-attributes '[{"Name": "email", "Value": "carlospolop@gmail.com"}, {"Name":"gender", "Value": "M"}, {"Name": "address", "Value": "street"}, {"Name": "custom:custom_name", "Value":"supername&\"*$"}]'
Puoi utilizzare questa funzionalità anche per enumerare gli utenti esistenti. Questo è il messaggio di errore quando un utente esiste già con quel nome:
An error occurred (UsernameExistsException) when calling the SignUp operation: User already exists
Note
Nota nel comando precedente come i custom attributes iniziano con âcustom:â.
Sappi anche che durante la registrazione non puoi creare nuovi custom attributes per lâutente. Puoi solo assegnare un valore ai default attributes (anche se non sono richiesti) e ai custom attributes specificati.
O semplicemente per testare se un client id esiste. Questo è lâerrore se il client-id non esiste:
An error occurred (ResourceNotFoundException) when calling the SignUp operation: User pool client 3ig612gjm56p1ljls1prq2miut does not exist.
Se solo lâamministratore può registrare utenti
Troverai questo errore e non sarai in grado di registrare o enumerare utenti:
An error occurred (NotAuthorizedException) when calling the SignUp operation: SignUp is not permitted for this user pool
Verifica della Registrazione
Cognito consente di verificare un nuovo utente verificando la sua email o il numero di telefono. Pertanto, quando si crea un utente, di solito sarĂ richiesto almeno il nome utente e la password e lâemail e/o il numero di telefono. Imposta solo uno che controlli in modo da ricevere il codice per verificare il tuo nuovo account utente in questo modo:
aws cognito-idp confirm-sign-up --client-id <cliet_id> \
--username aasdasd2 --confirmation-code <conf_code> \
--no-sign-request --region us-east-1
Warning
Anche se sembra che tu possa usare la stessa email e numero di telefono, quando devi verificare lâutente creato Cognito si lamenterĂ per lâuso delle stesse informazioni e non ti permetterĂ di verificare lâaccount.
Privilege Escalation / Aggiornamento degli Attributi
Per impostazione predefinita, un utente può modificare il valore dei suoi attributi con qualcosa come:
aws cognito-idp update-user-attributes \
--region us-east-1 --no-sign-request \
--user-attributes Name=address,Value=street \
--access-token <access token>
Privilegi di accesso agli attributi personalizzati
Caution
Potresti trovare attributi personalizzati utilizzati (come
isAdmin), poichĂŠ per impostazione predefinita puoi cambiare i valori dei tuoi attributi potresti essere in grado di escalare i privilegi cambiando il valore tu stesso!
Modifica dellâemail/nome utente per privilegi di accesso
Puoi utilizzare questo per modificare lâemail e il numero di telefono di un utente, ma poi, anche se lâaccount rimane verificato, quegli attributi sono impostati in stato non verificato (devi verificarli di nuovo).
Warning
Non sarai in grado di accedere con email o numero di telefono fino a quando non li verifichi, ma sarai in grado di accedere con il nome utente.
Nota che anche se lâemail è stata modificata e non verificata apparirĂ nel Token ID allâinterno del campoemail_verifiedsarĂ false, ma se lâapp non sta controllando questo potresti impersonare altri utenti.
Inoltre, nota che puoi mettere qualsiasi cosa allâinterno del campo
namesemplicemente modificando lâattributo name. Se unâapp controlla quello campo per qualche motivo invece di
Comunque, se per qualche motivo hai cambiato la tua email, ad esempio con una nuova a cui puoi accedere, puoi confermare lâemail con il codice che hai ricevuto a quellâindirizzo email:
aws cognito-idp verify-user-attribute \
--access-token <access_token> \
--attribute-name email --code <code> \
--region <region> --no-sign-request
Usa phone_number invece di email per cambiare/verificare un nuovo numero di telefono.
Note
Lâamministratore potrebbe anche abilitare lâopzione per accedere con un nome utente preferito dallâutente. Tieni presente che non potrai cambiare questo valore in nessun nome utente o preferred_username giĂ in uso per impersonare un altro utente.
Recupera/Cambia Password
Ă possibile recuperare una password semplicemente conoscendo il nome utente (o lâemail o il telefono sono accettati) e avendo accesso ad esso poichĂŠ un codice verrĂ inviato lĂŹ:
aws cognito-idp forgot-password \
--client-id <client_id> \
--username <username/email/phone> --region <region>
Note
La risposta del server sarĂ sempre positiva, come se il nome utente esistesse. Non puoi utilizzare questo metodo per enumerare gli utenti
Con il codice puoi cambiare la password con:
aws cognito-idp confirm-forgot-password \
--client-id <client_id> \
--username <username> \
--confirmation-code <conf_code> \
--password <pwd> --region <region>
Per cambiare la password è necessario conoscere la password precedente:
aws cognito-idp change-password \
--previous-password <value> \
--proposed-password <value> \
--access-token <value>
Autenticazione
Un pool di utenti supporta diversi modi per autenticarsi. Se hai un nome utente e una password, ci sono anche diversi metodi supportati per accedere.
Inoltre, quando un utente è autenticato nel Pool, vengono forniti 3 tipi di token: il Token ID, il Token di Accesso e il Token di Aggiornamento.
- Token ID: Contiene affermazioni riguardanti lâidentitĂ dellâutente autenticato, come
name,emailephone_number. Il token ID può anche essere utilizzato per autenticare gli utenti ai tuoi server di risorse o applicazioni server. Devi verificare la firma del token ID prima di poter fidarti di qualsiasi affermazione allâinterno del token ID se lo usi in applicazioni esterne. - Il Token ID è il token che contiene i valori degli attributi dellâutente, anche quelli personalizzati.
- Token di Accesso: Contiene affermazioni riguardanti lâutente autenticato, un elenco dei gruppi dellâutente e un elenco di scope. Lo scopo del token di accesso è di autorizzare le operazioni API nel contesto dellâutente nel pool di utenti. Ad esempio, puoi utilizzare il token di accesso per concedere al tuo utente lâaccesso per aggiungere, modificare o eliminare attributi utente.
- Token di Aggiornamento: Con i token di aggiornamento puoi ottenere nuovi Token ID e Token di Accesso per lâutente fino a quando il token di aggiornamento non è invalido. Per impostazione predefinita, il token di aggiornamento scade 30 giorni dopo che lâutente della tua applicazione accede al tuo pool di utenti. Quando crei unâapplicazione per il tuo pool di utenti, puoi impostare la scadenza del token di aggiornamento dellâapplicazione a qualsiasi valore tra 60 minuti e 10 anni.
ADMIN_NO_SRP_AUTH & ADMIN_USER_PASSWORD_AUTH
Questo è il flusso di autenticazione lato server:
- Lâapplicazione lato server chiama lâoperazione API
AdminInitiateAuth(invece diInitiateAuth). Questa operazione richiede credenziali AWS con permessi che includonocognito-idp:AdminInitiateAuthecognito-idp:AdminRespondToAuthChallenge. Lâoperazione restituisce i parametri di autenticazione richiesti. - Dopo che lâapplicazione lato server ha i parametri di autenticazione, chiama lâoperazione API
AdminRespondToAuthChallenge. Lâoperazione APIAdminRespondToAuthChallengeha successo solo quando fornisci credenziali AWS.
Questo metodo NON è abilitato per impostazione predefinita.
Per accedere devi conoscere:
- id del pool di utenti
- id del client
- nome utente
- password
- segreto del client (solo se lâapp è configurata per utilizzare un segreto)
Note
Per poter accedere con questo metodo, lâapplicazione deve consentire lâaccesso con
ALLOW_ADMIN_USER_PASSWORD_AUTH.
Inoltre, per eseguire questa azione hai bisogno di credenziali con i permessicognito-idp:AdminInitiateAuthecognito-idp:AdminRespondToAuthChallenge
aws cognito-idp admin-initiate-auth \
--client-id <client-id> \
--auth-flow ADMIN_USER_PASSWORD_AUTH \
--region <region> \
--auth-parameters 'USERNAME=<username>,PASSWORD=<password>,SECRET_HASH=<hash_if_needed>'
--user-pool-id "<pool-id>"
# Check the python code to learn how to generate the hsecret_hash
Codice per il Login
```python import boto3 import botocore import hmac import hashlib import base64client_id = â
boto_client = boto3.client(âcognito-idpâ, region_name=âus-east-1â)
def get_secret_hash(username, client_id, client_secret): key = bytes(client_secret, âutf-8â) message = bytes(fâ{username}{client_id}â, âutf-8â) return base64.b64encode(hmac.new(key, message, digestmod=hashlib.sha256).digest()).decode()
If the Client App isnât configured to use a secret
just delete the line setting the SECRET_HASH
def login_user(username_or_alias, password, client_id, client_secret, user_pool_id): try: return boto_client.admin_initiate_auth( UserPoolId=user_pool_id, ClientId=client_id, AuthFlow=âADMIN_USER_PASSWORD_AUTHâ, AuthParameters={ âUSERNAMEâ: username_or_alias, âPASSWORDâ: password, âSECRET_HASHâ: get_secret_hash(username_or_alias, client_id, client_secret) } ) except botocore.exceptions.ClientError as e: return e.response
print(login_user(username, password, client_id, client_secret, user_pool_id))
</details>
### USER_PASSWORD_AUTH
Questo metodo è un altro semplice e **tradizionale flusso di autenticazione utente e password**. à consigliato **migrare un metodo di autenticazione tradizionale** **a Cognito** e **consigliato** poi **disabilitarlo** e **utilizzare** invece il metodo **ALLOW_USER_SRP_AUTH** (poichÊ quest'ultimo non invia mai la password attraverso la rete).\
Questo **metodo NON è abilitato** per impostazione predefinita.
La principale **differenza** con il **metodo di autenticazione precedente** all'interno del codice è che **non è necessario conoscere l'ID del pool utenti** e che **non sono necessarie autorizzazioni extra** nel Cognito User Pool.
Per **accedere** è **necessario** conoscere:
- client id
- username
- password
- client secret (solo se l'app è configurata per utilizzare un segreto)
> [!NOTE]
> Per **poter accedere con questo metodo**, quell'applicazione deve consentire l'accesso con ALLOW_USER_PASSWORD_AUTH.
```python
aws cognito-idp initiate-auth --client-id <client-id> \
--auth-flow USER_PASSWORD_AUTH --region <region> \
--auth-parameters 'USERNAME=<username>,PASSWORD=<password>,SECRET_HASH=<hash_if_needed>'
# Check the python code to learn how to generate the secret_hash
Codice Python per il login
```python import boto3 import botocore import hmac import hashlib import base64client_id = â
boto_client = boto3.client(âcognito-idpâ, region_name=âus-east-1â)
def get_secret_hash(username, client_id, client_secret): key = bytes(client_secret, âutf-8â) message = bytes(fâ{username}{client_id}â, âutf-8â) return base64.b64encode(hmac.new(key, message, digestmod=hashlib.sha256).digest()).decode()
If the Client App isnât configured to use a secret
just delete the line setting the SECRET_HASH
def login_user(username_or_alias, password, client_id, client_secret, user_pool_id): try: return boto_client.initiate_auth( ClientId=client_id, AuthFlow=âADMIN_USER_PASSWORD_AUTHâ, AuthParameters={ âUSERNAMEâ: username_or_alias, âPASSWORDâ: password, âSECRET_HASHâ: get_secret_hash(username_or_alias, client_id, client_secret) } ) except botocore.exceptions.ClientError as e: return e.response
print(login_user(username, password, client_id, client_secret, user_pool_id))
</details>
### USER_SRP_AUTH
Questo scenario è simile al precedente ma **invece di inviare la password** attraverso la rete per effettuare il login, viene eseguita **un'autenticazione di sfida** (quindi nessuna password naviga nemmeno criptata attraverso la rete).\
Questo **metodo è abilitato** per impostazione predefinita.
Per **effettuare il login** è **necessario** conoscere:
- user pool id
- client id
- username
- password
- client secret (solo se l'app è configurata per utilizzare un segreto)
<details>
<summary>Codice per il login</summary>
```python
from warrant.aws_srp import AWSSRP
import os
USERNAME='xxx'
PASSWORD='yyy'
POOL_ID='us-east-1_zzzzz'
CLIENT_ID = '12xxxxxxxxxxxxxxxxxxxxxxx'
CLIENT_SECRET = 'secreeeeet'
os.environ["AWS_DEFAULT_REGION"] = "<region>"
aws = AWSSRP(username=USERNAME, password=PASSWORD, pool_id=POOL_ID,
client_id=CLIENT_ID, client_secret=CLIENT_SECRET)
tokens = aws.authenticate_user()
id_token = tokens['AuthenticationResult']['IdToken']
refresh_token = tokens['AuthenticationResult']['RefreshToken']
access_token = tokens['AuthenticationResult']['AccessToken']
token_type = tokens['AuthenticationResult']['TokenType']
REFRESH_TOKEN_AUTH & REFRESH_TOKEN
Questo metodo sarà sempre valido (non può essere disabilitato) ma è necessario avere un refresh token valido.
aws cognito-idp initiate-auth \
--client-id 3ig6h5gjm56p1ljls1prq2miut \
--auth-flow REFRESH_TOKEN_AUTH \
--region us-east-1 \
--auth-parameters 'REFRESH_TOKEN=<token>'
Codice per aggiornare
```python import boto3 import botocore import hmac import hashlib import base64client_id = â
boto_client = boto3.client(âcognito-idpâ, region_name=â
def refresh(client_id, refresh_token): try: return boto_client.initiate_auth( ClientId=client_id, AuthFlow=âREFRESH_TOKEN_AUTHâ, AuthParameters={ âREFRESH_TOKENâ: refresh_token } ) except botocore.exceptions.ClientError as e: return e.response
print(refresh(client_id, token))
</details>
### CUSTOM_AUTH
In questo caso, l'**autenticazione** verrĂ eseguita tramite l'**esecuzione di una funzione lambda**.
## Sicurezza Extra
### Sicurezza Avanzata
Per impostazione predefinita è disabilitata, ma se abilitata, Cognito potrebbe essere in grado di **trovare takeover di account**. Per ridurre la probabilità , dovresti accedere da una **rete all'interno della stessa città , utilizzando lo stesso user agent** (e IP se possibile)**.**
### **MFA Ricorda dispositivo**
Se l'utente accede dallo stesso dispositivo, la MFA potrebbe essere bypassata, quindi prova ad accedere dallo stesso browser con gli stessi metadati (IP?) per cercare di bypassare la protezione MFA.
## Ruoli IAM dei Gruppi di User Pool
Ă possibile aggiungere **utenti ai gruppi di User Pool** che sono correlati a uno **IAM role**.\
Inoltre, **gli utenti** possono essere assegnati a **piĂš di 1 gruppo con diversi IAM role** associati.
Nota che anche se un gruppo è all'interno di un gruppo con un IAM role associato, per poter accedere alle credenziali IAM di quel gruppo è necessario che il **User Pool sia fidato da un Identity Pool** (e conoscere i dettagli di quel Identity Pool).
Un altro requisito per ottenere il **ruolo IAM indicato nell'IdToken** quando un utente è autenticato nel User Pool (`aws cognito-idp initiate-auth...`) è che il **provider di autenticazione Identity Provider** deve indicare che il **ruolo deve essere selezionato dal token.**
<figure><img src="../../../../images/image (250).png" alt=""><figcaption></figcaption></figure>
I **ruoli** a cui un utente ha accesso sono **all'interno dell'`IdToken`**, e un utente può **selezionare quale ruolo desidera le credenziali** con il **`--custom-role-arn`** da `aws cognito-identity get-credentials-for-identity`.\
Tuttavia, se l'**opzione predefinita** è quella **configurata** (`use default role`), e provi ad accedere a un ruolo dall'IdToken, riceverai un'**errore** (ed è per questo che è necessaria la configurazione precedente):
An error occurred (InvalidParameterException) when calling the GetCredentialsForIdentity operation: Only SAML providers and providers with RoleMappings support custom role ARN.
> [!WARNING]
> Nota che il ruolo assegnato a un **User Pool Group** deve essere **accessibile dal Provider di IdentitĂ ** che **si fida del User Pool** (poichĂŠ le **credenziali di sessione del ruolo IAM verranno ottenute da esso**).
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "us-east-1:2361092e-9db6-a876-1027-10387c9de439"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}js
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
HackTricks Cloud

