Wazuh à l'état brut : 19 alertes pour 4 attaques simulées
Résumé
Round 1 de mon homelab SOC : quatre attaques simulées (Atomic Red Team) sur une VM Windows surveillée par Sysmon et Wazuh, avec les règles par défaut. Je reconstitue ce qui s'est passé à partir des alertes seules, puis je compare avec la vérité terrain : 19 alertes, 8 hypothèses justes, 8 partielles, 3 fausses. Mes conclusions sont celles prises pendant l'analyse ; la vérité terrain n'a été consultée qu'après.
Objectif
Établir une baseline « out of the box » (règles Wazuh par défaut + Sysmon) :
- Un script tire 4 tests Atomic Red Team au hasard et les exécute avec des délais aléatoires.
- Je reconstitue la séquence uniquement à partir des alertes.
- Je compare avec le journal de vérité terrain et je documente mes erreurs.
Environnement
Round réalisé le 16 octobre 2026 sur un lab local (KVM/QEMU, réseau NAT) :
- une VM Windows 10 LTSC 2021 (évaluation) avec Sysmon v15.22 (configuration SwiftOnSecurity) et l’agent Wazuh ;
- une VM Ubuntu Server avec Wazuh 4.14 (manager, indexer, dashboard) ;
- Atomic Red Team pour simuler les attaques.
L’architecture, le script, le journal de vérité terrain et la liste des alertes sont dans le dépôt GitHub.
Protocole
| Paramètre | Valeur |
|---|---|
| Tirage | 4 tests tirés dans un pool (scripts/round.ps1) |
| Délai entre tests | 60-150 s (aléatoire) |
| Outils autorisés | dashboard Wazuh, VirusTotal |
| Méthode de notes | une entrée par alerte : hypothèse (attaque / bruit) et justification |
Vérité terrain
| Action | Début (UTC) | Technique | Test Atomic Red Team |
|---|---|---|---|
| 1 | 15:58:59 | T1136.001 | Create a new user in a command prompt |
| 2 | 16:00:46 | T1547.001 | Reg Key Run |
| 3 | 16:01:54 | T1547.009 | Create shortcut to cmd in startup folders |
| 4 | 16:03:42 | T1059.003 | Writes text to a file and displays it |
Les 4 tests se sont terminés sans erreur (code de sortie 0). Journal complet : results/round-1/journal.csv.
Télémétrie observée
EID = identifiant d’événement Sysmon. Les alertes des sources ci-dessous totalisent les 19 alertes du round.
| Source | Volume |
|---|---|
| Alertes Wazuh (total) | 19 : action 1 = 8, action 2 = 3, action 3 = 3, action 4 = 1, bruit = 4 |
| Sysmon EID 1 (process create) | 56 événements → 6 alertes |
| Sysmon EID 11 (file create) | 5 événements → 4 alertes |
| Sysmon EID 12 (registry object) | 8 événements → 0 alerte |
| Sysmon EID 13 (registry value) | 33 événements → 1 alerte |
| Journal Security de Windows | 5 alertes (4720, 4722, 4728, 4732, 4738) |
| FIM (File Integrity Monitoring) | 1 alerte |
| Journaux système et application Windows | 2 alertes |
Reconstitution et verdicts
Verdict alerte par alerte
N° désigne le numéro de l’alerte dans l’ordre chronologique. Les alertes sont regroupées par action a posteriori : pendant le round, je les voyais dans cet ordre.
Le verdict porte sur mon hypothèse initiale, même quand je l’ai corrigée ensuite en cours d’analyse.
Légende :
- ✅ action et qualification bonnes
- ⚠️ action identifiée mais mal qualifiée
- ❌ hypothèse fausse
Pour le bruit : ✅ correctement écarté, ❌ pris pour une attaque.
Action 1 : création de compte local (T1136.001, 15:58:59)
| N° | Alerte | Hypothèse initiale |
|---|---|---|
| 3 ❌ |
cmd lancé par un processus anormal |
Probablement du bruit |
| 4 ❌ |
net.exe lancé par cmd |
Mise à jour Windows |
| 5 ✅ |
net1.exe : création d’utilisateur |
Compte backdoor possible, regroupé avec #3 et #4 (même seconde) |
| 6 ⚠️ |
Domain Users Group Changed (4728) | Attaque certaine, escalade de privilèges ? |
| 7 ✅ |
User account enabled or created (4720) | Début d’une chaîne d’événements liée |
| 8 ⚠️ |
User account enabled or created (4722) | Activation du compte, hypothèse d’escalade maintenue |
| 9 ✅ |
User account changed (4738) | L’opérateur utilise la session locale pour créer un compte |
| 10 ⚠️ |
Users Group Changed (4732), groupe Users |
Soupçon de droits administrateur |
Réalité :
- #3 et #4 :
cmdetnet.exeétaient les deux premiers maillons denet user /add, ni du bruit ni une mise à jour Windows. Je les ai écartés d’abord, puis reclassés comme attaque en lisant #6. - #6, #8, #10 : il n’y a pas d’escalade. Le compte est dans le groupe
None(#6) et dansUsers, pasAdministrators(#10).
Action 2 : persistance par clé Run (T1547.001, 16:00:46)
| N° | Alerte | Hypothèse initiale |
|---|---|---|
| 11 ⚠️ |
cmd, REG ADD ... Run |
Pertinence incertaine |
| 12 ✅ |
reg.exe, motif « Base64-like » |
Modification du registre liée à une attaque |
| 13 ⚠️ |
Entrée de registre exécutée au prochain logon | Liée à #12, création d’un compte admin ou d’un processus privilégié |
Réalité :
- #11 : c’est la commande qui écrit la clé Run, le début de l’action.
- #12 : la règle parle de Base64, mais la valeur ajoutée est un simple chemin. Le libellé est trompeur, ma lecture (modification du registre liée à une attaque) était juste.
- #13 : le but est la persistance. Le programme se lance au prochain logon, ce n’est pas un compte admin.
Action 3 : raccourci dans les dossiers Startup (T1547.009, 16:01:54)
| N° | Alerte | Hypothèse initiale |
|---|---|---|
| 15 ⚠️ |
FIM : fichier ajouté dans Startup | Escalade de privilèges sur un exécutable |
| 16 ⚠️ |
PowerShell copie un fichier dans Startup | Création en deux temps d’un fichier privilégié |
| 17 ⚠️ |
PowerShell crée un fichier « script » dans Startup (Roaming) | Transformation du fichier en script |
Réalité :
- #15 : le fichier est un raccourci
.lnk, et les permissions affichées sont celles du fichier, pas une modification par l’attaquant. - #15, #16, #17 : une seule commande PowerShell, deux fichiers
.lnk. #15 (FIM) et #16 (Sysmon) concernent le même fichier, dans le Startup commun (ProgramData), vu par deux capteurs. #17 concerne celui du Startup de l’utilisateur (Roaming). Les événements Sysmon derrière #16 et #17 ont le mêmeProcessGuid, à 15 ms d’écart.
Action 4 : exécution via cmd (T1059.003, 16:03:42)
| N° | Alerte | Hypothèse initiale |
|---|---|---|
| 19 ✅ |
cmd, echo Hello... |
Message de l’attaquant, probablement indépendant des actions précédentes |
Bruit système (4 alertes)
| N° | Alerte | Hypothèse initiale |
|---|---|---|
| 1 ✅ |
Service startup type changed (BITS) | Bruit |
| 2 ❌ |
License Activation (slui.exe) failed |
Tentative d’attaque, partiellement échouée |
| 14 ✅ |
Exécutable déposé dans un dossier souvent utilisé par les malwares (niveau 15) | Bruit : PowerShell met à jour un réglage |
| 18 ✅ |
Fichier déposé à la racine Windows (AM_Delta.exe) |
Mise à jour Windows |
Réalité :
- #2 est une activation de licence Windows (
Trigger=NetworkQuarantineRetry). - #14 est un fichier de test de politique PowerShell (
__PSScriptPolicyTest). - #18 est une mise à jour de Windows Defender.
Bilan chiffré
Sur 19 alertes (hypothèses initiales) : 8 ✅ 8 ⚠️ 3 ❌.
- Couverture : les 4 actions sont identifiées. Trois d’entre elles (1, 2 et 3) contiennent au moins une alerte mal qualifiée, l’action 4 est entièrement juste.
- Bruit : 3 alertes sur 4 correctement écartées (BITS,
__PSScriptPolicyTest,AM_Delta). L’activation de licence Windows a été prise pour une attaque. - Ce qui a marché : regroupement temporel (alertes #3 à #5, une fois #6 lue), lecture du contexte de session (#9), niveau 15 non surpondéré (#14), rejet de l’hypothèse d’une altération des signatures Defender (#18).
Ce que j’en retiens
Les quatre premiers viennent d’erreurs du round, le dernier d’un point qui a bien marché.
- Compter les actions, pas les événements. Une commande peut produire jusqu’à 8 alertes (action 1). L’action 3 en produit 3 : un seul PowerShell crée deux
.lnk, et le fichier du Startup commun est vu deux fois, par le FIM (#15) et par Sysmon (#16). J’ai lu #16 et #17 comme deux étapes alors que le mêmeProcessGuidà 15 ms d’écart figurait dans mes notes. Corréler parProcessGuid/Logon ID. - Lire les champs, pas les libellés ni les hash.
Usersn’est pasAdministrators(#10), un.lnkn’est pas un exécutable (#15). Les hash decmd.exeetreg.exene donnent rien sur VirusTotal : ce sont des binaires légitimes détournés (living off the land). Le signal est danscommandLine. - Classer sur la preuve, pas sur l’impression de familiarité. J’ai écarté de vraies actions parce que tous les champs affichaient Microsoft et que VirusTotal ne détectait rien (#3, #4), et j’ai pris pour une attaque une activation de licence parce que j’ai mal lu le champ
channel(#2). Dans les deux cas, regarder qui lance quoi : chaîne parent → enfant (cmd→net→net1) et ligne de commande. - Ne pas conclure à une escalade sans preuve de privilège. Création de compte et persistance ne sont pas de l’escalade (#6, #8, #10, #13, #15). Chercher le groupe cible (
Administrators) avant de parler de droits. - Niveau ≠ pertinence. Le niveau 15 du round était du bruit (
__PSScriptPolicyTest), la création de compte est au niveau 12 et la persistance Startup au niveau 14.
Limites
- Un seul poste Windows, un seul utilisateur, peu d’activité de fond : baseline trop propre pour estimer le bruit en production.
- Un seul round et 4 actions, avec des verdicts attribués après coup : les chiffres donnent un ordre de grandeur, pas une mesure. Une relecture indépendante serait nécessaire pour les valider.
- Atomic Red Team laisse des artefacts nominatifs (
T1136.001_CMD, « Atomic Red Team ») qu’un attaquant réel éviterait. - Résultats dépendants de la config Sysmon SwiftOnSecurity.
- Pas de corrélation multi-événements : les règles que j’ai lues évaluent chacune un événement isolé, et je n’ai pas encore exploré les mécanismes de corrélation de Wazuh (
frequency,if_matched_sid).
Suite
- Écrire les règles : silence du bruit
__PSScriptPolicyTest, et alignement du niveau d’alerte du Startup utilisateur (AppData\Roaming, niveau 9) sur celui du Startup commun (niveau 14). - Round 2 : même protocole et même grille de notation, règles custom actives, comparaison chiffrée avec cette baseline.