Chapitre 4.3 - Réponse aux Incidents & Forensique Numérique
Module 4 : Ingénierie Défensive & Durcissement Prérequis : Chapitre 4.2 (SIEM, SOAR & Ingénierie de Détection)
Table des Matières
- Cadre de Réponse aux Incidents - PICERL & NIST SP 800-61
- Triage & Périmètre - Évaluation Initiale de Compromission
- Collecte de Preuves & Chaîne de Custody
- Forensique Mémoire - Volatility & Analyse des Processus
- Forensique Disque - Imagerie, Récupération d'Artefacts & Timeline
- Forensique Réseau Pendant la RI - Analyse PCAP & Flux
- Analyse d'Artefacts Windows - Registre, Prefetch & Journaux d'Événements
- Analyse d'Artefacts Linux - Historique Bash, Cron & Systemd
- Confinement, Éradication & Récupération
- Cartographie MITRE ATT&CK
1. Cadre de Réponse aux Incidents - PICERL & NIST SP 800-61
Phases PICERL
Le cycle de vie standard de RI (SANS PICERL) :
| Phase | Objectif | Activités Clés | Échecs Courants |
|---|---|---|---|
| Préparation | Construire la capacité avant les incidents | Plan de RI, playbooks, outillage, contrat de retenue | Aucun plan jusqu'à la brèche |
| Identification | Détecter et confirmer un incident | Triage des alertes, évaluation du périmètre, classification de la sévérité | Détection lente - temps de présence long |
| Confinement | Limiter les dégâts sans détruire les preuves | Isolation réseau, réinitialisations d'identifiants, blocages pare-feu | Redémarrage avant capture mémoire |
| Éradication | Supprimer complètement la présence de l'attaquant | Suppression de maliciels, chasse aux backdoors, nettoyage des comptes | Mécanismes de persistance manqués |
| Récupération | Restaurer les systèmes affectés en toute sécurité | Reconstruction propre, correctifs, surveillance accrue | Retour en production trop tôt |
| Leçons Apprises | Améliorer la posture pour la prochaine fois | Revue post-incident, lacunes de détection, mises à jour des playbooks | Complètement ignoré sous pression |
Classification de la Sévérité des Incidents
#!/usr/bin/env python3
# severity_classifier.py - déterminer la sévérité d'un incident pour l'escalade
def classify_severity(indicators: dict) -> tuple:
"""
Retourne (niveau_sévérité, sla_escalade, actions_requises)
Basé sur NIST SP 800-61 impact fonctionnel + impact informationnel
"""
score = 0
reasons = []
# Évaluation de l'impact fonctionnel
if indicators.get('domain_admin_compromised'):
score += 50; reasons.append("Compte Domain Admin confirmé compromis")
if indicators.get('data_exfiltration_confirmed'):
score += 40; reasons.append("Exfiltration de données confirmée")
if indicators.get('ransomware_detected'):
score += 60; reasons.append("Activité ransomware/chiffrement détectée")
if indicators.get('lateral_movement_confirmed'):
score += 30; reasons.append("Mouvement latéral vers plusieurs hôtes")
if indicators.get('persistence_confirmed'):
score += 20; reasons.append("Mécanisme de persistance de l'attaquant trouvé")
if indicators.get('hosts_affected', 0) > 10:
score += 20; reasons.append(f"{indicators['hosts_affected']} hôtes affectés")
if indicators.get('critical_system_affected'):
score += 30; reasons.append("Système métier critique affecté")
if indicators.get('pii_data_at_risk'):
score += 25; reasons.append("Données PII/réglementées à risque")
# Seuils de sévérité
if score >= 80:
return ("CRITIQUE", "15 minutes", [
"Notification immédiate CISO/direction",
"Activer le contrat de retenue RI",
"Envisager une isolation à l'échelle du réseau",
"Notification juridique/conformité peut être requise"
])
elif score >= 50:
return ("ÉLEVÉ", "1 heure", [
"Notification du responsable d'équipe RI",
"Commencer le confinement immédiatement",
"Préserver toutes les preuves"
])
elif score >= 25:
return ("MOYEN", "4 heures", [
"Assigner un analyste senior",
"Commencer l'investigation",
"Surveiller l'escalade"
])
else:
return ("FAIBLE", "24 heures", [
"Assigner à la file standard",
"Investiguer pendant les heures ouvrables"
])
2. Triage & Périmètre - Évaluation Initiale de Compromission
Les 30 premières minutes d'une RI sont critiques. L'objectif n'est pas une analyse forensique complète - c'est la détermination rapide du périmètre : combien de systèmes sont affectés, que fait l'attaquant en ce moment, et l'attaque est-elle en cours.
Triage de Système en Direct - Windows
# Exécuter en tant qu'Administrateur - collecter rapidement l'état volatile du système
# L'ordre compte : le plus volatile d'abord
# 1. Horodatage actuel (pour corrélation de timeline)
Get-Date -Format "yyyy-MM-dd HH:mm:ss UTC" | Out-File C:\\\\IR\\triage.txt
[System.TimeZoneInfo]::Local | Out-File -Append C:\\\\IR\\triage.txt
# 2. Processus en cours avec chemins complets et hachages
Get-Process | Select-Object Name, Id, Path, CPU, WorkingSet, StartTime |
Export-Csv C:\\\\IR\\\\processes.csv -NoTypeInformation
# Hacher tous les exécutables de processus en cours (détecter LOLBins et usurpation)
Get-Process | Where-Object {$_.Path} | ForEach-Object {
$hash = (Get-FileHash $_.Path -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash
[PSCustomObject]@{
Name = $_.Name; PID = $_.Id; Path = $_.Path; SHA256 = $hash
}
} | Export-Csv C:\\\\IR\\\\process_hashes.csv -NoTypeInformation
# 3. Connexions réseau actives avec processus propriétaire
Get-NetTCPConnection -State Established,Listen |
Select-Object LocalAddress, LocalPort, RemoteAddress,
RemotePort, State, OwningProcess |
Export-Csv C:\\\\IR\\\\connections.csv -NoTypeInformation
# Croiser les connexions avec les processus
$procs = @{}
Get-Process | ForEach-Object { $procs[$_.Id] = $_.ProcessName }
Get-NetTCPConnection -State Established | ForEach-Object {
[PSCustomObject]@{
ProcessName = $procs[$_.OwningProcess]
PID = $_.OwningProcess
LocalAddress = $_.LocalAddress
LocalPort = $_.LocalPort
RemoteAddress= $_.RemoteAddress
RemotePort = $_.RemotePort
}
} | Export-Csv C:\\\\IR\\\\connections_with_process.csv -NoTypeInformation
# 4. Utilisateurs connectés (sessions actuelles)
query session # Sessions RDP
query user # Toutes les sessions interactives
Get-WmiObject Win32_LoggedOnUser | Select-Object Antecedent, Dependent
# 5. Tâches planifiées (vérification de persistance)
Get-ScheduledTask | Where-Object {$_.State -ne 'Disabled'} |
Select-Object TaskName, TaskPath, State,
@{N='Execute';E={$_.Actions.Execute}},
@{N='Arguments';E={$_.Actions.Arguments}} |
Export-Csv C:\\\\IR\\\\scheduled_tasks.csv -NoTypeInformation
# 6. Services (vérifier les nouveaux services suspects - psexec laisse un service)
Get-Service | Select-Object Name, DisplayName, Status, StartType |
Export-Csv C:\\\\IR\\\\services.csv -NoTypeInformation
# 7. Emplacements d'exécution automatique
$autorun_keys = @(
"HKLM:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run",
"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run",
"HKLM:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce",
"HKLM:\\\\SYSTEM\\\\CurrentControlSet\\\\Services"
)
foreach ($key in $autorun_keys) {
Get-ItemProperty $key -ErrorAction SilentlyContinue |
Out-File -Append C:\\\\IR\\\\autoruns.txt
}
# 8. Fichiers récemment modifiés (24 dernières heures - trouver outils/charges déposés)
Get-ChildItem C:\\\\Windows\\\\Temp, C:\\\\Users\\\\*\\\\AppData\\\\Local\\\\Temp,
C:\\\\ProgramData -Recurse -ErrorAction SilentlyContinue |
Where-Object {$_.LastWriteTime -gt (Get-Date).AddHours(-24)} |
Select-Object FullName, LastWriteTime, Length |
Export-Csv C:\\\\IR\\recent_files.csv -NoTypeInformation
Triage de Système en Direct - Linux
# Créer un répertoire de preuves horodaté
mkdir -p /tmp/ir_$(date +%Y%m%d_%H%M%S)
IR_DIR="/tmp/ir_$(date +%Y%m%d_%H%M%S)"
# 1. Informations système
date > $IR_DIR/timestamp.txt
uname -a >> $IR_DIR/sysinfo.txt
hostname >> $IR_DIR/sysinfo.txt
uptime >> $IR_DIR/sysinfo.txt
# 2. Processus en cours (arborescence complète)
ps auxf > $IR_DIR/processes.txt # Vue arborescente
ps aux --sort=-pcpu > $IR_DIR/processes_cpu.txt
ls -la /proc/*/exe 2>/dev/null > $IR_DIR/proc_exe_links.txt # Détecter les binaires supprimés mais en cours d'exécution
# Indicateur clé : "(deleted)" dans le lien exe = binaire exécuté puis supprimé
# 3. Connexions réseau
ss -tulnp > $IR_DIR/listening_ports.txt # Services en écoute
ss -tnp state established > $IR_DIR/established.txt # Connexions actives
netstat -rn > $IR_DIR/routes.txt # Table de routage
arp -a > $IR_DIR/arp_cache.txt # Cache ARP
# 4. Utilisateurs connectés
w > $IR_DIR/users.txt
who -a >> $IR_DIR/users.txt
last -n 50 > $IR_DIR/recent_logins.txt # 50 dernières connexions
# 5. Emplacements de persistance
crontab -l 2>/dev/null > $IR_DIR/crontab_root.txt
for user in $(cut -f1 -d: /etc/passwd); do
crontab -l -u $user 2>/dev/null | \\
awk -v u="$user" 'NF {print u": "$0}' >> $IR_DIR/crontabs_all.txt
done
ls -la /etc/cron* /var/spool/cron >> $IR_DIR/crontab_files.txt
# Vérifier les unités de service systemd récemment modifiées
find /etc/systemd /usr/lib/systemd /lib/systemd \\
-name "*.service" -newer /etc/passwd \\
2>/dev/null > $IR_DIR/new_systemd_units.txt
# 6. Fichiers récemment modifiés (trouver les outils déposés)
find / -not \\\\( -path /proc -prune \\\\) \\
-not \\\\( -path /sys -prune \\\\) \\
-newer /var/log/wtmp \\
-type f 2>/dev/null > $IR_DIR/recent_files.txt
# 7. Fichiers SUID/SGID (persistance via bit SUID)
find / -not \\\\( -path /proc -prune \\\\) \\
-perm -4000 -type f 2>/dev/null > $IR_DIR/suid_files.txt
# 8. Fichiers ouverts (trouver les outils C2 gardant des descripteurs ouverts)
lsof -nP 2>/dev/null > $IR_DIR/open_files.txt
lsof -nP -i 2>/dev/null > $IR_DIR/open_network_files.txt # Sockets réseau uniquement
# 9. Modules noyau chargés (détection de rootkit)
lsmod > $IR_DIR/kernel_modules.txt
# Vérification d'intégrité des paquets (détecter les binaires système modifiés)
rpm -Va 2>/dev/null > $IR_DIR/rpm_verify.txt # RHEL/CentOS
dpkg --verify 2>/dev/null > $IR_DIR/dpkg_verify.txt # Debian/Ubuntu
# Lignes avec "5" en première colonne = hachage modifié = fichier altéré
3. Collecte de Preuves & Chaîne de Custody
Principes de la Chaîne de Custody
Chaque élément de preuve doit être collecté avec une chaîne de custody documentée :
- Qui l'a collecté (nom de l'enquêteur, accréditations)
- Quand (date/heure avec fuseau horaire)
- Quoi (description exacte : nom d'hôte, IP, numéro de série du disque, hachage de l'image)
- Comment (outil utilisé, méthode, bloqueur d'écriture utilisé O/N)
- Où stocké (numéro de série du dispositif de stockage, emplacement, journal d'accès)
# Générer le hachage de preuve immédiatement après la collecte
# MD5 + SHA256 pour la défense en profondeur (les collisions MD5 existent mais pas SHA256)
sha256sum /evidence/workstation01_memory.lime > /evidence/workstation01_memory.lime.sha256
md5sum /evidence/workstation01_memory.lime > /evidence/workstation01_memory.lime.md5
# Documenter la collecte
cat > /evidence/COC_workstation01.txt << EOF
CHAÎNE DE CUSTODY
=================
Numéro de Dossier: IR-2024-042
Élément de Preuve: workstation01_memory.lime
Enquêteur: J. Smith (jsmith@corp.com)
Date de Collecte: $(date -u)
Nom d'Hôte: WORKSTATION-01
Adresse IP: 192.168.1.105
Méthode: Module noyau LiME chargé via SSH
Bloqueur d'Écriture: N/A (acquisition mémoire - volatile)
SHA256: $(sha256sum /evidence/workstation01_memory.lime | cut -d' ' -f1)
MD5: $(md5sum /evidence/workstation01_memory.lime | cut -d' ' -f1)
Stockage: USB Evidence (Série: SN1234567) - NAS Evidence - Conteneur chiffré
Notes: Système en cours d'exécution ; acquisition effectuée avant confinement
EOF
Collecte de Preuves à Distance à Grande Échelle
# Velociraptor - plateforme RI d'entreprise pour la collecte à distance
# Déployer comme serveur + agent sur l'ensemble du parc
# Serveur Velociraptor : collecter des artefacts depuis tous les endpoints simultanément
# Artefact VQL (Velociraptor Query Language) - collecter les journaux d'événements Windows à distance
velociraptor query '
SELECT * FROM hunt_results()
WHERE HuntId = "H.XXXXXXXX"
' --format json > /tmp/hunt_results.json
# Créer une chasse : collecter depuis tous les endpoints Windows
# Dans l'interface Velociraptor : Hunts - New Hunt - Sélectionner Artefacts :
# - Windows.EventLogs.Evtx (journaux Security, System, Application)
# - Windows.System.Pslist (processus en cours)
# - Windows.Network.Netstat (connexions)
# - Windows.Persistence.PersistentItems (tous les mécanismes de persistance)
# - Windows.System.Amcache (historique d'exécution)
# Création de chasse en ligne de commande
velociraptor --config /etc/velociraptor/server.config.yaml \\
artifacts collect Windows.System.Pslist \\
--args Hunt=true \\
--args ClientId="ALL"
4. Forensique Mémoire - Volatility & Analyse des Processus
La forensique mémoire récupère des artefacts qui n'existent qu'en RAM : processus en cours (y compris les maliciels sans fichier), connexions réseau au moment de la capture, chaînes déchiffrées (mots de passe, clés), shellcode injecté et ruches de registre chargées en mémoire.
Acquisition de la Mémoire
# Acquisition de mémoire Linux avec LiME (Linux Memory Extractor)
# LiME est un module noyau chargeable - méthode la plus forensiquement saine
# Compiler LiME pour le noyau cible (doit correspondre exactement)
git clone https://github.com/504ensicsLabs/LiME
cd LiME/src
make # Produit lime-<version_noyau>.ko
# Acquérir la mémoire directement dans un fichier (local)
sudo insmod lime-$(uname -r).ko \\
"path=/tmp/memory.lime format=lime"
# Acquérir via réseau pour éviter d'écrire sur le disque cible (préféré)
# Sur le poste de collecte :
nc -l -p 4444 > /evidence/target_memory.lime
# Sur la cible :
sudo insmod lime-$(uname -r).ko \\
"path=tcp:4444 format=lime" # Envoyer directement via réseau
# Acquisition de mémoire Windows
# winpmem - open source
winpmem_mini_x64_rc2.exe -o C:\\\\evidence\\\\memory.raw
# DumpIt - exécutable unique, déposer et exécuter
DumpIt.exe /O C:\\\\evidence\\\\memory.raw /Q
Volatility 3 - Analyse Mémoire
# Installer Volatility 3
pip install volatility3
# Lister les plugins disponibles
python3 vol.py -h
# Identifier le profil OS (Volatility 3 détecte automatiquement)
python3 vol.py -f memory.lime \\
windows.info # Informations système Windows
# ANALYSE DES PROCESSUS
# Lister tous les processus (pslist - depuis la liste EPROCESS)
python3 vol.py -f memory.lime windows.pslist
# Lister les processus en arborescence (relations parent-enfant)
python3 vol.py -f memory.lime windows.pstree
# Clé : chercher les relations parent-enfant inhabituelles (cmd.exe parent=Word, powershell parent=excel)
# Scanner les processus cachés (psscan - analyse les pool tags, trouve les cachés/terminés)
python3 vol.py -f memory.lime windows.psscan
# Processus dans psscan mais PAS dans pslist = cachés par rootkit
# Trouver les processus avec code injecté (malfind - cherche les régions mémoire RWX)
python3 vol.py -f memory.lime \\
windows.malfind \\
--pid 1234 # PID spécifique, ou omettre pour tous
# Sortie : régions mémoire avec permissions RWX + désassemblage des premiers octets
# INDICATEUR CLÉ : en-tête MZ dans région injectée = fichier PE injecté dans le processus
# Vider la mémoire d'un processus suspect pour analyse YARA
python3 vol.py -f memory.lime \\
windows.memmap \\
--pid 1234 \\
--dump # Vider toutes les sections mémoire du PID 1234
# ANALYSE RÉSEAU
# Connexions réseau actives/récentes (Windows)
python3 vol.py -f memory.lime windows.netstat
# Affiche : PID, nom du processus, adresse:port local/distant, état, heure de création
# Même les connexions FERMÉES sont souvent encore en mémoire
# EXTRACTION DES IDENTIFIANTS
# Extraire les hachages NTLM de la mémoire (processus lsass)
python3 vol.py -f memory.lime \\
windows.hashdump # Hachages SAM depuis le registre en mémoire
# Extraire les identifiants de domaine mis en cache
python3 vol.py -f memory.lime \\
windows.cachedump # Identifiants de connexion de domaine mis en cache
# Secrets LSA (mots de passe de comptes de service, identifiants stockés)
python3 vol.py -f memory.lime \\
windows.lsadump
# EXTRACTION D'ARTEFACTS
# Extraire l'historique des commandes (tampon d'entrée console)
python3 vol.py -f memory.lime \\
windows.cmdline # Lignes de commande de tous les processus
# Extraire les DLL chargées par processus (détecter injection/chargement latéral de DLL)
python3 vol.py -f memory.lime \\
windows.dlllist \\
--pid 1234
# Extraire les ruches de registre chargées en mémoire
python3 vol.py -f memory.lime \\
windows.registry.hivelist # Lister toutes les ruches chargées
# Extraire une valeur de clé de registre spécifique depuis la mémoire
python3 vol.py -f memory.lime \\
windows.registry.printkey \\
--key "SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run"
# Linux - historique bash depuis la mémoire
python3 vol.py -f memory.lime linux.bash
python3 vol.py -f memory.lime linux.pslist
python3 vol.py -f memory.lime linux.netstat
# Scanner la mémoire avec des règles YARA
python3 vol.py -f memory.lime \\
windows.yarascan \\
--yara-file /etc/yara/rules/cobalt_strike.yar
5. Forensique Disque - Imagerie, Récupération d'Artefacts & Timeline
Imagerie Forensique de Disque
# dd - fiable, disponible partout, lent
# Toujours utiliser un bloqueur d'écriture matériel si possible
# Image bit-à-bit du disque entier
dd if=/dev/sda \\\\ # Entrée : disque à analyser
of=/evidence/sda.img \\\\ # Sortie : fichier image
bs=512 \\\\ # Taille de bloc : 512 octets
conv=noerror,sync \\\\ # Continuer en cas d'erreur ; rembourrer avec des zéros
status=progress # Afficher la progression
# Vérifier l'intégrité de l'image immédiatement après
sha256sum /dev/sda > /evidence/sda.sha256_source
sha256sum /evidence/sda.img > /evidence/sda.sha256_image
diff <(cut -d' ' -f1 /evidence/sda.sha256_source) \\
<(cut -d' ' -f1 /evidence/sda.sha256_image)
# Doit correspondre - toute différence signifie que l'image est corrompue ou modifiée
# dcfldd - dd amélioré avec hachage et vérification intégrés
dcfldd if=/dev/sda \\
of=/evidence/sda.img \\
hash=sha256 \\
hashlog=/evidence/sda.hashlog \\\\ # Vérification continue du hachage
bs=512 \\
conv=noerror,sync
# ewfacquire - Format Expert Witness (EWF/E01) - supporte compression + métadonnées
ewfacquire \\
-t /evidence/workstation01 \\\\ # Nom de base de sortie (crée .E01, .E02...)
-c deflate \\\\ # Compression
-l /evidence/workstation01.log \\\\ # Journal d'acquisition
-C "IR-2024-042" \\\\ # Métadonnées numéro de dossier
-e "J. Smith" \\\\ # Nom de l'examinateur
/dev/sda
# Monter l'image en lecture seule pour l'analyse (n'analyser jamais l'original)
mkdir /mnt/evidence_sda
mount -o ro,noexec,loop,offset=$((512*2048)) \\
/evidence/sda.img \\\\ # Décalage = secteur de début de partition x 512
/mnt/evidence_sda
# Obtenir le décalage de secteur : mmls /evidence/sda.img - trouver le début de partition
Timeline du Système de Fichiers - The Sleuth Kit & Plaso
# The Sleuth Kit (TSK) - boîte à outils forensique de système de fichiers
# Lister les partitions dans l'image
mmls /evidence/sda.img
# Lister les fichiers avec les temps MAC (Modifié, Accédé, Changé)
# Format MACtime : Modifié | Accédé | Changé | Naissance (créé)
fls -r -m / \\
-o 2048 \\\\ # Décalage vers la partition NTFS (secteurs)
/evidence/sda.img > /tmp/bodyfile.txt
# Générer une timeline lisible à partir du bodyfile
mactime -b /tmp/bodyfile.txt \\
-d \\\\ # Sortie CSV
-z UTC > /tmp/timeline.csv
# Filtrer la timeline sur la fenêtre de l'incident
grep "2024-01-15" /tmp/timeline.csv | \\
grep -E "NTFS|ADDED|CHANGED" | \\
head -100
# Plaso (log2timeline) - timeline complète depuis TOUS les artefacts
# Traite : Registre, Journaux d'événements, fichiers LNK, Prefetch, MFT NTFS, historique navigateur, etc.
pip install plaso
# Créer une super timeline (prend des heures pour un disque complet)
log2timeline.py \\
--storage-file /tmp/evidence.plaso \\
--parsers win7 \\\\ # Groupe de parseurs pour Windows 7/10
/mnt/evidence_sda/ # Chemin vers l'image montée
# Filtrer et exporter en CSV
psort.py \\
--output-time-zone UTC \\
-o l2tcsv \\
-w /tmp/supertimeline.csv \\
/tmp/evidence.plaso \\
"date > '2024-01-14' AND date < '2024-01-16'" # Filtrer sur la fenêtre d'incident
# Artefacts clés automatiquement traités par Plaso :
# - $MFT (Table de Fichiers Maître NTFS)
# - Journaux d'événements Windows (.evtx)
# - Fichiers Prefetch (preuve d'exécution)
# - Ruches de registre (SOFTWARE, SYSTEM, NTUSER.DAT)
# - Fichiers LNK (fichiers récemment accédés)
# - Historique navigateur (Chrome, Firefox, IE/Edge)
# - Shellbags (historique de navigation de dossiers)
# - Listes de raccourcis
# - Corbeille (fichiers $I)
Artefacts NTFS Clés
# $MFT - Table de Fichiers Maître : chaque fichier/répertoire, horodatages, taille
# Extraire et analyser avec mftdump ou analyzeMFT
pip install analyzeMFT
analyzeMFT.py \\
-f /mnt/evidence_sda/\\\\$MFT \\
-o /tmp/mft_parsed.csv \\
-a # Détection d'anomalies (horodatage falsifié)
# $LogFile - Journal de transactions NTFS (récupérer fichiers supprimés, modifications récentes)
# $UsnJrnl:\\\\$J - Journal de Changement USN (journal d'activité du système de fichiers)
# Analyser le journal USN :
fsutil usn readjournal C: csv > C:\\\\IR\\usn_journal.csv # Système en direct
# Windows.edb - Base de données Windows Search (contenu de fichiers indexé)
# Contient : noms de fichiers, chemins, extraits de contenu des fichiers indexés
# Utile : trouver des documents qui ont pu être accédés/exfiltrés
esentutl /y \\
/mnt/evidence_sda/ProgramData/Microsoft/Search/Data/Applications/Windows/Windows.edb \\
/d /tmp/windows_search.edb /o
6. Forensique Réseau Pendant la RI - Analyse PCAP & Flux
# Si un TAP ou SPAN était actif - capturer le trafic de l'incident
# Sinon : reconstruire depuis les enregistrements NetFlow/IPFIX dans le SIEM
# Reconstruire les sessions TCP depuis PCAP (qui s'est connecté où, quelles données ont transité)
tcpflow -r /evidence/incident.pcap \\
-o /tmp/tcp_sessions/ \\\\ # Répertoire de sortie
-a \\\\ # Décoder la couche applicative
-g # Créer un graphe de flux
# Extraire tous les fichiers transférés depuis PCAP
tcpflow -r /evidence/incident.pcap \\
-o /tmp/extracted/ \\
"port 80"
# Wireshark/tshark - extraire des objets depuis PCAP
tshark -r /evidence/incident.pcap \\
--export-objects "http,/tmp/http_objects/" # Objets HTTP
tshark -r /evidence/incident.pcap \\
--export-objects "smb,/tmp/smb_objects/" # Transferts de fichiers SMB
# Reconstruire les requêtes DNS depuis PCAP (domaine C2, DGA, tunnelisation DNS)
tshark -r /evidence/incident.pcap \\
-Y 'dns.flags.response == 1' \\\\ # Réponses DNS uniquement
-T fields \\
-e frame.time \\
-e ip.src \\
-e dns.qry.name \\
-e dns.a > /tmp/dns_resolutions.txt
# Trouver l'exfiltration de données : grands transferts sortants
tshark -r /evidence/incident.pcap \\
-q \\
-z "conv,tcp" | \\\\ # Statistiques de conversations TCP
sort -t ' ' -k 10 -rn | \\\\ # Trier par total d'octets décroissant
head -20 # 20 conversations les plus volumineuses
# Identifier le pattern de balise C2 dans PCAP
python3 << 'EOF'
import dpkt, socket, collections, numpy as np
sessions = collections.defaultdict(list)
with open('/evidence/incident.pcap','rb') as f:
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
try:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
if isinstance(ip.data, dpkt.tcp.TCP):
tcp = ip.data
if tcp.flags & dpkt.tcp.TH_SYN and not tcp.flags & dpkt.tcp.TH_ACK:
src = socket.inet_ntoa(ip.src)
dst = socket.inet_ntoa(ip.dst)
sessions[f"{src}->{dst}:{tcp.dport}"].append(ts)
except: pass
print(f"{'Connexion':<50} {'Nb':>6} {'Intervalle Moy':>14} {'Gigue':>8}")
for conn, timestamps in sorted(sessions.items(), key=lambda x: len(x[1]), reverse=True)[:20]:
if len(timestamps) < 5: continue
intervals = np.diff(sorted(timestamps))
avg = np.mean(intervals)
jitter = np.std(intervals) / avg if avg > 0 else 999
flag = " BALISE?" if jitter < 0.2 and avg < 300 else ""
print(f"{conn:<50} {len(timestamps):>6} {avg:>13.1f}s {jitter:>7.3f}{flag}")
EOF
7. Analyse d'Artefacts Windows - Registre, Prefetch & Journaux d'Événements
Forensique du Registre
# Monter et analyser les ruches de registre depuis l'image disque
# Installer python-registry :
pip install python-registry
python3 << 'EOF'
from Registry import Registry
import datetime
# Analyser la ruche SOFTWARE - logiciels installés, clés run
reg = Registry.Registry("/mnt/evidence_sda/Windows/System32/config/SOFTWARE")
# Vérifier la clé Run (persistance au démarrage)
try:
key = reg.open("Microsoft\\\\\\\\Windows\\\\\\\\CurrentVersion\\\\\\\\Run")
print("=== Clé HKLM Run ===")
for value in key.values():
print(f" {value.name()}: {value.value()}")
print(f" Dernière Modification: {key.timestamp()}")
except: pass
# Analyser NTUSER.DAT pour les artefacts spécifiques à l'utilisateur
user_reg = Registry.Registry("/mnt/evidence_sda/Users/victim/NTUSER.DAT")
# RecentDocs - fichiers récemment ouverts (l'attaquant a peut-être accédé à des docs sensibles)
try:
key = user_reg.open("Software\\\\\\\\Microsoft\\\\\\\\Windows\\\\\\\\CurrentVersion\\\\\\\\Explorer\\\\\\\\RecentDocs")
print("\\n=== Documents Récents ===")
for subkey in key.subkeys():
for value in subkey.values():
if value.name() == "MRUListEx": continue
try:
# Les données de valeur sont binaires - décoder le nom de fichier
raw = value.value()
fname = raw[:raw.find(b'\\x00\\x00')].decode('utf-16-le', errors='replace')
print(f" {fname}")
except: pass
except: pass
# UserAssist - exécution de programmes GUI avec nombre d'exécutions et horodatage
import struct, codecs
try:
key = user_reg.open(
"Software\\\\\\\\Microsoft\\\\\\\\Windows\\\\\\\\CurrentVersion\\\\\\\\Explorer\\\\\\\\UserAssist\\\\"
"{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}\\\\\\\\Count")
print("\\n=== UserAssist (Exécutions GUI) ===")
for value in key.values():
name = codecs.decode(value.name(), 'rot_13') # Encodé en ROT-13
data = value.value()
if len(data) >= 72:
run_count = struct.unpack('<I', data[4:8])[0]
ts_raw = struct.unpack('<Q', data[60:68])[0]
if ts_raw > 0:
ts = datetime.datetime(1601,1,1) + datetime.timedelta(microseconds=ts_raw//10)
print(f" [{run_count:>4}x] {ts} | {name}")
except Exception as e:
print(f"Erreur UserAssist: {e}")
EOF
Analyse des Prefetch
# Les fichiers Prefetch enregistrent l'exécution des programmes : nom, nb d'exécutions, horodatages, fichiers chargés
# Emplacement : C:\\\\Windows\\\\Prefetch\\
# Requiert : Prefetch Windows activé (par défaut sur les non-serveurs)
pip install libscca-python # ou utiliser un analyseur prefetch
python3 << 'EOF'
import os, struct, datetime
def parse_prefetch(filepath):
"""Analyseur basique d'en-tête Prefetch"""
with open(filepath, 'rb') as f:
data = f.read()
# En-tête Prefetch version 26 (Windows 10)
signature = data[4:8]
if signature != b'MAM\\xf0' and signature[:3] != b'MAM':
return None
exec_name = data[16:76].decode('utf-16-le').rstrip('\\x00')
run_count = struct.unpack('<I', data[208:212])[0]
# 8 derniers horodatages d'exécution (Windows 10 stocke les 8 derniers)
timestamps = []
for i in range(8):
ts_raw = struct.unpack('<Q', data[128+i*8 : 136+i*8])[0]
if ts_raw > 0:
ts = datetime.datetime(1601,1,1) + datetime.timedelta(microseconds=ts_raw//10)
timestamps.append(str(ts))
return {'name': exec_name, 'run_count': run_count, 'timestamps': timestamps}
prefetch_dir = "/mnt/evidence_sda/Windows/Prefetch/"
results = []
for pf_file in os.listdir(prefetch_dir):
if not pf_file.endswith('.pf'): continue
result = parse_prefetch(os.path.join(prefetch_dir, pf_file))
if result:
results.append(result)
# Trier par exécution la plus récente
results.sort(key=lambda x: x['timestamps'][-1] if x['timestamps'] else '', reverse=True)
for r in results[:30]:
print(f"{r['timestamps'][-1] if r['timestamps'] else 'inconnu':26} "
f"[{r['run_count']:>4}x] {r['name']}")
EOF
# Alternativement : utiliser PECmd d'Eric Zimmermann (Windows uniquement)
PECmd.exe -d C:\\\\Windows\\\\Prefetch --csv C:\\\\IR\\\\prefetch.csv
Analyse des Journaux d'Événements Windows
# Analyser les fichiers .evtx hors ligne avec python-evtx ou wevtutil
pip install python-evtx
# Extraire tous les événements de connexion (4624) depuis Security.evtx capturé
python3 << 'EOF'
import Evtx.Evtx as evtx
import Evtx.Views as e_views
import xml.etree.ElementTree as ET
logon_types = {
'2': 'Interactive', '3': 'Network', '4': 'Batch',
'5': 'Service', '7': 'Unlock', '8': 'NetworkCleartext',
'9': 'NewCredentials', '10': 'RemoteInteractive', '11': 'CachedInteractive'
}
suspicious_events = []
with evtx.Evtx("/evidence/Security.evtx") as log:
for record in log.records():
try:
root = ET.fromstring(record.xml())
ns = {'e': 'http://schemas.microsoft.com/win/2004/08/events/event'}
event_id = root.find('.//e:EventID', ns).text
if event_id in ['4624', '4625', '4648', '4698', '4720', '7045']:
time_created = root.find('.//e:TimeCreated', ns).get('SystemTime')
data = {d.get('Name'): d.text
for d in root.findall('.//e:Data', ns) if d.get('Name')}
entry = {
'time': time_created,
'event_id': event_id,
'user': data.get('TargetUserName', ''),
'domain': data.get('TargetDomainName', ''),
'logon_type': logon_types.get(data.get('LogonType',''), data.get('LogonType','')),
'src_ip': data.get('IpAddress', ''),
'process': data.get('ProcessName', ''),
}
# Signaler les patterns suspects
if event_id == '4624' and data.get('LogonType') == '3' \\
and data.get('AuthenticationPackageName') == 'NTLM':
entry['FLAG'] = 'PtH POSSIBLE - CONNEXION RÉSEAU NTLM'
suspicious_events.append(entry)
elif event_id in ['4698', '4720', '7045']:
entry['FLAG'] = 'PERSISTANCE/PRIVILÈGE'
suspicious_events.append(entry)
except: pass
for e in sorted(suspicious_events, key=lambda x: x['time']):
print(f"{e['time'][:19]} | EID:{e['event_id']} | {e.get('FLAG','')} | "
f"User:{e['user']}@{e['domain']} | From:{e['src_ip']}")
EOF
8. Analyse d'Artefacts Linux - Historique Bash, Cron & Systemd
# Reconstruction de l'historique bash (les utilisateurs essaient souvent de le supprimer, mais des artefacts subsistent)
cat /home/*/.bash_history 2>/dev/null
cat /root/.bash_history 2>/dev/null
# bash_history peut être effacé - vérifier dans la capture mémoire et les sauvegardes
# Vérifier aussi : ~/.zsh_history, ~/.fish_history
# /var/log/auth.log - événements d'authentification et sudo
grep -E "sudo|su |Failed|Accepted|Invalid" /var/log/auth.log | \\
tail -200
# Vérifier les commandes exécutées via sudo (même si l'historique est effacé)
grep "COMMAND=" /var/log/auth.log | tail -50
# Journal systemd - journal d'événements système complet
journalctl \\
--since "2024-01-14 00:00:00" \\
--until "2024-01-15 23:59:59" \\
--no-pager \\
-o json > /tmp/journal_incident.json
# Filtrer le journal pour les événements pertinents à la sécurité
journalctl \\
-u sshd \\\\ # Événements du service SSH uniquement
--since "2024-01-14" \\
--no-pager
# Trouver les unités systemd nouvelles/modifiées (mécanisme de persistance)
find /etc/systemd /usr/lib/systemd /lib/systemd \\
-name "*.service" \\
-newer /etc/hostname \\
2>/dev/null \\
-exec cat {} \\\\;
# Détecter les bibliothèques partagées avec backdoor (détournement LD_PRELOAD)
# Vérifier /etc/ld.so.preload - tout ce qui s'y trouve = tous les processus utilisent cette bibliothèque
cat /etc/ld.so.preload 2>/dev/null # Devrait être vide ou absent
# Vérifier les entrées inhabituelles dans /etc/passwd (nouveaux comptes)
# Les comptes backdoor ont souvent UID 0 (équivalent root)
awk -F: '$3 == 0 {print "COMPTE ROOT:", $1}' /etc/passwd
awk -F: 'NF < 7 {print "ENTRÉE MALFORMÉE:", $0}' /etc/passwd
# Vérifier les ajouts de clés SSH autorisées (persistance)
find /home /root -name "authorized_keys" -exec ls -la {} \\\\; \\
-exec cat {} \\\\;
# Détection de webshell (fichiers récemment ajoutés aux répertoires web)
find /var/www /srv/www /opt/*/htdocs \\
-name "*.php" -o -name "*.asp" -o -name "*.jsp" \\
2>/dev/null \\
-newer /var/log/syslog \\
-exec ls -la {} \\\\;
# Détecter les patterns de webshell dans les fichiers PHP
grep -r \\
--include="*.php" \\
-l \\
-E "eval\\\\(base64_decode|system\\\\(|passthru\\\\(|exec\\\\(|\\\\$_POST\\\\[|shell_exec" \\
/var/www/ 2>/dev/null
9. Confinement, Éradication & Récupération
Stratégies de Confinement
# CONFINEMENT RÉSEAU
# Option 1 : Isolation complète (incidents CRITIQUES)
# Isolation par EDR (préférée - ne nécessite pas d'accès physique)
# CrowdStrike Falcon :
# Hosts - rechercher hôte - Contain Host
# Carbon Black :
# Devices - Quarantine
# Isolation basée sur iptables (solution de repli manuelle)
# Autoriser uniquement SSH depuis l'IP de l'équipe RI, bloquer tout le reste
iptables -I INPUT 1 -s IR_TEAM_IP -j ACCEPT
iptables -I OUTPUT 1 -d IR_TEAM_IP -j ACCEPT
iptables -I INPUT 2 -j DROP
iptables -I OUTPUT 2 -j DROP
iptables -I FORWARD 1 -j DROP
# Option 2 : Blocage ciblé (MOYEN - préserver la fonctionnalité)
# Bloquer la destination C2 spécifique confirmée par l'analyse PCAP
iptables -I OUTPUT -d C2_IP -j DROP
iptables -I OUTPUT -d C2_IP2 -j DROP
# Bloquer l'IP source de l'attaquant (si toujours actif)
iptables -I INPUT -s ATTACKER_IP -j DROP
# CONFINEMENT DES IDENTIFIANTS - ÉTAPE CRITIQUE
# Souvent omise - conduit à une re-compromission
# Si des identifiants ont été récupérés (Mimikatz, vidage LSA) :
# 1. Réinitialiser TOUS les comptes avec activité de connexion sur les hôtes compromis
# PowerShell : réinitialisation en masse des mots de passe pour les comptes affectés
$affected_users = @("jsmith", "admin", "svc-web", "helpdesk01")
foreach ($user in $affected_users) {
$newpass = ConvertTo-SecureString (New-Guid).ToString() -AsPlainText -Force
Set-ADAccountPassword -Identity $user `
-NewPassword $newpass `
-Reset
Set-ADUser $user -ChangePasswordAtLogon $true
Write-Host "Réinitialisé : $user"
}
# 2. Si les identifiants DA sont compromis : réinitialiser krbtgt DEUX FOIS (à 24 heures d'intervalle)
# La première réinitialisation invalide tous les tickets existants
# La deuxième réinitialisation garantit qu'aucun Golden Ticket ne reste valide
# Utiliser : New-KrbtgtKeys.ps1 de Microsoft
# 3. Révoquer toutes les sessions actives (forcer la ré-authentification)
# Azure AD :
Revoke-AzureADUserAllRefreshToken -ObjectId USER_OBJECT_ID
Liste de Contrôle d'Éradication
# Éradication systématique - trouver TOUTE persistance avant de déclarer propre
# 1. Autoruns (Autoruns d'Eric Zimmermann - standard de référence)
# Interface graphique : affiche tous les emplacements de démarrage automatique avec intégration VirusTotal
# Ligne de commande :
autorunsc.exe -accepteula -a * -c -h -vt > C:\\\\IR\\\\autoruns_scan.csv
# 2. Services
sc query type= all state= all | findstr /i "service_name\\\\|state"
# Comparer à une ligne de base connue bonne
# 3. Tâches planifiées
schtasks /query /fo csv /v > C:\\\\IR\\\\scheduled_tasks.csv
# 4. Abonnements WMI (persistance furtive - souvent manquée)
Get-WMIObject -Namespace root\\\\subscription -Class __EventFilter
Get-WMIObject -Namespace root\\\\subscription -Class __EventConsumer
Get-WMIObject -Namespace root\\\\subscription -Class __FilterToConsumerBinding
# Tout résultat ici (qui ne provient pas d'un logiciel connu) = persistance WMI
# Supprimer l'abonnement WMI
Get-WMIObject -Namespace root\\\\subscription -Class __FilterToConsumerBinding |
Where-Object {$_.Consumer -like "*malicious*"} |
Remove-WMIObject
# 5. Détournement COM (remplacement de registre HKCU)
Get-ChildItem "HKCU:\\\\Software\\\\Classes\\\\CLSID" |
Select-Object Name, @{N='Value';E={(Get-ItemProperty $_.PSPath).'(default)'}}
# 6. Secteur de démarrage / MBR (les ransomwares ciblent souvent)
# Linux : comparer à une ligne de base connue bonne
dd if=/dev/sda bs=512 count=1 | sha256sum # Hachage MBR
# Comparer au hachage de référence
# 7. Valider l'éradication avec un deuxième scan
# Lancer un scan complet AV/EDR APRÈS la suppression manuelle
# Vérifier l'absence d'indicateurs de re-infection dans le SIEM 24h après la récupération
Récupération
# NE JAMAIS restaurer depuis une sauvegarde effectuée après la date de compromission
# Trouver la dernière sauvegarde propre AVANT l'horodatage d'accès initial de l'attaquant
# (Déterminé par l'analyse forensique - première preuve de présence de l'attaquant)
# Déterminer la date d'infection à partir du premier artefact de l'attaquant
# Vérifier : premier processus malveillant dans Prefetch, première connexion C2 dans les journaux pare-feu,
# premier événement 4624 anormal, horodatage le plus ancien du fichier malveillant
# La reconstruction propre est toujours préférée à la correction d'un système compromis
# 1. Effacer et réimager depuis une image de référence connue bonne
# 2. Appliquer tous les correctifs avant de connecter au réseau
# 3. Restaurer les données uniquement depuis une sauvegarde pré-compromission
# 4. Valider avec un scan EDR avant utilisation en production
# Surveillance accrue post-récupération (30 jours de surveillance renforcée)
# - Augmenter la verbosité des journaux sur les hôtes récupérés
# - Activer la journalisation PowerShell renforcée (bloc de script + transcription)
# - Alerter sur TOUTE connexion depuis des comptes qui ont été compromis
# - Revue quotidienne de l'activité des hôtes récupérés pendant 30 jours
# Validation post-récupération
nmap -sV -p- RECOVERED_HOST # Vérifier l'absence de services inattendus
cme smb RECOVERED_HOST -u admin -p pass --processes # Vérifier les processus en cours
10. Cartographie MITRE ATT&CK
| Technique | ID | Méthode de Détection RI | Source de Preuves |
|---|---|---|---|
| Injection de Processus | T1055 | malfind - régions mémoire RWX | Capture mémoire (Volatility) |
| Maliciel Sans Fichier | T1059 | Artefacts en mémoire, aucun fichier disque | Forensique mémoire uniquement |
| Persistance Tâche Planifiée | T1053.005 | XML de tâche dans C:\Windows\System32\Tasks | Image disque + Event 4698 |
| Clé Run du Registre | T1547.001 | Analyse de ruche de registre | NTUSER.DAT, ruche SOFTWARE |
| Abonnement WMI | T1546.003 | Requête du référentiel WMI | Base de données référentiel WMI |
| Nouveau Service | T1543.003 | Vérification du hachage binaire de service | Ruche SYSTEM + Event 7045 |
| Exfiltration de Données | T1041 | Grands flux sortants dans PCAP | NetFlow + analyse PCAP |
| Extraction d'Identifiants | T1003 | Accès mémoire LSASS dans EDR | Capture mémoire + Event 4663 |
| Mouvement Latéral | T1021 | Corrélation de connexions inter-hôtes | Chaîne Event 4624 type 3 |
| Évasion : Falsification d'Horodatage | T1070.006 | Discordance MFT $STANDARD vs $FILENAME | Analyse MFT NTFS |
| Manipulation de Compte | T1098 | Nouveaux comptes dans AD, auth.log | Event 4720 + /etc/passwd |
| Initialisation Démarrage/Connexion | T1037 | Scripts de démarrage + unités systemd | Image disque + journalctl |