Cognito User Pools
Reading time: 15 minutes
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Osnovne informacije
User pool je direktorijum korisnika u Amazon Cognito. Sa user pool-om, vaši korisnici mogu da se prijave na vašu web ili mobilnu aplikaciju putem Amazon Cognito, ili da se federišu putem treće strane provajdera identiteta (IdP). Bilo da se vaši korisnici prijavljuju direktno ili putem treće strane, svi članovi user pool-a imaju profil u direktorijumu kojem možete pristupiti putem SDK-a.
User pool-ovi pružaju:
- Usluge registracije i prijave.
- Ugrađeni, prilagodljivi web UI za prijavu korisnika.
- Društvenu prijavu putem Facebook-a, Google-a, Login with Amazon, i Sign in with Apple, kao i putem SAML i OIDC provajdera identiteta iz vašeg user pool-a.
- Upravljanje direktorijumom korisnika i korisničkim profilima.
- Bezbednosne funkcije kao što su višefaktorska autentifikacija (MFA), provere za kompromitovane akreditive, zaštita od preuzimanja naloga, i verifikacija telefona i email-a.
- Prilagođeni radni tokovi i migracija korisnika putem AWS Lambda okidača.
Izvorni kod aplikacija obično takođe sadrži user pool ID i ID klijentske aplikacije, (i ponekad tajnu aplikacije?) koji su potrebni za prijavu korisnika u Cognito User Pool.
Potencijalni napadi
- Registracija: Po defaultu, korisnik se može registrovati sam, tako da može kreirati korisnika za sebe.
- Enumeracija korisnika: Funkcionalnost registracije može se koristiti za pronalaženje korisničkih imena koja već postoje. Ove informacije mogu biti korisne za napad brute-force.
- Brute-force prijava: U Autentifikaciji imate sve metode koje korisnik može koristiti za prijavu, možete pokušati da ih brute-force-ujete da pronađete validne akreditive.
Alati za pentesting
- Pacu, sada uključuje
cognito__enum
icognito__attack
module koji automatizuju enumeraciju svih Cognito resursa u nalogu i označavaju slabe konfiguracije, atribute korisnika korišćene za kontrolu pristupa, itd., i takođe automatizuju kreiranje korisnika (uključujući podršku za MFA) i eskalaciju privilegija na osnovu modifikabilnih prilagođenih atributa, upotrebljivih akreditiva identiteta, preuzimljivih uloga u id tokenima, itd.
Za opis funkcija modula pogledajte deo 2 blog posta. Za uputstva za instalaciju pogledajte glavnu Pacu stranicu.
# 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 je CLI alat u pythonu koji implementira različite napade na Cognito, uključujući neželjeno kreiranje naloga i oracle naloga. Proverite this link za više informacija.
# Install
pip install cognito-scanner
# Run
cognito-scanner --help
- CognitoAttributeEnum: Ovaj skript omogućava enumeraciju validnih atributa za korisnike.
python cognito-attribute-enu.py -client_id 16f1g98bfuj9i0g3f8be36kkrl
Registracija
User Pools omogućava podrazumevano da se registruju novi korisnici.
aws cognito-idp sign-up --client-id <client-id> \
--username <username> --password <password> \
--region <region> --no-sign-request
Ako bilo ko može da se registruje
Možda ćete naići na grešku koja ukazuje da treba da obezbedite više detalja o korisniku:
An error occurred (InvalidParameterException) when calling the SignUp operation: Attributes did not conform to the schema: address: The attribute is required
Možete pružiti potrebne detalje sa JSON-om kao što je:
--user-attributes '[{"Name": "email", "Value": "carlospolop@gmail.com"}, {"Name":"gender", "Value": "M"}, {"Name": "address", "Value": "street"}, {"Name": "custom:custom_name", "Value":"supername&\"*$"}]'
Možete koristiti ovu funkcionalnost takođe da enumerišete postojeće korisnike. Ovo je poruka o grešci kada korisnik već postoji sa tim imenom:
An error occurred (UsernameExistsException) when calling the SignUp operation: User already exists
note
Obratite pažnju na prethodnu komandu kako prilagođene atribute počinju sa "custom:".
Takođe, znajte da prilikom registracije ne možete kreirati nove prilagođene atribute za korisnika. Možete samo dodeliti vrednost podrazumevanim atributima (čak i ako nisu obavezni) i prilagođenim atributima koji su navedeni.
Ili samo da testirate da li klijent ID postoji. Ovo je greška ako klijent-ID ne postoji:
An error occurred (ResourceNotFoundException) when calling the SignUp operation: User pool client 3ig612gjm56p1ljls1prq2miut does not exist.
Ako samo administrator može da registruje korisnike
Naći ćete ovu grešku i nećete moći da registrujete ili enumerišete korisnike:
An error occurred (NotAuthorizedException) when calling the SignUp operation: SignUp is not permitted for this user pool
Verifikacija Registracije
Cognito omogućava da verifikujete novog korisnika verifikovanjem njegovog emaila ili broja telefona. Stoga, prilikom kreiranja korisnika obično će vam biti potrebni barem korisničko ime i lozinka, kao i email i/ili broj telefona. Samo postavite jedan koji kontrolišete kako biste primili kod za verifikaciju vašeg novokreiranog korisničkog naloga na sledeći način:
aws cognito-idp confirm-sign-up --client-id <cliet_id> \
--username aasdasd2 --confirmation-code <conf_code> \
--no-sign-request --region us-east-1
warning
Čak i ako izgleda da možete koristiti istu email adresu i broj telefona, kada treba da verifikujete kreiranog korisnika, Cognito će se žaliti na korišćenje istih informacija i neće vam dozvoliti da verifikujete nalog.
Eskalacija privilegija / Ažuriranje atributa
Po defaultu, korisnik može modifikovati vrednost svojih atributa sa nečim poput:
aws cognito-idp update-user-attributes \
--region us-east-1 --no-sign-request \
--user-attributes Name=address,Value=street \
--access-token <access token>
Privesc prilagođenih atributa
caution
Možete pronaći prilagođene atribute koji se koriste (kao što je isAdmin
), jer po defaultu možete promeniti vrednosti svojih atributa, možda ćete moći da escalate privilegije menjajući vrednost sami!
Privesc modifikacije emaila/korisničkog imena
Možete koristiti ovo da modifikujete email i broj telefona korisnika, ali tada, čak i ako račun ostane kao verifikovan, ti atributi su postavljeni u status neproveren (morate ih ponovo verifikovati).
warning
Nećete moći da se prijavite sa emailom ili brojem telefona dok ih ne verifikujete, ali ćete moći da se prijavite sa korisničkim imenom.
Imajte na umu da čak i ako je email modifikovan i nije verifikovan, pojaviće se u ID Tokenu unutar email
polja i polje email_verified
će biti false, ali ako aplikacija ne proverava to, možda ćete moći da se pretvarate da ste drugi korisnici.
Pored toga, imajte na umu da možete staviti bilo šta unutar
name
polja jednostavno modifikujući atribut imena. Ako aplikacija proverava to polje iz nekog razloga umesto
U svakom slučaju, ako ste iz nekog razloga promenili svoj email, na primer na novi na koji možete pristupiti, možete potvrditi email sa kodom koji ste primili na tu email adresu:
aws cognito-idp verify-user-attribute \
--access-token <access_token> \
--attribute-name email --code <code> \
--region <region> --no-sign-request
Koristite phone_number
umesto email
da promenite/overite novi broj telefona.
note
Administrator takođe može omogućiti opciju da se prijavite sa korisničkim imenom po izboru korisnika. Imajte na umu da nećete moći da promenite ovu vrednost na bilo koje korisničko ime ili preferred_username koje se već koristi za impersonaciju drugog korisnika.
Oporavak/Promena lozinke
Moguće je oporaviti lozinku samo znajući korisničko ime (ili email ili telefon se prihvata) i imati pristup jer će kod biti poslat tamo:
aws cognito-idp forgot-password \
--client-id <client_id> \
--username <username/email/phone> --region <region>
note
Odgovor servera će uvek biti pozitivan, kao da korisničko ime postoji. Ne možete koristiti ovu metodu za enumeraciju korisnika
Sa kodom možete promeniti lozinku sa:
aws cognito-idp confirm-forgot-password \
--client-id <client_id> \
--username <username> \
--confirmation-code <conf_code> \
--password <pwd> --region <region>
Da biste promenili lozinku, potrebno je da znate prethodnu lozinku:
aws cognito-idp change-password \
--previous-password <value> \
--proposed-password <value> \
--access-token <value>
Autentifikacija
Korisnički bazen podržava različite načine autentifikacije. Ako imate korisničko ime i lozinku, takođe su podržane različite metode za prijavu.
Pored toga, kada je korisnik autentifikovan u bazenu, dodeljuju se 3 vrste tokena: ID token, Access token i Refresh token.
- ID Token: Sadrži tvrdnje o identitetu autentifikovanog korisnika, kao što su
ime
,email
ibroj_telefona
. ID token se takođe može koristiti za autentifikaciju korisnika na vašim serverskim resursima ili aplikacijama. Morate verifikovati potpis ID tokena pre nego što možete verovati bilo kojim tvrdnjama unutar ID tokena ako ga koristite u spoljnim aplikacijama. - ID Token je token koji sadrži vrednosti atributa korisnika, čak i prilagođene.
- Access Token: Sadrži tvrdnje o autentifikovanom korisniku, listu grupa korisnika i listu opsega. Svrha access tokena je da ovlasti API operacije u kontekstu korisnika u korisničkom bazenu. Na primer, možete koristiti access token da dodelite svom korisniku pristup za dodavanje, promenu ili brisanje atributa korisnika.
- Refresh Token: Sa refresh tokenima možete dobiti nove ID tokene i Access tokene za korisnika dok refresh token nije nevažeći. Po defaultu, refresh token isteče 30 dana nakon što se korisnik prijavi u vaš korisnički bazen. Kada kreirate aplikaciju za svoj korisnički bazen, možete postaviti isteka refresh tokena aplikacije na bilo koju vrednost između 60 minuta i 10 godina.
ADMIN_NO_SRP_AUTH & ADMIN_USER_PASSWORD_AUTH
Ovo je tok autentifikacije sa servera:
- Aplikacija na serveru poziva
AdminInitiateAuth
API operaciju (umestoInitiateAuth
). Ova operacija zahteva AWS kredencijale sa dozvolama koje uključujucognito-idp:AdminInitiateAuth
icognito-idp:AdminRespondToAuthChallenge
. Operacija vraća potrebne parametre za autentifikaciju. - Nakon što aplikacija na serveru ima parametre za autentifikaciju, poziva
AdminRespondToAuthChallenge
API operaciju.AdminRespondToAuthChallenge
API operacija uspeva samo kada obezbedite AWS kredencijale.
Ova metoda NIJE omogućena po defaultu.
Da biste se prijavili, potrebno je da znate:
- id korisničkog bazena
- id klijenta
- korisničko ime
- lozinku
- tajnu klijenta (samo ako je aplikacija konfigurisana da koristi tajnu)
note
Da biste mogli da se prijavite ovom metodom, ta aplikacija mora dozvoliti prijavu sa ALLOW_ADMIN_USER_PASSWORD_AUTH
.
Pored toga, da biste izvršili ovu akciju, potrebni su vam kredencijali sa dozvolama 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 za prijavu
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
Ova metoda je još jedan jednostavan i tradicionalni korisnički i lozinka autentifikacioni tok. Preporučuje se da se migrira tradicionalna autentifikacija na Cognito i preporučuje se zatim da se onemogući i koristi metoda ALLOW_USER_SRP_AUTH umesto (jer ta nikada ne šalje lozinku preko mreže).
Ova metoda NIJE omogućena po defaultu.
Glavna razlika sa prethodnom autentifikacionom metodom unutar koda je da ne morate znati ID korisničkog bazena i da ne trebate dodatne dozvole u Cognito korisničkom bazenu.
Da biste se prijavili, potrebno je da znate:
- client id
- korisničko ime
- lozinku
- client secret (samo ako je aplikacija konfigurisana da koristi tajnu)
note
Da biste mogli da se prijavite ovom metodom, ta aplikacija mora omogućiti prijavu sa ALLOW_USER_PASSWORD_AUTH.
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 kod za prijavu
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
Ovaj scenario je sličan prethodnom, ali umesto slanja lozinke kroz mrežu za prijavu, izvodi se autentifikacija izazovom (tako da lozinka ne prolazi čak ni enkriptovana kroz mrežu).
Ova metoda je omogućena po defaultu.
Da biste se prijavili, potrebno je da znate:
- id korisničkog bazena
- id klijenta
- korisničko ime
- lozinku
- klijentsku tajnu (samo ako je aplikacija konfigurisana da koristi tajnu)
Code to login
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
Ova metoda će uvek biti validna (ne može biti onemogućena) ali morate imati validan refresh token.
aws cognito-idp initiate-auth \
--client-id 3ig6h5gjm56p1ljls1prq2miut \
--auth-flow REFRESH_TOKEN_AUTH \
--region us-east-1 \
--auth-parameters 'REFRESH_TOKEN=<token>'
Kod za osvežavanje
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
U ovom slučaju, autentifikacija će se vršiti kroz izvršenje lambda funkcije.
Dodatna sigurnost
Napredna sigurnost
Podrazumevano je onemogućena, ali ako je omogućena, Cognito bi mogao da pronađe preuzimanje naloga. Da biste smanjili verovatnoću, trebali biste se prijaviti sa mreže unutar istog grada, koristeći isti korisnički agent (i IP ako je to moguće).
MFA Zapamti uređaj
Ako se korisnik prijavi sa istog uređaja, MFA može biti zaobiđena, stoga pokušajte da se prijavite iz istog pregledača sa istim metapodacima (IP?) kako biste pokušali da zaobiđete MFA zaštitu.
IAM uloge grupa korisničkog bazena
Moguće je dodati korisnike u grupe korisničkog bazena koje su povezane sa jednom IAM ulogom.
Štaviše, korisnici mogu biti dodeljeni više od 1 grupi sa različitim IAM ulogama.
Napomena: čak i ako je grupa unutar grupe sa dodeljenom IAM ulogom, da bi mogla da pristupi IAM kredencijalima te grupe, potrebno je da Korisnički bazen bude poveren Identitetskom bazenu (i da zna detalje tog Identitetskog bazena).
Još jedan zahtev za dobijanje IAM uloge navedene u IdToken-u kada je korisnik autentifikovan u Korisničkom bazenu (aws cognito-idp initiate-auth...
) je da provajder autentifikacije identiteta treba da naznači da uloga mora biti odabrana iz tokena.
.png)
Uloge kojima korisnik ima pristup su unutar IdToken
, i korisnik može odabrati koju ulogu želi za kredencijale sa --custom-role-arn
iz aws cognito-identity get-credentials-for-identity
.
Međutim, ako je podrazumevana opcija ona konfigurisana (use default role
), i pokušate da pristupite ulozi iz IdToken-a, dobićete grešku (zato je potrebna prethodna konfiguracija):
An error occurred (InvalidParameterException) when calling the GetCredentialsForIdentity operation: Only SAML providers and providers with RoleMappings support custom role ARN.
warning
Imajte na umu da uloga dodeljena User Pool Group treba da bude dostupna od strane Identity Provider koji veruje User Pool (jer će session credentials IAM uloge biti dobijeni iz nje).
{
"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
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.