Forensique du risque et d'entra identity protection
Dans les architectures cloud contemporaines, la détection statique par signatures est impuissante face aux attaques ciblant l’identité : rejeu de cookies de session volés, pulvérisation de mots de passe via des proxys résidentiels ou phishing par reverse proxy (AiTM). Microsoft Entra Identity Protection constitue le moteur d’apprentissage automatique (Machine Learning) et d’analyse heuristique comportementale qui évalue en continu le niveau de risque de chaque identité et de chaque transaction d’authentification du tenant.
Pour l’analyste DFIR, les signaux d’Identity Protection constituent une source de preuve irremplaçable : révélation d’identifiants fuités sur le Dark Web, détection d’impossibilités physiques de déplacement (Impossible Travel) et mise au jour de cookies de session volés rejoués depuis des infrastructures malveillantes.
Cette fiche fournit une dissection technique d’Entra Identity Protection, de son architecture bivalente, de ses schémas JSON, des indicateurs critiques et des requêtes de threat hunting applicables en investigation.
Entra Identity Protection sépare l’évaluation du risque en deux dimensions analytiques complémentaires :
graph TD subgraph "Architecture bivalente Entra Identity Protection" AUTH[Requête d'authentification] --> ENGINE[Moteur d'évaluation des risques]
ENGINE -->|Heuristiques temps réel| S_RISK["1. Risque de Connexion (Niveau Transaction)<br/>Évalué à l'émission du jeton<br/>Table : AADUserRiskEvents"]
ENGINE -->|Intelligence globale asynchrone| U_RISK["2. Risque Utilisateur (Niveau Identité)<br/>Probabilité globale de compromission<br/>Table : AADRiskyUsers"]
S_RISK --> DET_RT[Détections Temps Réel<br/>IP anonyme, IP malveillante, Navigateur suspect] S_RISK --> DET_OFF[Détections Différées<br/>Impossible Travel, Jeton anormal, Identifiants fuités]
DET_RT --> COND_ACC[Évaluation Accès Conditionnel<br/>Exiger MFA, Exiger Changement MdP, Bloquer] DET_OFF --> COND_ACC
U_RISK --> REMED[État de Remédiation<br/>atRisk, confirmedCompromised, remediated, dismissed] end1. Risque de connexion (riskDetections / AADUserRiskEvents)
Section intitulée « 1. Risque de connexion (riskDetections / AADUserRiskEvents) »Représente la probabilité qu’une requête d’authentification spécifique et isolée n’émane pas du titulaire légitime du compte. Ce risque évalue des signaux contextuels : réputation de l’adresse IP source, conformité de l’appareil, empreinte du navigateur et vitesse de déplacement.
2. Risque utilisateur (riskyUsers / AADRiskyUsers)
Section intitulée « 2. Risque utilisateur (riskyUsers / AADRiskyUsers) »Représente la probabilité globale et cumulée que les identifiants d’une identité soient compromis. Contrairement au risque de connexion (propre à un événement ponctuel), le risque utilisateur persiste dans le temps jusqu’à sa remédiation explicite (réinitialisation sécurisée du mot de passe ou action administrative).
Détections temps réel vs détections différées (offline)
Section intitulée « Détections temps réel vs détections différées (offline) »La compréhension de la cinématique temporelle de détection est indispensable pour l’analyste forensique afin de ne pas interpréter prématurément l’absence d’un log :
| Type de détection | Mode de traitement | Latence typique | Scénarios de menace et logique de détection |
|---|---|---|---|
| Adresse IP anonyme | Temps réel | Immédiat (< 5s) | Requête provenant d’un nœud de sortie Tor, d’un VPN grand public ou d’un proxy d’anonymisation. |
| Adresse IP malveillante | Temps réel | Immédiat (< 5s) | Adresse IP répertoriée par la Threat Intelligence Microsoft comme participant à un botnet ou C2. |
| Navigateur suspect | Temps réel | Immédiat (< 5s) | En-têtes User-Agent anormaux, navigateurs d’automatisation (Puppeteer, Playwright) ou outils de scraping. |
| Propriétés de connexion inhabituelles | Temps réel | Immédiat (< 5s) | La connexion dévie des habitudes de l’utilisateur (nouvel appareil, nouvelle localisation, nouvelle application). |
| Déplacement impossible (impossible travel) | Différé (Offline) | 15 min à 2 heures | Deux authentifications successives distantes d’une vitesse physiquement impossible (> 1 000 km/h). |
| Jeton anormal (anomalous token) | Différé (Offline) | 1 à 4 heures | VOL DE SESSION CRITIQUE : La durée de vie, l’émetteur ou l’IP du jeton dévie de la signature initiale. |
| Anomalie d’émetteur de jeton | Différé (Offline) | 1 à 4 heures | Le jeton présenté a été forgé par un service de fédération non reconnu ou illégitime. |
| Identifiants fuités (leaked credentials) | Différé (Offline) | Quelques heures à 48h | Identifiants du compte découverts sur des pastes publics, des forums clandestins ou des logs d’infostealers. |
| Pulvérisation de mots de passe (password spray) | Différé (Offline) | 1 à 4 heures | Analyse globale de patterns d’échecs lents et distribués émanant d’infrastructures d’attaque connues. |
Dissection du schéma JSON : les champs clés
Section intitulée « Dissection du schéma JSON : les champs clés »1. Schéma des détections de risque (/identityProtection/riskDetections | AADUserRiskEvents)
Section intitulée « 1. Schéma des détections de risque (/identityProtection/riskDetections | AADUserRiskEvents) »| Champ (Graph API) | Champ (Log Analytics) | Signification forensique et interprétation |
|---|---|---|
id | Id | GUID unique de la détection de risque. |
requestId | RequestId | Corrélation directe avec le CorrelationId de SigninLogs pour retrouver la tentative d’authentification exacte. |
userId | UserId | GUID immuable de l’utilisateur concerné. |
userPrincipalName | UserPrincipalName | Identifiant du compte cible. |
riskEventType | RiskEventType | Type d’événement détecté (ex. anomalousToken, impossibleTravel, leakedCredentials). |
riskLevel | RiskLevel | Gravité de la détection : low, medium, high, none. |
riskState | RiskState | Statut opérationnel : atRisk, confirmedCompromised, remediated, dismissed, confirmedSafe. |
detectionTimingType | DetectionTimingType | Mode d’analyse : realtime (évalué au STS) ou offline (analysé par ML en différé). |
activity | Activity | Type d’action à l’origine de l’alerte : signin, user, servicePrincipal. |
ipAddress | IPAddress | Adresse IP source associée à la transaction suspecte. |
location | LocationDetails | Données de géolocalisation : ville, région, pays et coordonnées GPS estimées. |
additionalInfo | AdditionalInfo | Payload forensique enrichi : chaîne JSON détaillant la vitesse calculée (km/h), la localisation précédente ou les proxys. |
2. Schéma des utilisateurs à risque (/identityProtection/riskyUsers | AADRiskyUsers)
Section intitulée « 2. Schéma des utilisateurs à risque (/identityProtection/riskyUsers | AADRiskyUsers) »| Champ (Graph API) | Champ (Log Analytics) | Signification forensique et interprétation |
|---|---|---|
id | Id | GUID de l’utilisateur. |
userPrincipalName | UserPrincipalName | UPN du compte. |
riskLevel | RiskLevel | Niveau de risque cumulé : low, medium, high, none, hidden. |
riskState | RiskState | État de traitement : atRisk, confirmedCompromised, remediated, dismissed. |
riskDetail | RiskDetail | Motif ayant justifié ce niveau (ex. userReportedSuspiciousActivity, aiConfirmedSigninSafe). |
riskLastUpdatedDateTime | TimeGenerated | Horodatage de la dernière réévaluation du risque. |
Ce qui est possible vs ce qui n’est pas possible
Section intitulée « Ce qui est possible vs ce qui n’est pas possible »Ce qui est possible
Section intitulée « Ce qui est possible »- Calcul mathématique de la vitesse de déplacement : extraire
additionalInfodes événementsimpossibleTravelpour connaître la distance exacte en kilomètres et la vitesse calculée entre deux authentifications. - Confirmer formellement le rejeu de session : détecter les alertes
anomalousToken, constituant la preuve la plus robuste du vol de cookie AiTM ou de l’extraction d’un PRT. - Auditer la gestion des incidents par le SOC : identifier si un analyste a confirmé la compromission (
confirmedCompromised) ou rejeté l’alerte prématurément (dismissed). - Pivoter via RequestId : relier sans équivoque une détection de risque à son enregistrement dans les logs de connexion et aux accès aux données dans l’UAL Purview.
Ce qui n’est pas possible
Section intitulée « Ce qui n’est pas possible »- Exploiter la télémétrie sur les tenants sans licence P2 : la télémétrie complète requiert Entra ID P2 ou Microsoft 365 E5. Sur les plans Free ou P1, les détails sont masqués (
hidden) ou absents. - Conclure à l’innocuité par absence d’alerte : un attaquant opérant depuis un proxy résidentiel situé dans la même agglomération que la victime n’active généralement aucun modèle ML ; l’absence de risque ne prouve pas l’absence d’attaque.
- Régénérer rétroactivement le risque passé : l’acquisition d’une licence P2 en cours d’incident ne génère pas de détections sur les connexions antérieures.
- Observer les actions sur les fichiers OU e-mails : identity Protection analyse l’identité, pas les contenus des services applicatifs.
Méthodologie d’investigation : extraction et détection KQL
Section intitulée « Méthodologie d’investigation : extraction et détection KQL »# ==============================================================================# Hermes Codex - Extracteur forensique Entra Identity Protection# Exporte les utilisateurs à risque et les détections d'anomalies# ==============================================================================
Import-Module Microsoft.Graph.Authentication, Microsoft.Graph.Identity.SignIns -ErrorAction StopConnect-MgGraph -Scopes "IdentityRiskEvent.Read.All", "IdentityRiskyUser.Read.All" -NoWelcome
$OutDir = "./Entra_Risque_$(Get-Date -Format 'yyyyMMdd')"New-Item -ItemType Directory -Path $OutDir -Force | Out-Null
# 1. Extraire les utilisateurs à risqueWrite-Host "[*] Extraction des utilisateurs à risque du tenant..." -ForegroundColor Cyan$riskyUsersUri = "https://graph.microsoft.com/v1.0/identityProtection/riskyUsers?`$filter=riskLevel ne 'none'"$riskyUsers = [System.Collections.Generic.List[PSObject]]::new()do { $resp = Invoke-MgGraphRequest -Method GET -Uri $riskyUsersUri if ($resp.value) { $riskyUsers.AddRange($resp.value) } $riskyUsersUri = $resp.'@odata.nextLink' Start-Sleep -Milliseconds 150} while ($null -ne $riskyUsersUri)
$riskyUsersFile = "$OutDir/Utilisateurs_Risque.jsonl"$riskyUsers | ForEach-Object { $_ | ConvertTo-Json -Compress -Depth 10 } | Set-Content -Path $riskyUsersFileWrite-Host "[+] $($riskyUsers.Count) profils à risque exportés." -ForegroundColor Green
# 2. Extraire les détections détaillées (30 derniers jours)$DaysBack = 30$StartDate = (Get-Date).AddDays(-$DaysBack).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")Write-Host "[*] Extraction des détections de risque depuis $StartDate..." -ForegroundColor Cyan
$riskDetectionsUri = "https://graph.microsoft.com/v1.0/identityProtection/riskDetections?`$filter=activityDateTime ge $StartDate"$riskDetections = [System.Collections.Generic.List[PSObject]]::new()do { $resp = Invoke-MgGraphRequest -Method GET -Uri $riskDetectionsUri if ($resp.value) { $riskDetections.AddRange($resp.value) } $riskDetectionsUri = $resp.'@odata.nextLink' Start-Sleep -Milliseconds 150} while ($null -ne $riskDetectionsUri)
$riskDetectionsFile = "$OutDir/Detections_Risque.jsonl"$riskDetections | ForEach-Object { $_ | ConvertTo-Json -Compress -Depth 10 } | Set-Content -Path $riskDetectionsFileWrite-Host "[+] $($riskDetections.Count) événements de détection exportés." -ForegroundColor Green
# 3. Calcul des empreintes cryptographiques$h1 = Get-FileHash -Path $riskyUsersFile -Algorithm SHA256$h2 = Get-FileHash -Path $riskDetectionsFile -Algorithm SHA256Write-Host "[✓] Empreinte Utilisateurs SHA-256 : $($h1.Hash)" -ForegroundColor GreenWrite-Host "[✓] Empreinte Détections SHA-256 : $($h2.Hash)" -ForegroundColor Green// ==============================================================================// Détection de l'utilisation de jetons anormaux (Vol de session / Rejeu de jeton)// Technique MITRE ATT&CK : T1539 - Vol de cookie de session web// ==============================================================================AADUserRiskEvents| where TimeGenerated >= ago(30d)| where RiskEventType in ("anomalousToken", "tokenIssuerAnomaly")| project TimeGenerated, UserPrincipalName, RiskEventType, RiskLevel, RiskState, DetectionTimingType, IPAddress, LocationDetails, RequestId, CorrelationId| join kind=leftouter ( SigninLogs | where TimeGenerated >= ago(30d) | project CorrelationId, AppDisplayName, ClientAppUsed, ConditionalAccessStatus) on CorrelationId| project TimeGenerated, UserPrincipalName, RiskEventType, RiskLevel, AppDisplayName, ClientAppUsed, IPAddress, LocationDetails, ConditionalAccessStatus, CorrelationId| order by TimeGenerated desc// ==============================================================================// Analyse des alertes de déplacement impossible (Impossible Travel)// ==============================================================================AADUserRiskEvents| where TimeGenerated >= ago(30d)| where RiskEventType == "impossibleTravel"| extend ParsedInfo = parse_json(AdditionalInfo)| project TimeGenerated, UserPrincipalName, RiskLevel, RiskState, IPAddress, LocalisationActuelle = tostring(LocationDetails), LocalisationPrecedente = tostring(ParsedInfo[0].Value), VitesseCalculeeKmh = tostring(ParsedInfo[1].Value), CorrelationId| order by TimeGenerated desc// ==============================================================================// Audit des rejets d'alertes par des administrateurs (Dismiss user risk)// ==============================================================================AuditLogs| where TimeGenerated >= ago(30d)| where OperationName in ("Dismiss user risk", "Confirm user compromised")| mvexpand TargetResources| extend TargetUser = tostring(TargetResources.userPrincipalName)| project TimeGenerated, OperationName, TargetUser, AdminUPN = tostring(InitiatedBy.user.userPrincipalName), AdminIP = tostring(InitiatedBy.user.ipAddress), CorrelationId| order by TimeGenerated descExemple d’investigation : le cookie de session rejoué
Section intitulée « Exemple d’investigation : le cookie de session rejoué »Contexte de l’incident
Section intitulée « Contexte de l’incident »Un cadre dirigeant est ciblé par une campagne de phishing AiTM à 09h12 UTC. L’attaquant intercepte le cookie de session ESTSAUTH sur son reverse proxy et le rejoue depuis un serveur distant.
Traçabilité dans identity protection
Section intitulée « Traçabilité dans identity protection »- 09H12:15 UTC - l’authentification interactive :
- La victime s’authentifie sur le faux portail. Les sign-in logs consignent un succès avec validation MFA. Aucun risque n’est levé en temps réel car les identifiants et le MFA ont été validés.
- 09H15:30 UTC - rejeu du cookie par l’attaquant :
- L’attaquant injecte le cookie et appelle l’API Graph. Un log apparaît dans
AADNonInteractiveUserSignInLogsdepuis une adresse IP inconnue (194.26.29.11).
- L’attaquant injecte le cookie et appelle l’API Graph. Un log apparaît dans
- 11H42:00 UTC - détection différée par machine learning :
- Deux heures plus tard, le moteur d’analyse différé compare les caractéristiques du jeton (preuve de possession, trajectoire IP, empreinte TLS) avec la session initiale.
- Un enregistrement est validé dans
AADUserRiskEvents:RiskEventType:anomalousToken.RiskLevel:high.DetectionTimingType:offline.IPAddress:194.26.29.11.
- Le profil utilisateur dans
AADRiskyUsersbascule automatiquement àriskLevel: highetriskState: atRisk.
Sans l’examen de cette télémétrie différée, un intervenant qui n’aurait audité que les alertes temps réel aurait conclu à l’absence totale de preuve technique de détournement de jeton.
Doctrine transversale : télémétrie de risque vs preuve formelle
Section intitulée « Doctrine transversale : télémétrie de risque vs preuve formelle »Les détections algorithmiques d’Identity Protection doivent être situées rigoureusement dans l’échelle de certitude de Hermes Codex :
+-------------------------------------------------------------------------------+| LES 7 NIVEAUX DE CERTITUDE FORENSIQUE || || 1. Possible -> Le moteur de risque est activé et licencié (Entra P2). || 2. Configuré -> Les règles d'évaluation et le streaming SIEM sont actifs. || 3. Autorisé -> L'identité disposait des accès aux applications ciblées. || 4. Accessible -> L'accès distant aux interfaces était autorisé. || 5. Utilisé -> Une requête d'authentification a été traitée par le STS. || 6. Observé -> Une détection apparaît dans AADUserRiskEvents. || 7. Prouvé -> L'intrusion est prouvée par le saut d'IP et l'accès UAL. |+-------------------------------------------------------------------------------+Distinctions forensiques fondamentales
Section intitulée « Distinctions forensiques fondamentales »- Observé != malveillant : un événement
impossibleTravelest une anomalie statistique observée. Il se produit régulièrement de manière légitime lorsqu’un employé utilise un VPN d’entreprise (avec sortie à Francfort) tout en consultant ses e-mails sur smartphone (en 5G à Paris) dans un intervalle de quelques minutes. - Aucun risque observé != non compromis : un pirate utilisant un proxy résidentiel souscrit auprès du même FAI que la victime ne déclenche aucune alerte de risque. L’absence d’événement ne prouve en aucun cas la légitimité de la session.
- Observé + corrélé == prouvé : la certitude de la compromission exige de confronter la détection de risque (
anomalousToken) à d’autres traces tangibles :- Présence de logs de connexion simultanés avec des User-Agents contradictoires.
- Création de règles de transfert d’e-mails observée dans l’UAL lors de cette session.
- Déclaration formelle de l’utilisateur attestant qu’il n’utilisait pas le second équipement.
Pièges et confusions fréquentes
Section intitulée « Pièges et confusions fréquentes »| Piège | Cause technique | Conséquence pour l’enquête | Action corrective |
|---|---|---|---|
| Croire que « dismiss user risk » règle l’incident | Cliquer sur « Ignorer le risque utilisateur » remet le score à zéro dans l’interface. | Efface l’alerte mais laisse le cookie de session volé parfaitement valide. | Toujours révoquer les sessions actives (Revoke-MgUserSignInSession) et changer le mot de passe avant d’acquitter le risque. |
| Confondre risque de connexion et risque utilisateur | Le premier qualifie une requête ponctuelle ; le second qualifie la santé globale du compte. | Mauvais ciblage des règles d’accès conditionnel ou incompréhension de la portée de l’alerte. | Traiter le risque de connexion pour le blocage immédiat ; le risque utilisateur pour la remédiation profonde. |
| Attendre des alertes immédiates pour les détections différées | Des alertes critiques comme anomalousToken nécessitent plusieurs heures de calcul par les modèles ML. | Clôture prématurée d’une levée de doute sans voir l’alerte arriver a posteriori. | Réinterroger les journaux d’Identity Protection 12 à 24 heures après les faits pour capturer les détections offline. |
| Négliger le risque sur les identités de charge (workload identities) | Identity Protection évalue également les Principaux de service et Applications. | Passer à côté de compromissions applicatives majeures via des secrets dérobés. | Auditer servicePrincipalRiskDetections au même titre que les utilisateurs humains. |
| Sur-interpréter les alertes dues aux VPN d’entreprise | Les sorties réseau réparties sur plusieurs passerelles provoquent de faux positifs de déplacement impossible. | Perte de temps à investiguer des connexions légitimes de télétravailleurs. | Contrôler l’ASN et le nom de domaine de l’IP source avant de déclarer une attaque. |
État de la fonctionnalité en 2026
Section intitulée « État de la fonctionnalité en 2026 »Changements récents
Section intitulée « Changements récents »- Protection des identités de charge (workload identity protection) : profilage de risque étendu aux principaux de service et identités managées, repérant les volumes d’appels API anormaux.
- Révocation instantanée via continuous access evaluation (CAE) : dès qu’un compte passe en risque élevé, les services compatibles CAE (Exchange, Teams, SharePoint) mettent fin aux sessions actives sans attendre l’expiration du jeton.
- Points de terminaison graph v1.0 unifiés : remplacement des anciennes API de reporting par l’arborescence standardisée
/identityProtection/riskDetectionset/identityProtection/riskyUsers.
Fonctionnalités dépréciées
Section intitulée « Fonctionnalités dépréciées »- API d’audit de risque legacy (
/auditLogs/riskDetectionsen version bêta) : définitivement retirée au profit de l’arborescence v1.0 dédiée. - Portail autonome identity protection : intégralement fusionné dans le centre d’administration Microsoft Entra et le portail Microsoft Defender XDR.
Limitations actuelles
Section intitulée « Limitations actuelles »- Latence d’ingestion des identifiants fuités : bien que l’ingestion de bases compromises soit automatisée, la confrontation d’une fuite ciblée d’infostealers avec l’annuaire de l’entreprise peut nécessiter jusqu’à 48 heures.
- Verrou de licence P2 : la granularité de la télémétrie de risque demeure strictement conditionnée à la licence Entra ID P2 / E5.
Points clés à retenir
Section intitulée « Points clés à retenir »- Identity protection apporte la vérité comportementale : indispensable pour détecter le rejeu de jetons, les déplacements impossibles et les identifiants fuités sur le Dark Web.
- Distinguer le temps réel du différé : les alertes temps réel sont immédiates ; les détections d’analyses de jetons (
anomalousToken) prennent 1 à 4 heures. - Acquitter le risque n’est pas confiner : révoquer impérativement les sessions et changer le mot de passe avant de marquer le risque comme résolu.
- Vérifier les VPN avant de crier à l’attaque : confronter les alertes d’impossible travel aux adresses de sortie des VPN d’entreprise.
- L’absence d’alerte n’est pas un certificat de sécurité : les pirates utilisant des proxys résidentiels locaux contournent délibérément les algorithmes d’apprentissage automatique.
Références
Section intitulée « Références »- Microsoft Entra ID : présentation de Microsoft Entra Identity Protection
- Microsoft Graph API : type de ressource identityProtectionRoot
- Microsoft Learn : comment investiguer le risque dans Microsoft Entra Identity Protection
- Microsoft Learn : évaluation continue de l’accès (CAE) dans Microsoft Entra