Détection forensique & investigation des attaques AiTM
Bien que les frameworks de reverse proxy Adversary-in-the-Middle (AiTM) tels qu’Evilginx parviennent à contourner l’authentification multi-facteurs (MFA) interactive, ils laissent derrière eux une signature forensique particulièrement visible et discriminante dans la télémétrie cloud. Parce que l’attaque dissocie fondamentalement la négociation d’authentification initiale des opérations cybercriminelles ultérieures, elle engendre des anomalies structurelles dans le routage IP, les identifiants de session, les attributs matériels et les flux de rafraîchissement de jetons.
Pour l’analyste forensique et l’opérateur de SOC, identifier une attaque AiTM n’exige pas de déchiffrer le flux TLS ni d’accéder au serveur proxy de l’attaquant. La détection repose sur la corrélation croisée entre les connexions interactives, les rejeux de jetons non interactifs, les alertes de risque Entra ID Protection et les altérations consécutives des services SaaS.
Ce guide expose la signature architecturale des attaques AiTM dans les journaux Microsoft Entra ID et Purview, détaille une chronologie d’intrusion réelle reconstituée, fournit des requêtes de détection KQL éprouvées et décrit le protocole d’endiguement d’urgence.
1. La signature forensique de la double IP (dual-IP ingress)
Section intitulée « 1. La signature forensique de la double IP (dual-IP ingress) »La caractéristique structurelle déterminante d’une attaque AiTM est l’anomalie d’ingress à double adresse IP :
graph TD subgraph "Phase 1 : Authentification de la Victime (Ingress Handshake)" V_ACT[La victime s'authentifie via Evilginx] V_IP[IP #1 : IP du Proxy Inverse / IP Victime<br/>App : My Apps / OfficeHome<br/>ResultType = 0 (Succès)<br/>MFA Satisfied = True] V_ACT --> V_IP end
subgraph "Phase 2 : Extraction du Cookie de Session" V_IP --> PROXY_EXT[Evilginx capture ESTSAUTH & ESTSAUTHPERSISTENT<br/>Export vers la base de session du pirate] end
subgraph "Phase 3 : Rejeu de Session par l'Attaquant (Ingress Opérationnel)" PROXY_EXT --> ATT_ACT[L'attaquant injecte les cookies dans son navigateur] ATT_IP[IP #2 : Infrastructure de l'Attaquant<br/>Proxy Résidentiel / VPN / VPS<br/>App : Exchange Online / Graph API / SharePoint<br/>Rafraîchissement Non Interactif] ATT_ACT --> ATT_IP end
subgraph "Détection de l'Anomalie Forensique" V_IP -.->|Écart Structurel :<br/>ASN / FAI / Pays différents<br/>Changement de User-Agent<br/>Perte de l'état matériel conforme| DISCREPANCY{Delta Forensique} ATT_IP -.-> DISCREPANCY endManifestations forensiques de la double IP :
Section intitulée « Manifestations forensiques de la double IP : »- Décorrélation interactive vs non-interactive :
- La première connexion s’inscrit dans
SigninLogs(Interactive) sous l’IP #1 (l’adresse de sortie de la victime ou l’IP d’hébergement du reverse proxy). - Entre 2 et 15 minutes plus tard,
NonInteractiveUserSignInLogsouCloudAppEventsenregistre des requêtes pour le même compte sous l’IP #2 (un proxy résidentiel commercial, un VPN ou un nœud de sortie anonymisé).
- La première connexion s’inscrit dans
- Dégradation instantanée de la posture matérielle :
- La connexion initiale peut refléter un équipement d’entreprise conforme (
isCompliant: true,trustType: Workplace/AzureAdJoined). - La session rejouée perd toute télémétrie machine (
isCompliant: false,deviceId: null,trustType: null), les cookies de session ne véhiculant aucun certificat matériel TPM.
- La connexion initiale peut refléter un équipement d’entreprise conforme (
- Incohérence des user-agents :
- Un utilisateur s’authentifiant depuis un navigateur Chrome/Windows moderne génère soudainement des requêtes non interactives émanant de Linux/Python-requests, de Chromium headless ou d’une version de navigateur obsolète.
2. Sources télémétriques & attributs clés de corrélation
Section intitulée « 2. Sources télémétriques & attributs clés de corrélation »L’investigation d’une attaque AiTM nécessite de recouper plusieurs tables dans Microsoft Sentinel ou Defender XDR :
| Table Télémétrique | Attributs Clés de Corrélation | Preuve Forensique Apportée |
|---|---|---|
SigninLogs | CorrelationId, IPAddress, UserAgent, MfaDetail, ConditionalAccessStatus, AppDisplayName | Identifie la négociation d’authentification interactive initiale relayée par le proxy. |
NonInteractiveUserSignInLogs | OriginalRequestId, IPAddress, UserAgent, ResourceDisplayName, AutonomousSystemNumber | Révèle l’attaquant rejouant les jetons volés depuis une IP/ASN étrangère pour accéder aux services SaaS. |
UserRiskEvents | RiskEventType, RiskLevel, Source, IpAddress, DetectionTimingType | Enregistre les alertes d’Entra ID Protection : Atypical travel, Unfamiliar sign-in properties, Anomalous token. |
CloudAppEvents | AccountDisplayName, IPAddress, ActionType, RawEventData | Retrace les actions post-compromission : MailItemsAccessed, New-InboxRule, FileDownloaded. |
sequenceDiagram autonumber participant V as Navigateur Victime participant P as Proxy AiTM (IP 198.51.100.10) participant E as Entra ID (STS) participant A as Attaquant (IP 203.0.113.50) participant M as Exchange Online
V->>P: Saisie des identifiants + validation MFA P->>E: Relais de la négociation d'authentification E-->>P: Émission du cookie ESTSAUTH (Consigné dans SigninLogs : IP 198.51.100.10) P->>A: Extraction et livraison du cookie à l'attaquant Note over A: 4 minutes plus tard... A->>E: Présentation d'ESTSAUTH depuis l'IP 203.0.113.50 pour obtenir un jeton Exchange E-->>A: Émission du jeton d'accès (Consigné dans NonInteractiveUserSignInLogs : IP 203.0.113.50) A->>M: Requête vers l'API de messagerie (Consigné dans CloudAppEvents : MailItemsAccessed)3. Chronologie reconstituée : anatomie d’une intrusion réelle
Section intitulée « 3. Chronologie reconstituée : anatomie d’une intrusion réelle »L’enchaînement chronologique suivant illustre une compromission BEC classique opérée via Evilginx :
| Horodatage (UTC) | Table Télémétrique | Événement Observé / Valeur | Déduction Forensique |
|---|---|---|---|
| 14:02:11 | EmailEvents | Distribué : Email de phishing ayant pour objet "URGENT : Vérification Paie T1". | Distribution via un tenant partenaire compromis (voir Fiche 20). |
| 14:04:35 | UrlClickEvents | ActionType = UrlAllowed, Url = https://login.target-portal.net/auth. | L’utilisateur a cliqué sur le lien ; Safe Links n’a pas bloqué le domaine récent. |
| 14:05:18 | SigninLogs | ResultType = 0, IP = 198.51.100.10 (VPS Hetzner), App = OfficeHome, MFA = Satisfied. | La victime s’est authentifiée à travers le proxy Evilginx. |
| 14:08:42 | UserRiskEvents | RiskEventType = atypicalTravel, RiskLevel = High. | Le moteur Microsoft détecte un déplacement impossible entre le pays de la victime et le proxy. |
| 14:09:15 | NonInteractiveUserSignInLogs | ResultType = 0, IP = 203.0.113.50 (FAI Résidentiel, Nigeria), Resource = Exchange Online. | Rejeu de jeton par l’attaquant. Utilisation d’ESTSAUTH depuis son infrastructure. |
| 14:10:02 | CloudAppEvents | ActionType = MailItemsAccessed, OperationProperties[MailAccessType] = Sync. | Synchronisation massive de la boîte \Inbox via Graph API (voir Fiche 17). |
| 14:12:30 | CloudAppEvents | ActionType = New-InboxRule, RuleName = ..., DeleteMessage = True. | Persistance & évasion. Règle cachée supprimant les alertes de sécurité entrantes. |
4. Requêtes de chasse KQL en production
Section intitulée « 4. Requêtes de chasse KQL en production »4.1 corrélation entre connexion interactive et rejeu rapide depuis une IP étrangère
Section intitulée « 4.1 corrélation entre connexion interactive et rejeu rapide depuis une IP étrangère »Détecter les cas où une connexion interactive est suivie dans un délai de 60 minutes d’une connexion non interactive émanant d’un pays ou ASN différent :
let TimeDelta = 60m;let InteractiveSignins = SigninLogs| where TimeGenerated >= ago(7d)| where ResultType == 0| project InteractiveTime=TimeGenerated, UserPrincipalName, InteractiveIP=IPAddress, InteractiveCountry=Location, InteractiveASN=AutonomousSystemNumber, InteractiveUA=UserAgent, CorrelationId;let NonInteractiveSignins = NonInteractiveUserSignInLogs| where TimeGenerated >= ago(7d)| where ResultType == 0| project NonInteractiveTime=TimeGenerated, UserPrincipalName, ReplayIP=IPAddress, ReplayCountry=Location, ReplayASN=AutonomousSystemNumber, ReplayUA=UserAgent, ResourceDisplayName;InteractiveSignins| join kind=inner (NonInteractiveSignins) on UserPrincipalName| where NonInteractiveTime between (InteractiveTime .. (InteractiveTime + TimeDelta))| where InteractiveIP != ReplayIP and (InteractiveCountry != ReplayCountry or InteractiveASN != ReplayASN)| project UserPrincipalName, InteractiveTime, InteractiveIP, InteractiveCountry, InteractiveASN, NonInteractiveTime, ReplayIP, ReplayCountry, ReplayASN, ResourceDisplayName| sort by InteractiveTime desc4.2 détection de la perte de conformité matérielle lors du rejeu
Section intitulée « 4.2 détection de la perte de conformité matérielle lors du rejeu »Repérer les sessions ayant débuté sur un équipement conforme Intune ou hybride qui perdent instantanément leur état de conformité :
SigninLogs| where TimeGenerated >= ago(7d)| where ResultType == 0| extend DeviceState = tostring(DeviceDetail.isCompliant)| project TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName, DeviceState, UserAgent| join kind=inner ( NonInteractiveUserSignInLogs | where TimeGenerated >= ago(7d) | where ResultType == 0 | extend ReplayDeviceState = tostring(DeviceDetail.isCompliant) | project ReplayTime=TimeGenerated, UserPrincipalName, ReplayIP=IPAddress, ReplayApp=ResourceDisplayName, ReplayDeviceState, ReplayUA=UserAgent) on UserPrincipalName| where DeviceState == "true" and (ReplayDeviceState == "false" or isempty(ReplayDeviceState))| where ReplayTime between (TimeGenerated .. (TimeGenerated + 30m))| where IPAddress != ReplayIP| project UserPrincipalName, TimeGenerated, IPAddress, DeviceState, ReplayTime, ReplayIP, ReplayDeviceState, ReplayApp| sort by TimeGenerated desc4.3 chasse aux hébergeurs VPS atypiques pour les connexions utilisateurs
Section intitulée « 4.3 chasse aux hébergeurs VPS atypiques pour les connexions utilisateurs »Repérer les authentifications interactives issues d’ASNs de fournisseurs de VPS (DigitalOcean, Hetzner, Linode, OVH) qui ne correspondent jamais aux réseaux d’entreprises ou de collaborateurs à domicile :
let KnownHostingASNs = dynamic([14061, 24940, 63949, 16276, 51167]); // DigitalOcean, Hetzner, Linode, OVH, ContaboSigninLogs| where TimeGenerated >= ago(14d)| where ResultType == 0| where AutonomousSystemNumber in (KnownHostingASNs)| project TimeGenerated, UserPrincipalName, IPAddress, AutonomousSystemNumber, Location, AppDisplayName, UserAgent| sort by TimeGenerated desc5. Protocole d’endiguement rapide Face à une attaque AiTM
Section intitulée « 5. Protocole d’endiguement rapide Face à une attaque AiTM »Lorsqu’une compromission AiTM est confirmée, la réponse technique doit être foudroyante. Une simple réinitialisation de mot de passe n’invalide pas immédiatement les cookies de session ou les refresh tokens actifs si l’évaluation continue (CAE) n’est pas strictement imposée.
graph TD ALERT[Compromission AiTM Confirmée] --> STEP1[1. Révocation Immédiate des Jetons & Sessions<br/>Revoke-MgUserSignSession] STEP1 --> STEP2[2. Réinitialisation du Mot de Passe<br/>Rotation des condensats d'authentification] STEP2 --> STEP3[3. Audit & Purge des Méthodes MFA<br/>Supprimer numéros de secours et clés FIDO frauduleuses] STEP3 --> STEP4[4. Audit des Règles de Boîte & Transferts<br/>Supprimer les redirections et règles de masquage] STEP4 --> STEP5[5. Contrôle des Consentements OAuth Applicatifs<br/>Vérifier qu'aucune application n'a obtenu offline_access]Script PowerShell d’endiguement d’urgence :
Section intitulée « Script PowerShell d’endiguement d’urgence : »# Prérequis : Microsoft.Graph.Users, ExchangeOnlineManagement# Connect-MgGraph -Scopes "User.ReadWrite.All"# Connect-ExchangeOnline
$victimUPN = "alice.dupont@target.com"Write-Host "[!] DÉCLENCHEMENT DE L'ENDIGUEMENT D'URGENCE POUR LA VICTIME AiTM : $victimUPN" -ForegroundColor Red
# 1. Révocation immédiate de toutes les sessions activesRevoke-MgUserSignSession -UserId $victimUPNWrite-Host "[+] Sessions Entra ID et refresh tokens RÉVOQUÉS avec succès." -ForegroundColor Green
# 2. Contrôle des méthodes MFA enregistrées$mfaMethods = Get-MgUserAuthenticationMethod -UserId $victimUPNWrite-Host "[*] Examen des méthodes d'authentification enregistrées :" -ForegroundColor Yellow$mfaMethods | Select-Object Id, AdditionalProperties | Format-List
# 3. Détection des règles de boîte malveillantes$rules = Get-InboxRule -Mailbox $victimUPN$suspiciousRules = $rules | Where-Object { $_.ForwardTo -or $_.RedirectTo -or $_.DeleteMessage }if ($suspiciousRules) { Write-Warning "[!] Règles de boîte suspectes détectées :" $suspiciousRules | Format-Table Name, ForwardTo, RedirectTo, DeleteMessage # Décommenter pour supprimer automatiquement : # $suspiciousRules | ForEach-Object { Remove-InboxRule -Mailbox $victimUPN -Identity $_.Identity -Confirm:$false }}
# 4. Vérification des transferts automatiques au niveau de la boîte$mbx = Get-Mailbox -Identity $victimUPNif ($mbx.ForwardingSmtpAddress -or $mbx.ForwardingAddress) { Write-Error "[!] Transfert externe configuré vers : $($mbx.ForwardingSmtpAddress) / $($mbx.ForwardingAddress)" # Set-Mailbox -Identity $victimUPN -ForwardingSmtpAddress $null -ForwardingAddress $null}6. Maillage interne & navigation
Section intitulée « 6. Maillage interne & navigation »- Fiche précédente : 21. Mécanismes du Reverse Proxy Adversary-in-the-Middle (AiTM)
- Fiche suivante : 23. Attaques par Consentement OAuth & Phishing d’Application
- Fiches complémentaires :
- 09. Analyse des logs de connexion entra ID
- 10. Dissection approfondie des audit logs entra ID
- 12. Forensique entra ID protection & détection des risques
- 17. Audit de boîte mail & analyse de MailItemsAccessed
- 19. Kill chain de compromission de compte M365
- 28. Délégations et permissions abusives de boîtes mail
- 29. Règles de boîte de réception et redirections malveillantes