Cognito User Pools

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Osnovne informacije

Korisnički bazen je direktorijum korisnika u Amazon Cognitu. Sa korisničkim bazenom, vaši korisnici mogu da se prijave na vašu veb ili mobilnu aplikaciju putem Amazon Cognita, ili da federišu putem trećeg lica identiteta (IdP). Bez obzira da li se vaši korisnici prijavljuju direktno ili putem trećeg lica, svi članovi korisničkog bazena imaju profil direktorijuma kojem možete pristupiti putem SDK-a.

Korisnički bazeni pružaju:

  • Usluge registracije i prijave.

  • Ugrađeni, prilagodljivi veb korisnički interfejs za prijavu korisnika.

  • Društvenu prijavu sa Facebook-om, Google-om, Prijavom sa Amazon-om i Prijavom sa Apple-om, kao i putem SAML i OIDC provajdera identiteta iz vašeg korisničkog bazena.

  • Upravljanje korisničkim direktorijumom i korisničkim profilima.

  • Bezbednosne funkcije poput višefaktorske autentifikacije (MFA), provere kompromitovanih akreditiva, zaštite od preuzimanja naloga, i verifikacije telefonom i e-poštom.

  • Prilagođene radne tokove i migraciju korisnika putem AWS Lambda okidača.

Izvorni kod aplikacija obično takođe sadrži ID korisničkog bazena i ID klijentske aplikacije, (i ponekad tajnu aplikacije?) koje su potrebne da bi korisnik se prijavio na Cognito korisnički bazen.

Potencijalni napadi

  • Registracija: Podrazumevano, korisnik može sam sebe registrovati, 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 metodom pokušaja i greške.

  • Brute-force napad na prijavu: U odeljku Autentifikacija imate sve metode koje korisnik mora da koristi za prijavu, možete pokušati da ih napadnete metodom pokušaja i greške kako biste pronašli validne akreditive.

Alati za pentesting

  • Pacu, okvir za eksploataciju AWS-a, sada uključuje module "cognito__enum" i "cognito__attack" koji automatizuju enumeraciju svih Cognito resursa u nalogu i označavaju slabe konfiguracije, korisničke atribute korištene za kontrolu pristupa, itd., i takođe automatizuju kreiranje korisnika (uključujući podršku za MFA) i eskalaciju privilegija na osnovu modifikovanih prilagodljivih atributa, korisnih identitetskih kredencijala, uloga koje se mogu pretpostaviti u ID tokenima, itd.

Za opis funkcija modula pogledajte deo 2 blog posta. Za uputstva za instalaciju pogledajte glavnu Pacu stranicu.

Korišćenje

Primer korišćenja cognito__attack za pokušaj kreiranja korisnika i svih vektora eskalacije privilegija protiv datog identitetskog bazena i klijentske aplikacije korisničkog bazena:

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

Primer korišćenja cognito__enum alata za prikupljanje svih bazena korisnika, klijenata bazena korisnika, identitetskih bazena, korisnika, itd. vidljivih u trenutnom AWS nalogu:

Pacu (new:test) > run cognito__enum
  • Cognito Scanner je alat u CLI formatu napisan u Pythonu koji implementira različite napade na Cognito, uključujući neželjenu kreaciju naloga i orakl naloge.

Instalacija

$ pip install cognito-scanner

Upotreba

$ cognito-scanner --help

Za više informacija posetite https://github.com/padok-team/cognito-scanner

Registracija

User Pools podrazumevano omogućava registraciju novih korisnika.

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

Ako se bilo ko može registrovati

Možda ćete naići na grešku koja ukazuje da treba da pružite 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 pomoću JSON-a 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 i za enumeraciju postojećih korisnika. 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

Uočite u prethodnoj komandi kako prilagođeni atributi počinju sa "custom:". Takođe, imajte na umu da prilikom registracije ne možete kreirati nove prilagođene atribute za korisnika. Možete samo dati vrednost podrazumevanim atributima (čak i ako nisu obavezni) i specifikovanim prilagođenim atributima.

Ili samo da testirate da li postoji identifikator klijenta. Ovo je greška ako identifikator klijenta 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 nabrojite korisnike:

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

Provera registracije

Cognito omogućava verifikaciju novog korisnika putem provere njegove email adrese ili broja telefona. Stoga, prilikom kreiranja korisnika obično će vam biti potrebno barem korisničko ime i lozinka, kao i email i/ili broj telefona. Postavite onaj koji kontrolišete kako biste primili kod za verifikaciju vašeg nedavno kreiranog korisničkog računa kao što je ovde:

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

Čak i ako izgleda da možete koristiti isti email i broj telefona, kada treba da verifikujete kreiranog korisnika, Cognito će se žaliti zbog korišćenja istih informacija i neće vam dozvoliti da verifikujete nalog.

Eskalacija privilegija / Ažuriranje atributa

Podrazumevano, korisnik može izmeniti vrednost svojih atributa 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>

Eskalacija privilegija putem prilagođenih atributa

Možete naići na prilagođene atribute koji se koriste (kao što je isAdmin), jer prema podrazumevanim postavkama možete promeniti vrednosti svojih sopstvenih atributa i možda ćete moći eskalarirati privilegije menjajući vrednost sami!

Eskalacija privilegija putem izmene emaila/korisničkog imena

Možete koristiti ovo da izmenite email i broj telefona korisnika, ali čak i ako nalog ostane verifikovan, ti atributi su postavljeni u neverifikovan status (morati ćete ih ponovo verifikovati).

Nećete moći da se prijavite putem emaila ili broja telefona dok ih ne verifikujete, ali ćete moći da se prijavite koristeći korisničko ime. Imajte na umu da čak i ako je email izmenjen i nije verifikovan, pojaviće se u ID Token-u unutar polja email i polje email_verified će biti false, ali ako aplikacija ne proverava to, možete se predstaviti kao drugi korisnici.

Takođe, imajte na umu da možete staviti bilo šta unutar polja name samo menjajući atribut imena. Ako aplikacija proverava to polje iz nekog razloga umesto email (ili bilo kog drugog atributa), možda ćete moći da se predstavite kao drugi korisnici.

U svakom slučaju, ako iz nekog razloga promenite svoj email na primer na novi, možete potvrditi email sa kodom koji ste dobili 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 biste promenili/verifikovali novi broj telefona.

Administrator takođe može omogućiti opciju za prijavu sa korisničkim imenom po izboru korisnika. Imajte na umu da nećete moći promeniti ovu vrednost u bilo koje korisničko ime ili preferred_username koje već bude korišćeno kako biste se predstavili kao drugi korisnik.

Obnova/Promena Lozinke

Moguće je obnoviti lozinku samo znajući korisničko ime (ili email ili telefon su prihvaćeni) i imajući pristup tome jer će tamo biti poslat kod:

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

Odgovor servera će uvek biti pozitivan, kao da korisničko ime postoji. Ne možete koristiti ovu metodu za enumeraciju korisnika.

With the code you can change the password with:

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 znati prethodnu lozinku:

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

Autentikacija

Korisnički bazen podržava različite načine autentikacije. Ako imate korisničko ime i lozinku, podržani su i različiti metodi za prijavljivanje. Osim toga, kada je korisnik autentikovan u bazenu, dodeljuju se 3 vrste tokena: ID token, Pristupni token i Osvežavajući token.

  • ID Token: Sadrži tvrdnje o identitetu autentikovanog korisnika, kao što su ime, email i broj telefona. ID token se takođe može koristiti za autentikaciju korisnika na vašim serverskim 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.

  • Pristupni token: Sadrži tvrdnje o autentikovanom korisniku, listu grupa korisnika i listu opsega. Svrha pristupnog tokena je da autorizuje API operacije u kontekstu korisnika u korisničkom bazenu. Na primer, možete koristiti pristupni token da omogućite korisniku pristup za dodavanje, menjanje ili brisanje atributa korisnika.

  • Osvežavajući token: Pomoću osvežavajućih tokena možete dobiti nove ID tokene i pristupne tokene za korisnika dok je osvežavajući token važeći. Podrazumevano, osvežavajući token ističe 30 dana nakon što se vaš korisnik aplikacije prijavi u vaš korisnički bazen. Kada kreirate aplikaciju za svoj korisnički bazen, možete postaviti istek osvežavajućeg tokena aplikacije na bilo koju vrednost između 60 minuta i 10 godina.

ADMIN_NO_SRP_AUTH & ADMIN_USER_PASSWORD_AUTH

Ovo je autentikacioni tok na serverskoj strani:

  • Aplikacija na serverskoj strani poziva operaciju API-ja AdminInitiateAuth (umesto InitiateAuth). Ova operacija zahteva AWS akreditive sa dozvolama koje uključuju cognito-idp:AdminInitiateAuth i cognito-idp:AdminRespondToAuthChallenge. Operacija vraća potrebne parametre autentikacije.

  • Nakon što aplikacija na serverskoj strani dobije parametre autentikacije, poziva operaciju API-ja AdminRespondToAuthChallenge. Operacija API-ja AdminRespondToAuthChallenge uspeva samo kada pružite AWS akreditive.

Ovaj metod NIJE omogućen podrazumevano.

Za prijavu morate znati:

  • ID korisničkog bazena

  • ID klijenta

  • korisničko ime

  • lozinku

  • tajnu klijenta (samo ako je aplikacija konfigurisana da koristi tajnu)

Da biste mogli da se prijavite ovim metodom, aplikacija mora dozvoliti prijavu sa ALLOW_ADMIN_USER_PASSWORD_AUTH. Osim toga, da biste izvršili ovu radnju, potrebne su vam dozvole sa 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 prijavljivanje

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

Ova metoda je još jedan jednostavan i **tradicionalan tok autentikacije korisnika i lozinke**. Preporučuje se **migracija tradicionalnog** metoda autentikacije **na Cognito** i **preporučuje se** da se zatim **onemogući** i **umesto toga koristi** metoda **ALLOW\_USER\_SRP\_AUTH** (jer ta nikada ne šalje lozinku preko mreže).\
Ova **metoda NIJE omogućena** podrazumevano.

Glavna **razlika** u odnosu na **prethodnu metodu autentikacije** u kodu je da **ne morate znati ID bazena korisnika** i da **ne trebate dodatne dozvole** u bazenu korisnika Cognito.

Za **prijavu** morate znati:

* ID klijenta
* korisničko ime
* lozinku
* tajnu klijenta (samo ako je aplikacija konfigurisana da koristi tajnu)

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

Da biste **mogli da se prijavite ovom metodom**, aplikacija mora dozvoliti prijavu sa 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

Python kod za prijavljivanje```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.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>

### KORISNIK\_SRP\_AUTENTIFIKACIJA

Ovaj scenario je sličan prethodnom, ali umesto slanja lozinke preko mreže za prijavljivanje se vrši izazovna autentifikacija (tako da lozinka ne prolazi čak ni enkriptovana kroz mrežu).\
Ova **metoda je omogućena** po podrazumevanim podešavanjima.

Za **prijavljivanje** morate znati:

* ID bazena korisnika
* ID klijenta
* korisničko ime
* lozinku
* klijentski tajni ključ (samo ako je aplikacija konfigurisana da koristi tajni ključ)

<details>

<summary>Kod za prijavljivanje</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

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```python import boto3 import botocore import hmac import hashlib import base64

client_id = "" token = ''

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

U ovom slučaju će se **autentikacija** obavljati putem **izvršavanja lambda funkcije**.

## Dodatna sigurnost

### Napredna sigurnost

Podrazumevano je onemogućeno, ali ako je omogućeno, Cognito bi mogao da **pronađe preuzimanja naloga**. Da biste smanjili verovatnoću, trebalo bi da se prijavite sa **mreže unutar istog grada, koristeći isti korisnički agent** (i IP ako je moguće).

### **MFA Zapamti uređaj**

Ako se korisnik prijavi sa istog uređaja, MFA može biti zaobiđen, stoga pokušajte da se prijavite sa istim pregledačem sa istim metapodacima (IP?) kako biste pokušali da zaobiđete MFA zaštitu.

## IAM uloge grupa korisničkih bazena

Moguće je dodati **korisnike grupama korisničkih bazena** koje su povezane sa jednom **IAM ulogom**.\
Osim toga, **korisnici** mogu biti dodeljeni **više od 1 grupe sa različitim IAM ulogama**.

Imajte na umu da čak i ako je grupa unutar grupe sa priloženom IAM ulogom, da bi mogli pristupiti IAM akreditivima te grupe, potrebno je da je **Korisnički bazen poveren od strane bazena identiteta** (i da znate detalje tog bazena identiteta).

Još jedan preduslov da se **IAM uloga naznači u IdToken-u** kada se korisnik autentikuje u korisničkom bazenu (`aws cognito-idp initiate-auth...`) je da **provajder autentikacije identiteta** mora naznačiti da **uloga mora biti izabrana iz tokena**.

<figure><img src="../../../../.gitbook/assets/image (250).png" alt=""><figcaption></figcaption></figure>

**Uloge** kojima korisnik ima pristup su **unutar `IdToken`-a**, i korisnik može **izabrati za koju ulogu želi akreditive** sa **`--custom-role-arn`** iz `aws cognito-identity get-credentials-for-identity`.\
Međutim, ako je **podrazumevana opcija** ona **konfigurisana** (`koristi podrazumevanu ulogu`), i pokušate da pristupite ulozi iz IdToken-a, dobićete **grešku** (zato je potrebna prethodna konfiguracija):

<div data-gb-custom-block data-tag="code" data-overflow='wrap'>

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


</div>

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

Imajte na umu da uloga dodeljena **Grupi korisnika bazena** mora biti **dostupna od strane Provajdera identiteta** koji **veruje Bazenu korisnika** (jer će se **kredencijali sesije IAM uloge dobiti od njega**).

</div>
```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
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini da podržite HackTricks:

Last updated