mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 22:51:09 -07:00
Translated ['', 'src/pentesting-cloud/azure-security/az-basic-informatio
This commit is contained in:
+160
-86
@@ -4,7 +4,7 @@
|
||||
|
||||
## Osnovne informacije
|
||||
|
||||
Entra ID je Microsoftova cloud platforma za upravljanje identitetima i pristupom (IAM), koja služi kao osnovni sistem za autentifikaciju i autorizaciju za servise poput Microsoft 365 i Azure Resource Manager. Azure AD implementira OAuth 2.0 authorization framework i OpenID Connect (OIDC) protokol za autentifikaciju radi upravljanja pristupom resursima.
|
||||
Entra ID je Microsoft-ova cloud-based identity and access management (IAM) platforma, koja služi kao osnovni sistem za autentifikaciju i autorizaciju za servise kao što su Microsoft 365 i Azure Resource Manager. Azure AD implementira OAuth 2.0 authorization framework i OpenID Connect (OIDC) authentication protocol za upravljanje pristupom resursima.
|
||||
|
||||
### OAuth
|
||||
|
||||
@@ -13,88 +13,161 @@ Entra ID je Microsoftova cloud platforma za upravljanje identitetima i pristupom
|
||||
1. **Resource Server (RS):** Štiti resurse koje poseduje vlasnik resursa.
|
||||
2. **Resource Owner (RO):** Obično krajnji korisnik koji poseduje zaštićene resurse.
|
||||
3. **Client Application (CA):** Aplikacija koja traži pristup resursima u ime vlasnika resursa.
|
||||
4. **Authorization Server (AS):** Izdaje access tokens klijentskim aplikacijama nakon njihove autentifikacije i autorizacije.
|
||||
4. **Authorization Server (AS):** Izdaje pristupne tokene klijentskim aplikacijama nakon njihove autentikacije i autorizacije.
|
||||
|
||||
**Scopes i pristanak:**
|
||||
**Scopes i saglasnost:**
|
||||
|
||||
- **Scopes:** Granularne dozvole koje definiše resource server i koje preciziraju nivoe pristupa.
|
||||
- **Consent:** Proces kojim resource owner daje dozvolu client aplikaciji da pristupi resursima sa određenim scopes.
|
||||
- **Scopes:** Granularna dopuštenja definisana na resource server-u koja određuju nivoe pristupa.
|
||||
- **Consent:** Proces kojim vlasnik resursa daje klijentskoj aplikaciji dozvolu za pristup resursima sa određenim scope-ovima.
|
||||
|
||||
**Integracija sa Microsoft 365:**
|
||||
|
||||
- Microsoft 365 koristi Azure AD za IAM i sastoji se od više "first-party" OAuth aplikacija.
|
||||
- Ove aplikacije su duboko integrisane i često imaju međuzavisne servisne veze.
|
||||
- Da bi pojednostavio korisničko iskustvo i održao funkcionalnost, Microsoft dodeljuje "implied consent" ili "pre-consent" ovim first-party aplikacijama.
|
||||
- **Implied Consent:** Neke aplikacije su automatski **dobijaju pristup određenim scope-ovima bez izričitog odobrenja korisnika ili administratora**.
|
||||
- Ovi pre-consented scopes su obično skriveni i od korisnika i od administratora, što ih čini manje vidljivim u standardnim upravljačkim interfejsima.
|
||||
- Microsoft 365 koristi Azure AD za IAM i sastoji se iz više "first-party" OAuth aplikacija.
|
||||
- Ove aplikacije su duboko integrisane i često imaju međuzavisne servisne odnose.
|
||||
- Da bi se pojednostavio korisnički doživljaj i održala funkcionalnost, Microsoft dodeljuje "implied consent" ili "pre-consent" ovim first-party aplikacijama.
|
||||
- **Implied Consent:** Određene aplikacije su automatski **odobrene za pristup određenim scope-ovima bez eksplicitnog odobrenja korisnika ili administratora**.
|
||||
- Ovi pre-consentovani scope-ovi su obično skriveni i od korisnika i od administratora, što ih čini manje vidljivim u standardnim upravljačkim interfejsima.
|
||||
|
||||
**Tipovi klijentskih aplikacija:**
|
||||
|
||||
1. **Confidential Clients:**
|
||||
- Imaju sopstvene kredencijale (npr. lozinke ili sertifikate).
|
||||
- Mogu **sigurno da se autentifikuju** prema authorization server-u.
|
||||
- Poseduju svoje kredencijale (npr. lozinke ili sertifikate).
|
||||
- Mogu **sigurno se autentifikovati** prema authorization server-u.
|
||||
2. **Public Clients:**
|
||||
- Nemaju jedinstvene kredencijale.
|
||||
- Ne mogu se sigurno autentifikovati prema authorization server-u.
|
||||
- **Sigurnosna implikacija:** Napadač može da se lažno predstavi kao public client aplikacija prilikom zahteva za tokene, jer authorization server nema mehanizam za proveru legitimnosti aplikacije.
|
||||
- **Bezbednosna implikacija:** Napadač može da se lažno predstavlja kao public client aplikacija prilikom zahtevanja tokena, jer nema mehanizma da authorization server verifikuje legitimnost aplikacije.
|
||||
|
||||
## Autentifikacioni tokeni
|
||||
### ROPC / Password Grant
|
||||
|
||||
OAuth2 **Resource Owner Password Credentials** (**ROPC**) flow koristi direktan `POST` na `https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token` sa `grant_type=password`, `username`, `password`, `client_id`, i traženim `scope`. U Entra ID ovo je prvenstveno zanimljivo za **public clients** jer napadač može ponovo iskoristiti Microsoft first-party client IDs ili bilo koji drugi dozvoljeni public client bez potrebe za secret-om.
|
||||
```bash
|
||||
curl -X POST "https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token" \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
--data-urlencode "client_id=f05ff7c9-f75a-4acd-a3b5-f4b6a870245d" \
|
||||
--data-urlencode "client_info=1" \
|
||||
--data-urlencode "grant_type=password" \
|
||||
--data-urlencode "username=user@corp.com" \
|
||||
--data-urlencode "password=Password123!" \
|
||||
--data-urlencode "scope=https://graph.microsoft.com/.default"
|
||||
```
|
||||
If the credentials are valid and the flow is allowed, Entra can return **access tokens** and sometimes **refresh tokens** that are immediately usable against Microsoft Graph or the target resource.
|
||||
|
||||
### Klase zaobilaženja Entra ID sign-in log
|
||||
|
||||
Neki istorijski Entra ID bagovi su dozvoljavali **password validation** ili čak **full token issuance** bez generisanja očekivanog **Entra ID sign-in log** unosa. Ti slučajevi su ispravljeni, ali tehnike su i dalje korisne za razumevanje kako auth pipelines mogu zakazati na načine koji ostavljaju **downstream token use visible** dok je **upstream sign-in telemetry is absent**.
|
||||
|
||||
#### 1. Foreign-tenant endpoint for stealth password validation
|
||||
|
||||
Ako se zahtev pošalje token endpoint-u drugog tenant GUID-a, Entra može ipak proveriti da li je poslat password tačan za navedeni username pre nego što tok zakaže zato što korisnik ne postoji u tom stranom tenant-u. Istorijski je ovo omogućavalo:
|
||||
|
||||
- **Password spraying / credential validation** bez odgovarajućeg sign-in log zapisa u victim tenant-u
|
||||
- Razliku u odgovoru koja otkriva da li je password korak uspeo
|
||||
- No token issuance, ali manje telemetrije nego pri normalnom neuspelom logonu
|
||||
|
||||
#### 2. Force a post-password failure
|
||||
|
||||
Ako je parametar koji se koristi nakon credential validation nevažeći, kao što je nevažeći `client_id`, celokupna transakcija može da propadne iako je password već bio ispravan. Istorijski je ovo proizvelo prikaz neuspelog logovanja dok se krije činjenica da je pogodak password-a uspeo.
|
||||
|
||||
Šablon koji treba zapamtiti je:
|
||||
|
||||
- Password check succeeds
|
||||
- A later validation step fails
|
||||
- The log represents the final transaction state but not the successful password-validation step
|
||||
|
||||
#### 3. Trigger logging failure with oversized-but-valid values
|
||||
|
||||
Najopasnija klasa je kada zahtev ostane sintaktički važeći, autentifikacija uspe, **tokens are returned**, ali neko **logged field** bude dovoljno velik da slomi logging pipeline. Prijavljeni primeri su uključivali:
|
||||
|
||||
- Ponovljene validne scope-ove hiljadama puta, kao `openid openid openid ...`
|
||||
- Slanje predugačkog, ali i dalje prihvaćenog **User-Agent** header-a
|
||||
|
||||
Ovo ukazuje na opštu klasu problema gde:
|
||||
|
||||
1. Entra validates credentials and request syntax
|
||||
2. The token is issued successfully
|
||||
3. Logging attempts to persist a raw user-controlled field
|
||||
4. The logging write fails because of length or schema assumptions
|
||||
5. The user obtains a valid token with no corresponding sign-in record
|
||||
|
||||
Example of the repeated-scope pattern:
|
||||
```bash
|
||||
curl -X POST "https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token" \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
--data-urlencode "client_id=f05ff7c9-f75a-4acd-a3b5-f4b6a870245d" \
|
||||
--data-urlencode "client_info=1" \
|
||||
--data-urlencode "grant_type=password" \
|
||||
--data-urlencode "username=user@corp.com" \
|
||||
--data-urlencode "password=Password123!" \
|
||||
--data-urlencode "scope=$(for num in {1..10000}; do echo -n 'openid '; done)"
|
||||
```
|
||||
#### Napomena za otkrivanje / odbranu
|
||||
|
||||
Nemojte pretpostavljati da će svaka upotreba važećeg tokena imati odgovarajući Entra sign-in događaj. Prilikom istraživanja sumnjivih Graph aktivnosti, korrelirajte:
|
||||
|
||||
- **Ne-interaktivne sign-in logove**
|
||||
- **Graph Activity Logs**
|
||||
- **IP adresa**, **ID korisnika/objekta**, **identifikatori sesije/korelacije**, i **vremenske prozore**
|
||||
|
||||
Jedan praktičan metod validacije je da obuhvatite sumnjivi nevidljivi uspeh između dva normalna neuspešna logona i zatim proverite da li je očekivani niz `Failed -> Successful -> Failed` nestao srednji događaj nakon kašnjenja ingestovanja. Ako postoji downstream Graph aktivnost, ali sign-in log ne postoji, tretirajte to kao potencijalni **sign-in logging gap** ili uslov **token replay**.
|
||||
|
||||
## Authentication Tokens
|
||||
|
||||
Postoje **tri tipa tokena** koji se koriste u OIDC:
|
||||
|
||||
- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** Klijent predstavlja ovaj token resource server-u da bi **pristupio resursima**. Može se koristiti samo za specifičnu kombinaciju korisnika, klienta i resursa i **ne može biti opozvan** dok ne istekne - što je po defaultu 1 sat.
|
||||
- **ID Tokens**: Klijent prima ovaj **token od authorization server-a**. Sadrži osnovne informacije o korisniku. On je **vezan za specifičnu kombinaciju korisnika i klijenta**.
|
||||
- **Refresh Tokens**: Dodeljuje se klijentu zajedno sa access token-om. Koristi se za **dobijanje novih access i ID tokena**. Vezan je za specifičnu kombinaciju korisnika i klijenta i može biti opozvan. Podrazumevano isteknuće je **90 dana** za neaktivne refresh tokene i **nema isteka za aktivne tokene** (iz refresh token-a je moguće dobiti nove refresh tokene).
|
||||
- Refresh token bi trebalo da bude vezan za **`aud`**, za određene **scopes**, i za **tenant**, i trebao bi da može generisati access tokene samo za taj aud, scopes (i ništa više) i tenant. Međutim, to nije slučaj sa **FOCI applications tokens**.
|
||||
- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** Klijent predočuje ovaj token resource server-u da bi **pristupio resursima**. Može se koristiti samo za specifičnu kombinaciju korisnika, klijenta i resursa i **ne može biti opozvan** do isteka — to je po defaultu 1 sat.
|
||||
- **ID Tokens**: Klijent prima ovaj **token od authorization server-a**. Sadrži osnovne informacije o korisniku. **Povezan je sa specifičnom kombinacijom korisnika i klijenta**.
|
||||
- **Refresh Tokens**: Izdaju se klijentu zajedno sa access token-om. Koriste se za **dobijanje novih access i ID tokena**. Vežu se za specifičnu kombinaciju korisnika i klijenta i mogu biti opozvani. Podrazumevano vreme isteka je **90 dana** za neaktivne refresh tokene i **nema isteka za aktivne tokene** (korišćenjem refresh tokena moguće je dobiti nove refresh tokene).
|
||||
- Refresh token bi trebalo da bude vezan za **`aud`**, za neke **scopes**, i za **tenant** i trebalo bi da može da generiše access tokene samo za taj aud, te scope-ove (i ništa više) i tenant. Međutim, to nije slučaj sa **FOCI applications tokens**.
|
||||
- Refresh token je enkriptovan i samo Microsoft može da ga dekriptuje.
|
||||
- Dobijanje novog refresh token-a ne opoziva prethodni refresh token.
|
||||
- Dobijanjem novog refresh tokena se prethodni refresh token ne opoziva.
|
||||
|
||||
> [!WARNING]
|
||||
> Informacija o **conditional access** je **smeštena** unutar **JWT**. Dakle, ako zatražite **token sa dozvoljene IP adrese**, ta **IP** će biti **smeštena** u token i onda možete koristiti taj token sa **ne-dozvoljene IP adrese da pristupite resursima**.
|
||||
> Informacije za **conditional access** su **smeštene** unutar **JWT**. Dakle, ako zatražite **token sa dozvoljene IP adrese**, ta **IP** će biti **smeštena** u tokenu i onda možete koristiti taj token sa **ne-dozvoljene IP adrese da pristupite resursima**.
|
||||
|
||||
### Access Tokens "aud"
|
||||
|
||||
Polje navedeno u "aud" polju predstavlja **resource server** (aplikaciju) koja se koristi za prijavu.
|
||||
Polje označeno u "aud" polju je **resource server** (aplikacija) koja se koristi za prijavu.
|
||||
|
||||
Komanda `az account get-access-token --resource-type [...]` podržava sledeće tipove i svaki od njih će dodati specifičan "aud" u dobijeni access token:
|
||||
Komanda `az account get-access-token --resource-type [...]` podržava sledeće tipove i svaki od njih će dodati specifičan "aud" u rezultujući access token:
|
||||
|
||||
> [!CAUTION]
|
||||
> Imajte na umu da su sledeće samo API-ji koje podržava `az account get-access-token`, ali ima ih još.
|
||||
> Imajte na umu da su sledeći samo API-ji podržani od strane `az account get-access-token`, ali postoji još.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>aud examples</summary>
|
||||
<summary>primeri aud</summary>
|
||||
|
||||
- **aad-graph (Azure Active Directory Graph API)**: Koristi se za pristup legacy Azure AD Graph API-ju (deprecated), koji omogućava aplikacijama da čitaju i pišu podatke direktorijuma u Azure Active Directory (Azure AD).
|
||||
- **aad-graph (Azure Active Directory Graph API)**: Koristi se za pristup legacy Azure AD Graph API-ju (deprecated), koji omogućava aplikacijama čitanje i pisanje direktorijum podataka u Azure Active Directory (Azure AD).
|
||||
- `https://graph.windows.net/`
|
||||
|
||||
* **arm (Azure Resource Manager)**: Koristi se za upravljanje Azure resursima putem Azure Resource Manager API-ja. To uključuje operacije kao što su kreiranje, ažuriranje i brisanje resursa poput virtuelnih mašina, storage naloga i drugih.
|
||||
* **arm (Azure Resource Manager)**: Koristi se za upravljanje Azure resursima preko Azure Resource Manager API-ja. Ovo uključuje operacije poput kreiranja, ažuriranja i brisanja resursa kao što su virtuelne mašine, storage nalozi i više.
|
||||
- `https://management.core.windows.net/ or https://management.azure.com/`
|
||||
|
||||
- **batch (Azure Batch Services)**: Koristi se za pristup Azure Batch-u, servisu koji omogućava efikasno pokretanje aplikacija za paralelne i visokoperformantne računarske zadatke u cloudu.
|
||||
- **batch (Azure Batch Services)**: Koristi se za pristup Azure Batch-u, servisu koji omogućava efikasne velike paralelne i visokoperformansne kompjuterske aplikacije u cloudu.
|
||||
- `https://batch.core.windows.net/`
|
||||
|
||||
* **data-lake (Azure Data Lake Storage)**: Koristi se za interakciju sa Azure Data Lake Storage Gen1, skalabilnim servisom za skladištenje podataka i analitiku.
|
||||
* **data-lake (Azure Data Lake Storage)**: Koristi se za interakciju sa Azure Data Lake Storage Gen1, koji je skalabilan servis za skladištenje podataka i analitiku.
|
||||
- `https://datalake.azure.net/`
|
||||
|
||||
- **media (Azure Media Services)**: Koristi se za pristup Azure Media Services, koji pruža cloud-bazirane servise za obradu i isporuku video i audio sadržaja.
|
||||
- **media (Azure Media Services)**: Koristi se za pristup Azure Media Services, koji pruža cloud-bazirane servise za obradu i isporuku medija za video i audio sadržaj.
|
||||
- `https://rest.media.azure.net`
|
||||
|
||||
* **ms-graph (Microsoft Graph API)**: Koristi se za pristup Microsoft Graph API-ju, jedinstvenom endpointu za podatke iz Microsoft 365 servisa. Omogućava pristup podacima i uvidima iz servisa kao što su Azure AD, Office 365, Enterprise Mobility i Security servisi.
|
||||
* **ms-graph (Microsoft Graph API)**: Koristi se za pristup Microsoft Graph API-ju, ujedinjenom endpointu za podatke Microsoft 365 servisa. Omogućava pristup podacima i uvidima iz servisa poput Azure AD, Office 365, Enterprise Mobility i Security servisa.
|
||||
- `https://graph.microsoft.com`
|
||||
|
||||
- **oss-rdbms (Azure Open Source Relational Databases)**: Koristi se za pristup Azure Database servisima za open-source relacioni DB engine-e kao što su MySQL, PostgreSQL i MariaDB.
|
||||
- **oss-rdbms (Azure Open Source Relational Databases)**: Koristi se za pristup Azure Database servisima za open-source relacioni database engine-e kao što su MySQL, PostgreSQL i MariaDB.
|
||||
- `https://ossrdbms-aad.database.windows.net`
|
||||
|
||||
</details>
|
||||
|
||||
### Access Tokens Scopes "scp"
|
||||
|
||||
Opseg (scope) access token-a se čuva u ključu scp unutar JWT access tokena. Ovi scopes definišu čemu access token ima pristup.
|
||||
Opseg access tokena je pohranjen u scp ključu unutar access token JWT-a. Ti scope-ovi definišu čemu access token ima pristup.
|
||||
|
||||
Ako je JWT dozvoljen da kontaktira određeni API ali **nema scope** za izvršenje tražene akcije, **neće moći da izvrši akciju** sa tim JWT-om.
|
||||
Ako je JWT dozvoljen da kontaktira određeni API, ali **nema scope** za izvršenje tražene akcije, **neće moći da izvrši akciju** sa tim JWT-om.
|
||||
|
||||
### Primer: dobijanje refresh i access tokena
|
||||
### Primer dobijanja refresh i access tokena
|
||||
```python
|
||||
# Code example from https://github.com/secureworks/family-of-client-ids-research
|
||||
import msal
|
||||
@@ -144,32 +217,32 @@ scopes=["https://graph.microsoft.com/.default"],
|
||||
)
|
||||
pprint(new_azure_cli_bearer_tokens_for_graph_api)
|
||||
```
|
||||
### Ostala polja access tokena
|
||||
### Ostala polja access token-a
|
||||
|
||||
- **appid**: ID aplikacije koji je korišćen za generisanje tokena
|
||||
- **appidacr**: The Application Authentication Context Class Reference označava kako je client autentifikovan; za public client vrednost je 0, a ako je korišćen client secret vrednost je 1
|
||||
- **acr**: The Authentication Context Class Reference claim je "0" kada autentifikacija krajnjeg korisnika nije ispunila zahteve ISO/IEC 29115.
|
||||
- **amr**: Metod autentifikacije pokazuje kako je token autentifikovan. Vrednost “pwd” označava da je korišćena lozinka.
|
||||
- **groups**: Pokazuje grupe čiji je principal član.
|
||||
- **iss**: Issuer identifikuje security token service (STS) koji je generisao token. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (the uuid is the tenant ID)
|
||||
- **appid**: ID aplikacije koji se koristi za generisanje tokena
|
||||
- **appidacr**: Application Authentication Context Class Reference ukazuje kako je klijent autentifikovan; za public client vrednost je 0, a ako se koristi client secret vrednost je 1
|
||||
- **acr**: Authentication Context Class Reference tvrdnja je "0" kada autentifikacija krajnjeg korisnika nije ispunila zahteve ISO/IEC 29115.
|
||||
- **amr**: Authentication method ukazuje na koji način je token autentifikovan. Vrednost “pwd” označava da je korišćena lozinka.
|
||||
- **groups**: Označava grupe čiji je principal član.
|
||||
- **iss**: Issuer identifikuje security token service (STS) koji je generisao token. npr. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (the uuid is the tenant ID)
|
||||
- **oid**: Object ID principala
|
||||
- **tid**: Tenant ID
|
||||
- **iat, nbf, exp**: Issued at (vreme izdavanja), Not before (ne može se koristiti pre ovog vremena, obično ista vrednost kao iat), Expiration time (vreme isteka).
|
||||
- **iat, nbf, exp**: Issued at (kada je izdat), Not before (ne može se koristiti pre tog vremena, obično ista vrednost kao iat), Expiration time (vreme isteka).
|
||||
|
||||
|
||||
## FOCI Tokens Privilege Escalation
|
||||
|
||||
Ranije je pomenuto da refresh tokens treba da budu vezani za **scopes** sa kojima su generisani, za **application** i **tenant** za koje su generisani. Ako je bilo koja od ovih granica prekršena, moguće je eskalirati privilegije jer će biti moguće generisati access tokens za druge resurse i tenante kojima korisnik ima pristup i sa više scopes nego što je prvobitno bilo predviđeno.
|
||||
Ranije je pomenuto da refresh tokens treba da budu vezani za **scopes** sa kojima su generisani, za **application** i **tenant** za koje su generisani. Ako se bilo koja od ovih granica prekrši, moguće je escalate privileges jer će biti moguće generisati access tokens za druge resurse i tenants kojima korisnik ima pristup i sa više scopes nego što je originalno bilo predviđeno.
|
||||
|
||||
Štaviše, **ovo je moguće sa svim refresh tokens** u [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/) (Microsoft Entra accounts, Microsoft personal accounts, and social accounts like Facebook and Google) zato što, kako [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens) navode: "Refresh tokens are bound to a combination of user and client, but **aren't tied to a resource or tenant**. A client can use a refresh token to acquire access tokens **across any combination of resource and tenant** where it has permission to do so. Refresh tokens are encrypted and only the Microsoft identity platform can read them."
|
||||
Osim toga, **ovo je moguće sa svim refresh tokens** u [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/) (Microsoft Entra accounts, Microsoft personal accounts, and social accounts like Facebook and Google) jer, kao što [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens) navode: "Refresh tokens are bound to a combination of user and client, but **aren't tied to a resource or tenant**. A client can use a refresh token to acquire access tokens **across any combination of resource and tenant** where it has permission to do so. Refresh tokens are encrypted and only the Microsoft identity platform can read them."
|
||||
|
||||
Takođe, imajte na umu da su FOCI applications public applications, pa **nije potreban secret** za autentifikaciju prema serveru.
|
||||
Takođe, imajte na umu da su FOCI aplikacije public applications, tako da **no secret is needed** da bi se autentifikovalo na server.
|
||||
|
||||
Then known FOCI clients reported in the [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main) can be [**found here**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv).
|
||||
Poznati FOCI klijenti prijavljeni u [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main) mogu se [**found here**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv).
|
||||
|
||||
### Get different scope
|
||||
### Zatraži drugi scope
|
||||
|
||||
Following with the previous example code, in this code it's requested a new token for a different scope:
|
||||
Nastavljajući prethodni primer koda, u ovom kodu se zahteva novi token za drugi scope:
|
||||
```python
|
||||
# Code from https://github.com/secureworks/family-of-client-ids-research
|
||||
azure_cli_bearer_tokens_for_outlook_api = (
|
||||
@@ -186,7 +259,7 @@ scopes=[
|
||||
)
|
||||
pprint(azure_cli_bearer_tokens_for_outlook_api)
|
||||
```
|
||||
### Dohvatite drugačiji client i scope-ove
|
||||
### Nabavite drugog klijenta i različite opsege
|
||||
```python
|
||||
# Code from https://github.com/secureworks/family-of-client-ids-research
|
||||
microsoft_office_client = msal.PublicClientApplication("d3590ed6-52b3-4102-aeff-aad2292ab01c")
|
||||
@@ -204,53 +277,53 @@ pprint(microsoft_office_bearer_tokens_for_graph_api)
|
||||
```
|
||||
## NAA / BroCI (Nested App Authentication / Broker Client Injection)
|
||||
|
||||
A BroCI refresh token je obrazac posredovane razmene tokena gde se postojeći refresh token koristi sa dodatnim broker parametrima da bi se zatražili tokeni kao druga pouzdana first-party aplikacija.
|
||||
A BroCI refresh tokens is a brokered token exchange pattern where an existing refresh token is used with extra broker parameters to request tokens as another trusted first-party app.
|
||||
|
||||
Ovi refresh tokeni moraju biti izdate u tom broker kontekstu (a regular refresh token obično ne može da se koristi kao BroCI refresh token).
|
||||
These refresh tokens must be minted in that broker context (a regular refresh token usually cannot be used as a BroCI refresh token).
|
||||
|
||||
### Cilj i svrha
|
||||
|
||||
Cilj BroCI-ja je da ponovo iskoristi važeću korisničku sesiju iz lanca aplikacija koje podržavaju broker i zatraži tokene za drugi par pouzdanih aplikacija/resursa. Dakle, omogućava "eskalaciju privilegija" sa originalnog tokena.
|
||||
Cilj BroCI je ponovna upotreba važeće korisničke sesije iz lanca aplikacija koje podržavaju broker i zahtevanje tokena za drugi trusted first-party app/resource par. Time se omogućava "escalate privileges" iz originalnog tokena.
|
||||
|
||||
Sa napadačke perspektive, ovo je važno zato što:
|
||||
Sa ofanzivne perspektive, ovo je važno zato što:
|
||||
|
||||
- Može otključati pre-consented first-party putanje koje nisu dostupne standardnim refresh razmenama.
|
||||
- Može vratiti access tokene za visokovredne API-je (na primer Microsoft Graph) pod identitetima aplikacija sa širokim delegated permissions.
|
||||
- Može otključati pre-consented first-party app putanje koje nisu dostupne standardnim refresh razmenama.
|
||||
- Može vratiti access token-e za visokovredne API-je (na primer, Microsoft Graph) pod identitetima aplikacija sa širokim delegated permissions.
|
||||
- Proširuje mogućnosti post-authentication token pivotinga izvan klasičnog FOCI client switching.
|
||||
|
||||
Ono što se menja kod NAA/BroCI refresh tokena nije vidljivi format tokena, već **issuance context** i broker-povezani metadata koje Microsoft validira tokom brokerovanih refresh operacija.
|
||||
Ono što se menja kod NAA/BroCI refresh tokena nije vidljiv format tokena, već **issuance context** i broker-related metadata koju Microsoft validira tokom brokered refresh operacija.
|
||||
|
||||
NAA/BroCI token razmene **nisu** isto što i regularna OAuth refresh razmena.
|
||||
NAA/BroCI token exchanges are **not** the same as a regular OAuth refresh exchange.
|
||||
|
||||
- A regular refresh token (na primer dobijen via device code flow) je obično validan za standard `grant_type=refresh_token` operacije.
|
||||
- A BroCI request uključuje dodatni broker context (`brk_client_id`, broker `redirect_uri`, and `origin`).
|
||||
- Microsoft validira da li je predstavljeni refresh token izdat u odgovarajućem brokerovanom kontekstu.
|
||||
- Zbog toga, mnogi "normalni" refresh tokeni padaju u BroCI zahtevima sa greškama kao što su `AADSTS900054` ("Specified Broker Client ID does not match ID in provided grant").
|
||||
- Generalno ne možete "convert" normalan refresh token u BroCI-validan u kodu.
|
||||
- Potreban vam je refresh token koji je već izdat od strane kompatibilnog brokerovanog toka.
|
||||
- A regular refresh token (for example obtained via device code flow) is usually valid for standard `grant_type=refresh_token` operations.
|
||||
- A BroCI request includes additional broker context (`brk_client_id`, broker `redirect_uri`, and `origin`).
|
||||
- Microsoft validates whether the presented refresh token was minted in a matching brokered context.
|
||||
- Therefore, many "normal" refresh tokens fail in BroCI requests with errors such as `AADSTS900054` ("Specified Broker Client ID does not match ID in provided grant").
|
||||
- You generally cannot "convert" a normal refresh token into a BroCI-valid one in code.
|
||||
- You need a refresh token already issued by a compatible brokered flow.
|
||||
|
||||
Check the web **<https://entrascopes.com/>** to find BroCI configured apps an the trust relationships they have.
|
||||
|
||||
|
||||
### Mentalni model
|
||||
### Mental model
|
||||
|
||||
Razmislite o BroCI kao:
|
||||
Think of BroCI as:
|
||||
|
||||
user session -> brokered refresh token issuance -> brokered refresh call (brk_client_id + redirect_uri + origin) -> access token for target trusted app/resource
|
||||
`user session -> brokered refresh token issuance -> brokered refresh call (brk_client_id + redirect_uri + origin) -> access token for target trusted app/resource`
|
||||
|
||||
Ako se bilo koji deo tog broker lanca ne poklapa, razmena ne uspeva.
|
||||
If any part of that broker chain does not match, the exchange fails.
|
||||
|
||||
### Gde naći BroCI-validan refresh token
|
||||
### Gde pronaći BroCI-validan refresh token
|
||||
|
||||
Jedan praktičan način je prikupljanje saobraćaja portala u browseru:
|
||||
Jedan praktičan način je prikupljanje saobraćaja iz browser portala:
|
||||
|
||||
1. Prijavite se na `https://entra.microsoft.com` (ili Azure portal).
|
||||
2. Open DevTools -> Network.
|
||||
2. Otvorite DevTools -> Network.
|
||||
3. Filtrirajte po:
|
||||
- `oauth2/v2.0/token`
|
||||
- `management.core.windows.net`
|
||||
4. Identifikujte brokerovani token response i kopirajte `refresh_token`.
|
||||
5. Koristite taj refresh token sa odgovarajućim BroCI parametrima (`brk_client_id`, `redirect_uri`, `origin`) kada tražite tokene za ciljane aplikacije (na primer ADIbizaUX / Microsoft_Azure_PIMCommon scenariji).
|
||||
4. Identifikujte brokered token odgovor i kopirajte `refresh_token`.
|
||||
5. Koristite taj refresh token sa odgovarajućim BroCI parametrima (`brk_client_id`, `redirect_uri`, `origin`) prilikom zahtevanja tokena za ciljne aplikacije (na primer ADIbizaUX / Microsoft_Azure_PIMCommon scenariji).
|
||||
|
||||
### Uobičajene greške
|
||||
|
||||
@@ -533,24 +606,24 @@ raise SystemExit(main())
|
||||
|
||||
## Gde pronaći tokens
|
||||
|
||||
Sa aspekta napadača veoma je korisno znati gde je moguće pronaći access i refresh tokens, na primer kada je PC žrtve kompromitovan:
|
||||
Sa aspekta napadača, vrlo je interesantno znati gde je moguće pronaći access i refresh tokens kada je, na primer, računar žrtve kompromitovan:
|
||||
|
||||
- Inside **`<HOME>/.Azure`**
|
||||
- **`azureProfile.json`** sadrži informacije o korisnicima koji su bili prijavljeni ranije
|
||||
- **`clouds.config contains`** informacije o subscriptions
|
||||
- **`service_principal_entries.json`** sadrži kredencijale aplikacija (tenant id, clients i secret). Samo na Linux & macOS
|
||||
- **`azureProfile.json`** sadrži informacije o korisnicima koji su se prethodno prijavljivali
|
||||
- **`clouds.config contains`** info about subscriptions
|
||||
- **`service_principal_entries.json`** sadrži credentials aplikacija (tenant id, clients and secret). Samo na Linux & macOS
|
||||
- **`msal_token_cache.json`** sadrži access tokens i refresh tokens. Samo na Linux & macOS
|
||||
- **`service_principal_entries.bin`** i msal_token_cache.bin se koriste na Windows-u i šifrovani su sa DPAPI
|
||||
- **`msal_http_cache.bin`** je keš HTTP zahteva
|
||||
- Load it: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)`
|
||||
- **`service_principal_entries.bin`** i msal_token_cache.bin se koriste na Windows i šifrovani su DPAPI-jem
|
||||
- **`msal_http_cache.bin`** je keš HTTP request-a
|
||||
- Učitajte ga: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)`
|
||||
- **`AzureRmContext.json`** sadrži informacije o prethodnim prijavama korišćenjem Az PowerShell (ali bez kredencijala)
|
||||
- Inside **`C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\*`** se nalaze nekoliko `.bin` fajlova sa **access tokens**, ID tokens i podacima o nalogu šifrovanim korisnikovim DPAPI.
|
||||
- Moguće je pronaći više **access tokens** u `.tbres` fajlovima unutar **`C:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\`** koji sadrže base64 šifrovano DPAPI sa access tokens.
|
||||
- Na Linux i macOS možete dobiti **access tokens, refresh tokens i id tokens** iz Az PowerShell (ako je korišćen) pokretanjem `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"`
|
||||
- Na Windows ovo generiše samo id tokens.
|
||||
- Moguće je proveriti da li je Az PowerShell bio korišćen na Linux i macOS proverom da li postoji `$HOME/.local/share/.IdentityService/` (iako su sadržani fajlovi prazni i neupotrebljivi)
|
||||
- Ako je korisnik **ulogovan u Azure preko browser-a**, prema ovom [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) moguće je pokrenuti authentication flow sa **redirect to localhost**, naterati browser da automatski autorizuje prijavu i primiti refresh token. Imajte na umu da postoji samo nekoliko FOCI aplikacija koje dozvoljavaju redirect to localhost (kao az cli ili powershell module), tako da te aplikacije moraju biti dozvoljene.
|
||||
- Druga opcija objašnjena u blogu je upotreba alata [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow) koji može koristiti bilo koju aplikaciju zato što će **dohvatiti OAuth code da bi potom dobio refresh token iz title poslednje auth** stranice koristeći redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`.
|
||||
- Inside **`C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\*`** se nalaze nekoliko `.bin` fajlova sa **access tokens**, ID tokens i informacijama o nalogu šifrovanim korisnikovim DPAPI-jem.
|
||||
- Moguće je pronaći više **access tokens** u `.tbres` fajlovima unutar **`C:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\`** koji sadrže base64 šifrovano sa DPAPI-jem sa access tokens.
|
||||
- Na Linuxu i macOS-u možete dobiti **access tokens, refresh tokens and id tokens** iz Az PowerShell (ako je korišćen) pokretanjem `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"`
|
||||
- Na Windows-u ovo generiše samo id tokens.
|
||||
- Moguće je proveriti da li je Az PowerShell korišćen na Linuxu i macOS-u proverom da li postoji `$HOME/.local/share/.IdentityService/` (iako su sadržani fajlovi prazni i beskorisni)
|
||||
- Ako je korisnik **logged inside Azure with the browser**, prema ovom [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) moguće je pokrenuti authentication flow sa **redirect to localhost**, naterati browser da automatski autorizuje prijavu i primiti refresh token. Napomena da postoji samo nekoliko FOCI aplikacija koje dozvoljavaju redirect na localhost (kao az cli ili powershell module), tako da te aplikacije moraju biti dozvoljene.
|
||||
- Druga opcija objašnjena na blogu je korišćenje alata [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow) koji može koristiti bilo koju aplikaciju jer će **get the OAuth code to then get a refresh token from the title of the final auth** page koristeći redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`.
|
||||
|
||||
## References
|
||||
|
||||
@@ -558,5 +631,6 @@ Sa aspekta napadača veoma je korisno znati gde je moguće pronaći access i ref
|
||||
- [https://github.com/Huachao/azure-content/blob/master/articles/active-directory/active-directory-token-and-claims.md](https://github.com/Huachao/azure-content/blob/master/articles/active-directory/active-directory-token-and-claims.md)
|
||||
- [https://specterops.io/blog/2025/10/15/naa-or-broci-let-me-explain/](https://specterops.io/blog/2025/10/15/naa-or-broci-let-me-explain/)
|
||||
- [https://specterops.io/blog/2025/08/13/going-for-brokering-offensive-walkthrough-for-nested-app-authentication/](https://specterops.io/blog/2025/08/13/going-for-brokering-offensive-walkthrough-for-nested-app-authentication/)
|
||||
- [https://trustedsec.com/blog/full-disclosure-a-third-and-fourth-azure-sign-in-log-bypass-found](https://trustedsec.com/blog/full-disclosure-a-third-and-fourth-azure-sign-in-log-bypass-found)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user