Cognito User Pools
Tip
Ucz się & ćwicz AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Wspieraj HackTricks
- Sprawdź subscription plans!
- Dołącz do 💬 Discord group lub telegram group lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Podziel się hacking tricks, zgłaszając PRy do HackTricks i HackTricks Cloud github repos.
Podstawowe informacje
User pool to katalog użytkowników w Amazon Cognito. Dzięki user pool, Twoi użytkownicy mogą zalogować się do Twojej aplikacji internetowej lub mobilnej za pośrednictwem Amazon Cognito, lub federować przez dostawcę tożsamości (IdP) zewnętrznego. Niezależnie od tego, czy Twoi użytkownicy logują się bezpośrednio, czy przez stronę trzecią, wszyscy członkowie user pool mają profil katalogu, do którego możesz uzyskać dostęp za pośrednictwem SDK.
User pools oferują:
- Usługi rejestracji i logowania.
- Wbudowany, dostosowywalny interfejs użytkownika do logowania użytkowników.
- Logowanie społecznościowe za pomocą Facebooka, Google, Logowanie z Amazon oraz Logowanie z Apple, a także przez dostawców tożsamości SAML i OIDC z Twojego user pool.
- Zarządzanie katalogiem użytkowników i profilami użytkowników.
- Funkcje bezpieczeństwa, takie jak uwierzytelnianie wieloskładnikowe (MFA), kontrole dla skompromitowanych poświadczeń, ochrona przed przejęciem konta oraz weryfikacja telefonu i e-maila.
- Dostosowane przepływy pracy i migracja użytkowników za pomocą wyzwalaczy AWS Lambda.
Kod źródłowy aplikacji zazwyczaj zawiera również ID user pool oraz ID aplikacji klienckiej, (a czasami sekret aplikacji?), które są potrzebne do logowania użytkownika do Cognito User Pool.
Potencjalne ataki
- Rejestracja: Domyślnie użytkownik może zarejestrować się samodzielnie, więc mógłby stworzyć konto dla siebie.
- Enumeracja użytkowników: Funkcjonalność rejestracji może być używana do znajdowania nazw użytkowników, które już istnieją. Ta informacja może być przydatna do ataku brute-force.
- Brute-force logowania: W sekcji Uwierzytelnianie masz wszystkie metody, które użytkownik ma do logowania, możesz spróbować je brutalnie przetestować, aby znaleźć ważne poświadczenia.
Narzędzia do pentestingu
- Pacu, teraz zawiera moduły
cognito__enumicognito__attack, które automatyzują enumerację wszystkich zasobów Cognito w koncie i oznaczają słabe konfiguracje, atrybuty użytkowników używane do kontroli dostępu itp., a także automatyzują tworzenie użytkowników (w tym wsparcie dla MFA) oraz eskalację uprawnień na podstawie modyfikowalnych atrybutów niestandardowych, używalnych poświadczeń puli tożsamości, ról, które można przyjąć w tokenach id itp.
Aby uzyskać opis funkcji modułów, zobacz część 2 postu na blogu. Aby uzyskać instrukcje instalacji, zobacz główną stronę 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 to narzędzie CLI w Pythonie, które implementuje różne ataki na Cognito, w tym niechciane tworzenie kont i oracle kont. Sprawdź ten link po więcej informacji.
# Install
pip install cognito-scanner
# Run
cognito-scanner --help
- CognitoAttributeEnum: Ten skrypt umożliwia enumerację ważnych atrybutów dla użytkowników.
python cognito-attribute-enu.py -client_id 16f1g98bfuj9i0g3f8be36kkrl
Rejestracja
User Pools pozwala domyślnie na rejestrowanie nowych użytkowników.
aws cognito-idp sign-up --client-id <client-id> \
--username <username> --password <password> \
--region <region> --no-sign-request
Jeśli ktokolwiek może się zarejestrować
Możesz napotkać błąd wskazujący, że musisz podać więcej szczegółów dotyczących użytkownika:
An error occurred (InvalidParameterException) when calling the SignUp operation: Attributes did not conform to the schema: address: The attribute is required
Możesz dostarczyć potrzebne szczegóły w formacie JSON, takim jak:
--user-attributes '[{"Name": "email", "Value": "carlospolop@gmail.com"}, {"Name":"gender", "Value": "M"}, {"Name": "address", "Value": "street"}, {"Name": "custom:custom_name", "Value":"supername&\"*$"}]'
Możesz również użyć tej funkcjonalności do enumeracji istniejących użytkowników. Oto komunikat o błędzie, gdy użytkownik o tej nazwie już istnieje:
An error occurred (UsernameExistsException) when calling the SignUp operation: User already exists
Note
Zauważ w poprzedniej komendzie, jak niestandardowe atrybuty zaczynają się od “custom:”.
Również wiedz, że podczas rejestracji nie możesz tworzyć nowych niestandardowych atrybutów dla użytkownika. Możesz tylko przypisać wartość do domyślnych atrybutów (nawet jeśli nie są wymagane) oraz określonych niestandardowych atrybutów.
Lub po prostu, aby sprawdzić, czy identyfikator klienta istnieje. Oto błąd, jeśli identyfikator klienta nie istnieje:
An error occurred (ResourceNotFoundException) when calling the SignUp operation: User pool client 3ig612gjm56p1ljls1prq2miut does not exist.
Jeśli tylko administrator może rejestrować użytkowników
Znajdziesz ten błąd i nie będziesz mógł zarejestrować ani enumerować użytkowników:
An error occurred (NotAuthorizedException) when calling the SignUp operation: SignUp is not permitted for this user pool
Weryfikacja rejestracji
Cognito pozwala na weryfikację nowego użytkownika poprzez potwierdzenie jego adresu e-mail lub numeru telefonu. Dlatego podczas tworzenia użytkownika zazwyczaj będziesz musiał podać przynajmniej nazwę użytkownika i hasło oraz adres e-mail i/lub numer telefonu. Po prostu ustaw jeden który kontrolujesz, aby otrzymać kod do weryfikacji nowo utworzonego konta użytkownika w ten sposób:
aws cognito-idp confirm-sign-up --client-id <cliet_id> \
--username aasdasd2 --confirmation-code <conf_code> \
--no-sign-request --region us-east-1
Warning
Nawet jeśli wygląda na to, że możesz użyć tego samego adresu e-mail i numeru telefonu, gdy musisz zweryfikować utworzonego użytkownika, Cognito będzie narzekać na użycie tych samych informacji i nie pozwoli ci zweryfikować konta.
Eskalacja uprawnień / Aktualizacja atrybutów
Domyślnie użytkownik może zmienić wartość swoich atrybutów za pomocą czegoś takiego:
aws cognito-idp update-user-attributes \
--region us-east-1 --no-sign-request \
--user-attributes Name=address,Value=street \
--access-token <access token>
Privesc atrybutów niestandardowych
Caution
Możesz znaleźć atrybuty niestandardowe używane (takie jak
isAdmin), ponieważ domyślnie możesz zmieniać wartości swoich własnych atrybutów, co może pozwolić ci na eskalację uprawnień poprzez zmianę wartości samodzielnie!
Privesc modyfikacji e-maila/nazwy użytkownika
Możesz użyć tego do modyfikacji e-maila i numeru telefonu użytkownika, ale wtedy, nawet jeśli konto pozostaje zweryfikowane, te atrybuty są ustawione w statusie nieweryfikowanym (musisz je zweryfikować ponownie).
Warning
Nie będziesz mógł zalogować się za pomocą e-maila lub numeru telefonu dopóki ich nie zweryfikujesz, ale będziesz mógł zalogować się za pomocą nazwy użytkownika.
Zauważ, że nawet jeśli e-mail został zmodyfikowany i niezweryfikowany, pojawi się w tokenie ID w poluemail_verifiedbędzie fałszywe, ale jeśli aplikacja nie sprawdza tego, możesz podszyć się pod innych użytkowników.
Ponadto, zauważ, że możesz wpisać cokolwiek w pole
namepo prostu modyfikując atrybut nazwy. Jeśli aplikacja sprawdza to pole z jakiegoś powodu zamiast
W każdym razie, jeśli z jakiegoś powodu zmieniłeś swój e-mail na nowy, do którego masz dostęp, możesz potwierdzić e-mail za pomocą kodu, który otrzymałeś na ten adres e-mail:
aws cognito-idp verify-user-attribute \
--access-token <access_token> \
--attribute-name email --code <code> \
--region <region> --no-sign-request
Użyj phone_number zamiast email, aby zmienić/weryfikować nowy numer telefonu.
Note
Administrator może również włączyć opcję logowania za pomocą preferowanej nazwy użytkownika. Należy pamiętać, że nie będziesz mógł zmienić tej wartości na dowolną nazwę użytkownika lub preferred_username, która jest już używana do podszywania się pod innego użytkownika.
Przywracanie/Zmiana Hasła
Możliwe jest odzyskanie hasła, znając nazwę użytkownika (lub akceptowany jest email lub telefon), a dostęp do niego będzie możliwy, ponieważ kod zostanie tam wysłany:
aws cognito-idp forgot-password \
--client-id <client_id> \
--username <username/email/phone> --region <region>
Note
Odpowiedź serwera zawsze będzie pozytywna, jakby nazwa użytkownika istniała. Nie możesz użyć tej metody do enumeracji użytkowników
Za pomocą kodu możesz zmienić hasło na:
aws cognito-idp confirm-forgot-password \
--client-id <client_id> \
--username <username> \
--confirmation-code <conf_code> \
--password <pwd> --region <region>
Aby zmienić hasło, musisz znać poprzednie hasło:
aws cognito-idp change-password \
--previous-password <value> \
--proposed-password <value> \
--access-token <value>
Uwierzytelnianie
Pula użytkowników obsługuje różne sposoby uwierzytelniania. Jeśli masz nazwa użytkownika i hasło, obsługiwane są również różne metody logowania.
Ponadto, gdy użytkownik jest uwierzytelniony w Puli, przyznawane są 3 typy tokenów: Token ID, Token dostępu i Token odświeżania.
- Token ID: Zawiera roszczenia dotyczące tożsamości uwierzytelnionego użytkownika, takie jak
name,emailiphone_number. Token ID może być również używany do uwierzytelniania użytkowników w serwerach zasobów lub aplikacjach serwerowych. Musisz zweryfikować podpis tokena ID, zanim będziesz mógł zaufać jakimkolwiek roszczeniom wewnątrz tokena ID, jeśli używasz go w aplikacjach zewnętrznych. - Token ID to token, który zawiera wartości atrybutów użytkownika, nawet te niestandardowe.
- Token dostępu: Zawiera roszczenia dotyczące uwierzytelnionego użytkownika, listę grup użytkownika oraz listę zakresów. Celem tokena dostępu jest autoryzacja operacji API w kontekście użytkownika w puli użytkowników. Na przykład, możesz użyć tokena dostępu, aby przyznać swojemu użytkownikowi dostęp do dodawania, zmieniania lub usuwania atrybutów użytkownika.
- Token odświeżania: Dzięki tokenom odświeżania możesz uzyskać nowe tokeny ID i tokeny dostępu dla użytkownika, dopóki token odświeżania jest ważny. Domyślnie token odświeżania wygasa 30 dni po zalogowaniu się użytkownika do puli użytkowników. Gdy tworzysz aplikację dla swojej puli użytkowników, możesz ustawić czas wygaśnięcia tokena odświeżania aplikacji na dowolną wartość między 60 minutami a 10 latami.
ADMIN_NO_SRP_AUTH & ADMIN_USER_PASSWORD_AUTH
To jest przepływ uwierzytelniania po stronie serwera:
- Aplikacja po stronie serwera wywołuje operację API
AdminInitiateAuth(zamiastInitiateAuth). Ta operacja wymaga poświadczeń AWS z uprawnieniami, które obejmującognito-idp:AdminInitiateAuthicognito-idp:AdminRespondToAuthChallenge. Operacja zwraca wymagane parametry uwierzytelniania. - Po uzyskaniu parametrów uwierzytelniania przez aplikację po stronie serwera, wywołuje operację API
AdminRespondToAuthChallenge. Operacja APIAdminRespondToAuthChallengekończy się sukcesem tylko wtedy, gdy dostarczysz poświadczenia AWS.
Ta metoda NIE jest włączona domyślnie.
Aby zalogować się, musisz znać:
- identyfikator puli użytkowników
- identyfikator klienta
- nazwę użytkownika
- hasło
- sekret klienta (tylko jeśli aplikacja jest skonfigurowana do używania sekretu)
Note
Aby móc zalogować się tą metodą, ta aplikacja musi zezwalać na logowanie z
ALLOW_ADMIN_USER_PASSWORD_AUTH.
Ponadto, aby wykonać tę akcję, potrzebujesz poświadczeń z uprawnieniamicognito-idp:AdminInitiateAuthicognito-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
Kod do logowania
```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
Ta metoda to kolejny prosty i **tradycyjny proces uwierzytelniania użytkownika i hasła**. Zaleca się **migrację tradycyjnej** metody uwierzytelniania **do Cognito** i **zaleca się** następnie **wyłączenie** jej oraz **użycie** metody **ALLOW_USER_SRP_AUTH** zamiast (ponieważ ta nigdy nie przesyła hasła przez sieć).\
Ta **metoda NIE jest włączona** domyślnie.
Główna **różnica** w porównaniu do **poprzedniej metody uwierzytelniania** w kodzie polega na tym, że **nie musisz znać identyfikatora puli użytkowników** i że **nie potrzebujesz dodatkowych uprawnień** w Cognito User Pool.
Aby **zalogować się**, musisz znać:
- identyfikator klienta
- nazwę użytkownika
- hasło
- tajny klucz klienta (tylko jeśli aplikacja jest skonfigurowana do używania tajnego klucza)
> [!NOTE]
> Aby **móc zalogować się tą metodą**, ta aplikacja musi zezwalać na logowanie z 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
Kod Python do logowania
```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
Ten scenariusz jest podobny do poprzedniego, ale **zamiast wysyłać hasło** przez sieć, aby się zalogować, **przeprowadzana jest autoryzacja wyzwania** (więc żadne hasło nie jest przesyłane, nawet w formie zaszyfrowanej przez sieć).\
Ta **metoda jest włączona** domyślnie.
Aby **zalogować się**, musisz znać:
- identyfikator puli użytkowników
- identyfikator klienta
- nazwę użytkownika
- hasło
- sekret klienta (tylko jeśli aplikacja jest skonfigurowana do używania sekretu)
<details>
<summary>Code to 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
Ta metoda zawsze będzie ważna (nie można jej wyłączyć), ale musisz mieć ważny token odświeżania.
aws cognito-idp initiate-auth \
--client-id 3ig6h5gjm56p1ljls1prq2miut \
--auth-flow REFRESH_TOKEN_AUTH \
--region us-east-1 \
--auth-parameters 'REFRESH_TOKEN=<token>'
Kod do odświeżenia
```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
W tym przypadku **uwierzytelnianie** będzie przeprowadzane poprzez **wykonanie funkcji lambda**.
## Dodatkowe zabezpieczenia
### Zaawansowane zabezpieczenia
Domyślnie jest wyłączone, ale jeśli jest włączone, Cognito może być w stanie **znaleźć przejęcia konta**. Aby zminimalizować prawdopodobieństwo, powinieneś logować się z **sieci w tym samym mieście, używając tego samego agenta użytkownika** (i IP, jeśli to możliwe)**.**
### **MFA Pamiętaj urządzenie**
Jeśli użytkownik loguje się z tego samego urządzenia, MFA może być ominięte, dlatego spróbuj zalogować się z tej samej przeglądarki z tymi samymi metadanymi (IP?), aby spróbować obejść ochronę MFA.
## Role IAM grup użytkowników
Możliwe jest dodanie **użytkowników do grupy User Pool**, które są związane z jedną **rolą IAM**.\
Ponadto, **użytkownicy** mogą być przypisani do **więcej niż 1 grupy z różnymi rolami IAM**.
Zauważ, że nawet jeśli grupa znajduje się w grupie z przypisaną rolą IAM, aby móc uzyskać dostęp do poświadczeń IAM tej grupy, konieczne jest, aby **User Pool był zaufany przez Identity Pool** (i znał szczegóły tego Identity Pool).
Innym wymogiem, aby uzyskać **rolę IAM wskazaną w IdToken**, gdy użytkownik jest uwierzytelniony w User Pool (`aws cognito-idp initiate-auth...`), jest to, że **dostawca uwierzytelniania Identity Provider** musi wskazać, że **rola musi być wybierana z tokena.**
<figure><img src="../../../../images/image (250).png" alt=""><figcaption></figcaption></figure>
**Role**, do których użytkownik ma dostęp, są **w `IdToken`**, a użytkownik może **wybrać, dla której roli chciałby uzyskać poświadczenia** za pomocą **`--custom-role-arn`** z `aws cognito-identity get-credentials-for-identity`.\
Jednak jeśli **domyślna opcja** jest tą **skonfigurowaną** (`use default role`), a ty próbujesz uzyskać dostęp do roli z IdToken, otrzymasz **błąd** (dlatego potrzebna jest wcześniejsza konfiguracja):
An error occurred (InvalidParameterException) when calling the GetCredentialsForIdentity operation: Only SAML providers and providers with RoleMappings support custom role ARN.
> [!WARNING]
> Zauważ, że rola przypisana do **User Pool Group** musi być **dostępna dla Dostawcy Tożsamości**, który **ufa User Pool** (ponieważ **poświadczenia sesji roli IAM będą uzyskiwane z niego**).
```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
Ucz się & ćwicz AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Wspieraj HackTricks
- Sprawdź subscription plans!
- Dołącz do 💬 Discord group lub telegram group lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Podziel się hacking tricks, zgłaszając PRy do HackTricks i HackTricks Cloud github repos.
HackTricks Cloud

