Le contexte
Le FBI a publié le 21 mai 2026 une Public Service Announcement (PSA260521) alertant sur Kali365, une plateforme de Phishing-as-a-Service qui exploite le mécanisme OAuth 2.0 device code flow pour voler les tokens Microsoft 365 sans avoir besoin de capturer le mot de passe ni le code MFA. Le kit est distribué via Telegram à partir de 250 dollars par mois, et a été observé pour la première fois en avril 2026 par Arctic Wolf.
L’attaque n’est pas nouvelle dans son principe : Proofpoint avait documenté une augmentation volumétrique du device code phishing en septembre 2025, attribuée d’abord à des acteurs étatiques liés à la Russie, puis adoptée par des criminels financiers en octobre 2025. En février 2026, EvilTokens et Tycoon2FA avaient déjà industrialisé la technique, avec plusieurs centaines d’organisations compromises rapportées sur des campagnes associées. Kali365 va plus loin en ajoutant des leurres générés par IA, des dashboards de suivi en temps réel, et des templates de campagne automatisés.
Cet article explique le mécanisme technique de l’attaque, ce qui la distingue d’AiTM, et comment la bloquer côté Microsoft Entra.
Comment fonctionne le device code flow
Le device code flow est un mécanisme OAuth 2.0 légitime, conçu pour permettre l’authentification sur des appareils sans clavier ou avec des capacités d’entrée limitées : smart TV, consoles de salle de réunion, imprimantes, équipements IoT, etc. Le scénario d’usage légitime :
sequenceDiagram
participant D as Device limité<br/>(smart TV)
participant U as Utilisateur
participant M as Microsoft Entra ID
D->>M: Demande un device code
M-->>D: Renvoie un device code court<br/>(ex: B7HF5N9P)
D->>U: Affiche le code et l'URL<br/>microsoft.com/devicelogin
U->>M: Visite l'URL et entre le code<br/>+ s'authentifie (MFA)
M-->>U: Confirmation
M-->>D: Envoie les tokens OAuth<br/>(access + refresh)
D->>D: Session établie
Le mécanisme est sûr dans son usage prévu : le device limité ne reçoit jamais les identifiants, et l’utilisateur s’authentifie sur la vraie page Microsoft. Le problème, c’est que le mécanisme ne vérifie pas quel device a initié la demande : si l’attaquant initie lui-même la demande de device code et convainc la victime d’entrer ce code sur la vraie page Microsoft, c’est l’attaquant qui reçoit les tokens à la fin.
Le détournement par Kali365
sequenceDiagram
participant A as Attaquant<br/>(Kali365)
participant V as Victime
participant M as Microsoft Entra ID
A->>M: Génère un device code<br/>via le flow OAuth
M-->>A: Code à 8 caractères<br/>(ex: B7HF5N9P)
A->>V: Email phishing imitant<br/>DocuSign ou SharePoint<br/>+ code + URL devicelogin
V->>M: Visite microsoft.com/devicelogin<br/>(VRAIE page Microsoft)
V->>M: Entre le code + s'authentifie<br/>+ valide la MFA
M-->>A: Envoie les tokens OAuth<br/>(access + refresh)
A->>M: Utilise les tokens pour accéder<br/>à Outlook, Teams, OneDrive
A->>A: Crée des règles d'inbox malveillantes<br/>+ enregistre de nouveaux devices
Note over V,M: La victime ne voit rien d'anormal<br/>page Microsoft légitime, vraie MFA
Note over A,M: L'attaquant a maintenant un accès<br/>persistant sans mot de passe ni MFA
Le génie de l’attaque est qu’elle utilise uniquement des composants légitimes :
- L’email contient un vrai code Microsoft
- L’URL pointe vers
microsoft.com/devicelogin, qui est la vraie page Microsoft - La page d’authentification est la vraie page Microsoft
- La MFA est la vraie MFA
- Le token reçu est un vrai token Microsoft
Côté victime, aucun élément ne paraît anormal. Aucune URL suspecte, aucun certificat invalide, aucune page contrefaite. C’est ce qui rend la formation utilisateur particulièrement difficile sur ce vecteur.
Ce qui distingue Kali365 d’une attaque AiTM
Le device code phishing est souvent confondu avec les attaques AiTM (Adversary in the Middle) comme Storm-2949 documenté par Microsoft le 4 mai 2026. Les deux contournent la MFA mais par des mécanismes différents :
| Aspect | AiTM (ex: Storm-2949) | Device code phishing (ex: Kali365) |
|---|---|---|
| Page d’authentification | Faux portail qui relaie | Vraie page Microsoft |
| URL visible par la victime | URL phishing (souvent typosquattée) | URL Microsoft légitime |
| Interception du token | Interception active via proxy inverse (Evilginx, Modlishka) | Pas d’interception, l’attaquant reçoit directement le token |
| Protection FIDO2/passkey | Efficace (verifier impersonation resistance / RP binding) | Limitée (le token est valide après l’auth) |
| Protection Authentication Strength CA | Efficace | Limitée pour la même raison |
| Détection par l’utilisateur | Possible (URL, certificat) | Très difficile, rien d’anormal visible |
La conséquence pratique : le déploiement de méthodes phishing-resistant (FIDO2, passkeys, CBA) ne suffit pas pour bloquer Kali365. La MFA s’exécute correctement, le token est légitimement émis, et l’attaquant le récupère via le flow OAuth normal. La défense doit se faire au niveau du flow lui-même, pas au niveau de la méthode d’authentification.
Comment bloquer Kali365 dans Entra ID
⚠️ Note : La condition Conditional Access “Authentication flows” qui permet de cibler le device code flow est actuellement en Public Preview au moment de la rédaction. La feature est utilisable en production mais peut évoluer. Source : Microsoft Learn - Authentication flows.
Étape 1 : Auditer l’usage actuel du device code flow
Avant de bloquer, il faut savoir qui l’utilise légitimement dans votre tenant. Le mécanisme est utilisé par des services réels : Microsoft Authenticator sur certains appareils, PowerShell sur des serveurs sans browser, agents legacy, équipements de salle de réunion.
# Le module Beta est nécessaire pour authenticationProtocol filter
Install-Module Microsoft.Graph.Beta.Reports -Scope CurrentUser
Connect-MgGraph -Scopes "AuditLog.Read.All"
# Récupérer les sign-ins via device code flow des 30 derniers jours
$startDate = (Get-Date).AddDays(-30).ToString("yyyy-MM-ddTHH:mm:ssZ")
$filter = "createdDateTime ge $startDate and authenticationProtocol eq 'deviceCode'"
$signIns = Get-MgBetaAuditLogSignIn -Filter $filter -All
$signIns | Select-Object @{N='Date';E={$_.CreatedDateTime}},
UserPrincipalName,
AppDisplayName,
@{N='Location';E={"$($_.Location.City), $($_.Location.CountryOrRegion)"}},
@{N='IPAddress';E={$_.IpAddress}},
@{N='Status';E={$_.Status.ErrorCode}} |
Sort-Object Date -Descending |
Export-Csv "device-code-signins-audit.csv" -NoTypeInformation -Encoding UTF8
Examiner le résultat : qui utilise le device code flow, depuis quels appareils ou applications, et avec quelle fréquence. Identifier les usages métier légitimes pour les exclure de la politique de blocage.
Étape 2 : Créer une politique Conditional Access pour bloquer
# Le module Beta est nécessaire pour la condition authenticationFlows
Install-Module Microsoft.Graph.Beta.Identity.SignIns -Scope CurrentUser
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess"
$policy = @{
DisplayName = "Block Device Code Flow - All Users (Exceptions Excluded)"
State = "enabledForReportingButNotEnforced" # Démarrer en report-only
Conditions = @{
Users = @{
IncludeUsers = @("All")
ExcludeUsers = @("<break-glass-user-id-1>", "<break-glass-user-id-2>")
ExcludeGroups = @("<device-code-exception-group-id>")
}
Applications = @{
IncludeApplications = @("All")
}
AuthenticationFlows = @{
TransferMethods = "deviceCodeFlow"
}
}
GrantControls = @{
Operator = "OR"
BuiltInControls = @("block")
}
}
New-MgBetaIdentityConditionalAccessPolicy -BodyParameter $policy
La politique cible la condition authenticationFlows.transferMethods avec la valeur deviceCodeFlow. C’est la condition Conditional Access spécifique introduite par Microsoft pour ce cas d’usage.
Étape 3 : Bloquer aussi les authentication transfer policies
Les authentication transfer policies permettent à un utilisateur de transférer une session authentifiée d’un appareil à un autre (par exemple PC vers téléphone). C’est un mécanisme légitime, mais qui peut être détourné pour des scénarios similaires. Le FBI recommande de le bloquer aussi.
$policyTransfer = @{
DisplayName = "Block Authentication Transfer Policies - All Users"
State = "enabledForReportingButNotEnforced"
Conditions = @{
Users = @{
IncludeUsers = @("All")
ExcludeUsers = @("<break-glass-user-id-1>", "<break-glass-user-id-2>")
}
Applications = @{
IncludeApplications = @("All")
}
AuthenticationFlows = @{
TransferMethods = "authenticationTransfer"
}
}
GrantControls = @{
Operator = "OR"
BuiltInControls = @("block")
}
}
New-MgBetaIdentityConditionalAccessPolicy -BodyParameter $policyTransfer
Étape 4 : Activer la détection dans Microsoft Defender XDR
Microsoft Defender XDR génère deux alertes spécifiques pour ce vecteur d’attaque :
- “Suspicious Azure authentication through possible device code phishing” : déclenchée par des patterns anormaux d’utilisation du device code flow
- “User account compromise via OAuth device code phishing” : déclenchée après une compromission confirmée
Pour s’assurer que ces alertes sont actives dans votre tenant :
Microsoft Defender portal > Settings > XDR >
Custom detection rules > Create detection rule
Vérifier que les advanced hunting queries sur les sign-in events incluent les filtres AuthenticationProtocol == "deviceCode".
Une query KQL utile pour le threat hunting historique, dans Microsoft Defender XDR Advanced Hunting :
EntraIdSignInEvents
| where Timestamp > ago(30d)
| where AuthenticationProtocol == "deviceCode"
| where ErrorCode == 0 // Sign-in réussi
| extend SuspiciousLocation = iff(Country != "<your-country>", true, false)
| where SuspiciousLocation
| project Timestamp, AccountUpn, Application, IPAddress, Country, City, ClientAppUsed
| sort by Timestamp desc
Note : la table EntraIdSignInEvents remplace AADSignInEventsBeta depuis le 9 décembre 2025. Si votre tenant utilise encore l’ancienne table, adaptez le nom.
L’équivalent dans Microsoft Sentinel :
SigninLogs
| where TimeGenerated > ago(30d)
| where AuthenticationProtocol == "deviceCode"
| where ResultType == 0
| extend Country = tostring(LocationDetails.countryOrRegion)
| extend SuspiciousLocation = iff(Country != "<your-country>", true, false)
| where SuspiciousLocation
| project TimeGenerated, UserPrincipalName, AppDisplayName, IPAddress, Country, ClientAppUsed
| sort by TimeGenerated desc
Étape 5 : Activer Continuous Access Evaluation (CAE) et Token Protection
CAE permet à Entra ID de révoquer un token en temps réel quand un risque est détecté. Si Kali365 réussit malgré tout à voler un token, CAE peut le révoquer dès que des signaux anormaux apparaissent (changement de localisation, IP suspecte, etc.) sans attendre l’expiration naturelle du token.
Token Protection (Token Binding) en preview lie cryptographiquement un token à un appareil spécifique. Un token volé devient inutilisable depuis un autre device.
Le cas particulier des comptes break-glass
Les comptes break-glass doivent rester exclus de la politique de blocage du device code flow, pour éviter un verrouillage total en cas de problème. Mais ils doivent être protégés autrement :
- Politique CA dédiée qui exige FIDO2 + IP/localisation spécifique
- Alerte automatique sur toute activation
- Audit mensuel des sign-ins
- Stockage hors-ligne sécurisé du mot de passe et du device FIDO2
Indicateurs de compromission à surveiller
Arctic Wolf et le FBI ont observé les patterns suivants après compromission par Kali365 :
- Création de règles d’inbox malveillantes : règles qui suppriment ou déplacent automatiquement les emails Microsoft, FBI, Microsoft Security, et les notifications d’alerte
- Enregistrement de nouveaux devices dans le tenant victime, pour persister l’accès
- Création de Application registrations avec des permissions élevées
- Modifications des paramètres de transfert de mail externe
- Activité de découverte : énumération des groupes, des accès partagés, des règles CA
Pour le threat hunting sur ces indicateurs :
// Détection de nouvelles règles d'inbox récentes
OfficeActivity
| where TimeGenerated > ago(7d)
| where Operation in ("New-InboxRule", "Set-InboxRule")
| where Parameters has_any ("DeleteMessage", "MoveToFolder", "SubjectContainsWords", "FromAddressContainsWords")
| project TimeGenerated, UserId, ClientIP, Operation, Parameters
| sort by TimeGenerated desc
Phasage du déploiement
Le blocage du device code flow peut casser des workflows légitimes. Phasage recommandé :
| Phase | Durée | Action |
|---|---|---|
| 1 | Semaine 1-2 | Audit complet de l’usage actuel via les sign-in logs |
| 2 | Semaine 3 | Politique CA en mode “Report-only” pour tous |
| 3 | Semaine 4 | Analyse des cas qui auraient été bloqués, création des exceptions |
| 4 | Semaine 5 | Activation progressive sur les utilisateurs standard |
| 5 | Semaine 6 | Activation sur les comptes à privilèges |
| 6 | En continu | Audit mensuel des exceptions, alerte sur toute nouvelle utilisation |
Sources
- FBI IC3 Public Service Announcement PSA260521 - Source primaire officielle
- Microsoft Learn - OAuth 2.0 device authorization grant flow
- Microsoft Learn - Conditional Access authentication flows
- Microsoft Learn - Continuous Access Evaluation
- Microsoft Learn - Token Protection (Preview)
- Microsoft Security Blog - Storm-2949 AiTM campaign (pour comparaison avec AiTM)