TP 3 — Couverture MITRE & Corrélation (et ses limites)
Auteur : Thibaut Fontaine Institution : Université de la Réunion Date : 2026
Table des matières
Section intitulée « Table des matières »- Objectif & contexte
- Prérequis
- Étape 1 — Tagger les règles ATT&CK (R6a)
- Étape 2 — Générer le layer Navigator (S2AN)
- Étape 3 — Visualiser dans Navigator self-hosted
- Étape 4 — Corrélation 2 étages (R7)
- Étape 5 — La limite : pourquoi Loki ne fait pas tout
- Livrables & validation
- Annexe enseignant — corrigé
1. Objectif & contexte
Section intitulée « 1. Objectif & contexte »📡 Poste SOC · La Réunion — Acte 2, Détecter : vous armez Alfred Faure (Crozet), ~2 900 km. Liaison SATCOM nominale.
Vous savez écrire des règles (TP1). Vous savez les transformer en alertes (TP2). Maintenant on passe de « j’ai des règles » à « je couvre une surface » — et on apprend où votre stack s’arrête.
🔴 Au fil de l’enquête
Section intitulée « 🔴 Au fil de l’enquête »Une détection isolée ne raconte rien. Le jour J fut une chaîne : phishing (T1078) → escalade AD (T1068) → accès coffre (T1213) → exfil (T1041). Ici vous mesurez votre couverture ATT&CK (où sont vos angles morts ?) et vous corrélez plusieurs sources sur une même étape — pour voir la kill chain, pas des alertes éparses. C’est le dernier TP du module SIEM core : il clôt l’Acte 2.
Objectifs pédagogiques
Section intitulée « Objectifs pédagogiques »- Comprendre la détection comme discipline de couverture (pas de règles isolées).
- Générer un layer ATT&CK Navigator à partir d’un repo de règles Sigma (S2AN).
- Visualiser et lire la couverture (techniques couvertes / non couvertes / partielles).
- Construire une corrélation 2 étages en LogQL (détecte → re-détecte sur le stream de détections).
- Identifier et documenter les limites de Loki (pourquoi un XDR/Wazuh existe).
Architecture du TP3
Section intitulée « Architecture du TP3 »graph LR subgraph "Source" RULES[/Repo taaf-detections
règles Sigma taggées/] end subgraph "Génération couverture" S2AN[S2AN
parser Sigma] LAYER[/Layer ATT&CK
JSON Navigator/] NAV[MITRE Navigator
self-hosted] end subgraph "Corrélation 2 étages" R1[Règles TP1/TP2] STREAM[Stream Loki
'detections'] R2[Règle corrélation
count over time] end RULES --> S2AN S2AN --> LAYER LAYER --> NAV RULES --> R1 R1 -->|via webhook ou Alloy| STREAM STREAM --> R2 R2 -->|alerte 'kill chain'| AL([Alerte Grafana]) classDef src fill:#ffcc99,stroke:#333,stroke-width:2px classDef cov fill:#99ff99,stroke:#333,stroke-width:2px classDef corr fill:#99ccff,stroke:#333,stroke-width:2px class RULES src class S2AN,LAYER,NAV cov class R1,STREAM,R2,AL corr
2. Prérequis
Section intitulée « 2. Prérequis »# Vérifier le repo TP1/TP2cd ~/taaf-detectionsls rules/ # → 3+ règles Sigmagrep -l "tags:" rules/**/*.yml | wc -l # → 3+ (toutes taggées)
# Activer le venv Sigmasource ~/sigma-venv/bin/activateSi une règle n’a pas de tag attack.txxxx, vous devez la corriger maintenant (ouvrez le YAML, ajoutez les tags) — sans tag, S2AN ignore la règle silencieusement.
Installer S2AN
Section intitulée « Installer S2AN »S2AN (« Sigma to ATT&CK Navigator ») est un binaire Go qui parse un repo de règles Sigma et génère un layer JSON :
# Sur la VM soccurl -sL https://github.com/threatcode/s2an/releases/latest/download/s2an_linux_amd64 \ -o ~/sigma-venv/bin/s2anchmod +x ~/sigma-venv/bin/s2ans2an --version # → s2an 0.xInstaller MITRE Navigator self-hosted
Section intitulée « Installer MITRE Navigator self-hosted »docker run -d --name attack-navigator \ -p 4200:4200 \ --restart unless-stopped \ mitre/attack-navigator:latestAccès : http://IP_SOC:4200.
3. Étape 1 — Tagger les règles ATT&CK (R6a)
Section intitulée « 3. Étape 1 — Tagger les règles ATT&CK (R6a) »3.1 — Vérifier les tags existants
Section intitulée « 3.1 — Vérifier les tags existants »cd ~/taaf-detectionsgrep -A 5 "^tags:" rules/**/*.ymlSortie attendue : pour chaque règle, ≥ 1 ligne - attack.txxxx.
3.2 — Format canonique des tags
Section intitulée « 3.2 — Format canonique des tags »| Type | Exemple | Notes |
|---|---|---|
| Tactique | attack.initial_access | Une seule tactique principale par règle |
| Technique | attack.t1078 | Toujours minuscules, sans point |
| Sous-technique | attack.t1078.002 | Domain Accounts (sous T1078) |
3.3 — Ajouter les sous-techniques manquantes
Section intitulée « 3.3 — Ajouter les sous-techniques manquantes »Reprenez la règle TP1 vpn-auth-external-ip.yml. Le tag attack.t1078 (Valid Accounts) est trop générique. Précisez :
tags: - attack.initial_access - attack.t1078 - attack.t1078.002 # Domain Accounts (l'AD est compromis) - attack.t1133 # External Remote Services (VPN)Faites de même pour les 2 autres règles :
| Règle | Tags ATT&CK recommandés |
|---|---|
falco-classified-vault-read.yml | attack.collection · attack.t1213 · attack.t1213.002 (data from cloud storage) |
postgres-genetic-samples-no-approval.yml | attack.collection · attack.t1213.003 · attack.exfiltration · attack.t1041 |
3.4 — Commit
Section intitulée « 3.4 — Commit »git add rules/git commit -m "feat(detections): TP3 — sous-techniques ATT&CK affinées"4. Étape 2 — Générer le layer Navigator (S2AN)
Section intitulée « 4. Étape 2 — Générer le layer Navigator (S2AN) »4.1 — Lancer S2AN
Section intitulée « 4.1 — Lancer S2AN »cd ~/taaf-detectionss2an \ -r rules/ \ -o build/navigator/taaf-coverage-layer.json \ -n "TAAF SOC — couverture détections" \ --score-applied 100 \ --score-partial 50Options :
-r: repo à parser (récursif)-o: fichier de sortie JSON-n: nom du layer (visible dans Navigator)--score-applied: score affiché pour une technique entièrement couverte--score-partial: score pour une technique partiellement couverte
Sortie attendue (extrait JSON) :
{ "name": "TAAF SOC — couverture détections", "domain": "enterprise-attack", "techniques": [ { "techniqueID": "T1078.002", "score": 100, "comment": "vpn-auth-external-ip.yml", "color": "" }, { "techniqueID": "T1213.002", "score": 100, "comment": "falco-classified-vault-read.yml" }, { "techniqueID": "T1041", "score": 100, "comment": "postgres-genetic-samples-no-approval.yml" } ], "gradient": { "colors": ["#ff6666", "#ffe766", "#8ec843"], "minValue": 0, "maxValue": 100 }}4.2 — Voir les trous
Section intitulée « 4.2 — Voir les trous »Le layer ne contient que les techniques couvertes. Vous savez ce que vous manquez par soustraction.
Pour comparer à un référentiel APT :
# Télécharger le layer d'un groupe APT connu (par ex. Volt Typhoon)curl -sL https://attack.mitre.org/docs/enterprise-attack-v15.1/enterprise-attack-v15.1-layers/G1017-enterprise-layer.json \ -o build/navigator/volt-typhoon-layer.jsonDans Navigator, vous chargerez les deux layers et utiliserez layer expression (a - b) pour voir ce que Volt Typhoon fait que vous ne détectez pas.
5. Étape 3 — Visualiser dans Navigator self-hosted
Section intitulée « 5. Étape 3 — Visualiser dans Navigator self-hosted »5.1 — Charger le layer
Section intitulée « 5.1 — Charger le layer »- Ouvrez
http://IP_SOC:4200dans votre navigateur. - Open Existing Layer → Upload from local → sélectionnez
taaf-coverage-layer.json.
📸 Capture obligatoire #1 : matrice ATT&CK Enterprise avec vos techniques en vert (couvertes). Annotez 3 trous critiques (ex : T1068 Privilege Escalation — vous ne détectez PAS l’escalade svc_backup → Domain Admins).
5.2 — Comparer avec un référentiel APT
Section intitulée « 5.2 — Comparer avec un référentiel APT »- + (en haut) → Create New Layer → Create Layer from other layers.
- Domain : Enterprise.
- Score expression :
a - b(aveca= layer TAAF,b= layer APT). - Vous obtenez un layer négatif = ce que l’APT fait que vous ne détectez pas.
📸 Capture obligatoire #2 : layer a - b montrant les angles morts.
5.3 — Lecture : couverture vs surface d’attaque
Section intitulée « 5.3 — Lecture : couverture vs surface d’attaque »| Lecture | Conclusion |
|---|---|
| Beaucoup de techniques vertes mais sur 1 tactique seulement | Vous êtes spécialiste d’une phase, fragile sur le reste |
| Couverture diluée (1 règle par technique sur 10 tactiques) | Bonne diversité mais peu de profondeur |
| Trous sur Privilege Escalation / Defense Evasion | Vous voyez entrer, vous ne voyez pas la prise de contrôle |
La détection est une discipline de couverture, pas une collection de règles isolées. Cette lecture doit apparaître dans votre rapport.
6. Étape 4 — Corrélation 2 étages (R7)
Section intitulée « 6. Étape 4 — Corrélation 2 étages (R7) »Loki ne fait pas la corrélation native multi-événements ordonnée. Le pattern qu’on utilise : détecte → logge la détection → recherche la combinaison de détections.
6.1 — Étage 1 : Émettre un événement structuré sur chaque détection
Section intitulée « 6.1 — Étage 1 : Émettre un événement structuré sur chaque détection »Configurez Grafana Alerting pour, à chaque firing, écrire un événement JSON sur un stream Loki dédié.
Solution propre : utiliser un contact point webhook vers une URL qui pousse vers Loki. Sur la VM soc, montez un mini-relai Python (ou utilisez vector / fluent-bit) :
# vector.yaml — sur la VM soc, port 5000sources: grafana_alerts: type: http address: 0.0.0.0:5000 decoding: codec: json
transforms: to_loki: type: remap inputs: [grafana_alerts] source: | .stream = "soc_detections" .severity = .commonLabels.severity .rule = .commonLabels.alertname .attack_id = .commonLabels.attack_id .src_ip = .alerts[0].labels.src_ip .user = .alerts[0].labels.user .timestamp = now()
sinks: loki: type: loki inputs: [to_loki] endpoint: http://IP_VM2:3100 labels: stream: "soc_detections" severity: "{{ severity }}" encoding: codec: jsondocker run -d --name vector-relay \ -v $(pwd)/vector.yaml:/etc/vector/vector.yaml:ro \ -p 5000:5000 \ timberio/vector:latest -c /etc/vector/vector.yamlAjoutez dans Grafana un nouveau contact point webhook-soc-detections → URL http://IP_SOC:5000. Routez en parallèle de Discord (severity =~ ".*").
6.2 — Étage 2 : Règle de corrélation sur le stream soc_detections
Section intitulée « 6.2 — Étage 2 : Règle de corrélation sur le stream soc_detections »Créez la règle Sigma rules/correlation/killchain-phishing-to-exfil.yml :
title: Kill Chain — Phishing then Exfil (jour J pattern)id: 1a2b3c4d-5e6f-7890-abcd-1234567890abstatus: experimentaldescription: | Détecte la cooccurrence sur 30 minutes d'une alerte de phishing/auth externe (T1078) et d'une alerte d'exfil (T1041) pour le même utilisateur. Approxime la corrélation temporelle ordonnée (non supportée nativement par le backend Loki).references: - https://attack.mitre.org/techniques/T1078/ - https://attack.mitre.org/techniques/T1041/author: TAAF SOCdate: 2026/06/16logsource: product: grafana service: soc_detectionsdetection: phishing: stream: 'soc_detections' attack_id: 'T1078' exfil: stream: 'soc_detections' attack_id: 'T1041' timeframe: 30m condition: phishing and exfilfields: - user - src_ip - attack_idlevel: criticaltags: - attack.tactic.collection - attack.tactic.exfiltrationCompilation manuelle en LogQL (le backend n’a pas de mode natif timeframe croisé, on l’écrit à la main) :
sum by (user) ( count_over_time({stream="soc_detections", attack_id="T1078"}[30m]))andsum by (user) ( count_over_time({stream="soc_detections", attack_id="T1041"}[30m]))Provisionnez cette requête comme une 3ème alerte dans Grafana, sévérité critical, route vers discord-soc-critical.
6.3 — Vérifier sur les données du jour J
Section intitulée « 6.3 — Vérifier sur les données du jour J »Rejouez l’attaque (logger pour T1078, accès NextCloud pour T1213, requête PG pour T1041).
Résultat attendu : 3 alertes individuelles dans Discord (TP2), puis une 4ème alerte « Kill Chain » qui tombe après les deux premières dans une fenêtre de 30 min.
📸 Capture obligatoire #3 : message Discord « 🔥 Kill Chain detected ».
7. Étape 5 — La limite : pourquoi Loki ne fait pas tout
Section intitulée « 7. Étape 5 — La limite : pourquoi Loki ne fait pas tout »7.1 — Ce que ça veut dire en pratique
Section intitulée « 7.1 — Ce que ça veut dire en pratique »| Question | Loki natif | Wazuh / XDR |
|---|---|---|
| Détecter une chaîne ordonnée (A puis B puis C) ? | ⚠️ approx | ✅ natif |
| Compter sur une fenêtre glissante par entité ? | ✅ | ✅ |
| Corréler agent + réseau + endpoint en une vue ? | ⚠️ via streams | ✅ natif |
| Inventaire CVE ↔ activité runtime ? | ❌ | ✅ |
| FIM (intégrité fichiers) cross-référencé ? | ❌ | ✅ |
7.2 — Le pont vers le TP bonus Wazuh
Section intitulée « 7.2 — Le pont vers le TP bonus Wazuh »→ C’est précisément pourquoi les SIEM commerciaux et XDR existent. Le TP bonus Wazuh (en option) vous fera déployer un SIEM clé-en-main et comparer : ce que vous gagnez (corrélation native, FIM, vuln scanning, ~5000 règles out-of-box), ce que vous perdez (8 Go RAM JVM OpenSearch, 2ᵉ langage de requête, 2ᵉ vitre).
→ Pour la prod TAAF (golden-box 4 Go) : le SOC Grafana-natif que vous venez de construire est le bon choix. Pour une infra plus large (multi-sites avec endpoints Windows), Wazuh ou un XDR commercial est justifié.
7.3 — Le rapport (livrable narratif)
Section intitulée « 7.3 — Le rapport (livrable narratif) »Rédigez une note de 1 page (markdown) :
- Ce que mon SIEM Grafana-natif détecte bien (cite les 3 règles, leur LogQL, leur ATT&CK).
- Mes angles morts (cite 2-3 techniques visibles dans Navigator que vous ne couvrez pas — proposez la règle qui les couvrirait).
- Mes limites architecturales (corrélation temporelle ordonnée, pas de FIM, pas de scan vuln). Décision : justifié pour le contexte TAAF (golden-box, équipes réduites).
- Plan de migration vers un SIEM plus capable si la surface s’étend (Wazuh, Sentinel, Splunk).
8. Livrables & validation
Section intitulée « 8. Livrables & validation »Livrables (à pousser sur GitLab)
Section intitulée « Livrables (à pousser sur GitLab) »- Repo
taaf-detectionsfinalisé :rules/avec tous les tags ATT&CK affinés (sous-techniques quand pertinent)rules/correlation/killchain-phishing-to-exfil.ymlbuild/navigator/taaf-coverage-layer.jsonscripts/build-layer.shqui automatise S2ANdocs/limites-loki.md(la note 1 page de la § 7.3)
- Captures Navigator :
- Layer TAAF seul (techniques en vert)
- Layer
a - bvs APT de référence (les angles morts)
- Capture Discord : alerte « Kill Chain » qui tombe après les 3 alertes individuelles.
- Compose Vector (
vector.yaml+ commande de lancement) versionné dans le repomonitoring.
Grille de validation
Section intitulée « Grille de validation »| Critère | Pondération |
|---|---|
| Tags ATT&CK affinés (sous-techniques présentes quand pertinent) | 15 % |
| Layer Navigator généré et chargeable dans MITRE Navigator | 15 % |
Comparaison a - b vs un layer APT de référence | 10 % |
| Corrélation 2 étages fonctionne (alerte Kill Chain tombe après les détections élémentaires) | 25 % |
| Note technique 1 page (limites Loki + plan de migration) | 20 % |
| Repo Git propre, scripts reproductibles | 15 % |
Format de rendu : PDF nom-prenom-promo.pdf sur Moodle.
9. Annexe enseignant — corrigé
Section intitulée « 9. Annexe enseignant — corrigé »S2AN — script reproductible
Section intitulée « S2AN — script reproductible »scripts/build-layer.sh :
#!/usr/bin/env bashset -euo pipefailOUT="build/navigator"mkdir -p "$OUT"s2an \ -r rules/ \ -o "$OUT/taaf-coverage-layer.json" \ -n "TAAF SOC — couverture détections (auto)" \ --score-applied 100 --score-partial 50echo "[✓] Layer généré : $OUT/taaf-coverage-layer.json"Corrigé — couverture attendue (référence prof)
Section intitulée « Corrigé — couverture attendue (référence prof) »Pour la promo 2026-A, après les 3 règles TP1 + la règle correlation :
| Technique ATT&CK | Couverte ? |
|---|---|
| T1078.002 Domain Accounts | ✅ |
| T1133 External Remote Services | ✅ |
| T1213.002 Data from Cloud Storage | ✅ |
| T1213.003 Data from Code Repositories | ✅ |
| T1041 Exfiltration Over C2 | ✅ |
| T1068 Privilege Escalation | ❌ (gap classique — escalade svc_backup) |
| T1059.001 PowerShell | ❌ (traité Acte 3 — tp-module1-lotl-windows) |
| T1071.001 Web Protocols (C2) | ❌ (pourrait être ajouté avec une règle Zeek) |
→ L’étudiant doit identifier au moins T1068 et T1059.001 comme angles morts dans sa note.
Évaluation des erreurs courantes
Section intitulée « Évaluation des erreurs courantes »- Tags sans le préfixe
attack.(justet1078) → S2AN ignore. -10 %. - Layer généré mais pas chargeable (JSON cassé, mauvais
domain) → -10 %. - Corrélation faite avec
orau lieu deand→ l’alerte tombe sur chaque alerte individuelle, défait la corrélation. -15 %. - Note technique manquante ou sans plan de migration → -15 %.
Pont vers les TPs bonus
Section intitulée « Pont vers les TPs bonus »À la fin du TP3, l’étudiant a le SOC Grafana-natif complet. Les bonus :
- tp-wazuh-bonus : comparer avec un SIEM clé-en-main (gain de corrélation native vs coût RAM).
- tp-integration-windows : étendre la collecte côté Windows (Sysmon → Falco/Wazuh).
- tp-soar-capstone : orchestrer la réponse (Shuffle + MISP + Caldera).
Pont vers l’Acte 3
Section intitulée « Pont vers l’Acte 3 »L’Acte 3 (Audit & Purple Team) valide ce que vous avez construit ici :
tp-module1-lotl-windows(Acte 3) → comble le trou T1059.001 que vous avez identifié.tp-audit-ad-pingcastle(Acte 3) → traite la cause racine de T1068.tp-purple-team(Acte 3) → rejoue la kill chain et mesure combien d’étapes vos alertes attrapent réellement.