Az - Jetons & Applications Publiques

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Informations de base

Entra ID est la plateforme cloud d’identity and access management (IAM) de Microsoft, servant de système fondamental d’authentification et d’autorisation pour des services comme Microsoft 365 et Azure Resource Manager. Azure AD implémente le framework OAuth 2.0 et le protocole d’authentification OpenID Connect (OIDC) pour gérer l’accès aux ressources.

OAuth

Acteurs clés dans OAuth 2.0 :

  1. Resource Server (RS) : Protège les ressources appartenant au resource owner.
  2. Resource Owner (RO) : Généralement un utilisateur final qui possède les ressources protégées.
  3. Client Application (CA) : Une application cherchant à accéder aux ressources au nom du resource owner.
  4. Authorization Server (AS) : Délivre des access tokens aux client applications après les avoir authentifiés et autorisés.

Scopes et Consentement :

  • Scopes : Permissions granulaires définies sur le resource server spécifiant les niveaux d’accès.
  • Consentement : Le processus par lequel un resource owner accorde à une client application la permission d’accéder aux ressources avec des scopes spécifiques.

Intégration Microsoft 365 :

  • Microsoft 365 utilise Azure AD pour l’IAM et est composé de multiples applications OAuth “first-party”.
  • Ces applications sont profondément intégrées et ont souvent des relations de service interdépendantes.
  • Pour simplifier l’expérience utilisateur et maintenir la fonctionnalité, Microsoft accorde un “implied consent” ou un “pre-consent” à ces applications first-party.
  • Consentement implicite : Certaines applications se voient automatiquement accorder l’accès à des scopes spécifiques sans approbation explicite de l’utilisateur ou de l’administrateur.
  • Ces scopes pré-consentis sont typiquement cachés aux utilisateurs et aux administrateurs, les rendant moins visibles dans les interfaces de gestion standard.

Types de Client Application :

  1. Confidential Clients :
  • Possèdent leurs propres identifiants (par ex. mots de passe ou certificats).
  • Peuvent s’authentifier de manière sécurisée auprès de l’authorization server.
  1. Public Clients :
  • N’ont pas d’identifiants uniques.
  • Ne peuvent pas s’authentifier de façon sécurisée auprès de l’authorization server.
  • Implication de sécurité : Un attaquant peut usurper une public client application lors de la demande de tokens, puisqu’il n’existe pas de mécanisme permettant à l’authorization server de vérifier la légitimité de l’application.

Authentication Tokens

Il existe trois types de tokens utilisés en OIDC :

  • Access Tokens: Le client présente ce token au resource server pour accéder aux ressources. Il ne peut être utilisé que pour une combinaison spécifique d’utilisateur, de client et de ressource et ne peut pas être révoqué avant son expiration — soit 1 heure par défaut.
  • ID Tokens : Le client reçoit ce token de l’authorization server. Il contient des informations de base sur l’utilisateur. Il est lié à une combinaison spécifique d’utilisateur et de client.
  • Refresh Tokens : Fourni au client avec l’access token. Utilisé pour obtenir de nouveaux access et ID tokens. Il est lié à une combinaison spécifique d’utilisateur et de client et peut être révoqué. L’expiration par défaut est de 90 jours pour les refresh tokens inactifs et pas d’expiration pour les tokens actifs (il est possible d’obtenir de nouveaux refresh tokens à partir d’un refresh token).
  • Un refresh token devrait être lié à un aud, à certains scopes, et à un tenant et il ne devrait être capable de générer que des access tokens pour cet aud, ces scopes (et pas plus) et ce tenant. Cependant, ce n’est pas le cas avec les FOCI applications tokens.
  • Un refresh token est chiffré et seul Microsoft peut le déchiffrer.
  • Obtenir un nouveau refresh token ne révoque pas le refresh token précédent.

Warning

Les informations pour le conditional access sont stockées à l’intérieur du JWT. Donc, si vous demandez le token depuis une adresse IP autorisée, cette IP sera enregistrée dans le token et ensuite vous pourrez utiliser ce token depuis une IP non autorisée pour accéder aux ressources.

Access Tokens “aud”

Le champ indiqué dans la propriété “aud” est le resource server (l’application) utilisé pour effectuer la connexion.

La commande az account get-access-token --resource-type [...] prend en charge les types suivants et chacun d’eux ajoutera un “aud” spécifique dans l’access token résultant :

Caution

Notez que ce qui suit représente seulement les API supportées par az account get-access-token mais il en existe d’autres.

Exemples d'aud
  • aad-graph (Azure Active Directory Graph API) : Utilisé pour accéder à l’Azure AD Graph API legacy (dépréciée), qui permet aux applications de lire et écrire des données d’annuaire dans Azure Active Directory (Azure AD).
  • https://graph.windows.net/
  • arm (Azure Resource Manager) : Utilisé pour gérer les ressources Azure via l’API Azure Resource Manager. Cela inclut des opérations comme la création, la mise à jour et la suppression de ressources telles que des machines virtuelles, des comptes de stockage, et plus.
  • https://management.core.windows.net/ or https://management.azure.com/

  • batch (Azure Batch Services) : Utilisé pour accéder à Azure Batch, un service qui permet d’exécuter efficacement des applications de calcul parallèle à grande échelle et à haute performance dans le cloud.

  • https://batch.core.windows.net/

  • data-lake (Azure Data Lake Storage) : Utilisé pour interagir avec Azure Data Lake Storage Gen1, qui est un service évolutif de stockage de données et d’analytique.
  • https://datalake.azure.net/

  • media (Azure Media Services) : Utilisé pour accéder à Azure Media Services, qui fournit des services cloud de traitement et de distribution média pour le contenu vidéo et audio.

  • https://rest.media.azure.net

  • ms-graph (Microsoft Graph API) : Utilisé pour accéder à Microsoft Graph API, le point d’entrée unifié pour les données des services Microsoft 365. Il permet d’accéder aux données et insights de services comme Azure AD, Office 365, Enterprise Mobility et les services de sécurité.
  • https://graph.microsoft.com

  • oss-rdbms (Azure Open Source Relational Databases) : Utilisé pour accéder aux services de base de données Azure pour des moteurs relationnels open-source comme MySQL, PostgreSQL et MariaDB.

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

Access Tokens Scopes “scp”

Le scope d’un access token est stocké dans la clé scp à l’intérieur du JWT de l’access token. Ces scopes définissent ce à quoi l’access token a accès.

Si un JWT est autorisé à contacter une API spécifique mais n’a pas le scope pour effectuer l’action demandée, il ne pourra pas effectuer l’action avec ce 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)

Autres champs d’access token

  • appid: ID de l’application utilisée pour générer le token
  • appidacr: The Application Authentication Context Class Reference indique comment le client a été authentifié ; pour un public client la valeur est 0, et si un client secret est utilisé la valeur est 1
  • acr: The Authentication Context Class Reference claim est “0” lorsque l’authentification de l’utilisateur final n’a pas satisfait aux exigences de ISO/IEC 29115.
  • amr: The Authentication method indique comment le token a été authentifié. Une valeur “pwd” indique qu’un mot de passe a été utilisé.
  • groups: Indique les groupes dont le principal est membre.
  • iss: L’iss identifie le security token service (STS) qui a généré le token. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (le uuid est le tenant ID)
  • oid: L’object ID du principal
  • tid: Tenant ID
  • iat, nbf, exp: Issued at (moment où il a été émis), Not before (ne peut pas être utilisé avant ce moment, généralement même valeur que iat), Expiration time.

FOCI Tokens Privilege Escalation

Précédemment, il a été mentionné que refresh tokens devraient être liés aux scopes avec lesquels ils ont été générés, à l’application et au tenant pour lesquels ils ont été générés. Si l’une de ces frontières est rompue, il est possible d’escalader les privilèges car il sera possible de générer des access tokens pour d’autres ressources et tenants auxquels l’utilisateur a accès et avec plus de scopes que prévu initialement.

De plus, this is possible with all refresh tokens dans la Microsoft identity platform (Microsoft Entra accounts, Microsoft personal accounts, and social accounts like Facebook and Google) car, comme le mentionnent les docs : “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.”

De plus, notez que les applications FOCI sont des public applications, donc aucun secret n’est nécessaire pour s’authentifier auprès du serveur.

Les clients FOCI connus signalés dans la original research peuvent être found here.

Obtenir un scope différent

Suite à l’exemple de code précédent, dans ce code il est demandé un nouveau token pour un scope différent :

# 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)

Obtenir des clients et des scopes différents

# 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)

Où trouver des tokens

Du point de vue d’un attaquant, il est très intéressant de savoir où il est possible de trouver access and refresh tokens, par exemple si le PC d’une victime est compromis :

  • Inside <HOME>/.Azure
  • azureProfile.json contient des informations sur les logged in users du passé
  • clouds.config contains des infos sur les subscriptions
  • service_principal_entries.json contient les credentials des applications (tenant id, clients et secret). Only in Linux & macOS
  • msal_token_cache.json contient des access tokens et refresh tokens. Only in Linux & macOS
  • service_principal_entries.bin et msal_token_cache.bin sont utilisés sous Windows et sont chiffrés avec DPAPI
  • msal_http_cache.bin est un cache de requêtes HTTP
  • Load it: with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)
  • AzureRmContext.json contient des informations sur des previous logins utilisant Az PowerShell (mais sans credentials)
  • Inside C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\* se trouvent plusieurs fichiers .bin avec access tokens, ID tokens et des informations de compte chiffrées avec le DPAPI de l’utilisateur.
  • Il est possible de trouver plus d’access tokens dans les fichiers .tbres inside C:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\ qui contiennent un base64 chiffré avec DPAPI contenant des access tokens.
  • Sur Linux et macOS, vous pouvez obtenir access tokens, refresh tokens et id tokens depuis Az PowerShell (si utilisé) en exécutant pwsh -Command "Save-AzContext -Path /tmp/az-context.json"
  • Sous Windows ceci ne génère que des id tokens.
  • Il est possible de voir si Az PowerShell a été utilisé sur Linux et macOS en vérifiant si $HOME/.local/share/.IdentityService/ existe (même si les fichiers contenus sont vides et inutiles)
  • Si l’utilisateur est connecté à Azure via le browser, selon ce post il est possible de démarrer le flux d’authentification avec un redirect to localhost, faire en sorte que le browser autorise automatiquement la connexion, et recevoir le refresh token. Notez qu’il n’y a que quelques applications FOCI qui permettent redirect to localhost (comme az cli ou le powershell module), donc ces applications doivent être autorisées.
  • Une autre option expliquée dans le blog est d’utiliser l’outil BOF-entra-authcode-flow qui peut utiliser n’importe quelle application car il obtiendra le OAuth code pour ensuite récupérer un refresh token depuis le title of the final auth page en utilisant le redirect URI https://login.microsoftonline.com/common/oauth2/nativeclient.

References

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks