Cognito User Pools

Reading time: 15 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримка HackTricks

Основна інформація

User pool - це каталог користувачів в Amazon Cognito. За допомогою user pool ваші користувачі можуть увійти до вашого веб- або мобільного додатку через Amazon Cognito, або федеративно через постачальника ідентичності (IdP). Незалежно від того, чи входять ваші користувачі безпосередньо або через третю сторону, всі члени user pool мають профіль каталогу, до якого ви можете отримати доступ через SDK.

User pools надають:

  • Послуги реєстрації та входу.
  • Вбудований, налаштовуваний веб-інтерфейс для входу користувачів.
  • Соціальний вхід через Facebook, Google, Login with Amazon, Sign in with Apple, а також через постачальників ідентичності SAML та OIDC з вашого user pool.
  • Управління каталогом користувачів та профілями користувачів.
  • Функції безпеки, такі як багатофакторна аутентифікація (MFA), перевірки на компрометовані облікові дані, захист від захоплення облікового запису, а також перевірка телефону та електронної пошти.
  • Налаштовані робочі процеси та міграція користувачів через тригери AWS Lambda.

Код джерела додатків зазвичай також міститиме ID user pool та ID клієнтського додатку, (а іноді і секрет додатку?), які потрібні для входу користувача до Cognito User Pool.

Потенційні атаки

  • Реєстрація: За замовчуванням користувач може зареєструватися самостійно, тому він може створити обліковий запис для себе.
  • Перерахування користувачів: Функціональність реєстрації може бути використана для знаходження імен користувачів, які вже існують. Ця інформація може бути корисною для атаки методом грубої сили.
  • Брутфорс входу: У розділі Аутентифікація ви маєте всі методи, які користувач має для входу, ви можете спробувати атакувати їх методом грубої сили, щоб знайти дійсні облікові дані.

Інструменти для пентестингу

  • Pacu, тепер включає модулі cognito__enum та cognito__attack, які автоматизують перерахування всіх активів Cognito в обліковому записі та позначають слабкі конфігурації, атрибути користувачів, що використовуються для контролю доступу тощо, а також автоматизують створення користувачів (включаючи підтримку MFA) та ескалацію привілеїв на основі змінних атрибутів, що підлягають модифікації, використовуваних облікових даних пулу ідентичностей, ролей, які можна прийняти в токенах ідентичності тощо.
    Для опису функцій модулів дивіться частину 2 блог-посту. Для інструкцій з установки дивіться основну сторінку Pacu.
bash
# 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 - це інструмент CLI на python, який реалізує різні атаки на Cognito, включаючи небажане створення облікових записів та обліковий оракул. Перевірте this link для отримання додаткової інформації.
bash
# Install
pip install cognito-scanner
# Run
cognito-scanner --help
  • CognitoAttributeEnum: Цей скрипт дозволяє перераховувати дійсні атрибути для користувачів.
bash
python cognito-attribute-enu.py -client_id 16f1g98bfuj9i0g3f8be36kkrl

Реєстрація

User Pools дозволяє за замовчуванням реєструвати нових користувачів.

bash
aws cognito-idp sign-up --client-id <client-id> \
--username <username> --password <password> \
--region <region> --no-sign-request

Якщо будь-хто може зареєструватися

Ви можете знайти помилку, яка вказує на те, що вам потрібно надати більше деталей про користувача:

An error occurred (InvalidParameterException) when calling the SignUp operation: Attributes did not conform to the schema: address: The attribute is required

Ви можете надати необхідні деталі у форматі JSON, наприклад:

json
--user-attributes '[{"Name": "email", "Value": "carlospolop@gmail.com"}, {"Name":"gender", "Value": "M"}, {"Name": "address", "Value": "street"}, {"Name": "custom:custom_name", "Value":"supername&\"*$"}]'

Ви також можете використовувати цю функціональність для перерахунку існуючих користувачів. Ось повідомлення про помилку, коли користувач з таким ім'ям вже існує:

An error occurred (UsernameExistsException) when calling the SignUp operation: User already exists

note

Зверніть увагу в попередній команді, як кастомні атрибути починаються з "custom:".
Також знайте, що при реєстрації ви не можете створити нові кастомні атрибути для користувача. Ви можете лише надати значення за замовчуванням атрибутам (навіть якщо вони не є обов'язковими) та кастомним атрибутам, що вказані.

Або просто для перевірки, чи існує ідентифікатор клієнта. Це помилка, якщо client-id не існує:

An error occurred (ResourceNotFoundException) when calling the SignUp operation: User pool client 3ig612gjm56p1ljls1prq2miut does not exist.

Якщо лише адміністратор може реєструвати користувачів

Ви знайдете цю помилку і не зможете зареєструвати або перерахувати користувачів:

An error occurred (NotAuthorizedException) when calling the SignUp operation: SignUp is not permitted for this user pool

Підтвердження реєстрації

Cognito дозволяє підтвердити нового користувача, перевіряючи його електронну пошту або номер телефону. Тому, при створенні користувача, зазвичай вам буде потрібно принаймні ім'я користувача та пароль, а також електронна пошта та/або номер телефону. Просто вкажіть один який ви контролюєте, щоб ви отримали код для підтвердження вашого новоствореного користувацького акаунту ось так:

bash
aws cognito-idp confirm-sign-up --client-id <cliet_id> \
--username aasdasd2 --confirmation-code <conf_code> \
--no-sign-request --region us-east-1

warning

Навіть якщо здається, що ви можете використовувати ту ж електронну пошту та номер телефону, коли вам потрібно перевірити створеного користувача, Cognito буде скаржитися на використання тієї ж інформації і не дозволить вам підтвердити обліковий запис.

Підвищення привілеїв / Оновлення атрибутів

За замовчуванням користувач може змінювати значення своїх атрибутів за допомогою чогось на зразок:

bash
aws cognito-idp update-user-attributes \
--region us-east-1 --no-sign-request \
--user-attributes Name=address,Value=street \
--access-token <access token>

Привілейоване підвищення через користувацькі атрибути

caution

Ви можете знайти кастомні атрибути (такі як isAdmin), оскільки за замовчуванням ви можете змінювати значення своїх власних атрибутів, ви можете підвищити привілеї, змінивши значення самостійно!

Привілейоване підвищення через модифікацію електронної пошти/імені користувача

Ви можете використовувати це, щоб змінити електронну пошту та номер телефону користувача, але навіть якщо обліковий запис залишається перевіреним, ці атрибути встановлюються в статус неперевіреного (вам потрібно перевірити їх знову).

warning

Ви не зможете увійти за електронною поштою або номером телефону, поки не перевірите їх, але ви зможете увійти з іменем користувача.
Зверніть увагу, що навіть якщо електронна пошта була змінена і не перевірена, вона з'явиться в ID Token у полі email і поле email_verified буде false, але якщо додаток не перевіряє це, ви можете видавати себе за інших користувачів.

Більше того, зверніть увагу, що ви можете ввести будь-що в поле name, просто змінивши атрибут name. Якщо додаток перевіряє це поле з якоїсь причини замість email (або будь-якого іншого атрибута), ви можете бути в змозі видавати себе за інших користувачів.

У будь-якому випадку, якщо з якоїсь причини ви змінили свою електронну пошту, наприклад, на нову, до якої маєте доступ, ви можете підтвердити електронну пошту за кодом, який ви отримали на цю електронну адресу:

bash
aws cognito-idp verify-user-attribute \
--access-token <access_token> \
--attribute-name email --code <code> \
--region <region> --no-sign-request

Використовуйте phone_number замість email для зміни/перевірки нового номера телефону.

note

Адміністратор також може активувати опцію входу з бажаним ім'ям користувача. Зверніть увагу, що ви не зможете змінити це значення на будь-яке ім'я користувача або бажане_ім'я, яке вже використовується для видавання себе за іншого користувача.

Відновлення/Зміна пароля

Можливо відновити пароль, просто знаючи ім'я користувача (або приймаються email або телефон), і маючи доступ до нього, оскільки код буде надіслано туди:

bash
aws cognito-idp forgot-password \
--client-id <client_id> \
--username <username/email/phone> --region <region>

note

Відповідь сервера завжди буде позитивною, ніби ім'я користувача існує. Ви не можете використовувати цей метод для перерахунку користувачів

З кодом ви можете змінити пароль за допомогою:

bash
aws cognito-idp confirm-forgot-password \
--client-id <client_id> \
--username <username> \
--confirmation-code <conf_code> \
--password <pwd> --region <region>

Щоб змінити пароль, вам потрібно знати попередній пароль:

bash
aws cognito-idp change-password \
--previous-password <value> \
--proposed-password <value> \
--access-token <value>

Аутентифікація

Пул користувачів підтримує різні способи аутентифікації. Якщо у вас є ім'я користувача та пароль, також підтримуються різні методи для входу.
Більше того, коли користувач аутентифікований у пулі, надаються 3 типи токенів: ID токен, Access токен та Refresh токен.

  • ID токен: Він містить заяви про особу аутентифікованого користувача, такі як name, email та phone_number. ID токен також можна використовувати для аутентифікації користувачів на ваших ресурсних серверах або серверних додатках. Ви повинні перевірити підпис ID токена, перш ніж довіряти будь-яким заявам всередині ID токена, якщо ви використовуєте його в зовнішніх додатках.
  • ID токен є токеном, який містить значення атрибутів користувача, навіть користувацьких.
  • Access токен: Він містить заяви про аутентифікованого користувача, список груп користувача та список обсягів. Мета Access токена полягає в тому, щоб авторизувати API операції в контексті користувача в пулі користувачів. Наприклад, ви можете використовувати Access токен, щоб надати вашому користувачу доступ до додавання, зміни або видалення атрибутів користувача.
  • Refresh токен: За допомогою Refresh токенів ви можете отримати нові ID токени та Access токени для користувача, поки Refresh токен недійсний. За замовчуванням Refresh токен закінчує термін дії через 30 днів після того, як ваш користувач увійшов у ваш пул користувачів. Коли ви створюєте додаток для вашого пулу користувачів, ви можете встановити термін дії Refresh токена додатка на будь-яке значення від 60 хвилин до 10 років.

ADMIN_NO_SRP_AUTH & ADMIN_USER_PASSWORD_AUTH

Це потік аутентифікації на стороні сервера:

  • Додаток на стороні сервера викликає AdminInitiateAuth API операцію (замість InitiateAuth). Ця операція вимагає облікові дані AWS з дозволами, які включають cognito-idp:AdminInitiateAuth та cognito-idp:AdminRespondToAuthChallenge. Операція повертає необхідні параметри аутентифікації.
  • Після того, як додаток на стороні сервера отримав параметри аутентифікації, він викликає AdminRespondToAuthChallenge API операцію. API операція AdminRespondToAuthChallenge успішно виконується лише тоді, коли ви надаєте облікові дані AWS.

Цей метод НЕ активований за замовчуванням.

Щоб увійти, вам потрібно знати:

  • id пулу користувачів
  • id клієнта
  • ім'я користувача
  • пароль
  • секрет клієнта (тільки якщо додаток налаштовано на використання секрету)

note

Щоб мати можливість увійти за допомогою цього методу, цей додаток повинен дозволяти вхід з ALLOW_ADMIN_USER_PASSWORD_AUTH.
Більше того, для виконання цієї дії вам потрібні облікові дані з дозволами cognito-idp:AdminInitiateAuth та cognito-idp:AdminRespondToAuthChallenge

python
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
Код для входу
python
import boto3
import botocore
import hmac
import hashlib
import base64


client_id = "<client-id>"
user_pool_id = "<user-pool-id>"
client_secret = "<client-secret>"
username = "<username>"
password = "<pwd>"

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

USER_PASSWORD_AUTH

Цей метод є ще одним простим і традиційним методом аутентифікації користувача та пароля. Рекомендується мігрувати традиційний метод аутентифікації до Cognito і рекомендується потім відключити його та використовувати метод ALLOW_USER_SRP_AUTH замість цього (оскільки цей метод ніколи не надсилає пароль через мережу).
Цей метод НЕ активовано за замовчуванням.

Основна різниця з попереднім методом аутентифікації в коді полягає в тому, що вам не потрібно знати ID пулу користувачів і що вам не потрібні додаткові дозволи в Cognito User Pool.

Щоб увійти, вам потрібно знати:

  • client id
  • username
  • password
  • client secret (тільки якщо додаток налаштовано на використання секрету)

note

Щоб мати можливість увійти за допомогою цього методу, цей додаток повинен дозволяти вхід за допомогою 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
Python код для входу
python
import boto3
import botocore
import hmac
import hashlib
import base64


client_id = "<client-id>"
user_pool_id = "<user-pool-id>"
client_secret = "<client-secret>"
username = "<username>"
password = "<pwd>"

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

USER_SRP_AUTH

Цей сценарій подібний до попереднього, але замість того, щоб надсилати пароль через мережу для входу, виконується аутентифікація за допомогою виклику (тобто жоден пароль не передається, навіть зашифрований через мережу).
Цей метод увімкнено за замовчуванням.

Щоб увійти, вам потрібно знати:

  • ідентифікатор пулу користувачів
  • ідентифікатор клієнта
  • ім'я користувача
  • пароль
  • секрет клієнта (тільки якщо додаток налаштовано на використання секрету)
Код для входу
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

Цей метод завжди буде дійсним (його не можна вимкнути), але вам потрібен дійсний токен оновлення.

bash
aws cognito-idp initiate-auth \
--client-id 3ig6h5gjm56p1ljls1prq2miut \
--auth-flow REFRESH_TOKEN_AUTH \
--region us-east-1 \
--auth-parameters 'REFRESH_TOKEN=<token>'
Код для оновлення
python
import boto3
import botocore
import hmac
import hashlib
import base64

client_id = "<client-id>"
token = '<token>'

boto_client = boto3.client('cognito-idp', region_name='<region>')

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

CUSTOM_AUTH

У цьому випадку автентифікація буде виконуватися через виконання функції lambda.

Додаткова безпека

Розширена безпека

За замовчуванням вона вимкнена, але якщо її увімкнути, Cognito може виявити викрадення облікових записів. Щоб зменшити ймовірність, ви повинні увійти з мережі в межах одного міста, використовуючи той же агент користувача (і IP, якщо це можливо).

MFA Запам'ятати пристрій

Якщо користувач входить з того ж пристрою, MFA може бути обійдено, тому спробуйте увійти з того ж браузера з тими ж метаданими (IP?), щоб спробувати обійти захист MFA.

Ролі IAM груп користувачів

Можна додавати користувачів до групи User Pool, які пов'язані з однією IAM роллю.
Більше того, користувачі можуть бути призначені більше ніж до 1 групи з різними прикріпленими IAM ролями.

Зверніть увагу, що навіть якщо група знаходиться всередині групи з прикріпленою IAM роллю, для того щоб мати доступ до IAM облікових даних цієї групи, потрібно, щоб User Pool був довірений Identity Pool (і знати деталі цього Identity Pool).

Ще одна вимога для отримання IAM ролі, вказаної в IdToken, коли користувач автентифікований у User Pool (aws cognito-idp initiate-auth...), полягає в тому, що постачальник автентифікації Identity Provider повинен вказати, що роль повинна бути вибрана з токена.

Ролі, до яких має доступ користувач, знаходяться всередині IdToken, і користувач може вибрати, для якої ролі він хотів би отримати облікові дані з --custom-role-arn з aws cognito-identity get-credentials-for-identity.
Однак, якщо опція за замовчуванням є тією, що сконфігурована (використовувати роль за замовчуванням), і ви намагаєтеся отримати доступ до ролі з IdToken, ви отримаєте помилку (ось чому потрібна попередня конфігурація):

An error occurred (InvalidParameterException) when calling the GetCredentialsForIdentity operation: Only SAML providers and providers with RoleMappings support custom role ARN.

warning

Зверніть увагу, що роль, призначена для Групи користувачів повинна бути доступною для Постачальника ідентичності, який довіряє Групі користувачів (оскільки облікові дані сесії IAM ролі будуть отримані з неї).

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

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримка HackTricks