Cognito User Pools

Nauka hakowania AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Podstawowe informacje

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ć za pośrednictwem dostawcy tożsamości zewnętrznej (IdP). Bez względu na to, czy użytkownicy logują się bezpośrednio czy za pośrednictwem strony trzeciej, wszyscy członkowie puli użytkowników mają profil katalogowy, do którego można uzyskać dostęp za pomocą SDK.

Pule użytkowników zapewniają:

  • Usługi rejestracji i logowania.

  • Wbudowany, dostosowywalny interfejs użytkownika do logowania użytkowników.

  • Logowanie za pomocą mediów społecznościowych takich jak Facebook, Google, Logowanie za pomocą Amazona i Logowanie za pomocą Apple, oraz za pomocą 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 zabezpieczeń takie jak uwierzytelnianie wieloskładnikowe (MFA), sprawdzanie 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ż identyfikator puli użytkowników i identyfikator aplikacji klienckiej, (a czasami sekret aplikacji?) które są potrzebne do zalogowania się do puli użytkowników Cognito.

Potencjalne ataki

  • Rejestracja: Domyślnie użytkownik może się zarejestrować, więc mógłby utworzyć użytkownika dla siebie.

  • Wyliczanie użytkowników: Funkcjonalność rejestracji może być wykorzystana do znalezienia nazw użytkowników, które już istnieją. Te informacje mogą być przydatne do ataku metodą brutalnej siły.

  • Atak brutalnej siły logowania: W sekcji Uwierzytelnianie znajdziesz wszystkie metody, których użytkownik musi użyć do zalogowania się, możesz spróbować je atakować metodą brutalnej siły, aby znaleźć poprawne poświadczenia.

Narzędzia do testowania penetracyjnego

  • Pacu, framework eksploatacji AWS, teraz zawiera moduły "cognito__enum" i "cognito__attack", które automatyzują wyliczanie wszystkich zasobów Cognito w koncie i flagują słabe konfiguracje, atrybuty użytkownika używane do kontroli dostępu, itp., oraz automatyzują tworzenie użytkownika (w tym obsługę MFA) i eskalację uprawnień na podstawie modyfikowalnych niestandardowych atrybutów, użytecznych poświadczeń puli tożsamości, ról do przyjęcia 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.

Użycie

Przykładowe użycie ataku cognito__attack w celu próby utworzenia użytkownika i wszystkich wektorów eskalacji uprawnień przeciwko określonej puli tożsamości i klientowi puli użytkowników:

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

Przykładowe użycie cognito__enum do zebrania wszystkich pul użytkowników, klientów pul użytkowników, pul tożsamości, użytkowników itp. widocznych w bieżącym koncie AWS:

Pacu (new:test) > run cognito__enum
  • Cognito Scanner to narzędzie CLI napisane w języku Python, które implementuje różne ataki na Cognito, w tym niechciane tworzenie kont i konto oracle.

Instalacja

$ pip install cognito-scanner

Użycie

$ cognito-scanner --help

Dla dalszych informacji sprawdź https://github.com/padok-team/cognito-scanner

Rejestracja

Pule użytkowników domyślnie umożliwia rejestrację nowych użytkowników.

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

Jeśli każdy może się zarejestrować

Możesz napotkać błąd wskazujący, że musisz podac 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 podać potrzebne szczegóły za pomocą JSON, na przykład:

--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 funkcji do wyliczenia istniejących użytkowników. To jest komunikat błędu, gdy użytkownik o takiej 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:". Pamiętaj również, że podczas rejestracji nie możesz tworzyć nowych niestandardowych atrybutów dla użytkownika. Możesz jedynie przypisać wartość do domyślnych atrybutów (nawet jeśli nie są one wymagane) oraz określonych atrybutów niestandardowych.

Lub po prostu, aby sprawdzić, czy identyfikator klienta istnieje. To jest 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

Błąd ten spowoduje, że nie będziesz mógł zarejestrować ani wyliczyć użytkowników:

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

Weryfikacja rejestracji

Cognito umożliwia weryfikację nowego użytkownika poprzez zweryfikowanie jego adresu e-mail lub numeru telefonu. Dlatego podczas tworzenia użytkownika zazwyczaj będziesz musiał podać co najmniej nazwę użytkownika i hasło oraz adres e-mail i/lub numer telefonu. Ustaw jedno które kontrolujesz, aby otrzymać kod do weryfikacji twojego 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 zgłosi problem z użyciem tych samych informacji i nie pozwoli na weryfikację konta.

Eskalacja uprawnień / Aktualizacja atrybutów

Domyślnie użytkownik może zmieniać wartość swoich atrybutów za pomocą:

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

Przywileje podnoszenia atrybutów niestandardowych

Możesz znaleźć używane atrybuty niestandardowe (takie jak isAdmin), ponieważ domyślnie możesz zmieniać wartości swoich własnych atrybutów, możesz podnieść uprawnienia zmieniając wartość samodzielnie!

Przywileje modyfikacji e-maila/nazwy użytkownika

Możesz użyć tego do modyfikacji adresu e-mail i numeru telefonu użytkownika, ale nawet jeśli konto pozostaje zweryfikowane, te atrybuty są ustawione w stanie niezweryfikowanym (musisz je zweryfikować ponownie).

Nie będziesz w stanie zalogować się za pomocą adresu e-mail 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 adres e-mail został zmodyfikowany i nie został zweryfikowany, pojawi się on w Tokenie ID wewnątrz pola email i pole email_verified będzie false, ale jeśli aplikacja nie sprawdza tego, możesz podawać się za innych użytkowników.

Ponadto, zauważ, że możesz umieścić cokolwiek w polu name po prostu modyfikując atrybut nazwy. Jeśli aplikacja sprawdza to pole z jakiegoś powodu zamiast email (lub jakiegokolwiek innego atrybutu), możesz podawać się za innych użytkowników.

W każdym razie, jeśli z jakiegoś powodu zmieniłeś swój adres e-mail na przykład na nowy, możesz uzyskać dostęp, potwierdzając e-mail za pomocą otrzymanego w nim kodu:

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 do zmiany/weryfikacji nowego numeru telefonu.

Administrator może również włączyć opcję logowania za pomocą preferowanego nazwy użytkownika. Zauważ, że nie będziesz mógł zmienić tej wartości na żaden nazwa użytkownika lub preferred_username, który jest już używany do podszywania się pod innego użytkownika.

Odzyskiwanie/Zmiana Hasła

Możliwe jest odzyskanie hasła, znając jedynie nazwę użytkownika (lub akceptowany jest email lub telefon) i mając do niego dostęp, 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żna użyć tej metody do wyliczenia użytkowników.

Z kodem można 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 nazwę użytkownika i hasło, istnieją również różne obsługiwane metody logowania. Ponadto, gdy użytkownik jest uwierzytelniony w puli, są udostępniane 3 rodzaje tokenów: Token ID, Token dostępu i Token odświeżania.

  • Token ID: Zawiera twierdzenia dotyczące tożsamości uwierzytelnionego użytkownika, takie jak imię, e-mail i numer telefonu. Token ID można również użyć do uwierzytelniania użytkowników w serwerach zasobów lub aplikacjach serwerowych. Musisz zweryfikować podpis tokena ID, zanim będziesz mógł ufać jakimkolwiek twierdzeniom 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 twierdzenia dotyczące uwierzytelnionego użytkownika, listę grup użytkownika i 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ć tokenu dostępu do udzielenia użytkownikowi dostępu do dodawania, zmiany lub usuwania atrybutów użytkownika.

  • Token odświeżania: Dzięki tokenom odświeżania możesz uzyskać nowe tokeny ID i dostępu dla użytkownika, dopóki token odświeżania jest nieważny. Domyślnie token odświeżania wygasa 30 dni po zalogowaniu się użytkownika do puli użytkowników. Podczas tworzenia aplikacji dla puli użytkowników możesz ustawić wygaśnięcie 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 (zamiast InitiateAuth). Ta operacja wymaga poświadczeń AWS z uprawnieniami, które obejmują cognito-idp:AdminInitiateAuth i cognito-idp:AdminRespondToAuthChallenge. Operacja zwraca wymagane parametry uwierzytelniania.

  • Po uzyskaniu aplikacja po stronie serwera parametrów uwierzytelniania, wywołuje operację API AdminRespondToAuthChallenge. Operacja API AdminRespondToAuthChallenge udaje się tylko wtedy, gdy podasz 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życia sekretu)

Aby móc zalogować się tą metodą, aplikacja musi zezwalać na logowanie za pomocą ALLOW_ADMIN_USER_PASSWORD_AUTH. Ponadto, aby wykonać tę czynność, 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 przepływ uwierzytelniania użytkownika i hasła**. Zaleca się **migrację tradycyjnej** metody uwierzytelniania **do Cognito** i **zaleca się** następnie **wyłączenie** jej i **użycie** metody **ALLOW\_USER\_SRP\_AUTH** (ponieważ ta nigdy nie wysyła hasła przez sieć).\
Ta **metoda NIE jest włączona** domyślnie.

Główną **różnicą** w **porównaniu z poprzednią metodą uwierzytelniania** w kodzie jest to, że **nie musisz znać identyfikatora puli użytkowników** i **nie potrzebujesz dodatkowych uprawnień** w puli użytkowników Cognito.

Aby **zalogować się**, musisz znać:

* identyfikator klienta
* nazwę użytkownika
* hasło
* sekret klienta (tylko jeśli aplikacja jest skonfigurowana do użycia sekretu)

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

Aby **możliwe było zalogowanie się tą metodą**, aplikacja musi zezwalać na logowanie za pomocą 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

AUTORYZACJA_ZA_POMOCĄ_TOKENA_ODŚWIEŻANIA I TOKEN_ODŚWIEŻANIA

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