Translated ['', 'src/pentesting-cloud/azure-security/az-basic-informatio

This commit is contained in:
Translator
2026-03-31 16:57:16 +00:00
parent b99958d260
commit 6dccb992d8
@@ -4,83 +4,156 @@
## Informazioni di base
Entra ID è la piattaforma Microsoft per la gestione delle identità e degli accessi (IAM) basata sul cloud, che funge da sistema fondamentale di autenticazione e autorizzazione per servizi come Microsoft 365 e Azure Resource Manager. Azure AD implementa il framework di autorizzazione OAuth 2.0 e il protocollo di autenticazione OpenID Connect (OIDC) per gestire l'accesso alle risorse.
Entra ID è la piattaforma Microsoft basata sul cloud per identity and access management (IAM), che funge da sistema fondamentale di autenticazione e autorizzazione per servizi come Microsoft 365 e Azure Resource Manager. Azure AD implementa il framework di autorizzazione OAuth 2.0 e il protocollo di autenticazione OpenID Connect (OIDC) per gestire l'accesso alle risorse.
### OAuth
**Partecipanti chiave in OAuth 2.0:**
1. **Server di risorse (RS):** Protegge le risorse possedute dal proprietario della risorsa.
2. **Proprietario della risorsa (RO):** Tipicamente un utente finale che possiede le risorse protette.
3. **Applicazione client (CA):** Un'applicazione che richiede accesso alle risorse per conto del proprietario della risorsa.
4. **Server di autorizzazione (AS):** Emette access token alle applicazioni client dopo averle autenticato e autorizzate.
1. **Resource Server (RS):** Protegge le risorse di proprietà del resource owner.
2. **Resource Owner (RO):** Tipicamente un utente finale che possiede le risorse protette.
3. **Client Application (CA):** Un'applicazione che richiede accesso alle risorse per conto del resource owner.
4. **Authorization Server (AS):** Emette access token alle applicazioni client dopo averle autenticato e autorizzato.
**Ambiti e Consenso:**
**Scope e Consenso:**
- **Ambiti (Scopes):** Permessi granulari definiti sul server di risorse che specificano i livelli di accesso.
- **Consenso:** Il processo mediante il quale il proprietario della risorsa concede a un'applicazione client il permesso di accedere alle risorse con ambiti specifici.
- **Scopes:** Permessi granulari definiti sul resource server che specificano i livelli di accesso.
- **Consent:** Il processo tramite cui il resource owner concede a una client application il permesso di accedere a risorse con scope specifici.
**Integrazione con Microsoft 365:**
- Microsoft 365 utilizza Azure AD per IAM ed è composto da molteplici applicazioni OAuth "first-party".
- Microsoft 365 utilizza Azure AD per l'IAM ed è composto da molteplici applicazioni OAuth "first-party".
- Queste applicazioni sono profondamente integrate e spesso hanno relazioni di servizio interdipendenti.
- Per semplificare l'esperienza utente e mantenere la funzionalità, Microsoft concede "implied consent" o "pre-consent" a queste applicazioni first-party.
- **Implied Consent:** Alcune applicazioni vengono automaticamente **concesse l'accesso a specifici ambiti senza il consenso esplicito dell'utente o dell'amministratore**.
- Questi ambiti pre-consentiti sono tipicamente nascosti sia agli utenti sia agli amministratori, rendendoli meno visibili nelle interfacce di gestione standard.
- **Implied Consent:** Alcune applicazioni vengono automaticamente **concesse l'accesso a scope specifici senza l'approvazione esplicita dell'utente o dell'amministratore**.
- Questi scope pre-consentiti sono tipicamente nascosti sia agli utenti che agli amministratori, rendendoli meno visibili nelle interfacce di gestione standard.
**Tipi di Applicazioni Client:**
**Tipi di Client Application:**
1. **Confidential Clients:**
- Possiedono credenziali proprie (es. password o certificati).
- Possono **autenticarsi in modo sicuro** al server di autorizzazione.
- Possiedono proprie credenziali (es. password o certificati).
- Possono **autenticarsi in modo sicuro** all'authorization server.
2. **Public Clients:**
- Non hanno credenziali uniche.
- Non possono autenticarsi in modo sicuro al server di autorizzazione.
- **Implicazione di sicurezza:** Un attaccante può impersonare un'applicazione client pubblica quando richiede token, poiché non esiste un meccanismo per il server di autorizzazione per verificare la legittimità dell'applicazione.
- Non possono autenticarsi in modo sicuro all'authorization server.
- **Implicazione di sicurezza:** Un attaccante può impersonare un'applicazione client pubblica quando richiede token, poiché non esiste un meccanismo per l'authorization server per verificare la legittimità dell'applicazione.
## Token di Autenticazione
### ROPC / Password Grant
Il flow OAuth2 **Resource Owner Password Credentials** (**ROPC**) utilizza una POST diretta a `https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token` con `grant_type=password`, un `username`, `password`, un `client_id` e lo `scope` richiesto. In Entra ID questo è principalmente interessante per i **public clients** perché un attaccante può riutilizzare client ID first-party di Microsoft o qualsiasi altro public client consentito senza bisogno di un 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 le credenziali sono valide e il flusso è consentito, Entra può restituire **access tokens** e talvolta **refresh tokens** utilizzabili immediatamente contro Microsoft Graph o la risorsa di destinazione.
### Classi di bypass del Sign-In Log di Entra ID
Alcuni bug storici di Entra ID permettevano la **password validation** o perfino la **full token issuance** senza generare la prevista voce del **Entra ID sign-in log**. Questi casi sono stati corretti, ma le tecniche sono ancora utili per capire come le pipeline di autenticazione possano fallire in modi che lasciano l'**uso del token a valle visibile** mentre la **telemetria di sign-in a monte è assente**.
#### 1. Endpoint di tenant esterno per stealth password validation
Se la richiesta viene inviata all'endpoint token di un **different tenant GUID**, Entra può comunque verificare se la password inviata è corretta per lo username fornito prima che il flusso fallisca perché l'utente non esiste in quel tenant esterno. Storicamente questo permetteva:
- **Password spraying / credential validation** senza un corrispondente sign-in log nel tenant vittima
- Una differenza nella risposta che rivela se il passo della password ha avuto successo
- Nessuna token issuance, ma meno telemetria rispetto a un normale failed logon
#### 2. Forzare un post-password failure
Se un parametro usato **after** credential validation è invalido, come un `client_id` non valido, l'intera transazione può fallire anche se la password era già corretta. Storicamente questo generava una vista di login **failed** nascondendo il fatto che il tentativo di password aveva avuto successo.
Lo schema da ricordare è:
- **La verifica della password ha successo**
- Un successivo step di validazione fallisce
- Il log rappresenta lo stato finale della transazione ma non lo step di verifica della password che era andato a buon fine
#### 3. Innescare un malfunzionamento del logging con valori troppo lunghi ma validi
La classe più pericolosa è quando la richiesta rimane sintatticamente valida, l'autenticazione ha successo, **tokens are returned**, ma qualche **logged field** è così grande da rompere la pipeline di logging. Esempi riportati includevano:
- Ripetere scope validi migliaia di volte, ad esempio `openid openid openid ...`
- Fornire un header **User-Agent** eccessivamente lungo ma comunque accettato
Questo suggerisce una classe generale di problemi in cui:
1. Entra valida le credenziali e la sintassi della richiesta
2. Il token viene emesso con successo
3. Il logging tenta di persistere un campo grezzo controllato dall'utente
4. La scrittura del log fallisce a causa di limiti di lunghezza o assunzioni sullo schema
5. L'utente ottiene un token valido senza un corrispondente record di sign-in
Esempio del pattern di scope ripetuti:
```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)"
```
#### Nota Hunting / difensiva
Non presumere che ogni utilizzo di un token valido abbia un evento di sign-in di Entra corrispondente. Quando indaghi attività Graph sospette, correlare:
- **Log di sign-in non interattivi**
- **Graph Activity Logs**
- **indirizzo IP**, **user/object ID**, **identificatori di sessione/correlazione** e **finestre temporali**
Un metodo pratico di validazione consiste nel racchiudere un sospetto successo invisibile tra due normali logon falliti e poi verificare se la sequenza prevista `Failed -> Successful -> Failed` manca dell'evento centrale dopo il ritardo di ingestion. Se esiste attività Graph a valle ma non il log di sign-in, trattalo come una potenziale **lacuna nei log di sign-in** o una condizione di **token replay**.
## Authentication Tokens
Esistono **tre tipi di token** usati in OIDC:
- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** Il client presenta questo token al resource server per **accedere alle risorse**. Può essere usato solo per una specifica combinazione di utente, client e risorsa e **non può essere revocato** fino alla scadenza - che per default è 1 ora.
- **ID Tokens**: Il client riceve questo **token dal server di autorizzazione**. Contiene informazioni di base sull'utente. È **vincolato a una specifica combinazione di utente e client**.
- **Refresh Tokens**: Forniti al client insieme all'access token. Usati per **ottenere nuovi access e ID token**. Sono vincolati a una specifica combinazione di utente e client e possono essere revocati. La scadenza di default è **90 giorni** per i refresh token inattivi e **nessuna scadenza per i token attivi** (essendo possibile ottenere nuovi refresh token da un refresh token).
- Un refresh token dovrebbe essere legato a un `aud`, ad alcuni **scopes**, e a un **tenant** e dovrebbe essere in grado di generare solo access token per quell'aud, quegli scopes (e non oltre) e quel tenant. Tuttavia, questo non è il caso con i **token delle applicazioni FOCI**.
- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** Il client presenta questo token al resource server per **accedere alle risorse**. Può essere usato solo per una specifica combinazione di utente, client e risorsa e **non può essere revocato** fino alla scadenza - che è 1 ora per default.
- **ID Tokens**: Il client riceve questo **token dall'authorization server**. Contiene informazioni di base sull'utente. È **vincolato a una specifica combinazione di utente e client**.
- **Refresh Tokens**: Forniti al client insieme all'access token. Usati per **ottenere nuovi access token e ID token**. Sono vincolati a una specifica combinazione di utente e client e possono essere revocati. La scadenza predefinita è **90 giorni** per i refresh token inattivi e **nessuna scadenza per i token attivi** (da un refresh token è possibile ottenere nuovi refresh token).
- Un refresh token dovrebbe essere legato a un **`aud`**, a certi **scopes**, e a un **tenant** e dovrebbe poter generare access token solo per quell'aud, quegli scopes (e nient'altro) e tenant. Tuttavia, questo non è il caso con i **FOCI applications tokens**.
- Un refresh token è cifrato e solo Microsoft può decifrarlo.
- Ottenere un nuovo refresh token non revoca il precedente refresh token.
- Ottenere un nuovo refresh token non revoca il refresh token precedente.
> [!WARNING]
> Le informazioni per l'**accesso condizionale** sono **memorizzate** all'interno del **JWT**. Quindi, se richiedi il **token da un IP consentito**, quell'**IP** sarà **memorizzato** nel token e poi puoi usare quel token da un **IP non consentito per accedere alle risorse**.
> Le informazioni per il **conditional access** sono **memorizzate** all'interno del **JWT**. Quindi, se richiedi il **token da un indirizzo IP consentito**, quell'**IP** sarà **memorizzato** nel token e poi puoi usare quel token da un **IP non consentito per accedere alle risorse**.
### Access Tokens "aud"
Il valore indicato nel campo "aud" è il **resource server** (l'applicazione) utilizzato per effettuare il login.
Il valore indicato nel campo "aud" è il **resource server** (l'applicazione) usato per eseguire il login.
Il comando `az account get-access-token --resource-type [...]` supporta i seguenti tipi e ognuno di essi aggiungerà un "aud" specifico nell'access token risultante:
Il comando `az account get-access-token --resource-type [...]` supporta i seguenti tipi e ognuno di essi aggiungerà uno specifico "aud" nel access token risultante:
> [!CAUTION]
> Nota che quanto segue sono solo le API supportate da `az account get-access-token` ma ce ne sono di più.
> Nota che i seguenti sono solo le API supportate da `az account get-access-token` ma ce ne sono altre.
<details>
<summary>aud examples</summary>
- **aad-graph (Azure Active Directory Graph API)**: Usato per accedere alla legacy Azure AD Graph API (deprecata), che permette alle applicazioni di leggere e scrivere dati di directory in Azure Active Directory (Azure AD).
- **aad-graph (Azure Active Directory Graph API)**: Usato per accedere alla legacy Azure AD Graph API (deprecata), che permette alle applicazioni di leggere e scrivere dati della directory in Azure Active Directory (Azure AD).
- `https://graph.windows.net/`
* **arm (Azure Resource Manager)**: Usato per gestire le risorse Azure tramite l'API Azure Resource Manager. Questo include operazioni come creare, aggiornare e cancellare risorse come macchine virtuali, account di storage e altro.
* **arm (Azure Resource Manager)**: Usato per gestire le risorse Azure tramite l'API Azure Resource Manager. Include operazioni come creare, aggiornare e cancellare risorse come virtual machines, storage accounts e altro.
- `https://management.core.windows.net/ or https://management.azure.com/`
- **batch (Azure Batch Services)**: Usato per accedere ad Azure Batch, un servizio che abilita applicazioni di calcolo parallelo e ad alte prestazioni su larga scala nel cloud.
- **batch (Azure Batch Services)**: Usato per accedere a Azure Batch, un servizio che consente applicazioni di calcolo parallelo e ad alte prestazioni su larga scala nel cloud.
- `https://batch.core.windows.net/`
* **data-lake (Azure Data Lake Storage)**: Usato per interagire con Azure Data Lake Storage Gen1, un servizio scalabile di storage e analisi dati.
* **data-lake (Azure Data Lake Storage)**: Usato per interagire con Azure Data Lake Storage Gen1, che è un servizio scalabile di archiviazione dati e analisi.
- `https://datalake.azure.net/`
- **media (Azure Media Services)**: Usato per accedere ad Azure Media Services, che fornisce servizi cloud per l'elaborazione e la distribuzione di contenuti video e audio.
- `https://rest.media.azure.net`
* **ms-graph (Microsoft Graph API)**: Usato per accedere alla Microsoft Graph API, l'endpoint unificato per i dati dei servizi Microsoft 365. Permette di accedere a dati e informazioni da servizi come Azure AD, Office 365, Enterprise Mobility e servizi di Security.
* **ms-graph (Microsoft Graph API)**: Usato per accedere alla Microsoft Graph API, l'endpoint unificato per i dati dei servizi Microsoft 365. Permette di accedere ai dati e agli insight di servizi come Azure AD, Office 365, Enterprise Mobility e Security services.
- `https://graph.microsoft.com`
- **oss-rdbms (Azure Open Source Relational Databases)**: Usato per accedere ai servizi Database di Azure per motori relazionali open-source come MySQL, PostgreSQL e MariaDB.
@@ -88,13 +161,13 @@ Il comando `az account get-access-token --resource-type [...]` supporta i seguen
</details>
### Scope degli Access Tokens "scp"
### Access Tokens Scopes "scp"
Lo scope di un access token è memorizzato nella chiave scp all'interno del JWT dell'access token. Questi ambiti definiscono a cosa l'access token ha accesso.
Lo scope di un access token è memorizzato dentro la chiave scp nel JWT dell'access token. Questi scopes definiscono a cosa ha accesso l'access token.
Se un JWT è autorizzato a contattare una specifica API ma **non ha lo scope** per eseguire l'azione richiesta, **non sarà in grado di eseguire l'azione** con quel JWT.
### Esempio per ottenere 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,28 @@ scopes=["https://graph.microsoft.com/.default"],
)
pprint(new_azure_cli_bearer_tokens_for_graph_api)
```
### Altri campi dell'access token
### Altri campi degli access token
- **appid**: Application ID usato per generare il token
- **appidacr**: The Application Authentication Context Class Reference indica come il client è stato autenticato; per un public client il valore è 0, e se viene usato un client secret il valore è 1
- **acr**: The Authentication Context Class Reference claim è "0" quando l'autenticazione dell'utente finale non ha soddisfatto i requisiti di ISO/IEC 29115.
- **appid**: ID dell'applicazione utilizzato per generare il token
- **appidacr**: L'Application Authentication Context Class Reference indica come il client è stato autenticato; per un public client il valore è 0, e se viene usato un client secret il valore è 1
- **acr**: L'Authentication Context Class Reference claim è "0" quando l'autenticazione dell'end-user non ha soddisfatto i requisiti di ISO/IEC 29115.
- **amr**: The Authentication method indica come il token è stato autenticato. Un valore “pwd” indica che è stata usata una password.
- **groups**: Indica i gruppi di cui il principal è membro.
- **iss**: L'iss identifica lo Security Token Service (STS) che ha generato il token. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (the uuid is the tenant ID)
- **iss**: L'issuer identifica il security token service (STS) che ha generato il token. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (la uuid è il tenant ID)
- **oid**: L'object ID del principal
- **tid**: Tenant ID
- **iat, nbf, exp**: Issued at (quando è stato emesso), Not before (non può essere usato prima di questo tempo, solitamente stesso valore di iat), Expiration time.
- **iat, nbf, exp**: Issued at (quando è stato emesso), Not before (non può essere usato prima di questo momento, solitamente lo stesso valore di iat), Expiration time (tempo di scadenza).
## FOCI Tokens Privilege Escalation
In precedenza è stato menzionato che refresh tokens dovrebbero essere vincolati agli **scopes** con cui sono stati generati, all'**application** e al **tenant** a cui sono stati generati. Se uno qualsiasi di questi confini viene violato, è possibile effettuare privilege escalation poiché sarà possibile generare access tokens per altre risorse e tenant a cui l'utente ha accesso e con più scopes di quanto originariamente previsto.
In precedenza è stato menzionato che i refresh tokens dovrebbero essere legati agli **scopes** con cui sono stati generati, all'**application** e al **tenant** a cui sono stati assegnati. Se una di queste barriere viene infranta, è possibile escalate privileges in quanto sarà possibile generare access tokens verso altre risorse e tenant a cui l'utente ha accesso e con più scopes rispetto a quanto originariamente previsto.
Moreover, **this is possible with all refresh tokens** in the [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) because as the [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens) mention: "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."
Inoltre, questo è possibile con tutti i refresh tokens nella [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) perché, come menzionano le [**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."
Inoltre, nota che le FOCI applications sono public applications, quindi **no secret is needed** per autenticarsi al server.
Inoltre, nota che le FOCI applications sono public applications, quindi **non è necessario alcun secret** per autenticarsi al server.
I FOCI clients noti riportati nella [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main) possono essere [**found here**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv).
I FOCI clients noti riportati nella [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main) possono essere [**trovati qui**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv).
### Get different scope
@@ -186,7 +259,7 @@ scopes=[
)
pprint(azure_cli_bearer_tokens_for_outlook_api)
```
### Ottieni client e scopes diversi
### Ottenere client e scope diversi
```python
# Code from https://github.com/secureworks/family-of-client-ids-research
microsoft_office_client = msal.PublicClientApplication("d3590ed6-52b3-4102-aeff-aad2292ab01c")
@@ -204,32 +277,33 @@ pprint(microsoft_office_bearer_tokens_for_graph_api)
```
## NAA / BroCI (Nested App Authentication / Broker Client Injection)
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.
Un BroCI refresh token è un pattern di brokered token exchange in cui un refresh token esistente viene usato con parametri broker aggiuntivi per richiedere token come un'altra 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).
Questi refresh token devono essere emessi (minted) in quel contesto di broker (un refresh token normale di solito non può essere usato come BroCI refresh token).
### Obiettivo e scopo
Lo scopo di BroCI è riutilizzare una sessione utente valida da una catena di app compatibili con broker e richiedere token per una diversa coppia app/risorsa di fiducia. Questo permette di "escalare i privilegi" dal token originale.
L'obiettivo di BroCI è riutilizzare una sessione utente valida da una catena di app con capacità di broker e richiedere token per un'altra coppia app/risorsa trusted. Consentendo quindi di "escalate privileges" dal token originale.
Dal punto di vista offensivo, questo è importante perché:
Da una prospettiva offensiva, questo è rilevante perché:
- Può sbloccare percorsi di app first-party pre-consensuate non accessibili con normali refresh exchanges.
- Può restituire access token per API ad alto valore (per esempio, Microsoft Graph) sotto identità di app con ampi permessi delegati.
- Espande le opportunità di token pivoting post-authentication oltre il classico switching di client FOCI.
- Può sbloccare percorsi di first-party app pre-consentite non accessibili con i normali scambi di refresh.
- Può restituire access token per API ad alto valore (per esempio, Microsoft Graph) sotto identità di app con ampie delegated permissions.
- Estende le opportunità di token pivoting post-autenticazione oltre il classico FOCI client switching.
Ciò che cambia in un NAA/BroCI refresh token non è il formato visibile del token, ma il **contesto di emissione** e i metadati legati al broker che Microsoft verifica durante le operazioni di refresh brokered.
Ciò che cambia in un NAA/BroCI refresh token non è il formato visibile del token, ma il **contesto di emissione** e i metadati relativi al broker che Microsoft valida durante le operazioni di refresh brokerate.
NAA/BroCI token exchanges are **not** the same as a regular OAuth refresh exchange.
Gli scambi di token NAA/BroCI **non** sono gli stessi di un normale 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`).
- Microsoft validates whether the presented refresh token was minted in a matching brokered context.
- Therefore, many "normal" refresh tokens fail in BroCI requests with errors such as `AADSTS900054` ("Specified Broker Client ID does not match ID in provided grant").
- You generally cannot "convert" a normal refresh token into a BroCI-valid one in code.
- You need a refresh token already issued by a compatible brokered flow.
- Un refresh token normale (per esempio ottenuto tramite device code flow) è solitamente valido per le operazioni standard `grant_type=refresh_token`.
- Una richiesta BroCI include contesto broker aggiuntivo (`brk_client_id`, broker `redirect_uri`, e `origin`).
- Microsoft valida se il refresh token presentato è stato emesso in un contesto broker corrispondente.
- Di conseguenza, molti refresh token "normali" falliscono nelle richieste BroCI con errori come `AADSTS900054` ("Specified Broker Client ID does not match ID in provided grant").
- Generalmente non puoi "convertire" un refresh token normale in uno valido per BroCI via codice.
- Ti serve un refresh token già emesso da un flow brokered compatibile.
Check the web **<https://entrascopes.com/>** to find BroCI configured apps an the trust relationships they have.
Check the web **<https://entrascopes.com/>** to find BroCI configured apps and the trust relationships they have.
### Modello mentale
@@ -239,22 +313,22 @@ Pensa a BroCI come:
Se una qualsiasi parte di quella catena broker non corrisponde, lo scambio fallisce.
### Dove trovare un BroCI-valid refresh token
### Dove trovare un refresh token valido per BroCI
One practical way is browser portal traffic collection:
Un modo pratico è la raccolta del traffico del portale nel browser:
1. Accedi a `https://entra.microsoft.com` (or Azure portal).
1. Effettua il login su `https://entra.microsoft.com` (o Azure portal).
2. Apri DevTools -> Network.
3. Filtra per:
- `oauth2/v2.0/token`
- `management.core.windows.net`
4. Individua la risposta contenente il token brokered e copia `refresh_token`.
4. Identifica la risposta del token brokerato e copia `refresh_token`.
5. Usa quel refresh token con i parametri BroCI corrispondenti (`brk_client_id`, `redirect_uri`, `origin`) quando richiedi token per app target (per esempio scenari ADIbizaUX / Microsoft_Azure_PIMCommon).
### Errori comuni
- `AADSTS900054`: Il contesto del refresh token non corrisponde alla tupla broker fornita (`brk_client_id` / `redirect_uri` / `origin`) o il token non proviene da un flow portal brokered.
- `AADSTS7000218`: Il client flow selezionato richiede una credenziale confidenziale (`client_secret`/assertion), spesso visto quando si prova device code con un client non pubblico.
- `AADSTS900054`: Il contesto del refresh token non corrisponde alla tupla broker fornita (`brk_client_id` / `redirect_uri` / `origin`) oppure il token non proviene da un brokered portal flow.
- `AADSTS7000218`: Il flow client selezionato si aspetta una credenziale confidenziale (`client_secret`/assertion), spesso visto quando si prova device code con un client non-pubblico.
<details>
<summary>Helper Python per BroCI refresh (broci_auth.py)</summary>
@@ -532,24 +606,24 @@ raise SystemExit(main())
## Dove trovare i token
Dal punto di vista di un attacker è molto interessante sapere dove è possibile trovare access and refresh tokens quando, ad esempio, il PC di una vittima è compromesso:
Dal punto di vista di un attaccante è molto interessante sapere dove è possibile trovare access and refresh tokens, per esempio quando il PC di una vittima è compromesso:
- All'interno di **`<HOME>/.Azure`**
- **`azureProfile.json`** contiene informazioni sugli utenti autenticati in passato
- **`clouds.config contains`** contiene informazioni sulle sottoscrizioni
- **`service_principal_entries.json`** contiene le credenziali delle applicazioni (tenant id, client e secret). Solo in Linux & macOS
- All'interno **`<HOME>/.Azure`**
- **`azureProfile.json`** contiene informazioni sugli utenti che hanno effettuato l'accesso in passato
- **`clouds.config`** contiene informazioni sulle sottoscrizioni
- **`service_principal_entries.json`** contiene credenziali delle applicazioni (tenant id, client e secret). Solo in Linux & macOS
- **`msal_token_cache.json`** contiene access tokens e refresh tokens. Solo in Linux & macOS
- **`service_principal_entries.bin`** e msal_token_cache.bin sono usati in Windows e sono criptati con DPAPI
- **`msal_http_cache.bin`** è una cache di richieste HTTP
- Per caricarlo: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)`
- **`AzureRmContext.json`** contiene informazioni sui login precedenti usando Az PowerShell (ma senza credenziali)
- All'interno di **`C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\*`** ci sono diversi file `.bin` con **access tokens**, ID tokens e informazioni dell'account criptate con il DPAPI dell'utente.
- È possibile trovare altri **access tokens** nei file `.tbres` all'interno di **`C:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\`**, che contengono una base64 criptata con DPAPI contenente access tokens.
- In Linux e macOS puoi ottenere **access tokens, refresh tokens e id tokens** da Az PowerShell (se usato) eseguendo `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"`
- **`AzureRmContext.json`** contiene informazioni su accessi precedenti effettuati con Az PowerShell (ma senza credenziali)
- All'interno **`C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\*`** ci sono diversi file `.bin` con **access tokens**, ID tokens e informazioni account criptate con il DPAPI dell'utente.
- È possibile trovare altri **access tokens** nei file `.tbres` dentro **`C:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\`**, che contengono base64 criptati con DPAPI contenenti access tokens.
- In Linux e macOS puoi ottenere **access tokens, refresh tokens and id tokens** da Az PowerShell (se usato) eseguendo `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"`
- In Windows questo genera solo id tokens.
- È possibile verificare se Az PowerShell è stato usato su Linux e macOS controllando se esiste `$HOME/.local/share/.IdentityService/` (anche se i file contenuti sono vuoti e inutili)
- Se l'utente è **loggato in Azure tramite il browser**, secondo questo [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) è possibile avviare il flow di autenticazione con un **redirect to localhost**, far sì che il browser autorizzi automaticamente il login e ricevere il refresh token. Nota che ci sono solo poche applicazioni FOCI che permettono il redirect to localhost (come az cli o il modulo powershell), quindi queste applicazioni devono essere permesse.
- Un'altra opzione spiegata nel blog è usare lo strumento [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow) che può usare qualsiasi applicazione perché otterrà **il codice OAuth per poi ottenere un refresh token dal titolo della pagina di autenticazione finale** usando il redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`.
- Se l'utente è **loggato in Azure con il browser**, secondo questo [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) è possibile avviare il flusso di autenticazione con un **redirect a localhost**, far sì che il browser autorizzi automaticamente il login e ricevere il refresh token. Nota che solo poche applicazioni FOCI permettono redirect a localhost (come az cli o il modulo powershell), quindi queste applicazioni devono essere consentite.
- Un'altra opzione spiegata nel blog è usare lo strumento [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow) che può utilizzare qualsiasi applicazione perché otterrà **il codice OAuth per poi ottenere un refresh token dal titolo della pagina di auth finale** usando il redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`.
## Riferimenti
@@ -557,5 +631,6 @@ Dal punto di vista di un attacker è molto interessante sapere dove è possibile
- [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}}