Les 15 événements Windows qui trahissent un attaquant

Un attaquant qui prend pied dans un réseau Windows laisse des traces, presque toujours dans les mêmes quinze événements. Il crée des comptes, demande des tickets Kerberos, lance des processus, installe des services, et, pour finir, efface le journal. Voici lesquels, ce qui doit alerter, les pièges, et un script de détection que nous avons testé sur des événements de démonstration.

Ce qu’il faut retenir

  • Quinze événements couvrent l’essentiel : accès (4624, 4625, 4648, 4672), exécution (4688, 4104), persistance (4697, 4698, 4720, 4728 et 4732), vol d’identifiants (4768, 4769, 4662, 4776) et effacement des traces (1102).
  • Ils ne sont pas tous enregistrés par défaut. Chacun dépend d’une sous-catégorie de la stratégie d’audit avancée ; la ligne de commande des processus (4688) et le contenu des scripts PowerShell (4104) demandent en plus un réglage spécifique.
  • Un événement seul ne prouve rien ; c’est l’enchaînement qui alerte : un compte créé puis ajouté à Domain Admins quelques minutes plus tard, des échecs sur dix comptes différents depuis une même adresse, cinq tickets de service en RC4 ou plus en quelques minutes.
  • Le journal de la machine attaquée n’est pas une preuve fiable : l’événement 1102 existe précisément parce qu’on peut l’effacer. Il faut centraliser les journaux hors de la machine.

Avant de chercher : activer l’audit

Chaque page de la documentation Microsoft indique la sous-catégorie d’audit dont dépend l’événement. Si elle n’est pas activée sur la machine concernée, l’événement n’est pas écrit.

Sous-catégorie d’auditÉvénements
Audit Logon4624, 4625, 4648
Audit Special Logon4672
Audit Process Creation4688
Audit Security System Extension4697
Audit Other Object Access Events4698
Audit User Account Management4720
Audit Security Group Management4728, 4732
Audit Kerberos Authentication Service4768
Audit Kerberos Service Ticket Operations4769
Audit Directory Service Access4662 (sur les contrôleurs de domaine)
Audit Credential Validation4776
Other Events1102

Deux réglages supplémentaires sont nécessaires. Pour l’événement 4688, la ligne de commande est vide par défaut : Microsoft indique d’activer la stratégie de groupe « Administrative Templates\System\Audit Process Creation\Include command line in process creation events ». Pour l’événement 4104, il faut activer la journalisation des blocs de script PowerShell (« Turn on PowerShell Script Block Logging » dans la stratégie de groupe) ; Microsoft recommande d’y associer la journalisation protégée, car le contenu des scripts peut être sensible. Pour Windows PowerShell 5.1, l’événement est écrit dans le journal Microsoft-Windows-PowerShell/Operational.

Vous pouvez vérifier et régler l’audit en ligne de commande avec auditpol (nous n’avons pas de domaine Windows dans notre banc d’essai : ces deux commandes n’ont pas été exécutées pour cet article, vérifiez le nom exact des sous-catégories dans votre langue) :

auditpol /get /category:*
auditpol /set /subcategory:"Process Creation" /success:enable

La carte des quinze événements

Les quinze événements Windows classés en cinq colonnes : accès, exécution, persistance, identifiants, effacement des traces
Classement de l’auteur selon la phase d’intrusion où chaque événement est le plus utile.

Accès : qui se connecte, comment, avec quels droits

IDCe que l’événement ditCe qui doit alerterATT&CK
4624Ouverture de session réussie. Le champ « Logon Type » distingue 3 (réseau), 9 (NewCredentials), 10 (RemoteInteractive, c’est-à-dire le Bureau à distance)Type 10 depuis une adresse externe ou vers un contrôleur de domaine ou un serveur de sauvegarde ; comptes administrateurs hors des heures habituellesT1021.001, T1021.002
4625Échec d’ouverture de sessionUn même IP en échec sur beaucoup de comptes différents (pulvérisation) ; Microsoft recommande de surveiller tous les 4625 sur les comptes locaux et de service, qui ne devraient pas échouerT1110
4648Ouverture de session avec des identifiants explicites (un compte en utilise un autre)Utilisation d’un compte à privilèges depuis un poste où il ne devrait pas apparaître ; utilisation hors des heures de travail (recommandations de Microsoft)–
4672Privilèges spéciaux attribués à une nouvelle sessionSujet autre que SYSTEM, NETWORK SERVICE, LOCAL SERVICE et les administrateurs attendus ; privilège SeDebugPrivilege hors des comptes qui en ont besoin (recommandations de Microsoft)–

Exécution : ce qui tourne sur la machine

IDCe que l’événement ditCe qui doit alerterATT&CK
4688Un nouveau processus a été créé, avec sa ligne de commande si le réglage est activéExécutables hors de System32 et de Program Files ; outils d’énumération (whoami, net user) ; commandes de destruction des sauvegardes (vssadmin delete shadows, wmic shadowcopy delete, bcdedit), citées par la CISAT1059
4104Contenu d’un bloc de script PowerShell, dans le journal PowerShell/OperationalScripts encodés ou obscurcis, téléchargement puis exécution de code distant, appels à des outils d’attaque connusT1059.001

Persistance : ce qui reste après le départ de l’attaquant

IDCe que l’événement ditCe qui doit alerterATT&CK
4697Un service a été installé (le journal Système contient l’événement 7045 pour la même action)Fichier de service hors de %windir% et Program Files ; service qui s’exécute sous un compte utilisateur ; installation inattendue sur un serveur sensible (recommandations de Microsoft)T1543.003
4698Une tâche planifiée a été crééeToute création sur un serveur critique ; tâche à la racine de la bibliothèque ; contenu XML avec <LogonType>Password</LogonType> (le mot de passe est alors stocké en clair dans le gestionnaire d’informations d’identification, selon Microsoft)T1053.005
4720Un compte utilisateur a été crééCréation hors du processus habituel ; nom qui imite un compte existant à un caractère près ; créateur qui n’est pas un compte du supportT1136
4732 / 4728Un membre a été ajouté à un groupe de sécurité local (4732) ou global (4728)Tout ajout à Domain Admins, Enterprise Admins, Administrateurs : alerte immédiate, jour et nuitT1098

Identifiants : Kerberos, réplication et NTLM

IDCe que l’événement ditCe qui doit alerterATT&CK
4768Un ticket d’authentification Kerberos (TGT) a été demandéType de pré-authentification 0 (« Logon without Pre-Authentication ») : compte configuré sans pré-authentification, cible du AS-REP roasting ; adresse cliente hors des plages internes (Microsoft)T1558.004
4769Un ticket de service Kerberos a été demandéType de chiffrement 0x17 (RC4-HMAC) alors que 0x11 et 0x12 (AES) sont les valeurs attendues ; beaucoup de services demandés par un même compte en peu de tempsT1558.003
4662Une opération a été effectuée sur un objet de l’annuairePropriétés portant les GUID de droits de réplication 1131f6aa-… et 1131f6ad-… utilisés par un compte qui n’est pas un contrôleur de domaineT1003.006
4776Le contrôleur a tenté de valider des identifiants (authentification NTLM)Le même poste source qui valide de nombreux comptes différents ; comptes inactifs ou à ne jamais utiliser (recommandations de Microsoft)–

Effacement : la trace qui dit qu’on a voulu en effacer d’autres

IDCe que l’événement ditCe qui doit alerterATT&CK
1102Le journal d’audit a été effacéMicrosoft : « en principe, vous ne devriez pas voir cet événement » ; il faut enquêter sur chaque occurrenceT1685.005 (ancien T1070.001, que MITRE redirige)

MITRE cite parmi les usages observés de cette technique la commande wevtutil cl security chez APT28 et BlackCat. Un attaquant qui efface le journal produit lui-même l’événement 1102 : s’il est transmis à un serveur central avant l’effacement, l’alerte existe.

Quelques détails qui font la différence

  • 4769 en RC4. La documentation indique que RC4 (0x17) est la suite par défaut des systèmes antérieurs à Windows Vista et Server 2008, et qu’il faut surveiller les types autres que 0x11 et 0x12. Attention aux faux positifs : un compte de service ancien peut légitimement rester en RC4. MITRE rapproche aussi le Kerberoasting d’un nombre inhabituel de tickets demandés en peu de temps.
  • 4662 et la réplication. Les contrôleurs de domaine se répliquent légitimement entre eux : la règle porte sur les comptes qui ne sont pas des comptes machine. Cet événement n’est produit que si une liste de contrôle d’accès d’audit (SACL) est posée sur l’objet du domaine, en plus de la sous-catégorie d’audit.
  • 4624 et 4625 sont très bavards. Ne cherchez pas l’anomalie dans chaque ligne : agrégez par adresse, par compte et par type de session.
  • 4672 apparaît à chaque ouverture de session administrateur : utile pour dresser la liste de qui a des privilèges spéciaux, pas comme alerte brute.

Un script de détection, testé

Le script suivant (Python, bibliothèque standard uniquement) lit un export XML du journal Security (wevtutil qe Security /f:xml > sec.xml) et applique six règles : Kerberoasting, pulvérisation de mots de passe, ajout à un groupe privilégié, compte créé puis élevé en moins de 15 minutes, effacement du journal et DCSync.

#!/usr/bin/env python3
"""Chasse dans des événements Windows exportés en XML (wevtutil qe Security /f:xml > sec.xml)."""
import sys, re, xml.etree.ElementTree as ET
from collections import defaultdict
from datetime import datetime, timedelta

PRIV = {"Domain Admins", "Enterprise Admins", "Schema Admins", "Administrators", "Administrateurs",
        "Admins du domaine", "Administrateurs de l'entreprise"}
DCSYNC = ("1131f6aa-9c07-11d1-f79f-00c04fc2dcd2", "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2")


def events(path):
    raw = re.sub(r"<\?xml[^>]*\?>", "", open(path, encoding="utf-8-sig").read())
    root = ET.fromstring("<Events>" + raw + "</Events>")
    for ev in root:
        d = {}
        for el in ev.iter():
            tag = el.tag.split("}")[-1]
            if tag == "EventID": d["id"] = int(el.text)
            elif tag == "TimeCreated": d["t"] = datetime.fromisoformat(el.get("SystemTime").rstrip("Z")[:26])
            elif tag == "Data" and el.get("Name"): d[el.get("Name")] = (el.text or "").strip()
            elif len(el) == 0 and el.text and tag not in ("EventID", "Data"): d.setdefault(tag, el.text.strip())
        if "id" in d and "t" in d:
            yield d


def window(items, key, n, minutes, distinct):
    """Retourne les clés pour lesquelles >= n valeurs distinctes apparaissent dans une fenêtre glissante."""
    by = defaultdict(list)
    for e in items:
        by[key(e)].append(e)
    for k, lst in by.items():
        lst.sort(key=lambda e: e["t"])
        for i, first in enumerate(lst):
            seen = {distinct(e) for e in lst[i:] if e["t"] - first["t"] <= timedelta(minutes=minutes)}
            if len(seen) >= n:
                yield k, first["t"], sorted(seen)
                break


def hunt(evs, spn_min=5, spray_min=10):
    out = []
    ev = list(evs)
    tgs = [e for e in ev if e["id"] == 4769 and e.get("TicketEncryptionType") == "0x17" and e.get("Status") == "0x0"
           and not e.get("ServiceName", "").endswith("$") and e.get("ServiceName", "").lower() != "krbtgt"]
    for (user, ip), t, svc in window(tgs, lambda e: (e["TargetUserName"], e["IpAddress"]), spn_min, 10, lambda e: e["ServiceName"]):
        out.append((t, "KERBEROASTING", f"{user} depuis {ip} : tickets RC4 pour {len(svc)} services ({', '.join(svc[:4])}...)"))
    fails = [e for e in ev if e["id"] == 4625 and e.get("TargetUserName")]
    for ip, t, users in window(fails, lambda e: e["IpAddress"], spray_min, 10, lambda e: e["TargetUserName"]):
        out.append((t, "PULVERISATION", f"{ip} : échecs sur {len(users)} comptes différents en 10 min"))
    adds = [e for e in ev if e["id"] in (4728, 4732, 4756)]
    for e in adds:
        if e.get("TargetUserName") in PRIV:
            out.append((e["t"], "GROUPE_PRIVILEGIE", f"{e['MemberName']} ajouté à {e['TargetUserName']} par {e['SubjectUserName']}"))
    created = {e["TargetSid"]: e for e in ev if e["id"] == 4720}
    for e in adds:
        c = created.get(e.get("MemberSid"))
        if c and timedelta(0) <= e["t"] - c["t"] <= timedelta(minutes=15):
            out.append((e["t"], "COMPTE_CREE_PUIS_ELEVE", f"{c['TargetUserName']} créé par {c['SubjectUserName']}, ajouté à {e['TargetUserName']} {int((e['t']-c['t']).total_seconds())} s plus tard"))
    for e in ev:
        if e["id"] == 1102:
            out.append((e["t"], "JOURNAL_EFFACE", f"journal Security effacé par {e.get('SubjectUserName', '?')}"))
        if e["id"] == 4662 and not e.get("SubjectUserName", "").endswith("$") and any(g in e.get("Properties", "").lower() for g in DCSYNC):
            out.append((e["t"], "DCSYNC", f"droits de réplication utilisés par {e['SubjectUserName']}"))
    return sorted(out)


if __name__ == "__main__":
    for t, rule, msg in hunt(events(sys.argv[1])):
        print(f"{t:%Y-%m-%d %H:%M:%S}  {rule:<24} {msg}")

Nous l’avons testé sur 28 événements de démonstration que nous avons fabriqués en respectant les noms de champs des exemples XML de Microsoft Learn. Ce ne sont pas des événements issus d’une vraie intrusion : le test vérifie la logique des règles, pas leur taux de faux positifs dans votre réseau. Résultat :

2026-09-29 02:00:00  KERBEROASTING            jdupont@CONTOSO.LOCAL depuis ::ffff:10.0.5.23 : tickets RC4 pour 6 services (CIFS/files, FTP/backup, HTTP/intranet, HTTP/wiki...)
2026-09-29 02:30:00  PULVERISATION            203.0.113.9 : échecs sur 12 comptes différents en 10 min
2026-09-29 03:04:00  COMPTE_CREE_PUIS_ELEVE   administratr créé par svc-backup, ajouté à Domain Admins 240 s plus tard
2026-09-29 03:04:00  GROUPE_PRIVILEGIE        CN=administratr,CN=Users,DC=contoso,DC=local ajouté à Domain Admins par svc-backup
2026-09-29 05:00:00  JOURNAL_EFFACE           journal Security effacé par administratr
2026-09-29 05:05:00  DCSYNC                   droits de réplication utilisés par administratr

Les cas normaux mêlés aux données de test ne déclenchent rien : trois échecs de connexion d’un utilisateur, un ticket AES, l’ajout d’un compte à un groupe non privilégié, et la réplication effectuée par un compte machine de contrôleur de domaine. Le scénario « compte créé puis ajouté à Domain Admins » reprend celui de l’intrusion Lynx décrite dans notre article sur les rançongiciels. Les noms de groupes privilégiés du script sont ceux d’une installation anglaise et française : adaptez-les à votre annuaire.

Les pièges à éviter

  • Auditer sur la machine seulement. Sans centralisation, un attaquant qui efface le journal efface aussi la preuve. Transmettez les événements à un collecteur avant tout.
  • Tout activer sans réfléchir au volume. Le journal Security tourne vite sur un contrôleur de domaine ; dimensionnez la taille et la rétention, sinon les événements utiles sont écrasés en quelques heures.
  • Oublier la ligne de commande dans 4688. Sans elle, l’événement dit qu’un processus a démarré, pas ce qu’il a fait.
  • Chercher les outils par leur nom. Un exécutable renommé passe entre les mailles : privilégiez les comportements (création de compte, réplication, RC4 en rafale).
  • Ne pas horodater de façon cohérente. Des horloges qui dérivent rendent les corrélations sur quelques minutes impossibles.
  • Traiter les alertes seulement en journée. Voir notre article sur les rançongiciels : l’essentiel des déploiements a lieu hors des heures ouvrées.

Huit questions pour votre parc

  1. Les douze sous-catégories du tableau sont-elles activées sur les contrôleurs de domaine et les serveurs sensibles ?
  2. La ligne de commande des processus est-elle enregistrée (4688) ?
  3. La journalisation des blocs de script PowerShell est-elle active, avec protection des événements ?
  4. Les journaux quittent-ils la machine avant qu’un attaquant puisse les effacer ?
  5. Qui est alerté, à toute heure, d’un ajout à Domain Admins ?
  6. Savez-vous lister les comptes de service encore en RC4 ?
  7. Une SACL d’audit protège-t-elle l’objet du domaine pour détecter la réplication (4662) ?
  8. Avez-vous rejoué une attaque de test (compte créé puis élevé) pour vérifier que l’alerte se déclenche ?

En résumé

Quinze événements ne remplacent pas un outil de détection, mais ils suffisent à voir l’essentiel d’une intrusion Windows : les comptes créés, les groupes modifiés, les tickets Kerberos demandés en rafale, les services et tâches installés, la réplication de l’annuaire et l’effacement du journal. Le travail n’est pas de les connaître, mais de les activer, de les sortir de la machine et de décider qui les lit la nuit.

Transparence : cet article a été rédigé avec l’aide d’un assistant Claude. Les descriptions d’événements et les recommandations attribuées à Microsoft proviennent de leur documentation (pages consultées en septembre 2026) ; les correspondances ATT&CK ont été vérifiées sur attack.mitre.org. Le script a été exécuté sur des données synthétiques, les commandes auditpol ne l’ont pas été. Le classement par phase est le choix de l’auteur.

Sources