Skip to main content

Chapitre 2.1 - Analyse de paquets et dissection de protocoles

Module 2 : Analyse du trafic et detection des intrusions Niveau : Intermediaire a avance | Duree estimee de lecture : 60-75 min


Table des matieres

  1. Pourquoi l'analyse de paquets est importante
  2. Anatomie d'un paquet - De la trame Ethernet au payload
  3. Outils et techniques de capture
  4. Wireshark - Inspection approfondie
  5. Dissection de protocoles - TCP, UDP, HTTP, DNS, TLS
  6. Detection des patterns de trafic malveillants
  7. Forensique reseau - Reconstruction des sessions
  8. Diagramme d'architecture

1. Pourquoi l'analyse de paquets est importante

L'analyse de paquets est la discipline consistant a capturer, decoder et interpreter le trafic reseau brut. Elle se situe a l'intersection de l'offense et de la defense :

  • Pour les defenseurs : detecter les balises C2, l'exfiltration de donnees, le mouvement lateral, l'abus de protocoles
  • Pour les intervenants en cas d'incident : reconstruire ce qui s'est passe, etablir des chronologies, recuperer les fichiers transferes
  • Pour les red teamers : comprendre l'apparence de vos outils sur le reseau et comment vous fondre dans la masse
  • Pour les ingenieurs : deboguer les problemes de protocole, valider le chiffrement, confirmer les regles de pare-feu

Le principe fondamental : chaque interaction reseau laisse une trace. Les paquets ne mentent pas. Les journaux peuvent etre supprimes, mais si vous capturez le trafic au niveau du fil, les preuves sont preservees.

L'etat d'esprit de l'analyste

Lors de l'examen d'une capture, posez-vous les questions suivantes :

  • Quelle est la base de reference de ce reseau ? A quoi ressemble le comportement normal ?
  • Ce trafic est-il attendu de cette paire source/destination ?
  • Le volume, le timing et la direction correspondent-ils a l'usage declare ?
  • Le protocole est-il utilise comme prevu, ou est-il detourne ?

2. Anatomie d'un paquet - De la trame Ethernet au payload

Chaque paquet traversant un reseau Ethernet est un oignon d'en-tetes encapsules. Comprendre les champs de chaque couche est un prerequis pour les lire.

2.1 Structure en couches

+------------------------------------------------------------------+
| Trame Ethernet |
| +------------+------------+-------------------------------+ |
| | MAC Dst | MAC Src | EtherType (0x0800=IPv4) | |
| | 6 octets | 6 octets | 2 octets | |
| +------------+------------+-------------------------------+ |
| +------------------------------------------------------------+ |
| | En-tete IP (20+ octets) | |
| | Ver|IHL|DSCP|ECN| Longueur totale | Identification | |
| | Drapeaux|Decalage fragment|TTL|Protocole|Somme de ctrl | |
| | IP source (4 octets) | IP destination (4 octets) | |
| +------------------------------------------------------------+ |
| +------------------------------------------------------------+ |
| | En-tete TCP/UDP | |
| | Port Src (2) | Port Dst (2) | Numero de sequence (4) | |
| | Numero d'acquittement (4) | Decalage|Drapeaux|Fenetre | |
| +------------------------------------------------------------+ |
| +------------------------------------------------------------+ |
| | Donnees applicatives | |
| | (HTTP, DNS, enregistrement TLS, payload brut...) | |
| +------------------------------------------------------------+ |
+------------------------------------------------------------------+

2.2 Champs de l'en-tete IP - Pertinence securitaire

ChampTailleImportance pour la securite
TTL8 bitsEmpreinte du systeme d'exploitation (Linux=64, Windows=128, Cisco=255) ; decremente a chaque saut
Protocole8 bits6=TCP, 17=UDP, 1=ICMP - les canaux dissimules utilisent des protocoles inattendus
IP source32 bitsPeut etre usurpee (outil d'attaquant pour DoS, obscurcissement du scan)
Decalage fragment13 bitsAttaques par chevauchement de fragments pour contourner l'IDS
Drapeaux (DF, MF)3 bitsDF=Ne pas fragmenter ; fragments chevauchants utilises pour l'evasion
DSCP/ECN6+2 bitsParfois utilise pour les canaux dissimules
Identification16 bitsLes ID sequentiels fuient des infos OS ; utilise pour le scan inactif (Nmap -sI)

2.3 Champs de l'en-tete TCP - Pertinence securitaire

ChampTailleImportance pour la securite
Port source16 bitsLes plages de ports ephemeres different par OS (Linux : 32768-60999, Windows : 49152-65535)
Numero de sequence32 bitsISN previsible = risque de detournement de session ; attaques par reinitialisation TCP
Numero ACK32 bitsDoit correspondre a la seq attendue - les non-correspondances indiquent une injection
Drapeaux9 bitsSYN/FIN/RST/PSH/ACK/URG - combinaisons inhabituelles (Xmas, NULL, scan FIN)
Taille de fenetre16 bitsEmpreinte OS ; fenetre zero = controle de flux
Pointeur d'urgence16 bitsRarement utilise legitimement ; parfois utilise pour les donnees dissimulees

2.4 Drapeaux TCP et types de scan

Drapeaux de communication normale :
SYN -> Initiation de connexion
SYN + ACK -> Acquittement du serveur
ACK -> Acquittement de donnees
FIN + ACK -> Fermeture gracieuse de connexion
RST -> Reinitialisation abrupte de connexion

Combinaisons de drapeaux de scan :
SYN uniquement -> Scan SYN (furtif -- pas de poignee de main complete)
FIN uniquement -> Scan FIN (contourne les filtres de paquets sans etat)
FIN + URG + PSH -> Scan Xmas (tous "allumes" -- inhabituel, contourne certains IDS)
Pas de drapeaux -> Scan NULL (zero drapeaux -- non conforme RFC, evasion)
ACK uniquement -> Scan ACK (cartographie les regles de pare-feu -- revele filtre vs non filtre)
SYN + FIN -> Invalide -- signal d'alarme immediat dans l'IDS
SYN + RST -> Invalide -- signal d'alarme

Filtres tcpdump pour les combinaisons de drapeaux suspects :
tcpdump -i eth0 'tcp[tcpflags] & (tcp-fin|tcp-syn|tcp-rst|tcp-push|tcp-urg) == 0'
tcpdump -i eth0 'tcp[tcpflags] & (tcp-fin|tcp-urg|tcp-push) == (tcp-fin|tcp-urg|tcp-push)'
tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-fin) == (tcp-syn|tcp-fin)'

3. Outils et techniques de capture

3.1 tcpdump - Capture en ligne de commande

tcpdump est l'outil de capture universel sur Linux/Unix. Sa syntaxe Berkeley Packet Filter (BPF) est partagee par tcpdump, Wireshark, Snort, Suricata et de nombreux autres outils.

# Capture basique sur l'interface eth0
tcpdump -i eth0

# Capturer dans un fichier (toujours faire cela -- analyser hors ligne)
tcpdump -i eth0 -w capture.pcap

# Capturer avec un tampon plus grand (reduit les paquets perdus sur les liens charges)
tcpdump -i eth0 -B 4096 -w capture.pcap

# Capturer avec horodatages et sans resolution DNS (plus rapide, affiche les IP brutes)
tcpdump -i eth0 -nn -tttt -w capture.pcap
# -nn : ne pas resoudre les noms d'hotes ou les noms de port
# -tttt : afficher l'horodatage absolu avec la date

# Rotation des fichiers de capture : nouveau fichier tous les 100 Mo ou toutes les 3600 secondes
tcpdump -i eth0 -C 100 -G 3600 -w capture_%Y%m%d_%H%M%S.pcap

# -- Filtres BPF --

# Capturer uniquement le trafic vers/depuis un hote specifique
tcpdump -i eth0 host 10.0.0.50

# Capturer un port specifique
tcpdump -i eth0 port 443

# Capturer un sous-reseau
tcpdump -i eth0 net 10.0.0.0/24

# Capturer TCP uniquement (exclure le bruit UDP/ICMP)
tcpdump -i eth0 tcp

# Capturer les requetes DNS (port UDP 53) ET les reponses
tcpdump -i eth0 'udp port 53'

# Capturer le trafic HTTP et afficher le payload ASCII
tcpdump -i eth0 -A 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'

# Capturer tout le trafic SAUF SSH (eviter de capturer sa propre session)
tcpdump -i eth0 'not port 22'

# Detecter les scans de ports potentiels : paquets SYN vers plusieurs ports depuis une source
tcpdump -i eth0 'tcp[tcpflags] == tcp-syn' -nn | \
awk '{print $3}' | \
cut -d. -f1-4 | \
sort | uniq -c | sort -rn | head

# Capturer ICMP et afficher type/code
tcpdump -i eth0 icmp -v

3.2 tshark - Interface CLI de Wireshark

tshark fournit le moteur de dissection de Wireshark en ligne de commande - ideal pour l'analyse automatisee et les scripts.

# Lire un pcap et afficher avec des champs specifiques
tshark -r capture.pcap \
-T fields \
-e frame.time \
-e ip.src \
-e ip.dst \
-e tcp.dstport \
-e http.request.method \
-e http.request.uri \
-E header=y \
-E separator=, \
> requetes_http.csv

# Extraire toutes les requetes DNS d'une capture
tshark -r capture.pcap \
-Y "dns.flags.response == 0" \
-T fields \
-e frame.time \
-e ip.src \
-e dns.qry.name \
-e dns.qry.type

# Suivre un flux TCP specifique (reconstruire la conversation)
tshark -r capture.pcap \
-z follow,tcp,ascii,0 # Indice de flux 0

# Statistiques : principaux emetteurs par octets
tshark -r capture.pcap -q -z conv,ip | head -20

# Hierarchie de protocoles (quels protocoles sont dans la capture)
tshark -r capture.pcap -q -z io,phs

# Extraire les fichiers du trafic HTTP (images, executables, documents)
tshark -r capture.pcap \
--export-objects http,/tmp/fichiers_extraits/

# Trouver les sessions TCP de longue duree (balises C2 potentielles)
tshark -r capture.pcap -q -z conv,tcp | \
awk '{print $1, $3, $5, $9}' | \
sort -k4 -rn | head -20 # Trier par duree

# Dechiffrer le trafic TLS (necessite un fichier journal de cles)
tshark -r capture.pcap \
-o "tls.keylog_file:/tmp/clessl.log" \
-Y "http" \
-T fields -e http.request.full_uri

3.3 Positions de capture dans le reseau

La position de votre capteur de capture determine ce que vous pouvez voir :

SPAN / Miroir de port (Switched Port Analyzer) :

Dans un reseau commute, vous ne pouvez pas simplement brancher un portable et voir le trafic de tout le monde (contrairement aux hubs). Un port SPAN copie tout le trafic des ports sources vers un port de surveillance.

# Commutateur Cisco : configurer le port SPAN
Switch(config)# monitor session 1 source interface Gi0/1 - Gi0/24
Switch(config)# monitor session 1 destination interface Gi0/25
# Connecter maintenant le dispositif de capture a Gi0/25 -- voit tout le trafic de Gi0/1-24

# Linux : intercepter une interface bridge pour voir le trafic entre deux segments
ip link add br0 type bridge
ip link set eth0 master br0
ip link set eth1 master br0
ip link set br0 up
tcpdump -i br0 -w capture.pcap

4. Wireshark - Inspection approfondie

4.1 Filtres essentiels

Les filtres d'affichage Wireshark utilisent une syntaxe differente des filtres BPF tcpdump - ils operent sur les champs de protocole decodes.

# -- Filtres de base --
ip.addr == 10.0.0.50 # Trafic vers ou depuis cette IP
ip.src == 10.0.0.50 # Trafic depuis cette source
ip.dst == 10.0.0.50 # Trafic vers cette destination
tcp.port == 443 # Port source ou destination 443
tcp.dstport == 8080 # Port destination 8080
tcp.flags.syn == 1 # Drapeau SYN active
tcp.flags == 0x002 # SYN uniquement (detection de scan)
tcp.flags.syn == 1 && tcp.flags.ack == 0 # SYN sans ACK (scan semi-ouvert)

# -- Filtres specifiques aux protocoles --
http.request.method == "POST" # Requetes HTTP POST
http.response.code >= 500 # Erreurs serveur
dns.qry.name contains "evil" # Requete DNS contenant "evil"
dns.resp.ttl < 60 # Reponses DNS a faible TTL (fast-flux C2)
tls.handshake.type == 1 # TLS ClientHello
tls.record.version == 0x0301 # TLS 1.0 (depreciee)
smtp.req.command == "AUTH" # Tentatives d'authentification SMTP
ftp.request.command == "PASS" # Mot de passe FTP (en clair !)

# -- Filtres d'analyse avancee --
frame.len > 1400 # Grands paquets (exfiltration ? fragmentation ?)
tcp.analysis.retransmission # Retransmissions TCP (problemes reseau ou evasion)
tcp.analysis.zero_window # Fenetre zero -- problemes de controle de flux
tcp.analysis.duplicate_ack # ACK dupliques -- indicateur de perte de paquets
ip.ttl < 10 # Faible TTL -- paquet a traverse de nombreux sauts ou manipulation TTL
icmp.type == 8 && frame.len > 100 # Ping ICMP surdimensionne (tunneling ICMP)

# -- Chasse aux identifiants --
http contains "password" # Trafic HTTP contenant la chaine "password"
ftp # Tout FTP (identifiants en clair)
telnet # Tout Telnet (identifiants en clair)
pop || imap # Protocoles email (authentification souvent en clair)

4.2 Statistiques et fonctions d'analyse

Outils d'analyse du menu Wireshark :

Statistiques -> Hierarchie de protocoles
-> Affiche tous les protocoles dans la capture, % d'octets utilises
-> Anomalie : protocole inattendu (ex. IRC, IMAP dans le trafic d'entreprise)

Statistiques -> Conversations
-> Liste toutes les conversations TCP/UDP/IP avec les octets transferes
-> Trier par octets : grands transferts vers des IP externes = candidats a l'exfiltration

Statistiques -> Points de terminaison
-> Affiche tous les points de terminaison IP/MAC, paquets envoyes/recus
-> IP internes communicant avec de nombreuses IP externes = scanner ou botnet

Statistiques -> Graphique E/S
-> Volume de trafic dans le temps
-> Pics reguliers a intervalles fixes = battement de balise C2

Analyser -> Informations expertes
-> Detection automatique d'anomalies par Wireshark
-> Erreurs (rouge) : retransmissions TCP, echecs de somme de controle
-> Avertissements (jaune) : reinitialisation de connexion, problemes de fenetre
-> Notes (cyan) : anomalies de protocole

Analyser -> Suivre -> Flux TCP
-> Reconstruit la conversation de la couche applicative
-> Affiche requete + reponse sous forme lisible
-> Critique pour : analyse de session HTTP, capture d'identifiants en clair

Statistiques -> HTTP -> Requetes
-> Toutes les requetes HTTP par hote, chemin, agent utilisateur
-> Agents utilisateurs inhabituels = maliciels ou outils de scan

4.3 Regles de colorisation pour l'analyse de securite

La colorisation par defaut de Wireshark aide a reperer les problemes :

  • Fond noir (texte rouge) : Erreurs TCP, mauvaises sommes de controle
  • Rouge fonce : Erreurs HTTP (4xx, 5xx)
  • Violet clair : TCP SYN
  • Bleu clair : DNS
  • Vert clair : Trafic HTTP

Regle personnalisee pour la detection C2 :

# Ajouter une regle de colorisation personnalisee pour les connexions longues suspects :
# Modifier -> Regles de colorisation -> Nouveau
# Nom : "TCP Long Suspect"
# Filtre : tcp.time_relative > 3600 && tcp.flags.syn == 0
# Couleur : fond rouge vif

5. Dissection de protocoles

5.1 TCP - Analyse de la poignee de main a trois voies

# Capturer et annoter une poignee de main TCP
tcpdump -i eth0 -nn 'host 10.0.0.50 and port 80' -v

# Sortie attendue pour une poignee de main normale :
# 10:00:01.000 IP 10.0.0.10.54321 > 10.0.0.50.80: Flags [S], seq 0, win 64240, length 0
# ^ ^SYN ^ISN
# 10:00:01.001 IP 10.0.0.50.80 > 10.0.0.10.54321: Flags [S.], seq 0, ack 1, win 65535, length 0
# ^ ^SYN+ACK
# 10:00:01.002 IP 10.0.0.10.54321 > 10.0.0.50.80: Flags [.], ack 1, win 502, length 0
# ^ ^ACK

# Detecter les tempetes RST (tentative d'intrusion / DoS)
tcpdump -i eth0 'tcp[tcpflags] & tcp-rst != 0' -nn | \
awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn

# Detecter les connexions semi-ouvertes (inondation SYN)
ss -ant | grep SYN_RECV | wc -l
# Plus de 200 SYN_RECV est suspect
netstat -ant | grep SYN_RECV | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn

5.2 HTTP - Analyse des requetes/reponses

# Extraire toutes les requetes HTTP avec horodatages, methode, URI, code de reponse
tshark -r capture.pcap \
-Y "http.request or http.response" \
-T fields \
-e frame.time_relative \
-e ip.src \
-e ip.dst \
-e http.request.method \
-e http.request.uri \
-e http.response.code \
-e http.user_agent \
-E separator="|"

# Agents utilisateurs suspects a rechercher dans le trafic HTTP :
# curl/7.x.x -> requetes scriptees (automatisation / outils d'attaquant)
# python-requests -> scripte (tests d'intrusion, maliciels)
# Go-http-client -> outils bases sur Go (de nombreux frameworks C2)
# Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) -> tres ancien UA, probablement un maliciel
# (agent utilisateur vide) -> connexion socket brute, outil automatise
# Nikto, sqlmap, Masscan, dirbuster -> outils de scan

# Chasser les grands corps POST (exfiltration potentielle ou payload d'exploit)
tshark -r capture.pcap \
-Y "http.request.method == POST && http.content_length > 10000" \
-T fields \
-e ip.src -e http.request.uri -e http.content_length

# Detecter les tentatives de traversee de repertoire dans les URI HTTP
tshark -r capture.pcap \
-Y 'http.request.uri contains "../"' \
-T fields -e ip.src -e http.request.uri

# Detecter les patterns d'injection SQL dans les URI
tshark -r capture.pcap \
-Y 'http.request.uri matches "(?i)(union|select|insert|drop|exec|xp_)"' \
-T fields -e ip.src -e http.request.uri

5.3 DNS - Analyse des requetes

Le DNS est le protocole le plus riche en informations pour detecter l'activite malveillante - presque toute action reseau necessite du DNS.

# Extraire toutes les requetes DNS avec les IP de reponse
tshark -r capture.pcap \
-Y "dns" \
-T fields \
-e frame.time \
-e ip.src \
-e dns.qry.name \
-e dns.a \
-e dns.flags.response \
| grep "0$" # Uniquement les requetes (indicateur reponse = 0)

# Trouver les domaines avec un TTL suspicieusement bas (fast-flux C2)
tshark -r capture.pcap \
-Y "dns.flags.response == 1" \
-T fields \
-e dns.qry.name \
-e dns.resp.ttl \
| awk '$2 < 60 {print}' | sort -u

# Detecter le tunneling DNS : rechercher les etiquettes de sous-domaine longues
tshark -r capture.pcap \
-Y "dns" \
-T fields \
-e dns.qry.name \
| awk '{if(length($1) > 50) print $1}' | sort -u

# Calculer l'entropie des noms de requetes DNS (detection DGA)
python3 << 'EOF'
import math
from collections import Counter

# Coller les noms de requetes DNS ici (depuis la sortie tshark ou les journaux DNS)
domaines = [
"www.google.com",
"api.github.com",
"aGVsbG8.evil-c2.net", # Sous-domaine encode en base64
"xkjhdfqwer.biz", # Style DGA
"mail.company.com"
]

def entropie(s):
comptes = Counter(s)
total = len(s)
return -sum((c/total) * math.log2(c/total) for c in comptes.values())

for d in domaines:
etiquette = d.split('.')[0] # Premiere etiquette
e = entropie(etiquette)
drapeau = "SUSPECT" if e > 3.5 or len(etiquette) > 30 else "OK"
print(f"{d:45s} entropie={e:.2f} {drapeau}")
EOF

# Detecter le rebinding DNS (changement d'IP en succession rapide pour le meme domaine)
# L'attaquant change le DNS vers une IP interne apres que le navigateur a mis en cache la resolution initiale
tshark -r capture.pcap -Y "dns.flags.response == 1" \
-T fields -e dns.qry.name -e dns.a | \
sort | awk 'seen[$1]++ && seen[$1]==2 {print "PLUSIEURS IPs: "$0}'

5.4 TLS - Inspection de la poignee de main sans dechiffrement

Meme sans dechiffrer le TLS, la poignee de main revele des informations significatives.

# Extraire les details du TLS ClientHello (ce que le client supporte)
tshark -r capture.pcap \
-Y "tls.handshake.type == 1" \
-T fields \
-e ip.src \
-e tls.handshake.extensions_server_name \
-e tls.handshake.ciphersuite \
-e tls.handshake.extensions.supported_versions

# Empreinte JA3 : identifier les clients TLS par les parametres de poignee de main
# JA3 = MD5 de (SSLVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePoints)
# Les familles de maliciels ont des hachages JA3 caracteristiques independamment du payload

# Installer ja3 pour tshark
pip3 install pyshark

python3 << 'EOF'
import pyshark
import hashlib

def calculer_ja3(pkt):
"""Calculer le hachage JA3 depuis le TLS ClientHello"""
try:
tls = pkt.tls
if int(tls.handshake_type) != 1:
return None

version = tls.handshake_version
ciphers = tls.handshake_ciphersuite.replace(':', '-')
extensions = getattr(tls, 'handshake_extensions_type', '').replace(':', '-')
curves = getattr(tls, 'handshake_extensions_supported_group', '').replace(':', '-')
points = getattr(tls, 'handshake_extensions_ec_point_format', '').replace(':', '-')

ja3_str = f"{version},{ciphers},{extensions},{curves},{points}"
ja3_hash = hashlib.md5(ja3_str.encode()).hexdigest()
return ja3_hash, ja3_str
except AttributeError:
return None

cap = pyshark.FileCapture('capture.pcap', display_filter='tls.handshake.type==1')
for pkt in cap:
result = calculer_ja3(pkt)
if result:
ja3_hash, ja3_str = result
print(f"src={pkt.ip.src} JA3={ja3_hash}")
# Comparer avec les hachages JA3 connus de maliciels :
# Cobalt Strike par defaut : 72a589da586844d7f0818ce684948eea
# Metasploit par defaut : d4e457bda4060ac3a1e0ce55df394aa6
EOF

# Empreinte JARM -- identifier les SERVEURS TLS
# JARM envoie 10 TLS ClientHellos specialement construits, identifie les reponses du serveur
# Utile pour identifier l'infrastructure C2 independamment du certificat
pip3 install jarm-fingerprinter
python3 -m jarm 10.0.0.1 443
# Sortie : hachage JARM (ex. "07d14d16d21d21d00042d43d000000...")
# Comparer avec les hachages de serveurs C2 connus dans les flux de renseignement sur les menaces

6. Detection des patterns de trafic malveillants

6.1 Detection de balises C2

La balise C2 se caracterise par des connexions periodiques et regulieres vers une IP/domaine externe. L'intervalle de rappel est un signal de detection cle.

# Detecter les balises : trouver les connexions avec des intervalles de temps reguliers
# Extraire les horodatages de connexion par destination
python3 << 'EOF'
import subprocess, json
from collections import defaultdict
import statistics

# Lancer tshark pour extraire les horodatages TCP SYN par IP destination
sortie = subprocess.check_output([
'tshark', '-r', 'capture.pcap',
'-Y', 'tcp.flags.syn==1 && tcp.flags.ack==0',
'-T', 'fields',
'-e', 'frame.time_epoch',
'-e', 'ip.dst'
], text=True)

# Grouper par IP destination
connexions = defaultdict(list)
for ligne in sortie.strip().split('\n'):
if '\t' in ligne:
ts, dst = ligne.split('\t')
connexions[dst].append(float(ts))

# Analyser les intervalles pour chaque destination
print(f"{'IP Destination':20s} {'Connexions':12s} {'Intervalle moy':15s} {'Ecart-type':12s} {'Balise?'}")
print("-" * 75)
for dst, horodatages in sorted(connexions.items()):
if len(horodatages) < 4:
continue
horodatages.sort()
intervalles = [horodatages[i+1]-horodatages[i] for i in range(len(horodatages)-1)]
moy = statistics.mean(intervalles)
std = statistics.stdev(intervalles) if len(intervalles) > 1 else 0
ratio_gigue = std / moy if moy > 0 else 1
balise = "BALISE" if ratio_gigue < 0.1 and moy < 3600 else ""
print(f"{dst:20s} {len(horodatages):12d} {moy:15.1f}s {std:12.1f} {balise}")
EOF

6.2 Patterns d'exfiltration de donnees

# Detecter les grands transferts de donnees sortants
tshark -r capture.pcap -q -z conv,tcp | \
awk 'NR>5 {
split($1, src, ":")
split($3, dst, ":")
if ($6+0 > $8+0) { # Plus d'octets envoyes que recus = transfert sortant
print $1, "->", $3, "Sortant:", $6, "octets"
}
}' | sort -k5 -rn | head -20

# Detecter l'exfiltration DNS (volume eleve de requetes par domaine)
tshark -r capture.pcap -Y "dns.flags.response==0" \
-T fields -e dns.qry.name | \
awk -F. '{
n = NF; domaine = $(n-1)"."$n;
compteur[domaine]++
}
END {
for (d in compteur) if (compteur[d] > 100) print compteur[d], d
}' | sort -rn

# Detecter l'exfiltration HTTPS via des volumes de transfert inhabituels
# Grand POST vers une IP externe a des heures inhabituelles
tshark -r capture.pcap \
-Y "http.request.method==POST" \
-T fields \
-e frame.time \
-e ip.src \
-e ip.dst \
-e http.content_length | \
awk -F'\t' '$4+0 > 100000 {print}' # Corps POST > 100 Ko

6.3 Detection de scan de ports

# Detecter un scan horizontal : une source touchant de nombreuses destinations sur le meme port
# (ex. propagation de ver, mouvement lateral)
tshark -r capture.pcap \
-Y "tcp.flags.syn==1 && tcp.flags.ack==0" \
-T fields -e ip.src -e ip.dst | \
awk '{srcdst[$1][$2]=1} END {
for (src in srcdst) {
n = 0
for (dst in srcdst[src]) n++
if (n > 20) print src, "->", n, "destinations"
}
}'

# Detecter un scan vertical : une source touchant de nombreux ports sur la meme destination
# (enumeration de services)
tshark -r capture.pcap \
-Y "tcp.flags.syn==1 && tcp.flags.ack==0" \
-T fields -e ip.src -e ip.dst -e tcp.dstport | \
awk '{cle=$1" "$2; ports[cle][$3]=1}
END {
for (k in ports) {
n=0; for (p in ports[k]) n++
if (n > 15) print k, ":", n, "ports"
}
}'

# Detecter les sondes de detection OS de Nmap (envoie des paquets avec des options TCP inhabituelles)
# Rechercher les paquets TCP avec des tailles de fenetre et combinaisons d'options inhabituelles
tcpdump -r capture.pcap -v 'tcp[tcpflags] == tcp-syn' 2>/dev/null | \
grep -E "win [0-9]+ " | \
awk '{print $NF}' | \
sort | uniq -c | sort -rn
# Le scan SYN de Nmap utilise les tailles de fenetre 1024, 2048, 4096 en sequence

6.4 Anomalies de protocole

# Detecter des protocoles communs sur des ports non standards
# HTTP sur des ports autres que 80/443 (evasion ou pivot possibles)
tshark -r capture.pcap \
-Y "http && not tcp.port == 80 && not tcp.port == 443 && not tcp.port == 8080" \
-T fields -e ip.src -e ip.dst -e tcp.dstport -e http.request.uri

# DNS sur un port non standard (evasion par tunneling DNS)
tshark -r capture.pcap \
-Y "dns && not udp.port == 53 && not tcp.port == 53" \
-T fields -e ip.src -e ip.dst -e udp.dstport

# Paquets ICMP avec grand payload (tunneling)
tshark -r capture.pcap \
-Y "icmp && frame.len > 100" \
-T fields -e ip.src -e ip.dst -e frame.len -e data.len

# Identifiants en clair sur le reseau (protocoles historiques)
tcpdump -r capture.pcap -A -l 'port ftp or port 23 or port 110 or port 143' | \
grep -iE "(user|pass|login|password|auth)" | \
grep -v "^[[:space:]]*$"

7. Forensique reseau - Reconstruction des sessions

7.1 Extraction de fichiers depuis les captures

# Extraire les fichiers transferes par HTTP (executables, documents, images)
tshark -r capture.pcap \
--export-objects http,/tmp/http_extraits/

ls -la /tmp/http_extraits/
# Les fichiers sont nommes par le chemin URI HTTP
# Verifier les fichiers extraits pour les maliciels :
file /tmp/http_extraits/*
for f in /tmp/http_extraits/*; do
hachage=$(sha256sum "$f" | awk '{print $1}')
echo "$f: $hachage"
# Interroger VirusTotal, MalwareBazaar, etc.
done

# Extraire les fichiers transferes par SMB
tshark -r capture.pcap \
--export-objects smb,/tmp/smb_extraits/

# Reconstruire un flux TCP vers un fichier
tshark -r capture.pcap \
-z follow,tcp,raw,0 \
| xxd | head -50 # Afficher en hexadecimal

# Alternative : dpkt Python pour le reassemblage de flux brut
python3 << 'EOF'
import dpkt, socket

with open('capture.pcap', 'rb') as f:
pcap = dpkt.pcap.Reader(f)
flux = {}

for ts, buf in pcap:
try:
eth = dpkt.ethernet.Ethernet(buf)
if not isinstance(eth.data, dpkt.ip.IP): continue
ip = eth.data
if not isinstance(ip.data, dpkt.tcp.TCP): continue
tcp = ip.data

src = socket.inet_ntoa(ip.src)
dst = socket.inet_ntoa(ip.dst)
cle = f"{src}:{tcp.sport}->{dst}:{tcp.dport}"

if tcp.data:
flux.setdefault(cle, b'')
flux[cle] += tcp.data
except:
continue

for flux_id, donnees in flux.items():
if len(donnees) > 1000:
print(f"Flux {flux_id}: {len(donnees)} octets")
# Sauvegarder les grands flux pour analyse
fname = flux_id.replace(':', '_').replace('>', '_').replace('/', '_')
with open(f"/tmp/flux_{fname}.bin", 'wb') as out:
out.write(donnees)
EOF

7.2 Reconstruction de la chronologie

# Construire une chronologie des evenements reseau depuis une capture
tshark -r capture.pcap \
-T fields \
-e frame.time \
-e ip.src \
-e ip.dst \
-e _ws.col.Protocol \
-e _ws.col.Info \
-E separator="|" \
| sort > chronologie_reseau.txt

# Trouver la premiere et derniere occurrence de chaque connexion
tshark -r capture.pcap -q -z conv,tcp | \
awk 'NR>5 {print $1, "premier:", $5, "dernier:", $6, "duree:", $9}'

# Corroller avec les journaux systeme (combiner les artefacts reseau et hote)
# Joindre la chronologie reseau avec les horodatages auth.log
join <(awk -F'|' '{print $1, $2}' chronologie_reseau.txt | sort) \
<(grep "Failed password" /var/log/auth.log | awk '{print $1, $2, $3, $9}' | sort)

7.3 Automatisation de l'analyse Pcap avec Scapy

from scapy.all import *
from collections import defaultdict
import statistics

def analyser_pcap(fichier_pcap):
"""Analyse pcap comprehensive pour les incidents de securite"""

paquets = rdpcap(fichier_pcap)
print(f"Charge {len(paquets)} paquets\n")

# Suivre les statistiques
compteurs_syn = defaultdict(int)
requetes_dns = defaultdict(list)
grands_transferts = []
identifiants_clair = []

for pkt in paquets:
# Detection de scan SYN
if TCP in pkt and pkt[TCP].flags == 'S':
src = pkt[IP].src if IP in pkt else "inconnu"
compteurs_syn[src] += 1

# Journalisation des requetes DNS
if DNS in pkt and pkt[DNS].qr == 0:
requete = pkt[DNS].qd.qname.decode('utf-8', errors='ignore').rstrip('.')
src = pkt[IP].src if IP in pkt else "inconnu"
requetes_dns[src].append(requete)

# Detection de grand payload TCP (>10 Ko par paquet)
if TCP in pkt and Raw in pkt:
if len(pkt[Raw].load) > 10000:
grands_transferts.append({
'src': pkt[IP].src,
'dst': pkt[IP].dst,
'taille': len(pkt[Raw].load),
'temps': float(pkt.time)
})

# Detection d'identifiants FTP en clair
if TCP in pkt and Raw in pkt:
payload = pkt[Raw].load.decode('utf-8', errors='ignore')
if payload.startswith(('USER ', 'PASS ')):
identifiants_clair.append({
'src': pkt[IP].src,
'dst': pkt[IP].dst,
'donnees': payload.strip()
})

# Rapport des resultats
print("=== CANDIDATS SCAN DE PORTS ===")
for src, compteur in sorted(compteurs_syn.items(), key=lambda x: -x[1]):
if compteur > 50:
print(f" {src}: {compteur} SYNs")

print("\n=== VOLUME ELEVE DE REQUETES DNS ===")
for src, requetes in requetes_dns.items():
if len(requetes) > 100:
print(f" {src}: {len(requetes)} requetes")
# Afficher les domaines les plus interroges
from collections import Counter
top = Counter(requetes).most_common(5)
for domaine, cnt in top:
print(f" {domaine}: {cnt}x")

print("\n=== GRANDS TRANSFERTS ===")
for t in sorted(grands_transferts, key=lambda x: -x['taille'])[:10]:
print(f" {t['src']} -> {t['dst']}: {t['taille']:,} octets")

print("\n=== IDENTIFIANTS EN CLAIR ===")
for c in identifiants_clair:
print(f" {c['src']} -> {c['dst']}: {c['donnees']}")

# analyser_pcap('capture.pcap')

8. Diagramme d'architecture