Abus du device code flow OAuth & détournement de jetons
Parmi l’ensemble des vecteurs d’accès initial ciblant Microsoft 365, l’abus du flux d’autorisation d’équipement OAuth 2.0 (Device Authorization Grant - RFC 8628) — communément appelé phishing par Device Code Flow — occupe une place à part et particulièrement redoutable. Contrairement au phishing classique ou aux attaques Adversary-in-the-Middle (AiTM), cette attaque dirige la victime vers une URL 100 % légitime de Microsoft (https://microsoft.com/devicelogin), exploite des identifiants d’applications officielles de premier rang et ne requiert aucune infrastructure de domaine malveillant.
Dès lors qu’un collaborateur saisit sur le portail officiel de Microsoft un code généré par l’attaquant et valide son authentification multi-facteurs (MFA), le Security Token Service (STS) de Microsoft délivre des jetons d’accès et de rafraîchissement à hauts privilèges directement dans le terminal de commande du cybercriminel.
Ce guide détaille les mécanismes architecturaux du Device Code Flow, analyse la militarisation des identifiants d’applications Microsoft, décortique la télémétrie dans Entra ID et propose des requêtes KQL de détection ainsi que les politiques de neutralisation.
1. Architecture RFC 8628 vs détournement cybercriminel
Section intitulée « 1. Architecture RFC 8628 vs détournement cybercriminel »Le flux OAuth 2.0 Device Authorization Grant (RFC 8628) a été spécifié pour des équipements connectés dépourvus de navigateur web ou dotés de capacités de saisie limitées (téléviseurs connectés, consoles IoT, terminaux en ligne de commande) :
sequenceDiagram autonumber participant Attacker as Terminal Attaquant (TokenTactics / AADInternals) participant Entra as Microsoft Entra ID (STS) participant Victim as Collaborateur Ciblé (Navigateur)
Attacker->>Entra: POST /common/oauth2/v2.0/devicecode (Client ID: Azure CLI) Entra-->>Attacker: Renvoie user_code (ex: "ABCD-EFGH") + device_code + verification_uri Note over Attacker: L'attaquant lance une boucle d'interrogation sur /token en tâche de fond Attacker->>Victim: Leurre de Phishing : « Saisissez le code ABCD-EFGH sur https://microsoft.com/devicelogin » Victim->>Entra: Navigation vers l'URL officielle https://microsoft.com/devicelogin Note over Victim: Saisie du code "ABCD-EFGH" + Authentification Mot de Passe & MFA Entra-->>Victim: Message : « Tentez-vous de vous connecter à Microsoft Azure CLI ? » Victim->>Entra: Clic sur « Continuer » (MFA validé) Note over Entra: Négociation validée côté Microsoft ! Entra-->>Attacker: L'interrogation réussit ! Renvoi de l'Access Token + Refresh Token Note over Attacker: Prise de contrôle programmatique immédiate des ressources du tenant !Pourquoi cette attaque est particulièrement redoutable :
Section intitulée « Pourquoi cette attaque est particulièrement redoutable : »- Aucun risque de réputation de domaine : le message renvoie vers
https://microsoft.com/devicelogin. Aucune passerelle de messagerie (SEG) ni proxy web ne bloque le domaine racine de Microsoft. - Pré-consentement des applications officielles : les attaquants utilisent les identifiants d’applications Microsoft natives (Azure CLI, Microsoft Office, PowerShell). Ces outils étant nativement approuvés dans le tenant, ils ne déclenchent aucun écran d’alerte de consentement administrateur.
- Satisfaction complète du MFA : la victime ayant satisfait le challenge MFA, les jetons délivrés encapsulent la preuve de cette validation et déverrouillent l’accès aux ressources protégées par l’Accès Conditionnel.
2. Identifiants d’applications Microsoft détournés (first-party client IDs)
Section intitulée « 2. Identifiants d’applications Microsoft détournés (first-party client IDs) »Les attaquants initient la demande de code en spécifiant les identifiants d’applications officielles Microsoft :
| Nom de l’Application | Identifiant Client (AppId GUID) | Privilèges & Capacités par Défaut |
|---|---|---|
| Microsoft azure CLI | 04b07795-8ddb-461a-bbee-02f9e1bf7b46 | Gestion complète Azure Resource Manager (ARM), API Graph, Azure Key Vault, Stockage Azure. |
| Azure PowerShell | 1950a258-227b-4e31-a9cf-717495945fc2 | Administration complète du tenant et des souscriptions Azure. |
| Microsoft office | d3590ed6-52b3-4102-aeff-aad2292ab01c | Accès étendu aux APIs Exchange Online, SharePoint Online, OneDrive et Teams. |
| Microsoft graph CLI | 14d82eec-204b-4c2f-b354-c2419e407076 | Interrogation exhaustive de l’annuaire Graph et attribution de rôles. |
| Visual Studio | 872cd9fa-d31f-45e0-9eab-6e460a02d1f1 | Accès aux dépôts Azure DevOps et aux environnements de développement cloud. |
3. Empreinte forensique dans la télémétrie entra ID
Section intitulée « 3. Empreinte forensique dans la télémétrie entra ID »L’abus du Device Code Flow génère une signature spécifique dans les journaux de connexion. L’analyste doit articuler son analyse autour de deux phases temporelles :
graph TD subgraph "Phase 1 : Validation du Code (IP de la Victime)" V_LOG["Enregistrement SigninLogs<br/>AppDisplayName : Microsoft Azure CLI<br/>AuthenticationProtocol : deviceCode<br/>IPAddress : IP Entreprise Victime<br/>ResultType : 0 (Succès)<br/>MFA Satisfied : True"] end
subgraph "Phase 2 : Exploitation du Jeton (IP de l'Attaquant)" A_LOG["Enregistrement NonInteractiveUserSignInLogs<br/>AppDisplayName : Microsoft Azure CLI<br/>IPAddress : VPS / Proxy Attaquant<br/>ResourceDisplayName : Windows Azure Service Management API<br/>Jeton émis via Refresh Token"] end
V_LOG -->|Jeton délivré au pirate| A_LOG3.1 attributs clés de diagnostic télémétrique
Section intitulée « 3.1 attributs clés de diagnostic télémétrique »Dans la table SigninLogs sous Log Analytics ou Microsoft Sentinel :
AuthenticationProtocol: vaut impérativementdeviceCode.AppDisplayName: révèle l’outil ciblé (ex."Microsoft Azure CLI","Azure PowerShell").ClientAppUsed: vaut"Mobile Apps and Desktop clients".DeviceDetail: attributs souvent vides ou disparates. L’autorisation s’opère dans le navigateur de la victime, mais le terminal n’est pas lié en tant qu’équipement Azure CLI managé.- Discordance d’adresses IP : l’authentification interactive initiale (
SigninLogs) émane du réseau légitime de la victime, tandis que les requêtes applicatives suivantes (NonInteractiveUserSignInLogs) proviennent d’ASNs d’hébergeurs (DigitalOcean, AWS, Linode) ou de proxys résidentiels.
4. Requêtes de chasse KQL en production
Section intitulée « 4. Requêtes de chasse KQL en production »4.1 détection de toutes les connexions réussies par device code
Section intitulée « 4.1 détection de toutes les connexions réussies par device code »Établir la ligne de base et lister toutes les authentifications par Device Code sur le tenant :
SigninLogs| where TimeGenerated >= ago(14d)| where ResultType == 0| where AuthenticationProtocol == "deviceCode"| project TimeGenerated, UserPrincipalName, AppDisplayName, IPAddress, Location, ClientAppUsed, DeviceDetail, UserAgent, CorrelationId| sort by TimeGenerated desc4.2 détection de rejeu de jeton multi-IP post-device code
Section intitulée « 4.2 détection de rejeu de jeton multi-IP post-device code »Repérer les cas où une validation Device Code a lieu depuis une IP, suivie dans un délai de 2 heures d’un rafraîchissement de jeton non interactif depuis une adresse IP ou un pays différent pour la même application :
let DeviceCodeAuths = SigninLogs| where TimeGenerated >= ago(7d)| where ResultType == 0| where AuthenticationProtocol == "deviceCode"| project AuthTime=TimeGenerated, UserPrincipalName, AuthIP=IPAddress, AuthCountry=Location, AppDisplayName, CorrelationId;let TokenRefreshes = NonInteractiveUserSignInLogs| where TimeGenerated >= ago(7d)| where ResultType == 0| project RefreshTime=TimeGenerated, UserPrincipalName, RefreshIP=IPAddress, RefreshCountry=Location, AppDisplayName, ResourceDisplayName;DeviceCodeAuths| join kind=inner (TokenRefreshes) on UserPrincipalName, AppDisplayName| where RefreshTime between (AuthTime .. (AuthTime + 2h))| where AuthIP != RefreshIP and AuthCountry != RefreshCountry| project UserPrincipalName, AppDisplayName, AuthTime, AuthIP, AuthCountry, RefreshTime, RefreshIP, RefreshCountry, ResourceDisplayName| sort by AuthTime desc4.3 détection de profils non techniques utilisant des outils développeurs
Section intitulée « 4.3 détection de profils non techniques utilisant des outils développeurs »Identifier des collaborateurs des fonctions Finance, RH, Juridique ou Direction générale validant des outils en ligne de commande :
let DeveloperApps = dynamic([ "04b07795-8ddb-461a-bbee-02f9e1bf7b46", // Azure CLI "1950a258-227b-4e31-a9cf-717495945fc2", // Azure PowerShell "14d82eec-204b-4c2f-b354-c2419e407076" // Graph CLI]);SigninLogs| where TimeGenerated >= ago(14d)| where ResultType == 0| where AppId in (DeveloperApps)| where AuthenticationProtocol == "deviceCode"| project TimeGenerated, UserPrincipalName, AppDisplayName, IPAddress, Location, UserAgent| sort by TimeGenerated desc5. Architecture de durcissement et neutralisation
Section intitulée « 5. Architecture de durcissement et neutralisation »Pour neutraliser durablement les attaques par Device Code Flow, les organisations doivent déployer des règles d’Accès Conditionnel ciblées :
graph TD DEF[Architecture Anti-Device Code] --> L1[1. Conformité Matérielle Obligatoire<br/>Exiger un poste Hybride Entra ID ou conforme Intune] DEF --> L2[2. Forces d'Authentification Avancées<br/>Imposer le MFA résistant au phishing pour les outils admin] DEF --> L3[3. Ciblage des Groupes Non Techniques<br/>Bloquer explicitement Azure Management pour les profils métiers] DEF --> L4[4. Alerte SOC & Révocation Instantanée<br/>Règle Sentinel déclenchant Revoke-MgUserSignSession]5.1 imposer la conformité matérielle sur l’administration azure
Section intitulée « 5.1 imposer la conformité matérielle sur l’administration azure »Même si un collaborateur valide le code d’authentification, l’attaquant ne pourra pas exploiter le jeton sur sa propre machine si l’Accès Conditionnel exige un terminal conforme pour accéder à "Gestion des ressources Microsoft Azure" :
- Ressource cible :
Gestion des ressources Microsoft Azure(Azure Resource Manager) - Utilisateurs : tous les utilisateurs (hors comptes d’urgence / Break-Glass)
- Contrôle d’accès :
Exiger que le périphérique soit marqué comme conformeOUExiger un périphérique joint à Microsoft Entra hybride
5.2 script d’urgence en réponse à incident
Section intitulée « 5.2 script d’urgence en réponse à incident »Dès confirmation qu’un collaborateur a validé un code frauduleux :
# Prérequis : Module Microsoft.Graph.Users# Connect-MgGraph -Scopes "User.ReadWrite.All"
$compromisedUPN = "victim@target.com"Write-Host "[!] RÉVOCATION D'URGENCE POUR LA VICTIME DU DEVICE CODE : $compromisedUPN" -ForegroundColor Red
# Révocation immédiate de tous les refresh tokensRevoke-MgUserSignSession -UserId $compromisedUPNWrite-Host "[+] Tous les jetons de rafraîchissement et sessions ont été invalidés." -ForegroundColor Green6. Maillage interne & navigation
Section intitulée « 6. Maillage interne & navigation »- Fiche précédente : 24. Analyse Télémétrique du Password Spraying & Brute-Force
- Fiche suivante : 26. Élévation de Privilèges & Détournement de Rôles (Bloc VI — Persistance & Élévation de Privilèges)
- Fiches complémentaires :
- 02. Microsoft Entra ID : le plan d’identité
- 09. Analyse des logs de connexion entra ID
- 10. Dissection approfondie des audit logs entra ID
- 19. Kill chain de compromission de compte M365
- 21. Mécanismes du reverse proxy adversary-in-the-middle (AiTM)
- 23. Attaques par consentement OAuth & phishing d’application