From f669910ad27937e1554a3f79096e52b741d61887 Mon Sep 17 00:00:00 2001 From: Translator Date: Tue, 31 Mar 2026 16:56:17 +0000 Subject: [PATCH] Translated ['', 'src/pentesting-cloud/azure-security/az-basic-informatio --- .../az-tokens-and-public-applications.md | 258 +++++++++++------- 1 file changed, 166 insertions(+), 92 deletions(-) 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 46ead2908..4fa5dc127 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,100 +1,173 @@ -# Az - Токени та публічні додатки +# Az - Tokens & Public Applications {{#include ../../../banners/hacktricks-training.md}} -## Базова інформація +## Основна інформація -Entra ID — хмарна платформа Microsoft для управління ідентифікацією та доступом (IAM), яка слугує основною системою автентифікації та авторизації для сервісів, таких як Microsoft 365 та Azure Resource Manager. Azure AD реалізує рамки авторизації OAuth 2.0 та протокол автентифікації OpenID Connect (OIDC) для керування доступом до ресурсів. +Entra ID — хмарна платформа Microsoft для управління ідентифікацією та доступом (IAM), що виступає базовою системою автентифікації та авторизації для сервісів на кшталт Microsoft 365 та Azure Resource Manager. Azure AD реалізує фреймворк авторизації OAuth 2.0 і протокол автентифікації OpenID Connect (OIDC) для керування доступом до ресурсів. ### OAuth -**Ключові учасники OAuth 2.0:** +Ключові учасники OAuth 2.0: -1. **Resource Server (RS):** Захищає ресурси, що належать власникові ресурсу. +1. **Resource Server (RS):** Захищає ресурси, що належать власнику ресурсу. 2. **Resource Owner (RO):** Зазвичай кінцевий користувач, який володіє захищеними ресурсами. -3. **Client Application (CA):** Додаток, що запитує доступ до ресурсів від імені власника ресурсу. -4. **Authorization Server (AS):** Видає access tokens клієнтським додаткам після їх автентифікації та авторизації. +3. **Client Application (CA):** Додаток, що прагне отримати доступ до ресурсів від імені власника ресурсу. +4. **Authorization Server (AS):** Видає access tokens клієнтським додаткам після їх аутентифікації та авторизації. -**Scopes and Consent:** +Scopes та Consent: -- **Scopes:** Гранульовані дозволи, визначені на resource server, які конкретизують рівні доступу. -- **Consent:** Процес, за допомогою якого власник ресурсу надає клієнтському додатку дозвіл доступу до ресурсів з певними scopes. +- **Scopes:** Гранулярні дозволи, визначені на resource server, які вказують рівні доступу. +- **Consent:** Процес, під час якого resource owner надає client application дозвіл на доступ до ресурсів з конкретними scopes. -**Microsoft 365 Integration:** +Інтеграція з Microsoft 365: -- Microsoft 365 використовує Azure AD для IAM і складається з численних "first-party" OAuth додатків. -- Ці додатки глибоко інтегровані і часто мають взаємозалежні сервісні відносини. -- Щоб спростити досвід користувача та зберегти функціональність, Microsoft надає "implied consent" або "pre-consent" цим first-party додаткам. -- **Implied Consent:** Деяким додаткам автоматично **надається доступ до певних scopes без явного схвалення користувача або адміністратора**. -- Ці попередньо затверджені scopes зазвичай приховані як від користувачів, так і від адміністраторів, що робить їх менш помітними у стандартних інтерфейсах керування. +- Microsoft 365 використовує Azure AD для IAM і складається з кількох "first-party" OAuth додатків. +- Ці додатки глибоко інтегровані і часто мають взаємозалежні сервісні зв’язки. +- Щоб спростити роботу користувачів і зберегти функціональність, Microsoft надає цим first-party додаткам "implied consent" або "pre-consent". +- **Implied Consent:** Деяким додаткам автоматично надається доступ до певних scopes без явного схвалення користувачем або адміністратором. +- Ці pre-consented scopes зазвичай приховані від користувачів та адміністраторів, тому їх важче помітити в стандартних інтерфейсах керування. -**Типи клієнтських додатків:** +Типи Client Application: 1. **Confidential Clients:** -- Мають власні облікові дані (наприклад, паролі або сертифікати). -- Можуть **безпечно автентифікуватися** перед authorization server. +- Мають власні credentials (наприклад, passwords або certificates). +- Можуть безпечно аутентифікуватися перед authorization server. 2. **Public Clients:** -- Не мають унікальних облікових даних. -- Не можуть безпечно автентифікуватися перед authorization server. -- **Наслідок для безпеки:** Зловмисник може видавати себе за public client додаток при запиті токенів, оскільки authorization server не має механізму для перевірки легітимності додатку. +- Не мають унікальних credentials. +- Не можуть безпечно аутентифікуватися перед authorization server. +- **Security Implication:** Атакуючий може видавати себе за public client application при запиті токенів, оскільки немає механізму для authorization server перевірити легітимність додатка. -## Токени автентифікації +### ROPC / Password Grant -Є **три типи токенів**, що використовуються в OIDC: +Флоу OAuth2 **Resource Owner Password Credentials** (**ROPC**) використовує прямий `POST` до `https://login.microsoftonline.com//oauth2/v2.0/token` з `grant_type=password`, **username**, **password**, **client_id**, та запитаним **scope**. В Entra ID це особливо цікаво для **public clients**, оскільки атакуючий може повторно використовувати Microsoft first-party client IDs або будь-який інший дозволений public client без потреби в 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. -- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** Клієнт пред'являє цей токен resource server для **доступу до ресурсів**. Його можна використовувати лише для конкретної комбінації користувача, клієнта та ресурсу і **не можна відкликати** до закінчення терміну дії — за замовчуванням це 1 година. -- **ID Tokens**: Клієнт отримує цей **токен від authorization server**. Він містить базову інформацію про користувача. Він **зв'язаний з конкретною комбінацією користувача та клієнта**. -- **Refresh Tokens**: Надаються клієнту разом з access token. Використовуються для **отримання нових access та ID токенів**. Вони прив'язані до конкретної комбінації користувача і клієнта і можуть бути відкликані. Стандартний термін дії — **90 днів** для неактивних refresh токенів та **відсутність терміну дії для активних токенів** (з refresh token можна отримувати нові refresh токени). -- Refresh token має бути прив'язаний до значення **`aud`**, до певних **scopes**, та до **tenant** і повинен генерувати access tokens лише для того aud, тих scopes (і ні для чого більше) та tenant. Проте це не завжди дотримується для **FOCI applications tokens**. -- Refresh token зашифрований і лише Microsoft може його розшифрувати. +### Класи обходу журналу входів Entra ID + +Деякі історичні баги Entra ID дозволяли **password validation** або навіть **full token issuance** без створення очікуваного запису в **Entra ID sign-in log**. Ці випадки були виправлені, але техніки все ще корисні для розуміння того, як конвеєри автентифікації можуть давати збій так, що залишається **downstream token use visible**, тоді як **upstream sign-in telemetry is absent**. + +#### 1. Foreign-tenant endpoint for stealth password validation + +Якщо запит відправлено на token endpoint of a **different tenant GUID**, Entra може все ще перевірити, чи правильний наданий пароль для вказаного імені користувача перед тим, як потік завершиться помилкою через те, що користувач не існує в тому чужому tenant. Історично це дозволяло: + +- **Password spraying / credential validation** без відповідного запису про вхід у tenant жертви +- Різницю у відповіді, що виявляє, чи пройшов крок перевірки пароля +- Немає видачі токена, але менше телеметрії, ніж при звичайному невдалому вході + +#### 2. Force a post-password failure + +Якщо параметр, який використовується **після** перевірки облікових даних, недійсний, наприклад недійсний `client_id`, загальна транзакція може завершитися помилкою, навіть якщо пароль уже був правильним. Історично це давало вигляд **failed** входу, приховуючи те, що підбір пароля пройшов успішно. + +Схема, яку слід запам'ятати: + +- **Перевірка пароля успішна** +- Пізніша перевірка завершується помилкою +- Журнал відображає кінцевий стан транзакції, але не успішний крок перевірки пароля + +#### 3. Trigger logging failure with oversized-but-valid values + +Найнебезпечніший клас — коли запит залишається синтаксично валідним, автентифікація проходить, **tokens are returned**, але якесь **logged field** настільки велике, що ламає pipeline логування. Повідомлені приклади включали: + +- Повторення дійсних scopes тисячі разів, наприклад `openid openid openid ...` +- Надання надмірно довгого, але все ще прийнятого заголовка **User-Agent** + +Це вказує на загальний клас проблем, де: + +1. Entra перевіряє облікові дані та синтаксис запиту +2. Токен видається успішно +3. Логування намагається зберегти сире поле, контрольоване користувачем +4. Запис у журнал не вдається через обмеження довжини або припущення щодо схеми +5. Користувач отримує дійсний токен без відповідного запису про вхід + +Приклад патерну з повторенням scope'ів: +```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)" +``` +#### Зауваження для виявлення та захисту + +Не припускайте, що кожне валідне використання токена матиме відповідну Entra sign-in подію. Під час розслідування підозрілої Graph активності зіставляйте: + +- **Журнали входів без взаємодії (non-interactive sign-in logs)** +- **Журнали активності Graph** +- **IP address**, **user/object ID**, **session/correlation identifiers** та **time windows** + +Практичний метод валідації — обрамити підозрюваний «невидимий» успіх між двома звичайними невдалими входами й перевірити, чи після затримки інгестування відсутній очікуваний ланцюжок Failed -> Successful -> Failed. Якщо існує подальша Graph активність, але журнал sign-in відсутній, розглядайте це як потенційну проблему **sign-in logging gap** або стан **token replay**. + +## Authentication Tokens + +Існує **три типи токенів**, які використовуються в OIDC: + +- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** Клієнт пред'являє цей токен resource server для доступу до ресурсів. Він може використовуватися лише для конкретної комбінації user, client і resource і **не може бути відкликаний** до закінчення терміну дії — за замовчуванням це 1 година. +- **ID Tokens**: Клієнт отримує цей токен від authorization server. Він містить базову інформацію про користувача. Він **зв’язаний із конкретною комбінацією user та client**. +- **Refresh Tokens**: Надаються клієнту разом із access token. Використовуються для **отримання нових access та ID токенів**. Вони зв’язані з конкретною комбінацією user та client і можуть бути відкликані. Термін дії за замовчуванням — **90 днів** для неактивних refresh токенів і **без терміну дії для активних токенів** (оскільки з refresh token можливо отримати нові refresh tokens). +- Refresh token має бути прив’язаний до поля **`aud`**, до певних **scopes**, та до **tenant** і повинен дозволяти генерувати access токени лише для того aud, scopes (і не більше) та tenant. Проте це не так у випадку з токенами **FOCI applications**. +- Refresh token шифрується і лише Microsoft може його декодувати. - Отримання нового refresh token не відкликає попередній refresh token. > [!WARNING] -> Інформація для **conditional access** **зберігається** всередині **JWT**. Тому, якщо ви запитуєте **токен з дозволеної IP-адреси**, ця **IP** буде **збережена** в токені, і потім ви зможете використовувати цей токен з **недозволеної IP для доступу до ресурсів**. +> Інформація для **conditional access** **зберігається** всередині **JWT**. Тому, якщо ви запросите **token з дозволеної IP-адреси**, ця **IP** буде **збережена** в токені, і потім ви зможете використовувати цей токен із **недозволеної IP для доступу до ресурсів**. ### Access Tokens "aud" Поле, вказане в полі "aud", — це **resource server** (додаток), який використовується для виконання логіну. -Команда `az account get-access-token --resource-type [...]` підтримує наступні типи, і кожен з них додасть специфічний "aud" у результуючий access token: +Команда `az account get-access-token --resource-type [...]` підтримує наступні типи, і кожен з них додасть певний "aud" у результатний access token: > [!CAUTION] -> Зверніть увагу, що наведенi нижче — це лише API, які підтримує `az account get-access-token`, але їх більше. +> Зверніть увагу, що нижче перелічені лише API, які підтримує `az account get-access-token`, але їх більше.
-приклади aud +Приклади aud -- **aad-graph (Azure Active Directory Graph API)**: Використовується для доступу до застарілого Azure AD Graph API (deprecated), який дозволяє додаткам читати та записувати дані директорії в Azure Active Directory (Azure AD). +- **aad-graph (Azure Active Directory Graph API)**: Використовується для доступу до застарілого Azure AD Graph API (deprecated), який дозволяє додаткам читати й записувати дані каталогу в Azure Active Directory (Azure AD). - `https://graph.windows.net/` -* **arm (Azure Resource Manager)**: Використовується для управління ресурсами Azure через Azure Resource Manager API. Це включає операції створення, оновлення та видалення ресурсів, таких як віртуальні машини, облікові записи зберігання тощо. +- **arm (Azure Resource Manager)**: Використовується для керування ресурсами Azure через Azure Resource Manager API. Це включає операції створення, оновлення та видалення ресурсів, таких як віртуальні машини, облікові записи зберігання тощо. - `https://management.core.windows.net/ or https://management.azure.com/` -- **batch (Azure Batch Services)**: Використовується для доступу до Azure Batch — сервісу, що дозволяє ефективно запускати масштабні паралельні й високопродуктивні обчислювальні задачі в хмарі. +- **batch (Azure Batch Services)**: Використовується для доступу до Azure Batch — сервісу для ефективного виконання масштабних паралельних і високопродуктивних обчислювальних застосунків у хмарі. - `https://batch.core.windows.net/` -* **data-lake (Azure Data Lake Storage)**: Використовується для взаємодії з Azure Data Lake Storage Gen1 — масштабованим сервісом зберігання даних та аналітики. +- **data-lake (Azure Data Lake Storage)**: Використовується для взаємодії з Azure Data Lake Storage Gen1 — масштабованим сховищем для даних та аналітики. - `https://datalake.azure.net/` -- **media (Azure Media Services)**: Використовується для доступу до Azure Media Services, які надають хмарні сервіси обробки та доставки медіаконтенту (відео та аудіо). +- **media (Azure Media Services)**: Використовується для доступу до Azure Media Services, які надають хмарні сервіси для обробки та доставки медіаконтенту (відео та аудіо). - `https://rest.media.azure.net` -* **ms-graph (Microsoft Graph API)**: Використовується для доступу до Microsoft Graph API — уніфікованої точки доступу до даних сервісів Microsoft 365. Дозволяє отримувати доступ до даних і інсайтів з таких сервісів, як Azure AD, Office 365, Enterprise Mobility та Security services. +- **ms-graph (Microsoft Graph API)**: Використовується для доступу до Microsoft Graph API — уніфікованої точки доступу до даних сервісів Microsoft 365. Дозволяє отримувати дані й інсайти з таких сервісів, як Azure AD, Office 365, Enterprise Mobility та Security services. - `https://graph.microsoft.com` -- **oss-rdbms (Azure Open Source Relational Databases)**: Використовується для доступу до сервісів баз даних Azure для open-source реляційних СУБД, таких як MySQL, PostgreSQL та MariaDB. +- **oss-rdbms (Azure Open Source Relational Databases)**: Використовується для доступу до сервісів баз даних Azure для відкритих реляційних рушіїв, таких як MySQL, PostgreSQL та MariaDB. - `https://ossrdbms-aad.database.windows.net`
### Access Tokens Scopes "scp" -Область (scope) access token зберігається всередині ключа scp у JWT access token. Ці scopes визначають, до чого має доступ access token. +Сфера дії (scope) access token зберігається в ключі scp всередині JWT access token. Ці scopes визначають, до чого має доступ access token. -Якщо JWT дозволено звертатися до певного API, але він **не має scope**, необхідного для виконання запитуваної дії, то він **не зможе виконати цю дію** з цим JWT. +Якщо JWT має дозвіл звертатися до конкретного API, але **не має scope** для виконання запитуваної дії, він **не зможе виконати цю дію** з цим JWT. -### Приклад отримання refresh та access токенів +### Приклад отримання refresh & access token ```python # Code example from https://github.com/secureworks/family-of-client-ids-research import msal @@ -146,29 +219,29 @@ pprint(new_azure_cli_bearer_tokens_for_graph_api) ``` ### Інші поля access token -- **appid**: Application ID used to generate the token -- **appidacr**: The Application Authentication Context Class Reference вказує, як був аутентифікований client; для public client значення 0, а якщо використовується client secret — значення 1 -- **acr**: The Authentication Context Class Reference claim дорівнює "0", коли аутентифікація кінцевого користувача не відповідала вимогам ISO/IEC 29115. -- **amr**: The Authentication method вказує, як токен був аутентифікований. Значення “pwd” означає, що використано пароль. -- **groups**: Вказує групи, де principal є членом. -- **iss**: The issues ідентифікує security token service (STS), яка згенерувала токен. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (the uuid is the tenant ID) -- **oid**: The object ID of the principal +- **appid**: ID додатку, який використовується для генерації токена +- **appidacr**: Application Authentication Context Class Reference вказує, як був автентифікований клієнт; для public client значення 0, якщо використовується client secret — значення 1 +- **acr**: Authentication Context Class Reference — значення "0", коли автентифікація кінцевого користувача не відповідала вимогам ISO/IEC 29115. +- **amr**: Authentication method вказує, як був автентифікований токен. Значення “pwd” означає, що був використаний пароль. +- **groups**: Вказує групи, де цей суб'єкт є членом. +- **iss**: Issuer визначає службу безпеки токенів (STS), яка згенерувала токен. наприклад https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (uuid — це tenant ID) +- **oid**: Object ID суб'єкта - **tid**: Tenant ID -- **iat, nbf, exp**: Issued at (коли було видано), Not before (не можна використовувати до цього часу, зазвичай те саме значення, що iat), Expiration time (час закінчення дії). +- **iat, nbf, exp**: Issued at (коли було видано), Not before (не можна використовувати до цього часу, зазвичай те саме значення, що і iat), Expiration time. -## FOCI Tokens Privilege Escalation +## Ескалація привілеїв FOCI токенів -Раніше згадувалося, що refresh tokens повинні бути прив'язані до **scopes**, з якими вони були згенеровані, до **application** і **tenant**, для яких вони були згенеровані. Якщо будь-яке з цих обмежень порушується, it's possible to escalate privileges, оскільки стане можливим генерувати access tokens для інших ресурсів і tenants, до яких користувач має доступ, і з більшою кількістю scopes, ніж було передбачено спочатку. +Раніше згадувалось, що refresh tokens повинні бути прив'язані до **scopes**, з якими вони були згенеровані, до **application** і до **tenant**, для якого їх видано. Якщо будь-яка з цих меж порушується, можлива ескалація привілеїв, оскільки стане можливим генерувати access tokens для інших ресурсів і tenant-ів, до яких має доступ користувач, і з більшими scopes, ніж це було передбачено спочатку. -Більше того, **this is possible with all refresh tokens** у [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), оскільки, як згадують [**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." +Більше того, **це можливо з будь-якими refresh tokens** у Microsoft identity platform (Microsoft Entra accounts, Microsoft personal accounts, and social accounts like Facebook and Google), оскільки, як згадано в [**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." -Також зауважте, що FOCI applications є public applications, тож **no secret is needed** для аутентифікації на сервері. +Також зауважте, що FOCI applications — це public applications, тому **no secret is needed** для автентифікації на сервері. -Відомі 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). +Відомі FOCI clients, описані в [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main), можна [**знайти тут**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv). ### Get different scope -Далі, у прикладі коду вище, у цьому прикладі запитується новий токен для іншого scope: +Продовжуючи попередній приклад коду, у цьому прикладі запитується новий токен для іншого scope: ```python # Code from https://github.com/secureworks/family-of-client-ids-research azure_cli_bearer_tokens_for_outlook_api = ( @@ -185,7 +258,7 @@ scopes=[ ) pprint(azure_cli_bearer_tokens_for_outlook_api) ``` -### Отримати іншого клієнта та різні області доступу +### Отримати іншого клієнта та інші обсяги доступу ```python # Code from https://github.com/secureworks/family-of-client-ids-research microsoft_office_client = msal.PublicClientApplication("d3590ed6-52b3-4102-aeff-aad2292ab01c") @@ -203,23 +276,23 @@ pprint(microsoft_office_bearer_tokens_for_graph_api) ``` ## NAA / BroCI (Nested App Authentication / Broker Client Injection) -A BroCI refresh tokens — це схема посередницького обміну токенами, де існуючий refresh token використовується з додатковими broker параметрами для запиту токенів від імені іншого довіреного first-party app. +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. These refresh tokens must be minted in that broker context (a regular refresh token usually cannot be used as a BroCI refresh token). -### Goal and purpose +### Мета та призначення -Мета BroCI — повторно використати валідну сесію користувача з ланцюжка додатків, здатних працювати через broker, і запитати токени для іншої пари trusted app/resource. Це дозволяє "escalate privileges" відносно початкового токена. +Мета BroCI — повторно використати дійсну сесію користувача з ланцюга додатків, здатних виступати брокером, і запитати токени для іншої пари додаток/ресурс, що довіряються. Таким чином це дозволяє "ескалювати привілеї" від початкового токена. -З атакувальної точки зору це важливо, тому що: +З атакувальної перспективи це важливо, тому що: -- Це може розблокувати pre-consented first-party app шляхи, які недоступні при стандартних refresh exchanges. -- Це може повернути access tokens для високовартісних API (наприклад, Microsoft Graph) під ідентичностями app з широкими delegated permissions. -- Це розширює можливості пост-аутентифікаційного token pivoting за межі класичної FOCI client switching. +- Це може розблокувати шляхи для first-party додатків з попередньою згодою, які недоступні при стандартних refresh обмінах. +- Може повернути access token для високовартісних API (наприклад, Microsoft Graph) під ідентичностями додатків з широкими delegated permissions. +- Розширює можливості післяавтентифікаційного token pivoting поза межами класичного FOCI client switching. -Що змінюється у NAA/BroCI refresh token — це не видимий формат токена, а **context видачі** та broker-пов’язані метадані, які Microsoft валідовує під час brokered refresh операцій. +Що змінюється в NAA/BroCI refresh token — це не видимий формат токена, а **контекст видачі** та метадані, пов'язані з брокером, які Microsoft перевіряє під час брокерованих операцій оновлення. -NAA/BroCI token exchanges — це **не те саме**, що звичайний OAuth refresh exchange. +NAA/BroCI token exchanges are **not** the same as a regular OAuth refresh exchange. - 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`). @@ -231,7 +304,7 @@ NAA/BroCI token exchanges — це **не те саме**, що звичайни Check the web **** to find BroCI configured apps an the trust relationships they have. -### Mental model +### Ментальна модель Think of BroCI as: @@ -239,22 +312,22 @@ Think of BroCI as: If any part of that broker chain does not match, the exchange fails. -### Where to find a BroCI-valid refresh token +### Де знайти BroCI-valid refresh token One practical way is browser portal traffic collection: -1. Увійдіть до `https://entra.microsoft.com` (or Azure portal). -2. Відкрийте DevTools -> Network. -3. Фільтруйте за: +1. Sign in to `https://entra.microsoft.com` (or Azure portal). +2. Open DevTools -> Network. +3. Filter for: - `oauth2/v2.0/token` - `management.core.windows.net` -4. Знайдіть brokered token response і скопіюйте `refresh_token`. -5. Використайте цей refresh token з відповідними BroCI параметрами (`brk_client_id`, `redirect_uri`, `origin`) при запиті токенів для цільових додатків (наприклад ADIbizaUX / Microsoft_Azure_PIMCommon scenarios). +4. Identify the brokered token response and copy `refresh_token`. +5. Use that refresh token with matching BroCI parameters (`brk_client_id`, `redirect_uri`, `origin`) when requesting tokens for target apps (for example ADIbizaUX / Microsoft_Azure_PIMCommon scenarios). -### Common errors +### Типові помилки -- `AADSTS900054`: The refresh token context does not match the supplied broker tuple (`brk_client_id` / `redirect_uri` / `origin`) or the token is not from a brokered portal flow. -- `AADSTS7000218`: The selected client flow expects a confidential credential (`client_secret`/assertion), often seen when trying device code with a non-public client. +- `AADSTS900054`: Контекст refresh token не відповідає наведеному брокерному тріаді (`brk_client_id` / `redirect_uri` / `origin`) або токен не походить із брокерованого portal flow. +- `AADSTS7000218`: Обраний client flow очікує конфіденційний credential (`client_secret`/assertion), що часто трапляється при спробі device code з non-public client.
Python BroCI refresh helper (broci_auth.py) @@ -530,32 +603,33 @@ raise SystemExit(main()) ```
-## Де знайти токени +## Де знайти tokens -З точки зору нападника важливо знати, де можна знайти **access** і **refresh tokens**, наприклад коли ПК жертви скомпрометовано: +З точки зору атакуючого, дуже важливо знати, де можна знайти access та refresh tokens, наприклад якщо PC жертви скомпрометовано: - Всередині **`/.Azure`** -- **`azureProfile.json`** містить інформацію про попередні входи користувачів +- **`azureProfile.json`** містить інформацію про користувачів, які входили раніше - **`clouds.config contains`** інформацію про підписки -- **`service_principal_entries.json`** містить облікові дані застосунків (tenant id, clients і secret). Тільки в Linux & macOS -- **`msal_token_cache.json`** містить **access tokens** та **refresh tokens**. Тільки в Linux & macOS -- **`service_principal_entries.bin`** і msal_token_cache.bin використовуються в Windows і зашифровані за допомогою DPAPI +- **`service_principal_entries.json`** містить облікові дані додатків (tenant id, clients and secret). Лише в Linux & macOS +- **`msal_token_cache.json`** містить access tokens і refresh tokens. Лише в Linux & macOS +- **`service_principal_entries.bin`** та msal_token_cache.bin використовуються в Windows і зашифровані за допомогою DPAPI - **`msal_http_cache.bin`** — кеш HTTP-запитів -- Завантажити його: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)` -- **`AzureRmContext.json`** містить інформацію про попередні входи через Az PowerShell (але без облікових даних) -- У папці **`C:\Users\\AppData\Local\Microsoft\IdentityCache\*`** є декілька `.bin` файлів з **access tokens**, ID tokens та інформацією про акаунти, зашифрованою за допомогою DPAPI користувача. -- У файлах `.tbres` всередині **`C:\Users\\AppData\Local\Microsoft\TokenBroken\Cache\`** можна знайти додаткові **access tokens**; ці файли містять base64, зашифровані з допомогою DPAPI, що містять access tokens. -- У Linux і macOS можна отримати **access tokens, refresh tokens і id tokens** з Az PowerShell (якщо використовувався), виконавши `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"` +- Завантажити: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)` +- **`AzureRmContext.json`** містить інформацію про попередні входи з використанням Az PowerShell (але без облікових даних) +- Всередині **`C:\Users\\AppData\Local\Microsoft\IdentityCache\*`** знаходяться кілька `.bin` файлів з **access tokens**, ID tokens та інформацією про акаунти, зашифрованими за допомогою DPAPI користувача. +- Можна знайти більше **access tokens** у файлах `.tbres` всередині **`C:\Users\\AppData\Local\Microsoft\TokenBroken\Cache\`**, які містять base64, зашифрований DPAPI, з access tokens. +- У Linux та macOS можна отримати **access tokens, refresh tokens and id tokens** з Az PowerShell (якщо використовувався), виконавши `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"` - У Windows це генерує лише id tokens. -- Можна перевірити, чи використовувався Az PowerShell у Linux і macOS, перевіривши наявність `$HOME/.local/share/.IdentityService/` (хоча файли всередині зазвичай порожні й марні) -- Якщо користувач **logged inside Azure with the browser**, згідно з цим [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) можна ініціювати аутентифікацію з **redirect to localhost**, змусити браузер автоматично авторизувати вхід і отримати refresh token. Зауважте, що лише кілька FOCI applications дозволяють redirect to localhost (наприклад az cli або the powershell module), тому ці додатки мають бути дозволені. -- Інший варіант, описаний у блозі, — використати інструмент [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow), який може працювати з будь-яким застосунком, оскільки він **отримує OAuth code, щоб потім отримати refresh token з title фінальної auth сторінки**, використовуючи redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`. +- Можна перевірити, чи використовувався Az PowerShell в Linux та macSO, перевіривши чи існує `$HOME/.local/share/.IdentityService/` (хоча вкладені файли порожні і непридатні) +- Якщо користувач **logged inside Azure with the browser**, згідно з цим [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) можна почати authentication flow з **redirect to localhost**, змусити браузер автоматично авторизувати вхід та отримати resh token. Зауважте, що лише кілька FOCI applications дозволяють redicet to localhost (наприклад az cli або the powershell module), тож ці додатки мають бути дозволені. +- Інший варіант, пояснений у блозі — використовувати інструмент [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow), який може використовувати будь-який додаток, тому що він **отримує OAuth код, щоб потім отримати refresh token зі заголовка фінальної auth** сторінки, використовуючи redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`. -## Посилання +## References - [https://github.com/secureworks/family-of-client-ids-research](https://github.com/secureworks/family-of-client-ids-research) - [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}}