Cognito User Pools

Support HackTricks

Basic Information

Pula użytkowników to katalog użytkowników w Amazon Cognito. Dzięki puli użytkowników, 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 puli użytkowników mają profil katalogu, do którego możesz uzyskać dostęp za pośrednictwem SDK.

Pule użytkowników 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 i Logowanie z Apple, oraz przez dostawców tożsamości SAML i OIDC z Twojej puli użytkowników.

  • Zarządzanie katalogiem użytkowników i profilami użytkowników.

  • Funkcje bezpieczeństwa, takie jak uwierzytelnianie wieloskładnikowe (MFA), kontrole dotyczące 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 puli użytkowników oraz ID aplikacji klienckiej, (a czasami sekret aplikacji?), które są potrzebne do logowania użytkownika do puli użytkowników Cognito.

Potential attacks

  • Rejestracja: Domyślnie użytkownik może zarejestrować się samodzielnie, więc może stworzyć konto dla siebie.

  • Enumaracja 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ć przeprowadzić atak brute-force, aby znaleźć ważne poświadczenia.

Tools for pentesting

  • Pacu, teraz zawiera moduły cognito__enum i cognito__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 MFA) oraz eskalację uprawnień na podstawie modyfikowalnych atrybutów niestandardowych, używalnych poświadczeń z 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
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

Zauważ w poprzedniej komendzie, jak niestandardowe atrybuty zaczynają się od "custom:". Wiedz również, ż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

Zauważysz ten błąd i nie będziesz w stanie zarejestrować ani wyenumerować użytkowników:

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

Verifying Registration

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

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 zmieniać 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

Możesz znaleźć atrybuty niestandardowe (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 nawet jeśli konto pozostaje zweryfikowane, te atrybuty są ustawione w statusie nieweryfikowanym (musisz je zweryfikować ponownie).

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 polu email, a pole email_verified bę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 name, po prostu modyfikując atrybut nazwy. Jeśli aplikacja sprawdza to pole z jakiegoś powodu zamiast email (lub jakiegokolwiek innego atrybutu), możesz być w stanie podszyć się pod innych użytkowników.

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.

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 już jest używana do podszywania się pod innego użytkownika.

Przywracanie/Zmiana Hasła

Możliwe jest przywrócenie hasła, znając nazwę użytkownika (lub akceptowany jest email lub telefon), a dostęp do niego jest konieczny, ponieważ kod zostanie tam wysłany:

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

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>

Autoryzacja

Pula użytkowników obsługuje różne sposoby autoryzacji. 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 informacje o tożsamości uwierzytelnionego użytkownika, takie jak name, email i phone_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 informacjom 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 tych niestandardowych.

  • Token dostępu: Zawiera informacje o uwierzytelnionym użytkowniku, 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ć 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 autoryzacji po stronie serwera:

  • Aplikacja po stronie serwera wywołuje operację API AdminInitiateAuth (zamiast InitiateAuth). Ta operacja wymaga poświadczeń AWS z uprawnieniami, które obejmują cognito-idp:AdminInitiateAuth i cognito-idp:AdminRespondToAuthChallenge. Operacja zwraca wymagane parametry autoryzacji.

  • Po uzyskaniu parametrów autoryzacji przez aplikację po stronie serwera, wywołuje operację API AdminRespondToAuthChallenge. Operacja API AdminRespondToAuthChallenge koń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)

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 uprawnieniami cognito-idp:AdminInitiateAuth i cognito-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 base64

client_id = "" user_pool_id = "" client_secret = "" username = "" password = ""

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 sposób 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 wysył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 puli użytkowników Cognito.

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)

<div data-gb-custom-block data-tag="hint" data-style='info'>

Aby **móc się zalogować tą metodą**, ta aplikacja musi zezwalać na logowanie z ALLOW\_USER\_PASSWORD\_AUTH.

</div>

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

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

Last updated