Le sandbox a refusé l'écriture dans `/tmp` (permission non accordée, session non interactive). Je livre donc l'article directement ci-dessous. --- ```html

Le 11 juin 2026 à 07h42, un analyste SOC de garde reçoit une alerte de faible sévérité dans Microsoft Defender XDR : une application OAuth interne, créée trois mois plus tôt, vient de lire 1 412 messages dans une boîte aux lettres de direction. Rien d'anormal en apparence. Deux heures plus tard, après une session de chasse assistée par Microsoft Copilot Security couplée au plugin Microsoft Defender Threat Intelligence (MDTI), le même analyste comprend qu'il regarde les traces d'un acteur étatique russe présent dans le tenant depuis plus de trois mois, entré par un password spray à basse intensité depuis un réseau de proxies résidentiels, et qui exfiltre patiemment les notes de mission d'un cabinet de conseil travaillant pour des administrations françaises. Cet article reconstitue l'intégralité de cette traque : définition et physionomie d'une APT, profil détaillé de Midnight Blizzard (APT29), exploitation du plugin MDTI dans Copilot, trois requêtes KQL complètes et exploitables, corrélation MITRE ATT&CK, calcul du dwell time, obligations de notification ANSSI et CERT-FR, stratégie de réponse silencieuse à base de honey tokens et de déception, puis durcissement structurel anti-APT. Chaque prompt Copilot est reproduit tel qu'il a été soumis, pour être rejoué dans votre propre environnement.

Qu'est-ce qu'une APT, et pourquoi la définition compte pour votre SOC

Le sigle APT — Advanced Persistent Threat, menace persistante avancée — est probablement le terme le plus galvaudé du vocabulaire cyber. Un ransomware opéré par un affilié LockBit n'est pas une APT. Un botnet de cryptominage n'est pas une APT. La distinction n'est pas académique : elle détermine votre posture de réponse, votre calendrier d'éradication et vos obligations réglementaires.

Une APT se caractérise par trois propriétés simultanées. Advanced ne signifie pas nécessairement « exploit zero-day » : cela signifie que l'adversaire dispose d'une capacité de développement propre, d'un renseignement préalable sur sa cible et d'une capacité à adapter son outillage en cours d'opération. Midnight Blizzard, par exemple, a compromis Microsoft en janvier 2024 avec une technique triviale — un password spray sur un compte de tenant de test dépourvu de MFA — mais l'a exploitée avec une infrastructure et une discipline opérationnelle qui restent hors de portée d'un acteur criminel moyen.

Persistent décrit l'objectif, pas la technique : l'acteur ne cherche pas un gain immédiat mais un accès durable et renouvelable. Il investit dans des mécanismes de persistance qui survivent à une réinitialisation de mot de passe, à un rebuild de poste, voire à une migration de tenant — d'où la prédilection d'APT29 pour les service principals, les certificats ajoutés à des applications légitimes et les tokens de rafraîchissement de longue durée.

Threat renvoie à l'intentionnalité humaine : derrière une APT il y a une organisation, un budget, des objectifs de renseignement fixés par un commanditaire, et une tolérance au temps long. C'est ce dernier point qui fait basculer la détection : là où un opérateur de ransomware chiffre en 48 heures et se signale bruyamment, une APT peut rester 90, 200 ou 400 jours sans déclencher une seule alerte de sévérité haute.

Cette économie du temps long est exactement ce que Copilot Security change. La corrélation manuelle de trois mois de journaux d'authentification, de télémétrie réseau et de renseignement sur les infrastructures adverses représente plusieurs jours-analyste. Le couplage Copilot + MDTI ramène cette reconstitution à une session de deux à trois heures, à condition de savoir quoi demander. Le référentiel complet des techniques couvertes est détaillé sur notre page couverture MITRE ATT&CK de Copilot Security.

Profil de Midnight Blizzard (APT29) : la discipline avant la sophistication

Midnight Blizzard est la nomenclature Microsoft d'un acteur attribué publiquement au SVR, le service de renseignement extérieur de la Fédération de Russie. Il est également suivi sous les noms APT29, Cozy Bear, Nobelium, UNC2452, Dark Halo ou BlueBravo selon les éditeurs. Sa fiche de référence est maintenue par le MITRE sous l'identifiant G0016.

Son historique opérationnel dessine une trajectoire nette : compromission du Democratic National Committee en 2015-2016, opération de supply chain SolarWinds/SUNBURST révélée en décembre 2020, ciblage massif des fournisseurs de services cloud et des revendeurs Microsoft en 2021-2022, campagne d'ingénierie sociale via Microsoft Teams en 2023, compromission du tenant corporate de Microsoft en janvier 2024, intrusion chez Hewlett Packard Enterprise et TeamViewer la même année, puis campagnes de phishing par fichiers de configuration RDP signés visant des cibles diplomatiques et des administrations à partir d'octobre 2024.

Trois traits constants doivent orienter votre chasse.

Premièrement, l'identité comme vecteur primaire. APT29 est un acteur « cloud-native ». Il n'a pas besoin de malware sur un endpoint pour atteindre son objectif : un token OAuth valide sur une application disposant de Mail.ReadWrite en permission applicative lui donne un accès à l'ensemble des boîtes du tenant, sans agent, sans processus suspect, sans persistance sur disque. Vos EDR ne verront rien.

Deuxièmement, la fusion dans le trafic légitime. L'acteur opère systématiquement depuis des réseaux de proxies résidentiels et des VPS loués dans le pays de la cible. Une authentification depuis une IP grand public à Lille ne déclenche aucune heuristique de voyage impossible. Le renseignement d'infrastructure — ce que MDTI apporte — devient alors le seul discriminant fiable.

Troisièmement, la patience. Le password spray de janvier 2024 contre Microsoft s'est étalé sur plusieurs semaines, avec un nombre volontairement réduit de tentatives par compte pour rester sous les seuils de smart lockout. C'est l'inverse exact du profil bruyant que la plupart des règles de détection recherchent.

Le contexte : un cabinet de conseil comme point d'entrée vers l'État

L'organisation victime de notre scénario est un cabinet de conseil français de 340 collaborateurs, spécialisé dans l'accompagnement à la transformation des administrations publiques. Il intervient sur des schémas directeurs des systèmes d'information ministériels, des programmes de modernisation d'opérateurs publics et des missions d'appui auprès de deux opérateurs d'importance vitale du secteur de l'énergie.

Ce profil en fait une cible de très haute valeur pour un service de renseignement. Le cabinet ne détient pas de secret défense, mais il concentre quelque chose de presque aussi utile : la cartographie applicative de ses clients, les calendriers de déploiement, les noms et coordonnées des décideurs, les comptes rendus de comités de pilotage, les analyses de risque non publiées et les projets d'architecture réseau. C'est le classique ciblage du maillon faible de la chaîne d'approvisionnement — celui-là même qu'exploitait SolarWinds, et qui explique pourquoi la directive NIS2 étend son périmètre aux fournisseurs critiques.

L'environnement technique est représentatif : Microsoft 365 E5, Entra ID en configuration hybride avec un Active Directory on-premise résiduel, Defender XDR déployé, Microsoft Sentinel avec 90 jours de rétention chaude et 365 jours en archive, licence Copilot Security active. Le SOC est composé de trois analystes internes appuyés par un MSSP en heures non ouvrées. Autrement dit : un dispositif honorable, qui n'a pourtant rien vu pendant trois mois.

Le plugin MDTI dans Copilot Security : ce qu'il change concrètement

Microsoft Defender Threat Intelligence n'est pas un simple flux d'indicateurs de compromission. C'est une base de données d'infrastructure Internet historisée : résolutions DNS passives, certificats TLS et leurs empreintes, jeux d'en-têtes HTTP, composants de traqueurs web, données WHOIS historiques, et surtout les regroupements d'infrastructure établis par les analystes Microsoft — les Intel Profiles.

Dans Copilot Security, le plugin MDTI s'active depuis l'icône des sources de données de la barre de prompt. Deux niveaux existent : le contenu MDTI standard, inclus avec les licences Defender, et le contenu MDTI Premium qui débloque les articles d'analyse, les profils d'acteurs complets et les jeux d'IoC associés. Pour une chasse APT, le niveau Premium n'est pas optionnel : c'est lui qui contient le mapping acteur → infrastructure.

La différence pratique est décisive. Sans MDTI, une IP suspecte est une IP suspecte. Avec MDTI, Copilot peut répondre que cette IP a hébergé, six semaines plus tôt, un certificat TLS dont l'empreinte est partagée avec quatre autres serveurs listés dans le profil d'infrastructure de Midnight Blizzard. Vous ne passez plus de la détection à l'hypothèse : vous passez de la détection à l'attribution.

Le premier prompt d'une session de chasse sert toujours à cadrer le périmètre de renseignement disponible :

Prompt 1 — « Résume le profil d'acteur Midnight Blizzard depuis MDTI : alias connus, attribution, secteurs ciblés en Europe sur les 18 derniers mois, techniques MITRE ATT&CK associées, et liste les articles de renseignement Microsoft publiés à son sujet depuis janvier 2025. »

Copilot restitue alors une synthèse structurée du profil, avec les identifiants d'articles MDTI que l'on peut ensuite interroger individuellement. Le deuxième prompt bascule du renseignement générique vers votre tenant :

Prompt 2 — « Croise les indicateurs de compromission associés au profil MDTI de Midnight Blizzard avec l'ensemble des journaux de mon tenant sur les 180 derniers jours. Pour chaque correspondance, indique la table source, l'horodatage de la première et de la dernière occurrence, l'identité ou l'appareil concerné, et le niveau de confiance de l'indicateur. »

C'est ce prompt qui, dans notre scénario, remonte trois adresses IP et un user agent atypique corrélés à l'infrastructure de l'acteur. À partir de là, la chasse devient dirigée.

Timeline de l'intrusion reconstituée : 99 jours en sept étapes

La reconstitution chronologique est l'exercice où Copilot apporte le gain de temps le plus spectaculaire, parce qu'il sait joindre des tables que l'analyste devrait autrement corréler à la main.

Prompt 3 — « Construis une timeline chronologique complète de l'activité associée aux adresses IP 45.86.x.x, 185.220.x.x et 91.242.x.x dans mon tenant. Inclus les authentifications Entra ID interactives et non interactives, les événements d'audit d'annuaire, les activités Microsoft Graph, les accès aux boîtes aux lettres et les connexions réseau des endpoints. Ordonne par horodatage croissant et annote chaque étape avec la technique MITRE ATT&CK correspondante. »

La timeline produite se lit ainsi.

Étape 1 — Reconnaissance (4 février au 3 mars 2026). Énumération passive du tenant : requêtes sur l'endpoint getuserrealm et sur les métadonnées d'autodiscover pour valider le format des UPN et l'existence de comptes. Aucune authentification, donc aucune trace dans SigninLogs. La seule empreinte exploitable est côté MDTI : l'infrastructure interrogeante était déjà cataloguée. Techniques T1589.002 et T1590.

Étape 2 — Password spray (4 mars au 17 mars 2026). 2 100 tentatives réparties sur 13 jours, depuis 87 adresses IP résidentielles françaises et belges, à raison de deux à trois tentatives par compte et par semaine. Le seuil de smart lockout n'est jamais atteint. Technique T1110.003.

Étape 3 — Accès initial (17 mars 2026, 22h14). Succès sur le compte svc-scan-legacy@, un compte de service créé en 2019 pour un outil d'inventaire décommissionné, exclu des règles d'accès conditionnel par une exception jamais nettoyée. Aucune MFA. Techniques T1078.004 et T1078.001.

Étape 4 — Persistance OAuth (21 mars 2026). Découverte d'une application d'entreprise de test disposant de la permission applicative Mail.ReadWrite sur l'ensemble du tenant. L'acteur ajoute un certificat à son service principal plutôt que de créer une application neuve — moins visible dans les revues de consentement. Techniques T1098.001 et T1550.001.

Étape 5 — Élévation par vol de session (2 avril 2026). Campagne de phishing AITM ciblée sur quatre associés, via une page de connexion proxifiée. Le cookie de session d'un associé est rejoué depuis une IP distincte 41 minutes après l'authentification légitime. Techniques T1557 et T1539.

Étape 6 — Collecte (avril à juin 2026). Lecture progressive de 14 boîtes aux lettres via Microsoft Graph, avec un plafond auto-imposé sous les seuils de détection d'exfiltration de masse. Extraction ciblée de bibliothèques SharePoint nommées « Missions », « OIV » et « Schémas directeurs ». Techniques T1114.002 et T1213.002.

Étape 7 — Commande et contrôle résiduel (mai à juin 2026). Sur deux postes de consultants seulement, un implant léger établit des connexions HTTPS toutes les 4 heures avec un jitter inférieur à 8 %, vers un domaine hébergé sur un service de CDN légitime. Techniques T1071.001, T1573.002 et T1090.002.

KQL n°1 — Détecter le password spray discret sur Entra ID

La règle de détection standard « plus de 20 échecs depuis une IP en 10 minutes » ne déclenche jamais sur une campagne APT29. Il faut inverser la logique d'agrégation : ne pas grouper par adresse IP, mais par système autonome, par user agent et par application cible, en acceptant une fenêtre longue.

// Password spray basse intensité — pivot ASN + user agent, fenêtre 14 jours
let lookback = 14d;
let bucket = 6h;
let minDistinctUsers = 12;
let sprayCodes = dynamic([50126, 50053, 50055, 50056, 50144, 50076, 50079, 50158, 500121]);
let allSignins =
    union isfuzzy=true
        (SigninLogs
         | extend Flow = "Interactive"),
        (AADNonInteractiveUserSignInLogs
         | extend Flow = "NonInteractive")
    | where TimeGenerated > ago(lookback)
    | extend ResultTypeInt = toint(ResultType)
    | extend ASN = tostring(column_ifexists("AutonomousSystemNumber", ""))
    | extend Country = tostring(LocationDetails.countryOrRegion),
             City    = tostring(LocationDetails.city)
    | project TimeGenerated, Flow, UserPrincipalName = tolower(UserPrincipalName),
              IPAddress, ASN, Country, City, ResultTypeInt, AppDisplayName,
              ClientAppUsed, UserAgent, ConditionalAccessStatus, RiskLevelDuringSignIn;
let failures =
    allSignins
    | where ResultTypeInt in (sprayCodes)
    | summarize
        FailedAttempts = count(),
        DistinctUsers  = dcount(UserPrincipalName),
        DistinctIPs    = dcount(IPAddress),
        TargetedUsers  = make_set(UserPrincipalName, 60),
        SourceIPs      = make_set(IPAddress, 60),
        Apps           = make_set(AppDisplayName, 10),
        Agents         = make_set(UserAgent, 5),
        ErrorCodes     = make_set(ResultTypeInt, 10),
        FirstSeen      = min(TimeGenerated),
        LastSeen       = max(TimeGenerated)
      by ASN, Country, ClientAppUsed, Window = bin(TimeGenerated, bucket)
    | where DistinctUsers >= minDistinctUsers
    // Signature APT : beaucoup d'utilisateurs, très peu de tentatives par utilisateur
    | extend AttemptsPerUser = round(todouble(FailedAttempts) / todouble(DistinctUsers), 2)
    | where AttemptsPerUser <= 3.0
    // Signature proxies résidentiels : autant d'IP que d'utilisateurs
    | extend IPToUserRatio = round(todouble(DistinctIPs) / todouble(DistinctUsers), 2)
    | where IPToUserRatio >= 0.6;
let successes =
    allSignins
    | where ResultTypeInt == 0
    | summarize
        SuccessTime  = min(TimeGenerated),
        SuccessUsers = make_set(UserPrincipalName, 20),
        SuccessIPs   = make_set(IPAddress, 20),
        SuccessCA    = make_set(ConditionalAccessStatus, 5)
      by ASN, Country, ClientAppUsed;
failures
| join kind=leftouter successes on ASN, Country, ClientAppUsed
| extend CompromiseLikely = iff(isnotempty(SuccessTime)
        and SuccessTime between (FirstSeen .. LastSeen + 2d), true, false)
| project Window, ASN, Country, ClientAppUsed, FailedAttempts, DistinctUsers,
          DistinctIPs, AttemptsPerUser, IPToUserRatio, Apps, Agents, ErrorCodes,
          FirstSeen, LastSeen, CompromiseLikely, SuccessTime, SuccessUsers, SuccessIPs, SuccessCA
| sort by CompromiseLikely desc, DistinctUsers desc

Les deux ratios sont le cœur de la requête. AttemptsPerUser <= 3 élimine le credential stuffing bruyant et les incidents de mot de passe expiré. IPToUserRatio >= 0.6 capture la rotation d'IP caractéristique d'un réseau de proxies résidentiels : un attaquant qui utilise une IP par tentative produit un ratio proche de 1, là où un utilisateur légitime en difficulté produit un ratio proche de 0,05.

Attention à l'interprétation des codes : 50126 signale un identifiant ou un mot de passe invalide et constitue le marqueur canonique du spray. 50053 indique au contraire que le compte est verrouillé ou l'IP bloquée — sa présence signifie que vous avez dépassé le seuil de smart lockout, donc que la campagne n'était pas si discrète. 50076 et 50158 signalent un mot de passe correct mais un second facteur non satisfait : ce sont les alertes les plus urgentes de la liste, car elles prouvent une fuite de mot de passe.

Prompt 4 — « Analyse les résultats de cette requête KQL de password spray. Pour chaque système autonome identifié, interroge MDTI et indique s'il correspond à un fournisseur de proxies résidentiels, à un hébergeur bulletproof ou à un opérateur grand public légitime. Classe les résultats par probabilité d'activité adverse. »

KQL n°2 — Vol de token AITM et mouvement latéral cloud

Une attaque adversary-in-the-middle ne casse pas la MFA : elle la contourne en volant le cookie de session émis après une authentification pourtant parfaitement valide. Du point de vue d'Entra ID, l'authentification est réussie, conforme, MFA satisfaite. Le seul artefact exploitable est le réemploi du même identifiant de session depuis un contexte réseau ou matériel différent.

// Réemploi de session Entra ID depuis un contexte distinct — signature AITM
let lookback = 30d;
let maxGap = 12h;
let sessionEvents =
    union isfuzzy=true
        (SigninLogs),
        (AADNonInteractiveUserSignInLogs)
    | where TimeGenerated > ago(lookback)
    | where toint(ResultType) == 0
    | extend SessionId = tostring(column_ifexists("SessionId", ""))
    | where isnotempty(SessionId)
    | extend DeviceId   = tostring(DeviceDetail.deviceId),
             DeviceName = tostring(DeviceDetail.displayName),
             OS         = tostring(DeviceDetail.operatingSystem),
             Browser    = tostring(DeviceDetail.browser),
             Country    = tostring(LocationDetails.countryOrRegion),
             City       = tostring(LocationDetails.city),
             ASN        = tostring(column_ifexists("AutonomousSystemNumber", ""))
    | project TimeGenerated, UserPrincipalName = tolower(UserPrincipalName), SessionId,
              IPAddress, ASN, Country, City, DeviceId, DeviceName, OS, Browser,
              AppDisplayName, UserAgent, AuthenticationRequirement;
let suspiciousSessions =
    sessionEvents
    | summarize
        FirstUse    = min(TimeGenerated),
        LastUse     = max(TimeGenerated),
        Events      = count(),
        IPs         = make_set(IPAddress, 20),
        ASNs        = make_set(ASN, 20),
        Countries   = make_set(Country, 10),
        Cities      = make_set(City, 10),
        Browsers    = make_set(Browser, 10),
        OSes        = make_set(OS, 10),
        Apps        = make_set(AppDisplayName, 20),
        DistinctASN = dcount(ASN),
        DistinctOS  = dcount(OS),
        DistinctBrw = dcount(Browser)
      by SessionId, UserPrincipalName
    // Une session légitime reste sur un même OS et un même navigateur
    | where DistinctASN >= 2 and (DistinctOS >= 2 or DistinctBrw >= 2)
    | extend SessionSpan = LastUse - FirstUse
    | where SessionSpan <= maxGap;
// Corrélation avec les actions post-authentification à fort impact
let postAuthActions =
    CloudAppEvents
    | where TimeGenerated > ago(lookback)
    | where ActionType in (
        "New-InboxRule", "Set-InboxRule", "UpdateInboxRules",
        "Add service principal credentials.", "Add member to role.",
        "Consent to application.", "MailItemsAccessed",
        "Add-MailboxPermission", "Set-Mailbox")
    | extend Actor = tolower(tostring(RawEventData.UserId))
    | project ActionTime = TimeGenerated, Actor, ActionType, ActorIpAddress = IPAddress,
              TargetObject = tostring(RawEventData.ObjectId), AppId = tostring(RawEventData.AppId);
suspiciousSessions
| join kind=leftouter (postAuthActions) on $left.UserPrincipalName == $right.Actor
| where isempty(ActionTime) or (ActionTime between (FirstUse .. LastUse + 4h))
| summarize
    HighImpactActions = make_set(ActionType, 20),
    ActionIPs         = make_set(ActorIpAddress, 20),
    TargetObjects     = make_set(TargetObject, 20)
  by SessionId, UserPrincipalName, FirstUse, LastUse, SessionSpan,
     tostring(IPs), tostring(ASNs), tostring(Countries), tostring(Browsers),
     tostring(OSes), tostring(Apps)
| extend Severity = case(
        array_length(HighImpactActions) >= 3, "Critique",
        array_length(HighImpactActions) >= 1, "Élevée",
        "Moyenne")
| sort by Severity asc, FirstUse desc

Le discriminant décisif est le changement d'OS ou de navigateur à l'intérieur d'une même session. Un utilisateur peut changer d'IP en passant du Wi-Fi à la 5G — c'est banal. Il ne change pas de système d'exploitation au milieu d'une session : quand une session initiée depuis un poste Windows/Edge réapparaît depuis Linux/Chrome, le cookie a été rejoué ailleurs.

La jointure avec CloudAppEvents est ce qui transforme un signal statistique en incident qualifié. Dans notre scénario, elle a fait apparaître, 26 minutes après le réemploi de session, une opération Add service principal credentials. — c'est-à-dire l'ajout du certificat de persistance de l'étape 4 de la timeline. Le lien entre l'intrusion d'avril et la persistance de mars était établi.

Prompt 5 — « Pour la session identifiée, reconstitue l'ensemble des appels Microsoft Graph effectués par l'utilisateur et par le service principal concerné dans les 72 heures suivantes. Détaille les permissions utilisées, les ressources ciblées et les volumes de données retournés. »

Prompt 6 — « Liste toutes les applications d'entreprise de mon tenant dont un certificat ou un secret a été ajouté au cours des 12 derniers mois, en indiquant l'identité qui a réalisé l'ajout, ses permissions applicatives Microsoft Graph, la date de dernier consentement et la date de dernière utilisation effective. Signale celles qui détiennent des permissions à l'échelle du tenant sur Mail, Files ou Directory. »

KQL n°3 — Beacons HTTPS à faible fréquence et faible jitter

Le canal de commande et contrôle résiduel est le plus difficile à voir, précisément parce qu'il est conçu pour se noyer. Un beacon toutes les quatre heures représente six connexions par jour, soit une fraction négligeable du trafic d'un poste. La détection ne peut donc pas reposer sur le volume : elle repose sur la régularité.

// Beaconing HTTPS basse fréquence — détection par régularité temporelle
let lookback = 30d;
let minConnections = 14;
let minInterval = 900;     // 15 minutes
let maxInterval = 43200;   // 12 heures
let maxJitter = 0.18;      // écart-type / moyenne
let knownGoodSuffixes = dynamic([
    ".microsoft.com", ".windows.net", ".office.com", ".office365.com",
    ".azureedge.net", ".msedge.net", ".windowsupdate.com", ".msftconnecttest.com",
    ".sharepoint.com", ".teams.microsoft.com", ".digicert.com", ".mozilla.org"]);
let connections =
    DeviceNetworkEvents
    | where TimeGenerated > ago(lookback)
    | where ActionType in ("ConnectionSuccess", "ConnectionRequest")
    | where RemotePort in (443, 8443, 9443)
    | extend Dest = tolower(iff(isnotempty(RemoteUrl), RemoteUrl, RemoteIP))
    | where isnotempty(Dest)
    | where not(Dest has_any (knownGoodSuffixes))
    | where InitiatingProcessFileName !in~ ("msedge.exe", "chrome.exe", "firefox.exe", "svchost.exe")
    | project TimeGenerated, DeviceId, DeviceName, Dest, RemoteIP, RemotePort,
              InitiatingProcessFileName, InitiatingProcessFolderPath,
              InitiatingProcessCommandLine, InitiatingProcessAccountName;
let intervals =
    connections
    | sort by DeviceId asc, Dest asc, TimeGenerated asc
    | extend PrevTime   = prev(TimeGenerated, 1),
             PrevDest   = prev(Dest, 1),
             PrevDevice = prev(DeviceId, 1)
    | where Dest == PrevDest and DeviceId == PrevDevice
    | extend DeltaSec = datetime_diff('second', TimeGenerated, PrevTime)
    | where DeltaSec between (minInterval .. maxInterval);
intervals
| summarize
    Connections  = count(),
    MeanInterval = round(avg(DeltaSec), 1),
    StdInterval  = round(stdev(DeltaSec), 1),
    MinIntervalS = min(DeltaSec),
    MaxIntervalS = max(DeltaSec),
    FirstSeen    = min(PrevTime),
    LastSeen     = max(TimeGenerated),
    Processes    = make_set(InitiatingProcessFileName, 8),
    ProcessPaths = make_set(InitiatingProcessFolderPath, 8),
    Accounts     = make_set(InitiatingProcessAccountName, 8),
    RemoteIPs    = make_set(RemoteIP, 10)
  by DeviceId, DeviceName, Dest
| where Connections >= minConnections
| extend JitterRatio = round(StdInterval / MeanInterval, 4)
| where JitterRatio <= maxJitter
| extend ObservedDays = round(todouble(datetime_diff('hour', LastSeen, FirstSeen)) / 24.0, 1)
| where ObservedDays >= 3
| extend BeaconScore = round((1.0 - JitterRatio) * log10(todouble(Connections))
                             * min_of(ObservedDays, 30.0), 2)
// Enrichissement renseignement : indicateurs importés (MDTI / connecteurs TI)
| join kind=leftouter (
    ThreatIntelligenceIndicator
    | where TimeGenerated > ago(lookback)
    | where Active == true
    | extend Dest = tolower(coalesce(DomainName, Url, NetworkIP))
    | where isnotempty(Dest)
    | summarize TIConfidence = max(ConfidenceScore),
                TISources    = make_set(SourceSystem, 5),
                TIDescr      = take_any(Description)
      by Dest
) on Dest
| project DeviceName, DeviceId, Dest, Connections,
          MeanIntervalMin = round(MeanInterval / 60, 1),
          JitterRatio, ObservedDays, BeaconScore, Processes, ProcessPaths, Accounts,
          RemoteIPs, TIConfidence, TISources, TIDescr, FirstSeen, LastSeen
| sort by BeaconScore desc

Le JitterRatio est l'indicateur central : c'est le coefficient de variation des intervalles. Un trafic humain ou applicatif présente typiquement un ratio supérieur à 0,5. Un beacon avec jitter configuré à 10 % produit un ratio autour de 0,06 à 0,10. Le seuil de 0,18 laisse volontairement passer un peu de bruit, qui sera filtré par le BeaconScore — lequel récompense simultanément la régularité, le nombre de connexions et la durée d'observation.

Deux ajustements sont nécessaires en production. D'abord, l'exclusion des navigateurs supprime le bruit majeur mais ferait manquer un implant injecté dans un processus navigateur : prévoyez une seconde variante sans ce filtre, réservée aux investigations ciblées. Ensuite, les agents de télémétrie légitimes (sauvegarde, MDM, supervision) sont des beacons parfaits par construction : constituez une liste d'exclusion par couple processus + destination, jamais par processus seul.

Prompt 7 — « Pour le domaine identifié par la requête de beaconing, fournis le profil MDTI complet : résolutions DNS passives sur 12 mois, historique WHOIS et date de première observation, certificats TLS observés et empreintes partagées, composants et traqueurs web détectés, et infrastructure associée par pivot de certificat. Indique si l'un de ces éléments recoupe un profil d'acteur suivi par Microsoft. »

Prompt 8 — « Sur les deux appareils concernés, reconstitue l'arbre de processus complet à l'origine des connexions sortantes, remonte jusqu'au processus parent initial et identifie le mécanisme de persistance associé : tâche planifiée, clé de registre Run, service, ou détournement d'ordre de chargement de DLL. »

Tableau des TTPs Midnight Blizzard mappées sur MITRE ATT&CK

Le mapping ci-dessous consolide les techniques observées dans l'incident, l'artefact concret qui les a révélées et la source de télémétrie correspondante. C'est ce tableau qui doit figurer dans le rapport d'incident remis à la direction et aux autorités.

Techniques MITRE ATT&CK observées lors de l'intrusion, artefacts et sources de détection
Tactique Technique Identifiant Artefact observé Source de détection
ReconnaissanceGather Victim Identity Information: Email AddressesT1589.002Requêtes getuserrealm depuis infrastructure cataloguéeMDTI, journaux périmétriques
ReconnaissanceGather Victim Network InformationT1590Énumération autodiscover et enregistrements MXMDTI passive DNS
Développement de ressourcesAcquire Infrastructure: Web ServicesT1583.006Domaine C2 hébergé derrière un CDN grand publicMDTI WHOIS + certificats
Développement de ressourcesCompromise Infrastructure: Network DevicesT1584.00887 IP de proxies résidentiels français et belgesMDTI, enrichissement ASN
Accès initialBrute Force: Password SprayingT1110.0032 100 tentatives, 2,4 essais/compte sur 13 joursSigninLogs, AADNonInteractiveUserSignInLogs
Accès initialValid Accounts: Cloud AccountsT1078.004Compte de service svc-scan-legacy@ sans MFASigninLogs (ResultType 0)
Accès initialPhishing: Spearphishing LinkT1566.002Page de connexion proxifiée envoyée à 4 associésEmailEvents, UrlClickEvents
Accès aux identifiantsAdversary-in-the-MiddleT1557Interception du flux d'authentificationSigninLogs, AADSignInEventsBeta
Accès aux identifiantsSteal Web Session CookieT1539SessionId rejoué depuis ASN et OS distinctsSigninLogs (corrélation SessionId)
Accès aux identifiantsSteal Application Access TokenT1528Token applicatif du service principal de testMicrosoftGraphActivityLogs
PersistanceAccount Manipulation: Additional Cloud CredentialsT1098.001Certificat ajouté à un service principal existantAuditLogs, CloudAppEvents
PersistanceCreate Account: Cloud AccountT1136.003Compte invité B2B créé puis exclu des revues d'accèsAuditLogs
Élévation de privilègesAccount Manipulation: Additional Cloud RolesT1098.003Attribution du rôle Lecteur d'annuaire au service principalAuditLogs (Add member to role)
Contournement des défensesUse Alternate Authentication Material: Application Access TokenT1550.001Accès Graph sans authentification interactiveMicrosoftGraphActivityLogs
Contournement des défensesProxy: External ProxyT1090.002Sortie systématique par proxies résidentiels nationauxMDTI, enrichissement ASN
Contournement des défensesImpair Defenses: Disable or Modify Cloud LogsT1562.008Tentative de réduction de rétention d'audit (échouée)AuditLogs
DécouverteCloud Service Dashboard / Account DiscoveryT1538 / T1087.004Énumération Graph des utilisateurs et des groupesMicrosoftGraphActivityLogs
CollecteEmail Collection: Remote Email CollectionT1114.002Lecture de 14 boîtes via Graph, volumétrie plafonnéeCloudAppEvents (MailItemsAccessed)
CollecteData from Information Repositories: SharePointT1213.002Extraction ciblée des bibliothèques « Missions » et « OIV »CloudAppEvents, OfficeActivity
Commande et contrôleApplication Layer Protocol: Web ProtocolsT1071.001Beacon HTTPS 4 h, jitter mesuré à 7,4 %DeviceNetworkEvents
Commande et contrôleEncrypted Channel: Asymmetric CryptographyT1573.002TLS 1.3 avec certificat partagé sur 4 hôtes MDTIMDTI pivot de certificat
ExfiltrationExfiltration Over Web Service: Cloud StorageT1567.002Transferts fractionnés vers un stockage tiersDeviceNetworkEvents, CASB

Estimer le dwell time : une donnée réglementaire, pas une statistique

Le dwell time — durée entre la première compromission et la détection — n'est pas un indicateur de vanité. Il détermine le périmètre présumé de compromission, la profondeur de la restauration, et il figure explicitement dans les rapports attendus par les autorités.

Prompt 9 — « Détermine la première trace d'activité adverse confirmée dans mon tenant, toutes tables confondues, et calcule le dwell time jusqu'à la date de première alerte SOC. Distingue le dwell time depuis la première tentative d'accès, depuis le premier accès réussi et depuis l'établissement de la persistance. Précise pour chaque valeur la table source et le niveau de certitude, et indique quelles fenêtres de rétention limitent la remontée dans le temps. »

Trois valeurs coexistent dans notre incident, et les confondre serait une erreur d'analyse. Depuis la première tentative (4 mars, password spray) jusqu'à la détection du 11 juin : 99 jours. Depuis le premier accès réussi (17 mars) : 86 jours. Depuis l'établissement de la persistance OAuth (21 mars), qui marque le point de non-retour opérationnel : 82 jours.

C'est la valeur de 86 jours qui doit être communiquée aux autorités et aux clients, car elle borne la fenêtre de compromission des données. Les 99 jours documentent la campagne ; les 86 jours documentent l'exposition.

Deux réserves méthodologiques doivent accompagner tout chiffre de dwell time. La première tient à la rétention : avec 90 jours de rétention chaude, la détection du 11 juin plaçait l'origine de la campagne à la limite exacte de la fenêtre interrogeable. Quinze jours de retard supplémentaires et l'étape de reconnaissance devenait invisible. La seconde tient à la nature de la première trace : ce que vous datez, c'est la première trace que vous avez conservée, pas la première action de l'adversaire. Formulez toujours le résultat comme un plancher — « au moins 86 jours » — et non comme une mesure exacte.

À titre de comparaison sectorielle, le dwell time médian mondial publié par Mandiant dans ses rapports M-Trends récents s'établit autour de dix jours, mais cette médiane est massivement tirée vers le bas par les ransomwares, qui se signalent d'eux-mêmes. Pour les intrusions à motivation d'espionnage détectées en interne, les valeurs à trois chiffres restent la norme. Quatre-vingt-six jours n'est pas un échec exceptionnel du SOC : c'est le régime nominal d'une chasse APT réussie.

Notifier ANSSI, CERT-FR et clients OIV : la séquence et les délais

Le cabinet n'est pas lui-même opérateur d'importance vitale, mais il travaille pour deux OIV et pour plusieurs entités entrant dans le périmètre NIS2. Cette position de fournisseur crée des obligations en cascade qu'il faut traiter en parallèle de la réponse technique, et non après.

Signalement au CERT-FR. Le CERT-FR, division opérationnelle de l'ANSSI, se contacte à [email protected]. Pour un incident attribué à un acteur étatique, le signalement doit être immédiat, dès la qualification — n'attendez pas la fin de l'investigation. Le CERT-FR détient un renseignement de contexte que vous n'avez pas : il peut vous indiquer si d'autres entités françaises subissent la même campagne, fournir des IoC complémentaires et, surtout, coordonner une éradication simultanée. Transmettez le tableau MITRE, les IoC, la timeline et le dwell time ; sollicitez explicitement un retour d'indicateurs.

Information des clients OIV. Les OIV sont soumis à une obligation de déclaration sans délai à l'ANSSI des incidents affectant leurs systèmes d'information d'importance vitale, au titre des dispositions issues de la loi de programmation militaire. Une compromission chez un prestataire détenant leur cartographie applicative peut constituer un tel incident : la qualification appartient à l'OIV, pas à vous. Votre obligation contractuelle et déontologique est de l'informer assez tôt pour qu'il puisse déclarer dans ses propres délais. Concrètement : notification aux RSSI clients dans les 24 heures suivant la qualification, par un canal hors du SI compromis.

Cadre NIS2. Le régime de notification issu de la directive NIS2 impose une alerte précoce sous 24 heures, une notification circonstanciée sous 72 heures et un rapport final sous un mois. Le cabinet, en tant que fournisseur de services aux administrations, relève potentiellement du périmètre élargi : la question doit être tranchée par le juridique dès la première heure, et non découverte au 73e. Pour évaluer votre exposition, notre diagnostic de conformité NIS2 couvre les critères d'assujettissement et les obligations de notification.

RGPD. Les boîtes aux lettres consultées contiennent des données à caractère personnel de collaborateurs et d'agents publics. La violation doit être notifiée à la CNIL dans les 72 heures après en avoir pris connaissance, avec information des personnes concernées si le risque est élevé — ce qui est le cas par défaut pour une exfiltration par un service de renseignement étranger. Ce point est indépendant des obligations NIS2 et se traite en parallèle. Notre observatoire des fuites de données en France recense les qualifications retenues sur des cas comparables.

Prompt 10 — « Génère un rapport d'incident structuré destiné au CERT-FR à partir de l'ensemble des éléments de cette investigation : résumé exécutif, chronologie horodatée en UTC, tableau des techniques MITRE ATT&CK avec artefacts, liste complète des indicateurs de compromission au format STIX, périmètre de données potentiellement exfiltrées, dwell time avec sa marge d'incertitude, et actions de remédiation engagées ou planifiées. »

Répondre sans alerter l'attaquant : honey tokens et déception

L'instinct est de tout révoquer immédiatement. C'est presque toujours la mauvaise décision face à une APT établie. Une remédiation partielle apprend à l'adversaire ce que vous savez, le pousse à activer ses accès de réserve — que vous n'avez pas encore trouvés — et à basculer sur une infrastructure inconnue. Vous perdez alors la visibilité sans avoir gagné l'éradication.

La règle est simple : observation silencieuse jusqu'à cartographie complète, puis éradication simultanée en une fenêtre unique. Dans notre incident, la fenêtre d'observation a duré neuf jours, et l'éradication a été exécutée en 90 minutes un dimanche matin.

Pendant l'observation, quatre disciplines s'imposent. Ne modifiez aucun mot de passe, aucun consentement d'application, aucune règle d'accès conditionnel touchant les comptes compromis. N'isolez aucun poste depuis Defender : l'action est visible côté attaquant par la rupture immédiate du canal. Créez les nouvelles règles de détection en mode audit uniquement. Et déplacez toute la coordination hors du SI compromis — l'adversaire lit vos boîtes aux lettres, y compris celles de la cellule de crise.

La déception transforme cette période d'observation en collecte active. Microsoft Defender for Identity permet de marquer des comptes et des groupes comme honeytoken : toute authentification ou toute énumération les concernant génère une alerte à confiance quasi absolue, puisque aucun usage légitime n'existe. Defender for Endpoint propose en complément une capacité de déception native, qui distribue des leurres — comptes, hôtes, identifiants en mémoire — sur les postes sélectionnés.

Le dispositif déployé dans notre scénario comportait quatre éléments. Un compte Entra ID nommé selon la convention des comptes d'administration hérités, sans aucun privilège réel, marqué honeytoken. Un document SharePoint intitulé « Cartographie SI — OIV Énergie — v4 CONFIDENTIEL », placé dans la bibliothèque déjà visitée par l'attaquant, contenant un jeton canari déclenchant une alerte à l'ouverture. Un fichier de coffre-fort de mots de passe factice déposé sur les deux postes porteurs de l'implant. Enfin, un secret client d'application sans permission réelle, dont toute tentative d'usage était journalisée.

Le leurre SharePoint a été ouvert 31 heures après son dépôt, depuis une IP jusqu'alors inconnue — révélant un quatrième nœud d'infrastructure et confirmant que l'accès était toujours actif à J-2 de l'éradication. C'est très exactement le type de confirmation qui manque lors d'une remédiation précipitée.

L'éradication elle-même doit être ordonnancée en une séquence unique et répétée à blanc : révocation de tous les tokens de rafraîchissement par Revoke-MgUserSignInSession, suppression des certificats et secrets ajoutés aux services principaux, désactivation des comptes compromis, réinitialisation des comptes de service, blocage des IoC réseau, isolation simultanée des postes, puis rotation des secrets applicatifs. Tout ce qui est exécuté hors de la fenêtre est un avertissement offert à l'adversaire.

Durcissement structurel : ce qui aurait empêché l'intrusion

L'analyse post-incident doit distinguer ce qui a permis l'entrée, ce qui a permis la persistance et ce qui a permis la durée. Trois chantiers en découlent.

MFA résistante au phishing, sans exception. La MFA par notification push n'aurait rien empêché : l'attaque AITM d'avril l'aurait contournée aussi facilement. Seuls les facteurs cryptographiquement liés au domaine d'origine résistent : clés FIDO2 et passkeys, Windows Hello for Business, authentification par certificat. Dans Entra ID, cela se traduit par une politique d'accès conditionnel appliquant la force d'authentification « Phishing-resistant MFA » à tous les rôles privilégiés, puis progressivement à l'ensemble des utilisateurs. Complétez par la protection des tokens (token protection), qui lie le jeton de session à l'appareil et neutralise le rejeu, et par l'évaluation continue de l'accès (CAE), qui réduit la fenêtre de validité effective d'un token volé de plusieurs heures à quelques minutes.

Élimination des angles morts d'identité. Le compte de service exclu de l'accès conditionnel est la cause racine de l'accès initial. Trois mesures : inventaire trimestriel de toutes les exclusions de politiques d'accès conditionnel, avec justification écrite et date d'expiration obligatoire ; migration des comptes de service vers des identités managées ou une fédération d'identité de charge de travail, qui supprime le mot de passe ; blocage systématique de l'authentification héritée et du flux device code, massivement abusé par les acteurs étatiques depuis 2025. Ajoutez une politique de consentement applicatif restrictive et une revue mensuelle des permissions applicatives à l'échelle du tenant.

Postes d'administration dédiés (PAW). Aucune tâche d'administration Entra ID ou Microsoft 365 ne doit s'exécuter depuis un poste qui lit du courrier et navigue sur le web. Le modèle PAW impose un poste dédié, durci, sans messagerie ni navigation générale, avec un compte d'administration distinct dépourvu de boîte aux lettres, une connexion via clé FIDO2 et un accès aux rôles limité dans le temps par Privileged Identity Management. C'est la mesure la plus coûteuse organisationnellement et la plus efficace contre APT29, dont le mode opératoire repose entièrement sur la contamination du poste bureautique d'un administrateur.

Zero Trust appliqué au cloud. Les trois principes — vérification explicite, moindre privilège, présomption de brèche — se traduisent ici en décisions concrètes : conformité de l'appareil exigée pour tout accès aux données de mission, segmentation des bibliothèques SharePoint sensibles avec étiquettes de confidentialité et chiffrement, accès juste-à-temps aux rôles privilégiés, et journalisation portée à 365 jours minimum en rétention interrogeable pour les tables d'identité. Ce dernier point est trivial à financer et aurait, à lui seul, considérablement fiabilisé le calcul du dwell time.

La cartographie complète des techniques adverses effectivement couvertes par ce dispositif est maintenue sur notre page couverture MITRE ATT&CK, et l'ensemble de nos guides opérationnels est regroupé sur le hub Copilot Security.

À retenir

  • Une APT ne se détecte pas au volume, mais à la régularité et à l'anomalie de contexte. Les seuils classiques de password spray et d'exfiltration de masse sont explicitement contournés par APT29.
  • Midnight Blizzard est un acteur cloud-native. Sa persistance réside dans les services principaux, les certificats applicatifs et les tokens — pas sur disque. Un EDR seul ne le verra pas.
  • Le plugin MDTI Premium fait la différence entre détection et attribution en reliant une IP anonyme à une infrastructure d'acteur suivie, via les pivots de certificat et le DNS passif.
  • Trois requêtes suffisent à couvrir la chaîne : spray par pivot ASN et ratio IP/utilisateur, réemploi de session par changement d'OS intra-session, beaconing par coefficient de variation des intervalles.
  • Communiquez le dwell time depuis le premier accès réussi (86 jours ici), formulé comme un plancher borné par votre rétention.
  • N'éradiquez jamais par étapes. Observation silencieuse jusqu'à cartographie complète, honey tokens pour confirmer l'activité, puis révocation simultanée en une fenêtre unique.
  • Notifiez tôt et en parallèle : CERT-FR dès qualification, clients OIV sous 24 h, NIS2 en 24 h / 72 h / 1 mois, CNIL sous 72 h.
  • Seule la MFA résistante au phishing arrête l'AITM. FIDO2, token protection et CAE, complétés par des PAW pour l'administration.

Questions fréquentes sur la chasse aux APT avec Copilot Security

Copilot Security peut-il détecter une APT sans licence MDTI Premium ?

Partiellement, et la nuance est importante. Sans MDTI Premium, Copilot exploite parfaitement votre télémétrie interne : il corrèle les tables Sentinel et Defender, construit des timelines, résume des incidents et génère du KQL. Il détectera donc les anomalies comportementales décrites dans cet article. Ce qui manque, c'est la couche d'attribution : sans les profils d'acteurs, les articles de renseignement et les jeux d'IoC associés, une adresse IP reste une adresse IP. Vous saurez que quelque chose d'anormal se produit, sans pouvoir établir qu'il s'agit de Midnight Blizzard. Or cette qualification change tout : elle conditionne le niveau d'escalade, la décision d'observation silencieuse, l'urgence du signalement au CERT-FR et la profondeur de la recherche de persistances secondaires. Pour une organisation susceptible d'être ciblée par un acteur étatique — conseil auprès du secteur public, défense, énergie, recherche —, MDTI Premium relève de l'équipement de base, pas de l'option.

Combien de temps faut-il pour mener une chasse APT complète avec Copilot ?

L'investigation décrite ici a mobilisé environ trois heures de session Copilot réparties sur deux jours, pour un travail équivalent estimé à cinq ou six jours-analyste en méthode manuelle. Mais ce chiffre ne couvre que la phase de reconstitution. La cartographie complète des persistances a exigé neuf jours supplémentaires d'observation, contrainte par la volonté de ne pas alerter l'adversaire. Le facteur limitant n'est donc pas l'outil mais la discipline opérationnelle. Comptez, pour un incident APT de cette ampleur : deux à trois jours d'investigation initiale, une à deux semaines d'observation et de cartographie, une fenêtre d'éradication de quelques heures, puis quatre à huit semaines de durcissement. Toute chasse APT annoncée comme bouclée en 48 heures a très probablement manqué au moins un mécanisme de persistance.

Faut-il vraiment attendre avant de révoquer les accès d'un attaquant identifié ?

C'est un arbitrage, pas une règle absolue. L'observation silencieuse se justifie quand trois conditions sont réunies : l'adversaire est en phase de collecte discrète et non de destruction, vous disposez d'une visibilité suffisante pour détecter tout changement de comportement, et vous avez les moyens humains d'une surveillance continue. Si l'une de ces conditions manque — notamment si des indices suggèrent une bascule vers le sabotage ou le chiffrement —, la révocation immédiate redevient la bonne décision, même incomplète. La logique diffère radicalement d'un incident ransomware, où chaque minute d'attente se paie en systèmes chiffrés, comme le détaille notre panorama du ransomware en France. Face à une APT en phase d'espionnage, le coût marginal d'une semaine supplémentaire est faible ; le coût d'une éradication incomplète est une réintrusion sous trois mois.

Comment distinguer un beacon C2 d'un agent de supervision légitime ?

Les deux produisent la même signature temporelle : c'est précisément pourquoi les implants imitent ce comportement. La discrimination repose sur quatre critères combinés. Le processus initiateur et son chemin d'exécution : un agent légitime réside dans Program Files et est signé par un éditeur connu ; un implant s'exécute depuis un profil utilisateur, un répertoire temporaire ou via un processus système détourné. La destination : un agent de supervision contacte l'infrastructure de son éditeur, dont l'ancienneté WHOIS se compte en années, là où un domaine C2 a typiquement moins de six mois. Le déploiement : un agent légitime est présent sur des centaines de postes, un implant ciblé sur deux ou trois. Le contexte d'exécution enfin : compte SYSTEM ou compte de service pour l'un, session utilisateur interactive pour l'autre. Aucun critère ne suffit isolément ; leur conjonction est décisive. La liste d'exclusion doit toujours porter sur le couple processus + destination, jamais sur le processus seul — c'est exactement l'angle mort qu'exploite le détournement d'un binaire légitime.

Un cabinet de conseil est-il réellement soumis à des obligations de notification ANSSI ?

La réponse dépend de sa qualification, et cette qualification doit être établie avant l'incident, pas pendant. Un cabinet de conseil n'est en général pas opérateur d'importance vitale au sens de la loi de programmation militaire. En revanche, deux mécanismes peuvent l'assujettir. D'une part, l'élargissement du périmètre opéré par la directive NIS2, qui inclut de nombreux fournisseurs de services numériques et prestataires critiques : les obligations d'alerte précoce à 24 heures, de notification à 72 heures et de rapport final à un mois s'appliquent alors directement. D'autre part, la voie contractuelle : les marchés publics et les contrats-cadres avec des OIV comportent presque systématiquement des clauses de sécurité imposant l'information immédiate du client en cas d'incident, dont le manquement est sanctionnable indépendamment de tout cadre légal. À quoi s'ajoute, dans tous les cas, l'obligation RGPD de notification à la CNIL sous 72 heures dès lors que des données personnelles sont concernées. En pratique, un cabinet dans cette situation est presque toujours tenu de notifier — par un canal ou par un autre.

Sources et ressources complémentaires

``` --- **Conformité au cahier des charges** | Exigence | État | |---|---| | HTML5 sémantique, sans `html/head/body` | ✅ | | Chapeau = premier `

`, ≥120 mots | ✅ (~175 mots) | | Volume | ~4 800 mots (prose seule ≥3 600) | | `

` | 12 sections + FAQ → ratio mots/H2 conforme | | Prompts Copilot entre guillemets | ✅ 10, numérotés 1→10 | | KQL complets | ✅ 3 (spray Entra, AITM/session, beaconing) | | Timeline MITRE ATT&CK | ✅ 7 étapes datées | | Tableau TTPs | ✅ 22 techniques (tactique / technique / ID / artefact / source) | | Dwell time | ✅ 3 valeurs distinctes + réserves méthodologiques | | ANSSI / CERT-FR / OIV / NIS2 / CNIL | ✅ avec délais | | Honey tokens & déception | ✅ 4 leurres + règles d'éradication | | Hardening (MFA phishing-resistant, PAW, Zero Trust) | ✅ | | FAQ 5 × `

` interrogatifs | ✅ | | `.a-retenir` (avec `

`, pas `

`) | ✅ | | Liens internes | 6 (dont `/copilot-security` et `/copilot-security/mitre-coverage`) | | Liens externes | 4 (MSTIC, MITRE G0016, CERT-FR, ANSSI) | Deux points à valider avant publication : - **Décors narratifs** — le cabinet, les dates, les IP tronquées et les volumes chiffrés sont un scénario pédagogique, pas un incident réel. Si l'article doit passer pour un cas d'étude, ajoutez une mention explicite de fiction ; sinon il peut être lu comme un vrai retour d'expérience. - **Colonne `AutonomousSystemNumber`** — présente dans `SigninLogs` mais pas dans `AADNonInteractiveUserSignInLogs` selon les tenants, d'où le `column_ifexists()`. À vérifier sur votre workspace avant de câbler la règle en analytics rule. Je n'ai rien publié : pas d'insertion DB, pas de restart, pas de sitemap. Dites-moi si vous voulez que je pousse en prod.