diff --git a/src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md b/src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md index c25eb786e..4a51d5a6e 100644 --- a/src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md +++ b/src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md @@ -1,98 +1,171 @@ -# Az - Tokeny i aplikacje publiczne +# Az - Tokeny i Publiczne Aplikacje {{#include ../../../banners/hacktricks-training.md}} ## Podstawowe informacje -Entra ID jest chmurową platformą tożsamości i zarządzania dostępem (IAM) Microsoftu, służącą jako podstawowy system uwierzytelniania i autoryzacji dla usług takich jak Microsoft 365 i Azure Resource Manager. Azure AD implementuje framework OAuth 2.0 oraz protokół OpenID Connect (OIDC) do zarządzania dostępem do zasobów. +Entra ID to chmurowa platforma zarządzania tożsamością i dostępem (IAM) firmy Microsoft, pełniąca funkcję podstawowego systemu uwierzytelniania i autoryzacji dla usług takich jak Microsoft 365 i Azure Resource Manager. Azure AD implementuje OAuth 2.0 oraz OpenID Connect (OIDC), aby zarządzać dostępem do zasobów. ### OAuth -**Kluczowi uczestnicy w OAuth 2.0:** +**Główne podmioty w OAuth 2.0:** -1. **Resource Server (RS):** Chroni zasoby należące do właściciela zasobów. -2. **Resource Owner (RO):** Zwykle użytkownik końcowy będący właścicielem chronionych zasobów. -3. **Client Application (CA):** Aplikacja żądająca dostępu do zasobów w imieniu właściciela zasobów. -4. **Authorization Server (AS):** Wydaje tokeny dostępu aplikacjom klienckim po ich uwierzytelnieniu i autoryzacji. +1. **Resource Server (RS):** Chroni zasoby będące własnością Resource Owner. +2. **Resource Owner (RO):** Zazwyczaj użytkownik końcowy, który jest właścicielem chronionych zasobów. +3. **Client Application (CA):** Aplikacja żądająca dostępu do zasobów w imieniu właściciela zasobu. +4. **Authorization Server (AS):** Wydaje access tokens aplikacjom klienckim po ich uwierzytelnieniu i autoryzacji. -**Scopes and Consent:** +**Scopes i Consent:** -- **Scopes:** Szczegółowe uprawnienia zdefiniowane na serwerze zasobów, które określają poziomy dostępu. -- **Consent:** Proces, w którym właściciel zasobów udziela aplikacji klienckiej pozwolenia na dostęp do zasobów z określonymi zakresami. +- **Scopes:** Szczegółowe uprawnienia zdefiniowane na Resource Server, określające poziomy dostępu. +- **Consent:** Proces, w którym Resource Owner przyznaje aplikacji klienckiej uprawnienia do dostępu do zasobów w określonych zakresach. -**Integracja Microsoft 365:** +**Integracja z Microsoft 365:** -- Microsoft 365 wykorzystuje Azure AD dla IAM i składa się z wielu "first-party" aplikacji OAuth. +- Microsoft 365 korzysta z Azure AD do IAM i składa się z wielu aplikacji OAuth typu "first-party". - Te aplikacje są głęboko zintegrowane i często mają współzależne relacje usługowe. -- Aby uprościć doświadczenie użytkownika i zachować funkcjonalność, Microsoft przyznaje tym aplikacjom "implied consent" lub "pre-consent". -- **Implied Consent:** Niektórym aplikacjom automatycznie przyznawany jest dostęp do określonych zakresów bez wyraźnej zgody użytkownika lub administratora. -- Te pre-consented zakresy są zazwyczaj ukryte zarówno przed użytkownikami, jak i administratorami, co sprawia, że są mniej widoczne w standardowych interfejsach zarządzania. +- Aby uprościć doświadczenie użytkownika i zachować funkcjonalność, Microsoft przyznaje tym aplikacjom first-party "implied consent" albo "pre-consent". +- **Implied Consent:** Niektóre aplikacje mają automatycznie **przyznany dostęp do określonych zakresów bez wyraźnej zgody użytkownika lub administratora**. +- Te wstępnie zaakceptowane zakresy są zwykle ukryte zarówno przed użytkownikami, jak i administratorami, co sprawia, że są mniej widoczne w standardowych interfejsach zarządzania. **Typy aplikacji klienckich:** 1. **Confidential Clients:** - Posiadają własne poświadczenia (np. hasła lub certyfikaty). -- Mogą **bezpiecznie uwierzytelniać się** wobec serwera autoryzacji. +- Mogą bezpiecznie uwierzytelniać się wobec Authorization Server. 2. **Public Clients:** -- Nie mają unikalnych poświadczeń. -- Nie mogą bezpiecznie uwierzytelniać się w serwerze autoryzacji. -- **Implikacje bezpieczeństwa:** Atakujący może podszyć się pod aplikację publiczną przy żądaniu tokenów, ponieważ nie istnieje mechanizm pozwalający serwerowi autoryzacji zweryfikować prawdziwość aplikacji. +- Nie posiadają unikalnych poświadczeń. +- Nie mogą bezpiecznie uwierzytelniać się wobec Authorization Server. +- **Security Implication:** Atakujący może podszyć się pod aplikację public client podczas żądania tokenów, ponieważ Authorization Server nie ma mechanizmu do weryfikacji autentyczności aplikacji. + +### ROPC / Password Grant + +Flow OAuth2 Resource Owner Password Credentials (ROPC) używa bezpośredniego `POST` do `https://login.microsoftonline.com//oauth2/v2.0/token` z `grant_type=password`, `username`, `password`, `client_id` oraz żądanym `scope`. W Entra ID jest to szczególnie istotne dla public clients, ponieważ atakujący może ponownie użyć Microsoftowych first-party client IDs lub dowolnego innego dozwolonego public client bez potrzeby posiadania secret. +```bash +curl -X POST "https://login.microsoftonline.com//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. + +### Klasy obejść Entra ID Sign-In Log + +Niektóre historyczne błędy Entra ID pozwalały na **password validation** lub nawet na **full token issuance** bez wygenerowania oczekiwanego wpisu w **Entra ID sign-in log**. Te przypadki zostały naprawione, ale techniki te wciąż pomagają zrozumieć, jak potoki uwierzytelniania mogą zawieść w sposób, który pozostawia **downstream token use visible**, podczas gdy **upstream sign-in telemetry is absent**. + +#### 1. Foreign-tenant endpoint for stealth password validation + +Jeśli żądanie jest wysłane do token endpoint innego GUID tenantu, Entra może nadal sprawdzić, czy przesłane hasło jest poprawne dla podanej nazwy użytkownika, zanim flow zakończy się niepowodzeniem, bo użytkownik nie istnieje w tym obcym tenantcie. Historycznie pozwalało to na: + +- **Password spraying / credential validation** bez odpowiadającego sign-in log w tenantcie ofiary +- Różnicę w odpowiedzi ujawniającą, czy krok weryfikacji hasła powiódł się +- Brak wydania tokenu, ale mniejszą telemetrię niż przy normalnym nieudanym logowaniu + +#### 2. Force a post-password failure + +Jeśli parametr używany **po** walidacji poświadczeń jest nieprawidłowy, na przykład niepoprawny `client_id`, cała transakcja może się nie powieść, mimo że hasło było już poprawne. Historycznie dawało to widok **failed** login, jednocześnie ukrywając fakt, że zgadnięcie hasła się powiodło. + +Wzorzec do zapamiętania: + +- **Password check succeeds** +- Późniejszy krok walidacji zawodzi +- Log odzwierciedla końcowy stan transakcji, ale nie sam udany krok walidacji hasła + +#### 3. Trigger logging failure with oversized-but-valid values + +Najniebezpieczniejsza klasa to sytuacja, gdy żądanie pozostaje składniowo poprawne, uwierzytelnienie się powiodło, **tokens are returned**, ale jakieś **logged field** jest na tyle duże, że psuje pipeline logowania. Zgłaszane przykłady obejmowały: + +- Powtarzanie poprawnych scope’ów tysiące razy, np. `openid openid openid ...` +- Podanie nadmiernie długiego, ale nadal akceptowanego nagłówka **User-Agent** + +To sugeruje ogólną klasę problemów, gdzie: + +1. Entra waliduje poświadczenia i składnię żądania +2. Token zostaje wydany pomyślnie +3. Logowanie próbuje zapisać pole kontrolowane przez użytkownika +4. Zapis logu kończy się niepowodzeniem z powodu długości lub założeń schematu +5. Użytkownik otrzymuje poprawny token bez odpowiadającego wpisu sign-in + +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)" +``` +#### Uwaga dla huntingu / obrony + +Nie zakładaj, że każde prawidłowe użycie tokena będzie miało odpowiadające zdarzenie Entra sign-in. Podczas badania podejrzanej aktywności Graph, koreluj: + +- **Non-interactive sign-in logs** +- **Graph Activity Logs** +- **IP address**, **user/object ID**, **session/correlation identifiers**, oraz **okna czasowe** + +Praktyczną metodą walidacji jest objąć podejrzany niewidoczny sukces pomiędzy dwoma zwykłymi nieudanymi logonami, a następnie sprawdzić, czy oczekiwana sekwencja `Failed -> Successful -> Failed` nie traci środkowego zdarzenia po opóźnieniu w ingestowaniu. Jeżeli istnieje późniejsza aktywność w Graph, ale brak jest wpisu w sign-in log, traktuj to jako potencjalną lukę w logowaniu sign-in lub jako warunek **token replay**. ## Tokeny uwierzytelniające -W OIDC używa się **trzech typów tokenów**: +Istnieją **trzy typy tokenów** używane w OIDC: -- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** Klient przedstawia ten token serwerowi zasobów, aby **uzyskać dostęp do zasobów**. Może być użyty tylko dla konkretnej kombinacji użytkownika, klienta i zasobu i **nie może zostać unieważniony** przed wygaśnięciem — domyślnie 1 godzina. -- **ID Tokens**: Klient otrzymuje ten **token od serwera autoryzacji**. Zawiera podstawowe informacje o użytkowniku. Jest **powiązany z konkretną kombinacją użytkownika i klienta**. -- **Refresh Tokens**: Dostarczane klientowi wraz z access tokenem. Służą do **uzyskania nowych access i ID tokenów**. Są powiązane z konkretną kombinacją użytkownika i klienta i mogą być unieważnione. Domyślny okres wygaśnięcia to **90 dni** dla nieaktywnych refresh tokenów i **brak wygaśnięcia dla aktywnych tokenów** (z refresh tokena można uzyskać nowe refresh tokeny). -- Refresh token powinien być powiązany z **`aud`**, z pewnymi **scopes**, oraz z **tenantem** i powinien móc generować access tokeny tylko dla tego aud, tych scopes (i nie więcej) oraz tego tenant. Jednak nie dotyczy to **FOCI applications tokens**. -- Refresh token jest zaszyfrowany i tylko Microsoft może go odszyfrować. +- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** Klient przedstawia ten token serwerowi zasobów, aby **uzyskać dostęp do zasobów**. Może być użyty tylko dla konkretnej kombinacji użytkownika, klienta i zasobu i **nie może być unieważniony** aż do wygaśnięcia — domyślnie jest to 1 godzina. +- **ID Tokens**: Klient otrzymuje ten **token od authorization server**. Zawiera podstawowe informacje o użytkowniku. Jest **powiązany z konkretną kombinacją użytkownika i klienta**. +- **Refresh Tokens**: Dostarczane klientowi razem z access token. Używane do **uzyskania nowych access i ID tokenów**. Są powiązane z konkretną kombinacją użytkownika i klienta i mogą być unieważnione. Domyślny okres ważności to **90 dni** dla nieaktywnych refresh tokenów i **brak wygaśnięcia dla aktywnych tokenów** (ponieważ z refresh tokenu można otrzymać nowe refresh tokeny). +- Refresh token powinien być powiązany z wartością **`aud`**, z pewnymi **scopes**, oraz z **tenantem** i powinien generować access tokeny tylko dla tego aud, tych scopes (i nie więcej) oraz tego tenanta. Jednakże tak nie jest w przypadku tokenów aplikacji **FOCI**. +- Refresh token jest szyfrowany i tylko Microsoft może go odszyfrować. - Uzyskanie nowego refresh tokena nie unieważnia poprzedniego refresh tokena. > [!WARNING] -> Informacje dotyczące **conditional access** są **przechowywane** wewnątrz **JWT**. Zatem, jeśli zażadasz **tokena z dozwolonego adresu IP**, ten **IP** zostanie **zapisany** w tokenie i potem możesz użyć tego tokena z **niedozwolonego adresu IP, aby uzyskać dostęp do zasobów**. +> Informacje dla **conditional access** są **przechowywane** wewnątrz **JWT**. Zatem jeśli zażądasz **tokenu z dozwolonego adresu IP**, ten **IP** zostanie **zapisany** w tokenie i następnie możesz użyć tego tokenu z **nie-dozwolonego IP, aby uzyskać dostęp do zasobów**. ### Access Tokens "aud" -Wartość w polu "aud" to **resource server** (aplikacja), do której służy logowanie. +Pole wskazane w polu "aud" to **resource server** (aplikacja) używany do przeprowadzenia logowania. -Polecenie `az account get-access-token --resource-type [...]` obsługuje następujące typy i każdy z nich doda specyficzne "aud" w otrzymanym access tokenie: +Polecenie `az account get-access-token --resource-type [...]` obsługuje następujące typy i każdy z nich doda określone "aud" w powstałym access tokenie: > [!CAUTION] -> Należy pamiętać, że poniższe to tylko API wspierane przez `az account get-access-token`, ale jest ich więcej. +> Zauważ, że poniższe to tylko API wspierane przez `az account get-access-token`, ale istnieje ich więcej.
aud examples -- **aad-graph (Azure Active Directory Graph API)**: Używane do dostępu do przestarzałego Azure AD Graph API (deprecated), które pozwala aplikacjom czytać i zapisywać dane katalogowe w Azure Active Directory (Azure AD). +- **aad-graph (Azure Active Directory Graph API)**: Używane do dostępu do przestarzałego Azure AD Graph API (deprecated), które pozwala aplikacjom na odczyt i zapis danych katalogowych w Azure Active Directory (Azure AD). - `https://graph.windows.net/` -* **arm (Azure Resource Manager)**: Używane do zarządzania zasobami Azure przez API Azure Resource Manager. Obejmuje operacje tworzenia, aktualizacji i usuwania zasobów takich jak maszyny wirtualne, konta storage i inne. +* **arm (Azure Resource Manager)**: Używane do zarządzania zasobami Azure poprzez Azure Resource Manager API. Obejmuje operacje takie jak tworzenie, aktualizacja i usuwanie zasobów, takich jak maszyny wirtualne, konta storage i inne. - `https://management.core.windows.net/ or https://management.azure.com/` -- **batch (Azure Batch Services)**: Używane do dostępu do Azure Batch, usługi umożliwiającej efektywne uruchamianie aplikacji przetwarzania równoległego i wysokiej wydajności w chmurze. +- **batch (Azure Batch Services)**: Używane do dostępu do Azure Batch, usługi umożliwiającej wydajne uruchamianie aplikacji równoległych i wysokowydajnych w chmurze. - `https://batch.core.windows.net/` * **data-lake (Azure Data Lake Storage)**: Używane do interakcji z Azure Data Lake Storage Gen1, skalowalną usługą przechowywania danych i analiz. - `https://datalake.azure.net/` -- **media (Azure Media Services)**: Używane do dostępu do Azure Media Services, które oferują przetwarzanie i dystrybucję mediów w chmurze dla treści wideo i audio. +- **media (Azure Media Services)**: Używane do dostępu do Azure Media Services, które zapewniają przetwarzanie i dostarczanie treści wideo i audio w chmurze. - `https://rest.media.azure.net` -* **ms-graph (Microsoft Graph API)**: Używane do dostępu do Microsoft Graph API, zunifikowanego punktu końcowego dla danych usług Microsoft 365. Pozwala uzyskać dostęp do danych i informacji z usług takich jak Azure AD, Office 365, Enterprise Mobility i usług bezpieczeństwa. +* **ms-graph (Microsoft Graph API)**: Używane do dostępu do Microsoft Graph API, zunifikowanego endpointu dla danych usług Microsoft 365. Pozwala na dostęp do danych i informacji z usług takich jak Azure AD, Office 365, Enterprise Mobility i Security services. - `https://graph.microsoft.com` -- **oss-rdbms (Azure Open Source Relational Databases)**: Używane do dostępu do usług baz danych Azure dla otwartoźródłowych silników relacyjnych takich jak MySQL, PostgreSQL i MariaDB. +- **oss-rdbms (Azure Open Source Relational Databases)**: Używane do dostępu do usług baz danych Azure dla otwartych silników relacyjnych, takich jak MySQL, PostgreSQL i MariaDB. - `https://ossrdbms-aad.database.windows.net`
### Access Tokens Scopes "scp" -Zakres access tokena jest przechowywany w kluczu scp wewnątrz JWT access tokena. Te zakresy definiują, do czego access token ma dostęp. +Zakres access tokena jest przechowywany wewnątrz klucza scp w access tokenie JWT. Te scopes definiują, do czego access token ma dostęp. -Jeśli JWT ma prawo kontaktować się z konkretnym API, ale **nie ma zakresu** potrzebnego do wykonania żądanej akcji, **nie będzie w stanie wykonać tej akcji** z tym JWT. +Jeśli JWT ma uprawnienie do kontaktu z konkretnym API, ale **nie ma scope'u** do wykonania żądanej akcji, **nie będzie w stanie wykonać tej akcji** przy użyciu tego JWT. ### Przykład pobierania refresh i access tokena ```python @@ -144,31 +217,32 @@ scopes=["https://graph.microsoft.com/.default"], ) pprint(new_azure_cli_bearer_tokens_for_graph_api) ``` -### Inne pola access token +### Inne pola tokenu dostępu - **appid**: Application ID używany do wygenerowania tokenu -- **appidacr**: Application Authentication Context Class Reference wskazuje, w jaki sposób klient został uwierzytelniony — dla public client wartość to 0, a jeśli użyto client secret wartość to 1 -- **acr**: Authentication Context Class Reference — claim ma wartość "0", gdy uwierzytelnienie end-user nie spełniło wymagań ISO/IEC 29115. -- **amr**: Authentication method wskazuje, w jaki sposób token został uwierzytelniony. Wartość „pwd” oznacza użycie hasła. +- **appidacr**: Application Authentication Context Class Reference wskazuje, w jaki sposób klient został uwierzytelniony; dla public client wartość to 0, a jeśli użyto client secret wartość to 1 +- **acr**: Authentication Context Class Reference claim ma wartość "0", gdy uwierzytelnienie końcowego użytkownika nie spełniało wymagań ISO/IEC 29115. +- **amr**: Authentication method wskazuje, w jaki sposób token został uwierzytelniony. Wartość “pwd” oznacza, że użyto hasła. - **groups**: Wskazuje grupy, których członkiem jest principal. -- **iss**: iss identyfikuje security token service (STS), które wygenerowało token. np. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (uuid to tenant ID) -- **oid**: object ID principala +- **iss**: Issuer identyfikuje security token service (STS), które wygenerowało token. np. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (uuid to tenant ID) +- **oid**: Object ID principala - **tid**: Tenant ID -- **iat, nbf, exp**: Issued at (kiedy został wydany), Not before (nie może być używany przed tym czasem, zwykle ta sama wartość co iat), Expiration time. +- **iat, nbf, exp**: Issued at (kiedy został wydany), Not before (nie może być używany przed tym czasem, zazwyczaj ta sama wartość co iat), Czas wygaśnięcia. -## Escalacja uprawnień tokenów FOCI -Wcześniej wspomniano, że refresh tokens powinny być powiązane z **scopes**, dla których zostały wygenerowane, z **application** oraz z **tenant**, do którego zostały wystawione. Jeśli któraś z tych granic zostanie naruszona, możliwa jest eskalacja uprawnień — można wygenerować access tokens do innych zasobów i tenants, do których użytkownik ma dostęp, oraz z większymi scope niż pierwotnie zamierzono. +## FOCI Tokens Privilege Escalation -Co więcej, **this is possible with all refresh tokens** w [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/) (Microsoft Entra accounts, Microsoft personal accounts, oraz konta social jak Facebook i Google), ponieważ jak wspominają [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens): "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." +Wcześniej wspomniano, że refresh tokens powinny być powiązane z **scopes**, dla których zostały wygenerowane, z **application** oraz z **tenant**, do którego zostały przypisane. Jeśli którakolwiek z tych granic zostanie naruszona, możliwe jest eskalowanie przywilejów — będzie można wygenerować access tokens do innych zasobów i tenantów, do których użytkownik ma dostęp, i z większymi zakresami niż pierwotnie zamierzono. -Dodatkowo, warto zauważyć, że FOCI applications są public applications, więc **no secret is needed** do uwierzytelnienia na serwerze. +Co więcej, **jest to możliwe dla wszystkich refresh tokens** w [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/) (Microsoft Entra accounts, Microsoft personal accounts oraz konta społecznościowe jak Facebook i Google), ponieważ jak wspominają [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens): "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." -Znane FOCI clients zgłoszone w [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main) można [**znaleźć tutaj**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv). +Dodatkowo warto zauważyć, że aplikacje FOCI są publicznymi aplikacjami, więc **nie jest wymagany żaden sekret** do uwierzytelnienia się na serwerze. -### Get different scope +Znane klienty FOCI zgłoszone w [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main) można [**znaleźć tutaj**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv). -Kontynuując poprzedni przykład kodu, w tym kodzie żądany jest nowy token dla innego scope: +### Uzyskaj inny zakres + +Kontynuując poprzedni kod przykładowy, w tym kodzie żądany jest nowy token dla innego scope: ```python # Code from https://github.com/secureworks/family-of-client-ids-research azure_cli_bearer_tokens_for_outlook_api = ( @@ -209,15 +283,15 @@ These refresh tokens must be minted in that broker context (a regular refresh to ### Goal and purpose -The goal of BroCI is to reuse a valid user session from a broker-capable app chain and request tokens for another trusted app/resource pair. Therefore, allowing to "escalate privileges" from the original token. +Celem BroCI jest ponowne wykorzystanie ważnej sesji użytkownika z łańcucha aplikacji obsługujących brokera i zażądanie tokenów dla innej pary aplikacja/resource zaufanej przez system. Pozwala to na „eskalację uprawnień” względem oryginalnego tokena. -From an offensive perspective, this matters because: +Z ofensywnego punktu widzenia ma to znaczenie, ponieważ: -- It can unlock pre-consented first-party app paths that are not accessible with standard refresh exchanges. -- It can return access tokens for high-value APIs (for example, Microsoft Graph) under app identities with broad delegated permissions. -- It expands post-authentication token pivoting opportunities beyond classic FOCI client switching. +- Może odblokować ścieżki pre-consented first-party app, które nie są dostępne przy standardowych wymianach refresh. +- Może zwrócić access tokens dla wysokowartościowych API (na przykład Microsoft Graph) pod tożsamościami aplikacji mających szerokie uprawnienia delegated. +- Rozszerza możliwości pivotowania tokenami po uwierzytelnieniu poza klasyczną zmianą klienta FOCI. -What changes in a NAA/BroCI refresh token is not the visible token format, but the **issuance context** and broker-related metadata that Microsoft validates during brokered refresh operations. +To, co zmienia się w NAA/BroCI refresh tokenie, to nie widoczny format tokena, lecz **kontekst wydania** i metadane związane z brokerem, które Microsoft weryfikuje podczas brokerowanych operacji odświeżania. NAA/BroCI token exchanges are **not** the same as a regular OAuth refresh exchange. @@ -233,15 +307,15 @@ Check the web **** to find BroCI configured apps an th ### Mental model -Think of BroCI as: +Traktuj BroCI jako: `user session -> brokered refresh token issuance -> brokered refresh call (brk_client_id + redirect_uri + origin) -> access token for target trusted app/resource` -If any part of that broker chain does not match, the exchange fails. +Jeśli jakakolwiek część tego łańcucha brokera nie pasuje, wymiana zakończy się niepowodzeniem. ### Where to find a BroCI-valid refresh token -One practical way is browser portal traffic collection: +Jednym z praktycznych sposobów jest zbieranie ruchu przeglądarki w portalu: 1. Sign in to `https://entra.microsoft.com` (or Azure portal). 2. Open DevTools -> Network. @@ -532,24 +606,24 @@ raise SystemExit(main()) ## Gdzie znaleźć tokeny -Z perspektywy atakującego bardzo ważne jest wiedzieć, gdzie można znaleźć access i refresh tokeny, gdy np. PC ofiary zostanie skompromitowany: +Z perspektywy atakującego bardzo istotne jest wiedzieć, gdzie można znaleźć access i refresh tokens, np. gdy komputer ofiary zostanie przejęty: -- Wewnątrz **`/.Azure`** -- **`azureProfile.json`** zawiera informacje o zalogowanych użytkownikach z przeszłości -- **`clouds.config contains`** informacje o subskrypcjach +- Inside **`/.Azure`** +- **`azureProfile.json`** zawiera informacje o wcześniej zalogowanych użytkownikach +- **`clouds.config`** zawiera informacje o subskrypcjach - **`service_principal_entries.json`** zawiera dane uwierzytelniające aplikacji (tenant id, clients i secret). Tylko w Linux & macOS - **`msal_token_cache.json`** zawiera access tokens i refresh tokens. Tylko w Linux & macOS -- **`service_principal_entries.bin`** i msal_token_cache.bin są używane w Windows i są zaszyfrowane przy użyciu DPAPI +- **`service_principal_entries.bin`** i `msal_token_cache.bin` są używane w Windows i są szyfrowane za pomocą DPAPI - **`msal_http_cache.bin`** to cache żądań HTTP - Load it: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)` -- **`AzureRmContext.json`** zawiera informacje o poprzednich logowaniach za pomocą Az PowerShell (ale bez poświadczeń) -- Wewnątrz **`C:\Users\\AppData\Local\Microsoft\IdentityCache\*`** znajduje się kilka plików `.bin` z **access tokens**, ID tokens i informacjami o koncie zaszyfrowanymi przy użyciu DPAPI użytkownika. -- Można znaleźć więcej **access tokens** w plikach `.tbres` wewnątrz **`C:\Users\\AppData\Local\Microsoft\TokenBroken\Cache\`**, które zawierają base64 zaszyfrowane przy użyciu DPAPI z access tokenami. -- W Linux i macOS możesz uzyskać **access tokens, refresh tokens i id tokens** z Az PowerShell (jeśli używany) uruchamiając `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"` +- **`AzureRmContext.json`** zawiera informacje o wcześniejszych logowaniach przy użyciu Az PowerShell (ale bez poświadczeń) +- Inside **`C:\Users\\AppData\Local\Microsoft\IdentityCache\*`** znajduje się kilka plików `.bin` z **access tokens**, ID tokens i informacjami o koncie zaszyfrowanymi za pomocą DPAPI użytkownika. +- W plikach `.tbres` wewnątrz **`C:\Users\\AppData\Local\Microsoft\TokenBroken\Cache\`** można znaleźć więcej **access tokens**; zawierają base64 zaszyfrowany przy użyciu DPAPI z access tokens. +- W Linux i macOS można uzyskać **access tokens, refresh tokens and id tokens** z Az PowerShell (jeśli używany) uruchamiając `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"` - W Windows to generuje tylko id tokens. -- Można sprawdzić, czy Az PowerShell był używany w Linux i macOS sprawdzając, czy istnieje `$HOME/.local/share/.IdentityService/` (chociaż zawarte pliki są puste i bezużyteczne) -- Jeśli użytkownik jest **zalogowany w Azure przez przeglądarkę**, zgodnie z tym [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) można uruchomić flow uwierzytelniania z **redirect to localhost**, sprawić, by przeglądarka automatycznie zatwierdziła logowanie i otrzymać refresh token. Zauważ, że tylko kilka aplikacji FOCI pozwala na redirect to localhost (np. az cli lub moduł powershell), więc te aplikacje muszą być dozwolone. -- Inną opcją opisaną w blogu jest użycie narzędzia [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow), które może użyć dowolnej aplikacji, ponieważ ono **pobierze OAuth code, a następnie uzyska refresh token z tytułu finalnej strony autoryzacji** używając redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`. +- Można sprawdzić, czy Az PowerShell było używane w Linux i macOS, sprawdzając, czy istnieje `$HOME/.local/share/.IdentityService/` (choć zawarte pliki są puste i bezużyteczne) +- Jeśli użytkownik jest **zalogowany do Azure w przeglądarce**, zgodnie z tym [**postem**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) można rozpocząć flow uwierzytelniania z **przekierowaniem na localhost**, sprawić, by przeglądarka automatycznie autoryzowała logowanie i otrzymać refresh token. Zwróć uwagę, że tylko kilka aplikacji FOCI pozwala na redirect to localhost (np. az cli lub moduł PowerShell), więc te aplikacje muszą być dozwolone. +- Inną opcją opisaną w blogu jest użycie narzędzia [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow), które może użyć dowolnej aplikacji, ponieważ **pobierze OAuth code, by następnie uzyskać refresh token z tytułu końcowej strony autoryzacji** używając redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`. ## Referencje @@ -557,5 +631,6 @@ Z perspektywy atakującego bardzo ważne jest wiedzieć, gdzie można znaleźć - [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}}