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:
+154
-81
@@ -2,55 +2,128 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Informações Básicas
|
||||
## Informação Básica
|
||||
|
||||
Entra ID é a plataforma de identity and access management (IAM) baseada em nuvem da Microsoft, servindo como o sistema fundamental de autenticação e autorização para serviços como Microsoft 365 e Azure Resource Manager. Azure AD implementa o framework de autorização OAuth 2.0 e o protocolo de autenticação OpenID Connect (OIDC) para gerenciar o acesso a recursos.
|
||||
Entra ID é a plataforma de identity and access management (IAM) baseada na cloud da Microsoft, servindo como o sistema fundamental de autenticação e autorização para serviços como Microsoft 365 e Azure Resource Manager. Azure AD implementa o framework de autorização OAuth 2.0 e o protocolo de autenticação OpenID Connect (OIDC) para gerir o acesso a recursos.
|
||||
|
||||
### OAuth
|
||||
|
||||
**Principais Participantes no OAuth 2.0:**
|
||||
**Principais participantes no OAuth 2.0:**
|
||||
|
||||
1. **Resource Server (RS):** Protege recursos pertencentes ao resource owner.
|
||||
2. **Resource Owner (RO):** Tipicamente um usuário final que possui os recursos protegidos.
|
||||
3. **Client Application (CA):** Uma aplicação que busca acessar recursos em nome do resource owner.
|
||||
4. **Authorization Server (AS):** Emite access tokens para aplicações clientes após autenticar e autorizar elas.
|
||||
2. **Resource Owner (RO):** Tipicamente um utilizador final que é dono dos recursos protegidos.
|
||||
3. **Client Application (CA):** Uma aplicação que procura aceder a recursos em nome do resource owner.
|
||||
4. **Authorization Server (AS):** Emite access tokens para as client applications após as autenticar e autorizar.
|
||||
|
||||
**Scopes e Consentimento:**
|
||||
**Escopos e Consentimento:**
|
||||
|
||||
- **Scopes:** Permissões granulares definidas no resource server que especificam níveis de acesso.
|
||||
- **Consentimento:** O processo pelo qual um resource owner concede a uma client application permissão para acessar recursos com scopes específicos.
|
||||
- **Escopos:** Permissões granulares definidas no resource server que especificam níveis de acesso.
|
||||
- **Consentimento:** O processo pelo qual um resource owner concede a uma client application permissão para aceder a recursos com escopos específicos.
|
||||
|
||||
**Integração com Microsoft 365:**
|
||||
|
||||
- Microsoft 365 utiliza Azure AD para IAM e é composto por múltiplas aplicações OAuth "first-party".
|
||||
- Essas aplicações são profundamente integradas e frequentemente têm relações de serviço interdependentes.
|
||||
- Para simplificar a experiência do usuário e manter a funcionalidade, a Microsoft concede "implied consent" ou "pre-consent" a essas aplicações first-party.
|
||||
- **Implied Consent:** Certas aplicações são automaticamente **concedidas acesso a scopes específicos sem aprovação explícita do usuário ou administrador**.
|
||||
- Esses scopes pré-consentidos tipicamente ficam ocultos tanto de usuários quanto de administradores, tornando-os menos visíveis nas interfaces de gerenciamento padrão.
|
||||
- Estas aplicações estão profundamente integradas e frequentemente têm relações de serviço interdependentes.
|
||||
- Para simplificar a experiência do utilizador e manter a funcionalidade, a Microsoft concede "implied consent" ou "pre-consent" a estas aplicações first-party.
|
||||
- **Implied Consent:** Certas aplicações são automaticamente **concedidas acesso a escopos específicos sem aprovação explícita do utilizador ou do administrador approva**l.
|
||||
- Estes escopos pre-consentidos são tipicamente ocultos tanto dos utilizadores quanto dos administradores, tornando-os menos visíveis nas interfaces de gestão padrão.
|
||||
|
||||
**Tipos de Client Application:**
|
||||
|
||||
1. **Confidential Clients:**
|
||||
- Possuem suas próprias credenciais (ex.: passwords ou certificados).
|
||||
- Podem **autenticar-se com segurança** ao authorization server.
|
||||
- Possuem as suas próprias credenciais (por exemplo, passwords ou certificates).
|
||||
- Podem **autenticar-se de forma segura** ao authorization server.
|
||||
2. **Public Clients:**
|
||||
- Não possuem credenciais únicas.
|
||||
- Não podem autenticar-se com segurança ao authorization server.
|
||||
- **Implicação de Segurança:** Um atacante pode se passar por uma public client application ao requisitar tokens, pois não existe um mecanismo para o authorization server verificar a legitimidade da aplicação.
|
||||
- Não têm credenciais únicas.
|
||||
- Não conseguem autenticar-se de forma segura ao authorization server.
|
||||
- **Implicação de Segurança:** Um atacante pode personificar uma public client application ao requisitar tokens, já que não existe um mecanismo para o authorization server verificar a legitimidade da aplicação.
|
||||
|
||||
### ROPC / Password Grant
|
||||
|
||||
O OAuth2 **Resource Owner Password Credentials** (**ROPC**) flow usa um POST direto para `https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token` com `grant_type=password`, um **username**, **password**, um **client_id**, e o **scope** solicitado. Em Entra ID isto é principalmente interessante para **public clients** porque o atacante pode reutilizar Microsoft first-party client IDs ou qualquer outro public client permitido sem precisar de um secret.
|
||||
```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"
|
||||
```
|
||||
Se as credenciais forem válidas e o fluxo for permitido, Entra pode retornar **access tokens** e às vezes **refresh tokens** que são imediatamente utilizáveis contra Microsoft Graph ou o recurso alvo.
|
||||
|
||||
### Entra ID Sign-In Log Bypass Classes
|
||||
|
||||
Alguns bugs históricos do Entra ID permitiam **password validation** ou até mesmo **full token issuance** sem gerar a esperada entrada no **registro de autenticação do Entra ID**. Esses casos foram corrigidos, mas as técnicas ainda são úteis para entender como pipelines de autenticação podem falhar de formas que deixam o **uso downstream de tokens visível** enquanto a **telemetria de sign-in a montante está ausente**.
|
||||
|
||||
#### 1. Endpoint de tenant estrangeiro para stealth password validation
|
||||
|
||||
Se a requisição for enviada ao token endpoint de um **different tenant GUID**, Entra ainda pode validar se a senha enviada está correta para o username fornecido antes do fluxo falhar porque o usuário não existe naquele tenant estrangeiro. Historicamente isso permitia:
|
||||
|
||||
- **Password spraying / credential validation** sem um log de sign-in correspondente no tenant da vítima
|
||||
- Uma diferença na resposta que revela se a etapa de senha teve sucesso
|
||||
- Nenhuma emissão de token, mas menos telemetria do que um logon falho normal
|
||||
|
||||
#### 2. Forçar uma falha pós-senha
|
||||
|
||||
Se um parâmetro usado **após** a credential validation for inválido, como um `client_id` inválido, a transação geral pode falhar mesmo que a senha já estivesse correta. Historicamente isso produzia uma visão de login **falho** enquanto ocultava que a tentativa de adivinhação da senha havia sido bem-sucedida.
|
||||
|
||||
O padrão a lembrar é:
|
||||
|
||||
- **Password check succeeds**
|
||||
- Uma etapa de validação posterior falha
|
||||
- O log representa o estado final da transação mas não o passo bem-sucedido de password-validation
|
||||
|
||||
#### 3. Acionar falha de logging com valores válidos porém oversized
|
||||
|
||||
A classe mais perigosa é quando a requisição permanece sintaticamente válida, a autenticação tem sucesso, **tokens are returned**, mas algum **campo registrado** é grande o suficiente para quebrar o pipeline de logging. Exemplos reportados incluíam:
|
||||
|
||||
- Repetir scopes válidos milhares de vezes, como `openid openid openid ...`
|
||||
- Fornecer um header **User-Agent** excessivamente longo mas ainda aceito
|
||||
|
||||
Isso sugere uma classe geral de problemas onde:
|
||||
|
||||
1. Entra valida credenciais e a sintaxe da requisição
|
||||
2. O token é emitido com sucesso
|
||||
3. O mecanismo de logging tenta persistir um campo bruto controlado pelo usuário
|
||||
4. A escrita de logging falha por causa do tamanho ou de suposições de esquema
|
||||
5. O usuário obtém um token válido sem um registro de autenticação correspondente
|
||||
|
||||
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)"
|
||||
```
|
||||
#### Hunting / nota defensiva
|
||||
|
||||
Não assuma que todo uso válido de token terá um evento de Entra sign-in correspondente. Ao investigar atividade suspeita no Graph, correlacione:
|
||||
|
||||
- **Logs de sign-in não interativos**
|
||||
- **Graph Activity Logs**
|
||||
- **endereço IP**, **ID de usuário/objeto**, **identificadores de sessão/correlação** e **janelas de tempo**
|
||||
|
||||
Um método prático de validação é enquadrar um sucesso invisível suspeito entre dois logons normais falhos e então verificar se a sequência esperada `Failed -> Successful -> Failed` está faltando o evento do meio após o atraso de ingestão. Se existir atividade downstream no Graph mas o log de sign-in não estiver presente, trate como uma potencial **sign-in logging gap** ou condição de **token replay**.
|
||||
|
||||
## Tokens de Autenticação
|
||||
|
||||
Existem **três tipos de tokens** usados em OIDC:
|
||||
|
||||
- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** O cliente apresenta esse token ao resource server para **acessar recursos**. Pode ser usado apenas para uma combinação específica de usuário, client e resource e **não pode ser revogado** até expirar — isto é 1 hora por padrão.
|
||||
- **ID Tokens**: O cliente recebe esse **token do authorization server**. Contém informações básicas sobre o usuário. É **vinculado a uma combinação específica de usuário e client**.
|
||||
- **Refresh Tokens**: Fornecidos ao cliente junto com o access token. Usados para **obter novos access e ID tokens**. São vinculados a uma combinação específica de usuário e client e podem ser revogados. A expiração padrão é **90 dias** para refresh tokens inativos e **sem expiração para tokens ativos** (a partir de um refresh token é possível obter novos refresh tokens).
|
||||
- Um refresh token deve estar atrelado a um **`aud`**, a alguns **scopes**, e a um **tenant** e só deve ser capaz de gerar access tokens para aquele aud, scopes (e nada mais) e tenant. Porém, isso não acontece com os tokens de aplicações **FOCI**.
|
||||
- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** O cliente apresenta este token ao resource server para **acessar recursos**. Pode ser usado apenas para uma combinação específica de usuário, cliente e recurso e **cannot be revoked** até expirar - isto é 1 hora por padrão.
|
||||
- **ID Tokens**: O cliente recebe este **token do authorization server**. Contém informações básicas sobre o usuário. Está **bound to a specific combination of user and client**.
|
||||
- **Refresh Tokens**: Fornecido ao cliente com o access token. Usado para **obter novos access e ID tokens**. Está ligado a uma combinação específica de usuário e cliente e pode ser revogado. O tempo padrão de expiração é **90 days** para refresh tokens inativos e **no expiry for active tokens** (porque a partir de um refresh token é possível obter novos refresh tokens).
|
||||
- Um refresh token deve estar vinculado a um **`aud`**, a alguns **scopes**, e a um **tenant** e deve ser capaz de gerar access tokens apenas para esse aud, scopes (e nada mais) e tenant. No entanto, isso não é o caso com **FOCI applications tokens**.
|
||||
- Um refresh token é criptografado e somente a Microsoft pode descriptografá-lo.
|
||||
- Obter um novo refresh token não revoga o refresh token anterior.
|
||||
|
||||
> [!WARNING]
|
||||
> Informações para **acesso condicional** são **armazenadas** dentro do **JWT**. Então, se você requisitar o **token a partir de um endereço IP permitido**, esse **IP** será **armazenado** no token e então você pode usar esse token a partir de um **IP não permitido para acessar os recursos**.
|
||||
> Informação para **conditional access** é **armazenada** dentro do **JWT**. Então, se você solicitar o **token a partir de um endereço IP permitido**, esse **IP** será **armazenado** no token e então você poderá usar esse token a partir de um **IP não permitido para acessar os recursos**.
|
||||
|
||||
### Access Tokens "aud"
|
||||
|
||||
@@ -59,42 +132,42 @@ O campo indicado no campo "aud" é o **resource server** (a aplicação) usado p
|
||||
O comando `az account get-access-token --resource-type [...]` suporta os seguintes tipos e cada um deles adicionará um "aud" específico no access token resultante:
|
||||
|
||||
> [!CAUTION]
|
||||
> Note que os seguintes são apenas as APIs suportadas por `az account get-access-token`, mas existem mais.
|
||||
> Note que os itens a seguir são apenas as APIs suportadas por `az account get-access-token` mas existem mais.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>aud examples</summary>
|
||||
<summary>exemplos de aud</summary>
|
||||
|
||||
- **aad-graph (Azure Active Directory Graph API)**: Usado para acessar a legacy Azure AD Graph API (deprecated), que permite às aplicações ler e escrever dados de diretório no Azure Active Directory (Azure AD).
|
||||
- **aad-graph (Azure Active Directory Graph API)**: Usado para acessar a legada Azure AD Graph API (deprecated), que permite que aplicações leiam e escrevam dados de diretório no Azure Active Directory (Azure AD).
|
||||
- `https://graph.windows.net/`
|
||||
|
||||
* **arm (Azure Resource Manager)**: Usado para gerenciar recursos do Azure através da Azure Resource Manager API. Isso inclui operações como criar, atualizar e deletar recursos como virtual machines, storage accounts e mais.
|
||||
* **arm (Azure Resource Manager)**: Usado para gerenciar recursos do Azure através da Azure Resource Manager API. Isso inclui operações como criar, atualizar e excluir recursos como máquinas virtuais, contas de armazenamento e mais.
|
||||
- `https://management.core.windows.net/ or https://management.azure.com/`
|
||||
|
||||
- **batch (Azure Batch Services)**: Usado para acessar Azure Batch, um serviço que permite aplicações de computação paralela e de alto desempenho em grande escala na nuvem.
|
||||
- **batch (Azure Batch Services)**: Usado para acessar o Azure Batch, um serviço que possibilita aplicações de computação paralela em larga escala e de alto desempenho de forma eficiente na nuvem.
|
||||
- `https://batch.core.windows.net/`
|
||||
|
||||
* **data-lake (Azure Data Lake Storage)**: Usado para interagir com Azure Data Lake Storage Gen1, que é um serviço escalável de armazenamento de dados e analytics.
|
||||
* **data-lake (Azure Data Lake Storage)**: Usado para interagir com o Azure Data Lake Storage Gen1, que é um serviço escalável de armazenamento de dados e análise.
|
||||
- `https://datalake.azure.net/`
|
||||
|
||||
- **media (Azure Media Services)**: Usado para acessar Azure Media Services, que fornece processamento e entrega de mídia na nuvem para conteúdo de vídeo e áudio.
|
||||
- **media (Azure Media Services)**: Usado para acessar o Azure Media Services, que fornece serviços baseados em nuvem para processamento e entrega de mídia de vídeo e áudio.
|
||||
- `https://rest.media.azure.net`
|
||||
|
||||
* **ms-graph (Microsoft Graph API)**: Usado para acessar a Microsoft Graph API, o endpoint unificado para dados dos serviços Microsoft 365. Permite acessar dados e insights de serviços como Azure AD, Office 365, Enterprise Mobility e Security services.
|
||||
* **ms-graph (Microsoft Graph API)**: Usado para acessar a Microsoft Graph API, o endpoint unificado para dados dos serviços do Microsoft 365. Permite acessar dados e insights de serviços como Azure AD, Office 365, Enterprise Mobility e serviços de Segurança.
|
||||
- `https://graph.microsoft.com`
|
||||
|
||||
- **oss-rdbms (Azure Open Source Relational Databases)**: Usado para acessar serviços de Database do Azure para engines relacionais open-source como MySQL, PostgreSQL e MariaDB.
|
||||
- **oss-rdbms (Azure Open Source Relational Databases)**: Usado para acessar serviços de banco de dados do Azure para motores relacionais open-source como MySQL, PostgreSQL e MariaDB.
|
||||
- `https://ossrdbms-aad.database.windows.net`
|
||||
|
||||
</details>
|
||||
|
||||
### Access Tokens Scopes "scp"
|
||||
|
||||
O escopo de um access token é armazenado dentro da chave scp dentro do JWT do access token. Esses scopes definem a que o access token tem acesso.
|
||||
O escopo de um access token é armazenado dentro da chave scp dentro do access token JWT. Esses scopes definem a que o access token tem acesso.
|
||||
|
||||
Se um JWT está autorizado a contatar uma API específica mas **não tem o scope** para executar a ação requerida, ele **não conseguirá executar a ação** com aquele JWT.
|
||||
Se um JWT estiver autorizado a contatar uma API específica mas **não tiver o scope** para executar a ação solicitada, **não será capaz de executar a ação** com esse JWT.
|
||||
|
||||
### Exemplo de obtenção de refresh & access token
|
||||
### Get refresh & access token example
|
||||
```python
|
||||
# Code example from https://github.com/secureworks/family-of-client-ids-research
|
||||
import msal
|
||||
@@ -144,28 +217,27 @@ scopes=["https://graph.microsoft.com/.default"],
|
||||
)
|
||||
pprint(new_azure_cli_bearer_tokens_for_graph_api)
|
||||
```
|
||||
### Outros campos do access token
|
||||
### Other access token fields
|
||||
|
||||
- **appid**: Application ID usada para gerar o token
|
||||
- **appidacr**: The Application Authentication Context Class Reference indica como o client foi autenticado; para um public client o valor é 0, e se um client secret foi usado o valor é 1
|
||||
- **acr**: The Authentication Context Class Reference claim é "0" quando a autenticação do usuário final não atendeu aos requisitos da ISO/IEC 29115.
|
||||
- **amr**: Indica como o token foi autenticado. Um valor de “pwd” indica que uma senha foi usada.
|
||||
- **appid**: ID da application usado para gerar o token
|
||||
- **appidacr**: O Application Authentication Context Class Reference indica como o cliente foi autenticado; para um cliente público o valor é 0, e se um client secret for usado o valor é 1
|
||||
- **acr**: A claim Authentication Context Class Reference é "0" quando a autenticação do usuário final não atendeu aos requisitos da ISO/IEC 29115.
|
||||
- **amr**: O método de autenticação indica como o token foi autenticado. Um valor “pwd” indica que uma password foi usada.
|
||||
- **groups**: Indica os grupos dos quais o principal é membro.
|
||||
- **iss**: O issuer identifica o security token service (STS) que gerou o token. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (the uuid is the tenant ID)
|
||||
- **iss**: O issuer identifica o security token service (STS) que gerou o token. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (o uuid é o tenant ID)
|
||||
- **oid**: O object ID do principal
|
||||
- **tid**: Tenant ID
|
||||
- **iat, nbf, exp**: Issued at (quando foi emitido), Not before (não pode ser usado antes deste momento, normalmente mesmo valor que iat), Expiration time (tempo de expiração).
|
||||
- **iat, nbf, exp**: Issued at (quando foi emitido), Not before (não pode ser usado antes deste horário, geralmente mesmo valor que iat), Expiration time.
|
||||
|
||||
## FOCI Tokens Privilege Escalation
|
||||
|
||||
## Escalonamento de privilégios com FOCI Tokens
|
||||
Anteriormente foi mencionado que refresh tokens deveriam estar vinculados aos **scopes** com os quais foram gerados, à **application** e ao **tenant** para os quais foram emitidos. Se qualquer uma dessas fronteiras for quebrada, é possível escalar privilégios, pois será possível gerar tokens de acesso para outros recursos e tenants aos quais o usuário tem acesso e com mais scopes do que originalmente pretendido.
|
||||
|
||||
Anteriormente foi mencionado que refresh tokens devem estar vinculados aos **scopes** com que foram gerados, à **application** e ao **tenant** para os quais foram gerados. Se alguma dessas fronteiras for quebrada, é possível escalar privilégios, pois será possível gerar access tokens para outros recursos e tenants aos quais o usuário tem acesso e com mais scopes do que o originalmente pretendido.
|
||||
Além disso, isto é possível com todos os refresh tokens na [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/) (Microsoft Entra accounts, Microsoft personal accounts, e contas sociais como Facebook e Google) porque, como as [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens) mencionam: "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."
|
||||
|
||||
Além disso, **isso é possível com todos os refresh tokens** na [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) porque como os [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens) mencionam: "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."
|
||||
Observe também que as FOCI applications são public applications, portanto **no secret is needed** para autenticar no servidor.
|
||||
|
||||
Além disso, note que as aplicações FOCI são public applications, então **nenhum secret é necessário** para autenticar ao servidor.
|
||||
|
||||
Os FOCI clients conhecidos reportados na [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main) podem ser [**found here**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv).
|
||||
Os FOCI clients conhecidos reportados na [**pesquisa original**](https://github.com/secureworks/family-of-client-ids-research/tree/main) podem ser [**encontrados aqui**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv).
|
||||
|
||||
### Get different scope
|
||||
|
||||
@@ -186,7 +258,7 @@ scopes=[
|
||||
)
|
||||
pprint(azure_cli_bearer_tokens_for_outlook_api)
|
||||
```
|
||||
### Obter client e scopes diferentes
|
||||
### Obter cliente e escopos diferentes
|
||||
```python
|
||||
# Code from https://github.com/secureworks/family-of-client-ids-research
|
||||
microsoft_office_client = msal.PublicClientApplication("d3590ed6-52b3-4102-aeff-aad2292ab01c")
|
||||
@@ -204,32 +276,32 @@ pprint(microsoft_office_bearer_tokens_for_graph_api)
|
||||
```
|
||||
## NAA / BroCI (Nested App Authentication / Broker Client Injection)
|
||||
|
||||
A BroCI refresh tokens é um padrão de troca de token brokered onde um refresh token existente é usado com parâmetros adicionais do broker para solicitar tokens como outro first-party app confiável.
|
||||
A BroCI refresh token é um padrão de brokered token exchange onde um refresh token existente é usado com parâmetros adicionais do broker para solicitar tokens como outra first-party app confiável.
|
||||
|
||||
These refresh tokens must be minted in that broker context (a regular refresh token usually cannot be used as a BroCI refresh token).
|
||||
Esses refresh tokens precisam ser mintados nesse contexto de broker (um refresh token normal geralmente não pode ser usado como um BroCI refresh token).
|
||||
|
||||
### Goal and purpose
|
||||
|
||||
O objetivo do BroCI é reutilizar uma sessão de usuário válida de uma cadeia de apps com suporte a broker e solicitar tokens para outro par app/recurso confiável. Portanto, permitindo "escalar privilégios" a partir do token original.
|
||||
O objetivo do BroCI é reutilizar uma sessão de usuário válida de uma cadeia de apps com capacidade de broker e solicitar tokens para outro par app/recurso confiável. Assim, permitindo "escalar privilégios" a partir do token original.
|
||||
|
||||
Do ponto de vista ofensivo, isso importa porque:
|
||||
|
||||
- Pode desbloquear caminhos de first-party app pré-consentidos que não são acessíveis com trocas de refresh padrão.
|
||||
- Pode desbloquear caminhos de first-party apps com consent prévio que não são acessíveis com refresh exchanges padrão.
|
||||
- Pode retornar access tokens para APIs de alto valor (por exemplo, Microsoft Graph) sob identidades de app com permissões delegadas amplas.
|
||||
- Expande as oportunidades de pivot pós-autenticação com tokens além da troca clássica de clientes FOCI.
|
||||
- Expande oportunidades de pivot pós-autenticação com tokens além do clássico FOCI client switching.
|
||||
|
||||
O que muda em um NAA/BroCI refresh token não é o formato visível do token, mas o **contexto de emissão** e os metadados relacionados ao broker que a Microsoft valida durante operações de refresh brokered.
|
||||
|
||||
NAA/BroCI token exchanges não são a mesma coisa que uma troca OAuth refresh regular.
|
||||
NAA/BroCI token exchanges não são o mesmo que um OAuth refresh exchange regular.
|
||||
|
||||
- Um refresh token regular (por exemplo obtido via device code flow) geralmente é válido para operações padrão `grant_type=refresh_token`.
|
||||
- Um refresh token regular (por exemplo obtido via device code flow) normalmente é válido para operações padrão `grant_type=refresh_token`.
|
||||
- Uma requisição BroCI inclui contexto adicional do broker (`brk_client_id`, broker `redirect_uri`, e `origin`).
|
||||
- A Microsoft valida se o refresh token apresentado foi emitido em um contexto brokered correspondente.
|
||||
- Portanto, muitos refresh tokens "normais" falham em requisições BroCI com erros como `AADSTS900054` ("Specified Broker Client ID does not match ID in provided grant").
|
||||
- Geralmente você não pode "converter" um refresh token normal em um válido para BroCI via código.
|
||||
- Geralmente você não pode "converter" um refresh token normal em um válido para BroCI em código.
|
||||
- Você precisa de um refresh token já emitido por um fluxo brokered compatível.
|
||||
|
||||
Check the web <https://entrascopes.com/> to find BroCI configured apps an the trust relationships they have.
|
||||
Consulte o site <https://entrascopes.com/> para encontrar apps configurados para BroCI e os relacionamentos de confiança que eles têm.
|
||||
|
||||
|
||||
### Mental model
|
||||
@@ -238,24 +310,24 @@ Pense no BroCI como:
|
||||
|
||||
`user session -> brokered refresh token issuance -> brokered refresh call (brk_client_id + redirect_uri + origin) -> access token for target trusted app/resource`
|
||||
|
||||
Se qualquer parte dessa cadeia de broker não coincidir, a troca falha.
|
||||
Se qualquer parte dessa cadeia de broker não corresponder, a troca falha.
|
||||
|
||||
### Where to find a BroCI-valid refresh token
|
||||
|
||||
Uma maneira prática é coletar o tráfego do portal no navegador:
|
||||
Uma forma prática é coletar tráfego do portal no browser:
|
||||
|
||||
1. Sign in to `https://entra.microsoft.com` (or Azure portal).
|
||||
2. Open DevTools -> Network.
|
||||
3. Filter for:
|
||||
1. Faça sign in em `https://entra.microsoft.com` (ou Azure portal).
|
||||
2. Abra DevTools -> Network.
|
||||
3. Filtre por:
|
||||
- `oauth2/v2.0/token`
|
||||
- `management.core.windows.net`
|
||||
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).
|
||||
4. Identifique a resposta de token brokered e copie o `refresh_token`.
|
||||
5. Use esse refresh token com os parâmetros BroCI correspondentes (`brk_client_id`, `redirect_uri`, `origin`) ao solicitar tokens para apps alvo (por exemplo cenários ADIbizaUX / Microsoft_Azure_PIMCommon).
|
||||
|
||||
### 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`: O contexto do refresh token não corresponde à tupla de broker fornecida (`brk_client_id` / `redirect_uri` / `origin`) ou o token não é de um fluxo portal brokered.
|
||||
- `AADSTS7000218`: O fluxo de cliente selecionado espera uma credencial confidencial (`client_secret`/assertion), frequentemente visto ao tentar device code com um cliente não-public.
|
||||
|
||||
<details>
|
||||
<summary>Python BroCI refresh helper (broci_auth.py)</summary>
|
||||
@@ -533,24 +605,24 @@ raise SystemExit(main())
|
||||
|
||||
## Onde encontrar tokens
|
||||
|
||||
Do ponto de vista de um atacante, é muito interessante saber onde é possível encontrar access and refresh tokens quando, por exemplo, o PC de uma vítima é comprometido:
|
||||
Do ponto de vista de um atacante, é muito útil saber onde é possível encontrar access tokens e refresh tokens quando, por exemplo, o PC de uma vítima é comprometido:
|
||||
|
||||
- Dentro de **`<HOME>/.Azure`**
|
||||
- **`azureProfile.json`** contém informações sobre usuários que fizeram login no passado
|
||||
- **`clouds.config contains`** contém informações sobre assinaturas
|
||||
- **`service_principal_entries.json`** contém credenciais de aplicações (tenant id, clients e secret). Apenas em Linux & macOS
|
||||
- Inside **`<HOME>/.Azure`**
|
||||
- **`azureProfile.json`** contém informações sobre usuários que fizeram login anteriormente
|
||||
- **`clouds.config`** contém informações sobre assinaturas
|
||||
- **`service_principal_entries.json`** contém credenciais de aplicações (tenant id, clients and secret). Apenas em Linux & macOS
|
||||
- **`msal_token_cache.json`** contém access tokens e refresh tokens. Apenas em Linux & macOS
|
||||
- **`service_principal_entries.bin`** e **`msal_token_cache.bin`** são usados no Windows e são encriptados com DPAPI
|
||||
- **`service_principal_entries.bin`** e `msal_token_cache.bin` são usados no Windows e estão criptografados com DPAPI
|
||||
- **`msal_http_cache.bin`** é um cache de requisições HTTP
|
||||
- Carregue-o: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)`
|
||||
- Load it: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)`
|
||||
- **`AzureRmContext.json`** contém informação sobre logins anteriores usando Az PowerShell (mas sem credenciais)
|
||||
- Dentro de **`C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\*`** há vários ficheiros `.bin` com **access tokens**, ID tokens e informação de conta encriptada com o DPAPI do usuário.
|
||||
- É possível encontrar mais **access tokens** nos ficheiros `.tbres` dentro de **`C:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\`**, que contêm um base64 encriptado com DPAPI com access tokens.
|
||||
- No Linux e macOS você pode obter **access tokens, refresh tokens e id tokens** do Az PowerShell (se usado) executando `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"`
|
||||
- No Windows isto gera apenas id tokens.
|
||||
- É possível verificar se Az PowerShell foi usado no Linux e macOS checando se `$HOME/.local/share/.IdentityService/` existe (embora os ficheiros contidos sejam vazios e inúteis)
|
||||
- Se o usuário estiver **logado no Azure com o browser**, de acordo com este [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) é possível iniciar o fluxo de autenticação com um **redirect to localhost**, fazer o browser autorizar automaticamente o login e receber o refresh token. Note que existem apenas algumas aplicações FOCI que permitem redirect to localhost (como az cli ou o módulo do powershell), portanto essas aplicações devem ser permitidas.
|
||||
- Outra opção explicada no blog é usar a ferramenta [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow) que pode usar qualquer aplicação porque ela irá **get the OAuth code to then get a refresh token from the title of the final auth** page usando o redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`.
|
||||
- Inside **`C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\*`** há vários arquivos `.bin` com **access tokens**, ID tokens e informações de conta criptografadas com o DPAPI do usuário.
|
||||
- É possível encontrar mais **access tokens** nos arquivos `.tbres` dentro de **`C:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\`** que contêm um base64 criptografado com DPAPI contendo access tokens.
|
||||
- Em Linux e macOS você pode obter **access tokens, refresh tokens e id tokens** do Az PowerShell (se usado) executando `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"`
|
||||
- No Windows isso gera apenas id tokens.
|
||||
- É possível verificar se o Az PowerShell foi usado em Linux e macOS checando se `$HOME/.local/share/.IdentityService/` existe (embora os arquivos contidos sejam vazios e inúteis)
|
||||
- Se o usuário estiver **logado no Azure com o browser**, de acordo com este [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) é possível iniciar o fluxo de autenticação com um **redirecionamento para localhost**, fazer o browser autorizar automaticamente o login e receber o refresh token. Note que há apenas algumas aplicações FOCI que permitem redirection para localhost (como az cli ou o módulo PowerShell), então essas aplicações devem estar autorizadas.
|
||||
- Outra opção explicada no blog é usar a ferramenta [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow) que pode usar qualquer aplicação porque ela irá **obter o código OAuth para então pegar um refresh token a partir do título da página final de autenticação** usando o redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`.
|
||||
|
||||
## Referências
|
||||
|
||||
@@ -558,5 +630,6 @@ Do ponto de vista de um atacante, é muito interessante saber onde é possível
|
||||
- [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