-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathwaf_interactive.html
More file actions
552 lines (535 loc) · 41.5 KB
/
Copy pathwaf_interactive.html
File metadata and controls
552 lines (535 loc) · 41.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WAF — Web Application Firewall : modèles, déploiement, OWASP CRS, tuning</title>
<style>
:root{--bg:#f8fafc;--card:#fff;--border:#e2e8f0;--text:#1e293b;--muted:#64748b;--acc:#ea580c;--acc2:#c2410c;--blue600:#2563eb;--green:#16a34a;--red:#dc2626;--orange:#ea580c;--purple:#7c3aed;--grad1:#431407;--grad2:#7c2d12}
@media(prefers-color-scheme:dark){:root{--bg:#0d0d0d;--card:#1a1a1a;--border:#2a2a2a;--text:#e2e8f0;--muted:#94a3b8}}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:'Segoe UI',system-ui,sans-serif;background:var(--bg);color:var(--text);line-height:1.6}
header{background:linear-gradient(135deg,var(--grad1),var(--grad2));padding:2rem 1rem;text-align:center;border-bottom:2px solid var(--acc)}
header h1{font-size:2rem;font-weight:800;color:#fff}
header p{color:#fdba74;margin-top:.4rem;font-size:.95rem}
nav{position:sticky;top:0;z-index:100;background:var(--card);border-bottom:1px solid var(--border);padding:.5rem 1rem;display:flex;gap:.5rem;flex-wrap:wrap;justify-content:center}
.tab-btn{padding:.4rem 1rem;border:none;border-radius:999px;cursor:pointer;font-size:.85rem;font-weight:600;background:var(--border);color:var(--muted);transition:all .2s}
.tab-btn.active{background:var(--blue600);color:#fff}
.tab-btn:hover:not(.active){background:var(--acc);color:#fff}
section{display:none;max-width:1100px;margin:0 auto;padding:1.5rem 1rem}
section.active{display:block}
h2{font-size:1.4rem;font-weight:700;margin-bottom:1rem;color:var(--acc)}
h3{font-size:1.1rem;font-weight:600;margin:1.2rem 0 .6rem}
.grid{display:grid;gap:1rem}.g2{grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}.g3{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}
.card{background:var(--card);border:1px solid var(--border);border-radius:.75rem;padding:1.2rem}
.card h4{font-size:1rem;font-weight:700;margin-bottom:.5rem;color:var(--acc)}
.codeblk{background:#1e1e2e;color:#cdd6f4;border-radius:.5rem;padding:1rem;font-family:'Cascadia Code','Fira Code',monospace;font-size:.82rem;overflow-x:auto;margin:.5rem 0;line-height:1.7;white-space:pre-wrap}
.c-kw{color:#89b4fa}.c-str{color:#a6e3a1}.c-comment{color:#6c7086;font-style:italic}.c-val{color:#f9e2af}.c-fn{color:#cba6f7}.c-op{color:#94e2d5}
table{width:100%;border-collapse:collapse;font-size:.85rem;margin:.5rem 0}
th{background:var(--acc);color:#fff;padding:.5rem .75rem;text-align:left}
td{padding:.45rem .75rem;border-bottom:1px solid var(--border)}
tr:hover td{background:var(--border)}
.info-box{background:var(--card);border-left:4px solid var(--acc);border-radius:.5rem;padding:.8rem 1rem;margin:.5rem 0}
.info-box.green{border-color:var(--green)}.info-box.red{border-color:var(--red)}.info-box.blue{border-color:var(--blue600)}.info-box.orange{border-color:var(--orange)}.info-box.purple{border-color:var(--purple)}
.badge{display:inline-block;padding:.2rem .6rem;border-radius:999px;font-size:.75rem;font-weight:600;margin:.1rem}
.badge-blue{background:#dbeafe;color:#1d4ed8}.badge-green{background:#dcfce7;color:#15803d}
.badge-red{background:#fee2e2;color:#b91c1c}.badge-yellow{background:#fef3c7;color:#92400e}
.badge-purple{background:#ede9fe;color:#6d28d9}.badge-indigo{background:#e0e7ff;color:#3730a3}
@media(prefers-color-scheme:dark){.badge-blue{background:#1e3a5f;color:#93c5fd}.badge-green{background:#14532d;color:#86efac}.badge-red{background:#450a0a;color:#fca5a5}.badge-yellow{background:#451a03;color:#fcd34d}.badge-purple{background:#2e1065;color:#c4b5fd}.badge-indigo{background:#1e1b4b;color:#a5b4fc}}
.stack{display:flex;flex-direction:column;gap:.3rem;margin:.5rem 0}
.layer{border-radius:.4rem;padding:.5rem .8rem;font-size:.82rem;font-weight:600;text-align:center;color:#fff}
.layer.hw{background:#475569}.layer.hyp{background:var(--acc)}.layer.host{background:#0891b2}.layer.guest{background:var(--green)}.layer.app{background:var(--purple)}.layer.ring{background:#7c3aed}
.quiz-q{background:var(--card);border:1px solid var(--border);border-radius:.75rem;padding:1.2rem;margin:.8rem 0}
.quiz-q p{font-weight:600;margin-bottom:.7rem}
.quiz-opt{padding:.5rem .8rem;border:1px solid var(--border);border-radius:.4rem;margin:.3rem 0;cursor:pointer;transition:all .2s}
.quiz-opt:hover{border-color:var(--acc);background:rgba(79,70,229,.05)}
.quiz-opt.correct{background:#dcfce7;border-color:var(--green);color:#166534}
.quiz-opt.wrong{background:#fee2e2;border-color:var(--red);color:#991b1b}
@media(prefers-color-scheme:dark){.quiz-opt.correct{background:#14532d;color:#86efac}.quiz-opt.wrong{background:#450a0a;color:#fca5a5}}
#quiz-score{display:none;text-align:center;padding:1.5rem;background:var(--card);border-radius:.75rem;margin-top:1rem;font-size:1.1rem;font-weight:700}
</style>
</head>
<body>
<header>
<h1>WAF — Web Application Firewall</h1>
<p>Protection applicative L7 — modèles de détection, déploiement, OWASP CRS, ModSecurity/Coraza & tuning</p>
</header>
<nav>
<button class="tab-btn active" onclick="showTab('overview')">Vue d'ensemble</button>
<button class="tab-btn" onclick="showTab('models')">Modèles de détection</button>
<button class="tab-btn" onclick="showTab('deploy')">Déploiement</button>
<button class="tab-btn" onclick="showTab('rules')">Règles & OWASP CRS</button>
<button class="tab-btn" onclick="showTab('protect')">Protections concrètes</button>
<button class="tab-btn" onclick="showTab('tuning')">Tuning & exploitation</button>
<button class="tab-btn" onclick="showTab('quiz')">Quiz</button>
</nav>
<section id="overview" class="active">
<h2>Vue d'ensemble</h2>
<div class="grid g2">
<div class="card">
<h4>Qu'est-ce qu'un WAF ?</h4>
<p style="font-size:.88rem;margin-bottom:.5rem">Un <strong>Web Application Firewall</strong> est un dispositif (matériel, logiciel ou service) qui filtre, surveille et bloque le trafic <strong>HTTP/HTTPS</strong> entre les clients et une application web. Il inspecte le contenu applicatif (URL, en-têtes, paramètres, cookies, corps JSON/XML/form) pour détecter et neutraliser les attaques visant la <strong>couche 7</strong> du modèle OSI.</p>
<div class="info-box">
Contrairement à un pare-feu réseau qui raisonne en IP/ports, un WAF <em>comprend</em> le protocole HTTP : il décode, normalise (canonicalisation) puis évalue la sémantique de la requête avant de la transmettre à l'application.
</div>
</div>
<div class="card">
<h4>WAF vs Firewall réseau (L3/L4)</h4>
<table>
<tr><th>Critère</th><th>Firewall L3/L4</th><th>WAF L7</th></tr>
<tr><td>Couche OSI</td><td>3-4 (IP/TCP-UDP)</td><td>7 (HTTP/HTTPS)</td></tr>
<tr><td>Unité de décision</td><td>IP, port, protocole, état</td><td>Requête HTTP, payload, contexte</td></tr>
<tr><td>Voit le contenu ?</td><td>Non (chiffré opaque)</td><td>Oui (terminaison/déchiffrement TLS)</td></tr>
<tr><td>Bloque une injection SQL ?</td><td>Non</td><td>Oui</td></tr>
<tr><td>Exemples</td><td>iptables, pfSense, Palo Alto</td><td>ModSecurity, Cloudflare, AWS WAF</td></tr>
</table>
<div class="info-box blue" style="margin-top:.4rem;font-size:.82rem">
Les deux sont <strong>complémentaires</strong> : le firewall réseau filtre le périmètre, le WAF protège la logique applicative. Aucun ne remplace l'autre.
</div>
</div>
</div>
<div class="card" style="margin-top:1rem">
<h4>Où se place le WAF dans la chaîne ?</h4>
<div class="stack">
<div class="layer guest">Client / Navigateur / Bot</div>
<div class="layer host">Firewall réseau (L3/L4) — IP, ports</div>
<div class="layer hyp">WAF (L7) — inspection HTTP/HTTPS, terminaison TLS</div>
<div class="layer app">Reverse proxy / Load balancer</div>
<div class="layer hw">Serveur applicatif (backend, API)</div>
</div>
<p style="font-size:.85rem;margin-top:.4rem">Le WAF s'insère <strong>en amont de l'application</strong>, après le filtrage réseau. Pour inspecter le HTTPS, il doit le plus souvent <strong>terminer le TLS</strong> (déchiffrer) afin d'analyser le contenu en clair, puis ré-chiffrer vers le backend.</p>
</div>
<div class="grid g2" style="margin-top:1rem">
<div class="card">
<h4>Ce que protège un WAF — OWASP Top 10 (2021)</h4>
<table>
<tr><th>Catégorie OWASP</th><th>Couvert par WAF ?</th></tr>
<tr><td>A01 Broken Access Control</td><td>Partiel (règles ciblées)</td></tr>
<tr><td>A02 Cryptographic Failures</td><td>Faible (côté app)</td></tr>
<tr><td>A03 Injection (SQLi, XSS…)</td><td><strong>Fort</strong></td></tr>
<tr><td>A04 Insecure Design</td><td>Non (conception)</td></tr>
<tr><td>A05 Security Misconfiguration</td><td>Partiel</td></tr>
<tr><td>A06 Vulnerable Components</td><td>Virtual patching</td></tr>
<tr><td>A07 Auth Failures</td><td>Rate limiting, anti brute-force</td></tr>
<tr><td>A10 SSRF</td><td>Partiel (règles)</td></tr>
</table>
</div>
<div class="card">
<h4>Ce qu'un WAF ne fait PAS</h4>
<ul style="font-size:.85rem;padding-left:1.2rem;line-height:1.85">
<li>Il ne <strong>corrige pas</strong> les vulnérabilités du code (mitigation, pas remédiation)</li>
<li>Il ne protège pas contre les <strong>failles de logique métier</strong> (workflow abusé légitimement)</li>
<li>Il ne remplace pas l'authentification, l'autorisation ni le chiffrement</li>
<li>Il est <strong>contournable</strong> (techniques d'évasion d'encodage)</li>
<li>Il génère des <strong>faux positifs</strong> qui peuvent casser l'application</li>
<li>Il ne voit pas le trafic <strong>est-ouest</strong> interne s'il est en bordure</li>
</ul>
<div class="info-box red" style="margin-top:.4rem;font-size:.82rem">
Un WAF est une <strong>défense en profondeur</strong>, pas un substitut au code sécurisé. PCI-DSS l'exige (req. 6.4.2) mais en complément du SDLC.
</div>
</div>
</div>
<div class="card" style="margin-top:1rem">
<h4>Glossaire essentiel</h4>
<table>
<tr><th>Terme</th><th>Définition</th></tr>
<tr><td><strong>L7 / couche applicative</strong></td><td>Niveau OSI où vit HTTP ; cible du WAF</td></tr>
<tr><td><strong>Signature</strong></td><td>Motif connu d'attaque (regex, chaîne) déclenchant une règle</td></tr>
<tr><td><strong>Modèle négatif / positif</strong></td><td>Bloquer ce qui est mauvais (blacklist) / autoriser ce qui est connu bon (whitelist)</td></tr>
<tr><td><strong>Anomaly scoring</strong></td><td>Cumul de points par règle ; blocage au-delà d'un seuil</td></tr>
<tr><td><strong>Paranoia Level (PL)</strong></td><td>Niveau d'agressivité du CRS (1 à 4)</td></tr>
<tr><td><strong>Faux positif (FP)</strong></td><td>Trafic légitime bloqué à tort</td></tr>
<tr><td><strong>Faux négatif (FN)</strong></td><td>Attaque réelle non détectée</td></tr>
<tr><td><strong>Virtual patching</strong></td><td>Règle WAF qui bloque l'exploitation d'une CVE en attendant le correctif</td></tr>
<tr><td><strong>RASP</strong></td><td>Runtime Application Self-Protection — protection intégrée dans l'app</td></tr>
<tr><td><strong>CRS</strong></td><td>OWASP Core Rule Set — jeu de règles génériques de référence</td></tr>
</table>
</div>
</section>
<section id="models">
<h2>Modèles de détection</h2>
<div class="grid g2">
<div class="card">
<h4>Modèle négatif (blacklist / signatures)</h4>
<p style="font-size:.85rem;margin-bottom:.4rem">On définit ce qui est <strong>interdit</strong> : le WAF compare chaque requête à une base de <strong>signatures</strong> d'attaques connues (regex SQLi, XSS, payloads de scanners…). Tout ce qui ne correspond à aucune signature passe.</p>
<ul style="font-size:.85rem;padding-left:1.2rem;line-height:1.8">
<li><span class="badge badge-green">+</span> Déploiement rapide, peu de config initiale</li>
<li><span class="badge badge-green">+</span> Faible taux de faux positifs</li>
<li><span class="badge badge-red">−</span> Inefficace contre le <strong>0-day</strong> et les variantes inédites</li>
<li><span class="badge badge-red">−</span> Contournable par évasion d'encodage</li>
<li><span class="badge badge-red">−</span> Exige une mise à jour permanente des signatures</li>
</ul>
</div>
<div class="card">
<h4>Modèle positif (whitelist / learning)</h4>
<p style="font-size:.85rem;margin-bottom:.4rem">On définit ce qui est <strong>autorisé</strong> : type, longueur et format attendus de chaque paramètre, méthodes HTTP permises, URL valides. Tout ce qui dévie est bloqué. Souvent construit par une phase d'<strong>apprentissage</strong> (learning) du trafic légitime.</p>
<ul style="font-size:.85rem;padding-left:1.2rem;line-height:1.8">
<li><span class="badge badge-green">+</span> Bloque le 0-day (rien d'inconnu ne passe)</li>
<li><span class="badge badge-green">+</span> Très efficace sur une app stable et bien profilée</li>
<li><span class="badge badge-red">−</span> Coûteux à construire et maintenir</li>
<li><span class="badge badge-red">−</span> Faux positifs élevés sur app dynamique</li>
<li><span class="badge badge-red">−</span> Le modèle dérive à chaque évolution de l'app</li>
</ul>
</div>
</div>
<div class="grid g2" style="margin-top:1rem">
<div class="card">
<h4>Modèle hybride</h4>
<p style="font-size:.85rem">La plupart des WAF modernes combinent les deux : signatures négatives (couverture rapide des menaces connues) <strong>+</strong> modèle positif sur les paramètres critiques (formulaires de login, API). C'est l'approche recommandée pour équilibrer couverture et faux positifs.</p>
</div>
<div class="card">
<h4>Détection par anomalie & scoring</h4>
<p style="font-size:.85rem;margin-bottom:.4rem">Plutôt que bloquer dès la 1re signature, chaque règle déclenchée ajoute des <strong>points</strong> (anomaly score). La requête n'est bloquée que si le score cumulé dépasse un <strong>seuil</strong>. C'est le mécanisme du <strong>OWASP CRS</strong>.</p>
<div class="codeblk"><span class="c-comment"># Exemple de scoring (CRS)</span>
SQLi pattern <span class="c-op">+5</span> (critique)
XSS pattern <span class="c-op">+5</span> (critique)
en-tête suspect <span class="c-op">+3</span> (erreur)
anomalie protocole <span class="c-op">+2</span> (warning)
<span class="c-comment"># Seuil inbound par défaut : 5 → bloqué</span></div>
</div>
</div>
<div class="card" style="margin-top:1rem">
<h4>Détection par Machine Learning</h4>
<p style="font-size:.85rem;margin-bottom:.4rem">Les WAF récents (Cloudflare, Imperva, F5) ajoutent des modèles <strong>ML</strong> qui apprennent une <em>baseline</em> du trafic et détectent les déviations comportementales : profils de bots, séquences de requêtes anormales, scoring de réputation. Utile contre les attaques polymorphes que les signatures ratent.</p>
<ul style="font-size:.85rem;padding-left:1.2rem;line-height:1.8">
<li><span class="badge badge-green">+</span> S'adapte aux attaques inconnues / polymorphes</li>
<li><span class="badge badge-green">+</span> Détection comportementale (bots, fraude)</li>
<li><span class="badge badge-red">−</span> « Boîte noire » difficile à auditer/expliquer</li>
<li><span class="badge badge-red">−</span> Sensible au <em>data poisoning</em> et au drift</li>
</ul>
</div>
<div class="card" style="margin-top:1rem">
<h4>Comparatif des modèles</h4>
<table>
<tr><th>Modèle</th><th>Principe</th><th>0-day</th><th>Faux positifs</th><th>Maintenance</th></tr>
<tr><td><strong>Négatif</strong></td><td>Bloque le connu mauvais</td><td>Faible</td><td>Faibles</td><td>Mise à jour signatures</td></tr>
<tr><td><strong>Positif</strong></td><td>Autorise le connu bon</td><td>Fort</td><td>Élevés</td><td>Lourde (profil app)</td></tr>
<tr><td><strong>Hybride</strong></td><td>Combinaison des deux</td><td>Moyen-fort</td><td>Modérés</td><td>Moyenne</td></tr>
<tr><td><strong>Anomalie/scoring</strong></td><td>Cumul de points + seuil</td><td>Moyen</td><td>Ajustables</td><td>Tuning du seuil</td></tr>
<tr><td><strong>ML</strong></td><td>Baseline comportementale</td><td>Fort</td><td>Variables</td><td>Réentraînement</td></tr>
</table>
</div>
</section>
<section id="deploy">
<h2>Modes de déploiement</h2>
<div class="grid g2">
<div class="card">
<h4>Reverse proxy inline</h4>
<div class="stack">
<div class="layer guest">Client</div>
<div class="layer hyp">WAF (reverse proxy, termine TLS)</div>
<div class="layer hw">Backend applicatif</div>
</div>
<p style="font-size:.85rem;margin-top:.4rem">Le WAF est <strong>sur le chemin</strong> du trafic, agit comme reverse proxy : il termine le TLS, inspecte, puis relaie. C'est le mode le plus courant — seul mode capable de <strong>bloquer activement</strong> et de modifier les requêtes.</p>
<p style="font-size:.83rem;margin-top:.3rem"><span class="badge badge-green">+</span> Blocage réel <span class="badge badge-red">−</span> Point de défaillance/latence, doit voir le TLS</p>
</div>
<div class="card">
<h4>Bridge / Transparent</h4>
<p style="font-size:.85rem;margin-bottom:.4rem">Le WAF s'insère en <strong>couche 2</strong> (pont réseau), sans changer l'adressage IP ni terminer le TLS de façon visible. Transparent pour l'architecture : pas de reconfiguration DNS/IP.</p>
<p style="font-size:.83rem"><span class="badge badge-green">+</span> Déploiement discret, faible latence <span class="badge badge-red">−</span> Inspection HTTPS limitée sans clés, moins de fonctions</p>
</div>
</div>
<div class="grid g2" style="margin-top:1rem">
<div class="card">
<h4>Out-of-band (monitoring / SPAN)</h4>
<p style="font-size:.85rem;margin-bottom:.4rem">Le WAF reçoit une <strong>copie</strong> du trafic (port mirror/SPAN, TAP). Il <strong>détecte et alerte</strong> mais ne peut pas bloquer en temps réel (au mieux il envoie un TCP RST). Idéal pour observer/tuner avant de passer inline.</p>
<p style="font-size:.83rem"><span class="badge badge-green">+</span> Zéro impact sur la prod <span class="badge badge-red">−</span> Pas de blocage actif fiable</p>
</div>
<div class="card">
<h4>WAF cloud / CDN (SaaS)</h4>
<p style="font-size:.85rem;margin-bottom:.4rem">Le trafic est routé (par DNS) vers le réseau du fournisseur qui filtre <strong>en périphérie</strong> avant de relayer vers l'origine. Combine WAF, CDN, anti-DDoS et anti-bot.</p>
<p style="font-size:.83rem;margin-bottom:.3rem"><strong>Exemples :</strong> Cloudflare, AWS WAF (+ CloudFront/ALB/API GW), Akamai, Azure Front Door, Imperva Cloud.</p>
<p style="font-size:.83rem"><span class="badge badge-green">+</span> Aucun matériel, scalabilité, DDoS L3-L7 <span class="badge badge-red">−</span> Le provider déchiffre votre trafic, dépendance externe</p>
</div>
</div>
<div class="grid g2" style="margin-top:1rem">
<div class="card">
<h4>WAF embarqué (module serveur)</h4>
<p style="font-size:.85rem;margin-bottom:.4rem">Le WAF est un <strong>module</strong> du serveur web lui-même : ModSecurity (Apache/Nginx/IIS) ou son successeur <strong>Coraza</strong>. Pas de saut réseau supplémentaire, accès direct au contexte de la requête.</p>
<p style="font-size:.83rem"><span class="badge badge-green">+</span> Gratuit, intégré, contexte complet <span class="badge badge-red">−</span> Consomme les ressources du serveur, gestion par hôte</p>
</div>
<div class="card">
<h4>RASP (Runtime App Self-Protection)</h4>
<p style="font-size:.85rem;margin-bottom:.4rem">Pas un WAF : un agent <strong>dans l'application</strong> (JVM, .NET, runtime) qui instrumente l'exécution. Il voit le contexte réel (requête SQL exécutée, fichier ouvert), donc <strong>très peu de faux positifs</strong>.</p>
<p style="font-size:.83rem"><span class="badge badge-green">+</span> Contexte d'exécution, immunisé à l'évasion d'encodage <span class="badge badge-red">−</span> Spécifique au langage, surcoût runtime</p>
</div>
</div>
<div class="card" style="margin-top:1rem">
<h4>Comparatif des modes</h4>
<table>
<tr><th>Mode</th><th>Position</th><th>Blocage</th><th>TLS</th><th>Impact prod</th></tr>
<tr><td><strong>Reverse proxy inline</strong></td><td>Sur le chemin</td><td>Oui</td><td>Termine</td><td>Latence + SPOF</td></tr>
<tr><td><strong>Bridge/transparent</strong></td><td>L2 sur le chemin</td><td>Oui</td><td>Limité</td><td>Faible</td></tr>
<tr><td><strong>Out-of-band</strong></td><td>Copie (SPAN)</td><td>Non (RST)</td><td>Passif</td><td>Nul</td></tr>
<tr><td><strong>Cloud/CDN</strong></td><td>Edge fournisseur</td><td>Oui</td><td>Termine (provider)</td><td>Dépend du DNS</td></tr>
<tr><td><strong>Embarqué</strong></td><td>Dans le serveur web</td><td>Oui</td><td>Déjà déchiffré</td><td>CPU serveur</td></tr>
<tr><td><strong>RASP</strong></td><td>Dans l'app</td><td>Oui</td><td>N/A (en clair)</td><td>Runtime</td></tr>
</table>
</div>
</section>
<section id="rules">
<h2>Règles & OWASP CRS</h2>
<div class="grid g2">
<div class="card">
<h4>ModSecurity & Coraza</h4>
<p style="font-size:.85rem;margin-bottom:.4rem"><strong>ModSecurity</strong> est le moteur WAF open source historique (module Apache/Nginx/IIS), avec son langage <strong>SecRules</strong>. Le projet C est désormais en fin de vie ; <strong>Coraza</strong> (Go, OWASP) en est le successeur compatible SecLang, embarquable dans Caddy, Envoy, Nginx via coraza-spoa.</p>
<div class="info-box orange" style="font-size:.82rem">
ModSecurity n'est qu'un <strong>moteur</strong> : sans jeu de règles, il ne bloque rien. On lui charge le <strong>OWASP CRS</strong>.
</div>
</div>
<div class="card">
<h4>OWASP Core Rule Set (CRS)</h4>
<p style="font-size:.85rem;margin-bottom:.4rem">Jeu de règles <strong>génériques</strong> et gratuit, maintenu par l'OWASP, couvrant SQLi, XSS, LFI/RFI, RCE, scanners, anomalies de protocole… Compatible ModSecurity et Coraza. C'est la base de référence d'un WAF open source.</p>
<ul style="font-size:.85rem;padding-left:1.2rem;line-height:1.8">
<li>Détection <strong>générique</strong> (pas par CVE)</li>
<li>Mécanisme d'<strong>anomaly scoring</strong></li>
<li><strong>Paranoia Levels</strong> ajustables</li>
<li>Exclusions par application (WordPress, Drupal…)</li>
</ul>
</div>
</div>
<div class="grid g2" style="margin-top:1rem">
<div class="card">
<h4>Paranoia Levels (PL)</h4>
<table>
<tr><th>PL</th><th>Agressivité</th><th>Faux positifs</th><th>Usage</th></tr>
<tr><td><strong>PL1</strong></td><td>Base</td><td>Très faibles</td><td>Défaut, prod générale</td></tr>
<tr><td><strong>PL2</strong></td><td>Renforcé</td><td>Modérés</td><td>App sensibles, après tuning</td></tr>
<tr><td><strong>PL3</strong></td><td>Élevé</td><td>Élevés</td><td>Données critiques</td></tr>
<tr><td><strong>PL4</strong></td><td>Maximal</td><td>Très élevés</td><td>Environnement verrouillé</td></tr>
</table>
<p style="font-size:.82rem;margin-top:.3rem">Monter en PL augmente la couverture <strong>et</strong> les faux positifs. On augmente progressivement, après avoir traité les exclusions.</p>
</div>
<div class="card">
<h4>Phases de traitement (ModSecurity)</h4>
<table>
<tr><th>Phase</th><th>Moment</th></tr>
<tr><td><strong>1</strong></td><td>En-têtes de la requête reçus</td></tr>
<tr><td><strong>2</strong></td><td>Corps de la requête (body) reçu</td></tr>
<tr><td><strong>3</strong></td><td>En-têtes de la réponse</td></tr>
<tr><td><strong>4</strong></td><td>Corps de la réponse (fuite de données)</td></tr>
<tr><td><strong>5</strong></td><td>Logging</td></tr>
</table>
<p style="font-size:.82rem;margin-top:.3rem">La majorité des règles inbound agissent en <strong>phase 2</strong> (après lecture du body).</p>
</div>
</div>
<div class="card" style="margin-top:1rem">
<h4>Anatomie d'une règle SecRule</h4>
<div class="codeblk"><span class="c-comment"># SecRule VARIABLES "OPERATOR" "ACTIONS"</span>
SecRule ARGS|REQUEST_HEADERS <span class="c-str">"@rx (?i:union\s+select)"</span> \
<span class="c-str">"id:1001,\
phase:2,\
block,\
t:none,t:urlDecodeUni,t:lowercase,\
msg:'SQL Injection: UNION SELECT',\
logdata:'Match: %{MATCHED_VAR}',\
severity:'CRITICAL',\
tag:'attack-sqli'"</span>
<span class="c-comment"># Mode anomaly scoring (CRS) : on incrémente un score</span>
SecRule ARGS <span class="c-str">"@detectSQLi"</span> \
<span class="c-str">"id:942100,phase:2,block,\
setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"</span></div>
<p style="font-size:.82rem;margin-top:.3rem"><strong>Variables</strong> (où chercher) · <strong>Opérateur</strong> (<code>@rx</code>, <code>@detectSQLi</code>, <code>@detectXSS</code>, <code>@pmFromFile</code>…) · <strong>Transformations</strong> <code>t:</code> (décodage, normalisation avant comparaison) · <strong>Actions</strong> (id, phase, block/deny/pass, setvar, msg, tag).</p>
</div>
<div class="grid g2" style="margin-top:1rem">
<div class="card">
<h4>Règle custom & rate limiting</h4>
<div class="codeblk"><span class="c-comment"># Bloquer une méthode HTTP non désirée</span>
SecRule REQUEST_METHOD <span class="c-str">"@streq TRACE"</span> \
<span class="c-str">"id:2001,phase:1,deny,status:<span class="c-val">405</span>,\
msg:'Methode TRACE interdite'"</span>
<span class="c-comment"># Limiter /login : 5 tentatives / 60 s par IP</span>
SecAction <span class="c-str">"id:2010,phase:1,nolog,pass,\
initcol:ip=%{REMOTE_ADDR},\
setvar:ip.attempts=+1,expirevar:ip.attempts=<span class="c-val">60</span>"</span>
SecRule IP:ATTEMPTS <span class="c-str">"@gt 5"</span> \
<span class="c-str">"id:2011,phase:1,deny,status:<span class="c-val">429</span>,\
msg:'Rate limit /login depasse'"</span></div>
</div>
<div class="card">
<h4>Exceptions & faux positifs</h4>
<p style="font-size:.85rem;margin-bottom:.4rem">On <strong>désactive</strong> une règle légitimement déclenchée plutôt que baisser tout le PL.</p>
<div class="codeblk"><span class="c-comment"># Désactiver une règle pour une URL precise</span>
SecRule REQUEST_URI <span class="c-str">"@beginsWith /api/import"</span> \
<span class="c-str">"id:3001,phase:1,pass,nolog,\
ctl:ruleRemoveById=<span class="c-val">942100</span>"</span>
<span class="c-comment"># Retirer un champ d'une regle (param riche en HTML)</span>
SecRuleUpdateTargetById <span class="c-val">941100</span> \
<span class="c-str">"!ARGS:editor_content"</span></div>
<div class="info-box red" style="margin-top:.4rem;font-size:.82rem">
Toujours cibler l'exception (par règle, URL ou paramètre) : <strong>ne jamais</strong> désactiver le moteur globalement.
</div>
</div>
</div>
</section>
<section id="protect">
<h2>Protections concrètes</h2>
<div class="card">
<h4>Mapping OWASP Top 10 → comment le WAF intervient</h4>
<table>
<tr><th>Attaque</th><th>Mécanisme</th><th>Détection WAF</th></tr>
<tr><td><strong>Injection SQL</strong></td><td><code>' OR 1=1 --</code>, UNION SELECT</td><td><code>@detectSQLi</code>, libinjection, signatures CRS 942xxx</td></tr>
<tr><td><strong>XSS</strong></td><td><code><script></code>, handlers <code>onerror=</code></td><td><code>@detectXSS</code>, CRS 941xxx</td></tr>
<tr><td><strong>Path traversal / LFI</strong></td><td><code>../../etc/passwd</code></td><td>Décodage + regex chemins, CRS 930xxx</td></tr>
<tr><td><strong>RCE / Command injection</strong></td><td><code>; cat /etc/passwd</code>, backticks</td><td>Signatures de commandes shell, CRS 932xxx</td></tr>
<tr><td><strong>RFI</strong></td><td>Inclusion d'URL distante</td><td>Détection URL dans paramètres</td></tr>
<tr><td><strong>SSRF</strong></td><td>Forcer une requête serveur interne</td><td>Blocage IP internes/métadonnées (169.254.169.254)</td></tr>
<tr><td><strong>HTTP Request Smuggling</strong></td><td>Désync CL/TE</td><td>Normalisation stricte des en-têtes</td></tr>
</table>
</div>
<div class="grid g2" style="margin-top:1rem">
<div class="card">
<h4>Rate limiting & anti credential-stuffing</h4>
<ul style="font-size:.85rem;padding-left:1.2rem;line-height:1.8">
<li><strong>Rate limiting</strong> : plafonner les requêtes par IP / session / token sur un endpoint sensible (login, OTP, API)</li>
<li><strong>Credential stuffing</strong> : détecter les vagues de login avec des couples volés → challenge, blocage, leaked-credential check</li>
<li><strong>Anti brute-force</strong> : tempo progressif, verrouillage</li>
<li><strong>Account takeover (ATO)</strong> : scoring comportemental</li>
</ul>
</div>
<div class="card">
<h4>Protection anti-bot</h4>
<ul style="font-size:.85rem;padding-left:1.2rem;line-height:1.8">
<li>Empreinte TLS/JA3, fingerprint navigateur</li>
<li>Challenges <strong>JS</strong>, <strong>CAPTCHA</strong>, proof-of-work (Turnstile)</li>
<li>Réputation IP, ASN, listes de bots connus</li>
<li>Détection de l'<strong>automation</strong> (headless, vitesse, séquences)</li>
<li>Gestion des <em>bons</em> bots (Googlebot vérifié par rDNS)</li>
</ul>
</div>
</div>
<div class="grid g2" style="margin-top:1rem">
<div class="card">
<h4>DDoS L7 & virtual patching</h4>
<p style="font-size:.85rem;margin-bottom:.4rem"><strong>DDoS applicatif (L7)</strong> : flood de requêtes HTTP coûteuses (HTTP flood, Slowloris, recherche lourde). Le WAF mitige par rate limiting, challenge, caching, drop des requêtes lentes — distinct du DDoS volumétrique L3/L4 (anti-DDoS réseau).</p>
<p style="font-size:.85rem"><strong>Virtual patching</strong> : déployer une règle WAF bloquant l'exploitation d'une <strong>CVE</strong> précise (ex. Log4Shell, Spring4Shell) <em>avant</em> que l'application soit corrigée. Gain de temps critique pour l'équipe.</p>
</div>
<div class="card">
<h4>Géo-blocage & protection des API</h4>
<ul style="font-size:.85rem;padding-left:1.2rem;line-height:1.8">
<li><strong>Géo-blocage</strong> : filtrer par pays (GeoIP) — utile mais contournable par VPN/proxy</li>
<li><strong>Schema validation API</strong> : valider chaque requête contre l'<strong>OpenAPI/Swagger</strong> (méthode, route, types, champs requis)</li>
<li>Détection des <strong>API shadow/zombie</strong> non documentées</li>
<li>Contrôle du <strong>débit par clé API</strong> et par consommateur</li>
<li>Inspection <strong>JSON/GraphQL</strong> (profondeur, taille, batching abusif)</li>
</ul>
</div>
</div>
<div class="info-box blue" style="margin-top:1rem;font-size:.82rem">
<strong>Positive security pour API :</strong> avec une spec OpenAPI, le WAF passe en modèle positif — tout ce qui n'est pas explicitement décrit (route inconnue, type incorrect, champ en trop) est rejeté. C'est l'approche la plus robuste pour les API REST.
</div>
</section>
<section id="tuning">
<h2>Tuning & exploitation</h2>
<div class="grid g2">
<div class="card">
<h4>Détection vs Blocage</h4>
<table>
<tr><th>Mode</th><th>Comportement</th></tr>
<tr><td><strong>Detection (DetectionOnly)</strong></td><td>Logue les alertes sans bloquer — phase d'observation</td></tr>
<tr><td><strong>Blocking (On)</strong></td><td>Applique l'action (deny, drop, redirect)</td></tr>
<tr><td><strong>Learning</strong></td><td>Construit/affine un modèle positif à partir du trafic réel</td></tr>
</table>
<div class="info-box orange" style="margin-top:.4rem;font-size:.82rem">
<strong>Démarche type :</strong> déployer en <em>detection only</em> → analyser les alertes → créer les exclusions → basculer en <em>blocking</em> → monter le PL progressivement.
</div>
</div>
<div class="card">
<h4>Faux positifs / faux négatifs</h4>
<ul style="font-size:.85rem;padding-left:1.2rem;line-height:1.8">
<li><strong>Faux positif (FP)</strong> : requête légitime bloquée → frustration utilisateur, app cassée. On corrige par exclusion ciblée.</li>
<li><strong>Faux négatif (FN)</strong> : attaque non détectée → compromission. On corrige en montant le PL ou ajoutant des règles.</li>
<li>Arbitrage permanent : baisser les FP augmente le risque de FN et inversement.</li>
<li>Mesurer avant/après chaque changement avec des données de prod.</li>
</ul>
</div>
</div>
<div class="card" style="margin-top:1rem">
<h4>Logging & intégration SIEM</h4>
<div class="codeblk"><span class="c-comment"># ModSecurity : log d'audit JSON pour le SIEM</span>
SecAuditEngine RelevantOnly
SecAuditLogParts <span class="c-str">"ABIJDEFHZ"</span>
SecAuditLogFormat JSON
SecAuditLog /var/log/modsec_audit.json
<span class="c-comment"># Champs utiles cote SIEM (Splunk/ELK/Sentinel)</span>
<span class="c-comment"># - transaction.client_ip, request.uri</span>
<span class="c-comment"># - rule.id, rule.msg, rule.severity</span>
<span class="c-comment"># - tx.anomaly_score (score cumule)</span></div>
<p style="font-size:.82rem;margin-top:.3rem">Corréler les alertes WAF avec le SIEM permet de distinguer le scan isolé d'une campagne ciblée, et d'alimenter le SOC.</p>
</div>
<div class="card" style="margin-top:1rem">
<h4>Contournement de WAF — techniques d'évasion</h4>
<p style="font-size:.85rem;margin-bottom:.4rem">Un attaquant tente de faire passer un payload malveillant <em>sans</em> matcher de signature. Le WAF se défend par des <strong>transformations de normalisation</strong> (<code>t:</code>) appliquées avant comparaison.</p>
<div class="codeblk"><span class="c-comment"># Exemples de payloads d'evasion (a NORMALISER)</span>
<span class="c-comment"># Encodage URL / double encodage</span>
?id=1%2527%2520OR%25201%253D1 <span class="c-comment"># %25 = double encode</span>
<span class="c-comment"># Variation de casse + commentaires inline SQL</span>
UnIoN/**/SeLeCt 1,2,3
<span class="c-comment"># Encodage Unicode / overlong UTF-8 du <</span>
%u003Cscript%u003E <span class="c-comment"># <script></span>
<span class="c-comment"># Eclatement par parametres / pollution (HPP)</span>
?q=union&q=select <span class="c-comment"># HTTP Parameter Pollution</span>
<span class="c-comment"># Defense : t:urlDecodeUni, t:removeComments,</span>
<span class="c-comment"># t:lowercase, t:compressWhitespace</span></div>
<div class="info-box red" style="margin-top:.4rem;font-size:.82rem">
Le décodage récursif et la canonicalisation stricte sont la clé : une requête doit être <strong>normalisée</strong> exactement comme le backend l'interprétera, sinon l'évasion réussit.
</div>
</div>
<div class="card" style="margin-top:1rem">
<h4>Acteurs & solutions du marché</h4>
<table>
<tr><th>Solution</th><th>Type</th><th>Particularité</th></tr>
<tr><td><strong>Cloudflare</strong></td><td>Cloud/CDN</td><td>Edge mondial, anti-DDoS, Turnstile, ML</td></tr>
<tr><td><strong>AWS WAF</strong></td><td>Cloud</td><td>Intégré CloudFront/ALB/API GW, Managed Rules</td></tr>
<tr><td><strong>F5 BIG-IP ASM / Advanced WAF</strong></td><td>Appliance/virtuel</td><td>Référence entreprise, modèle positif fort</td></tr>
<tr><td><strong>Imperva</strong></td><td>Cloud/on-prem</td><td>WAF + DAM, threat intelligence</td></tr>
<tr><td><strong>Akamai (App & API Protector)</strong></td><td>Cloud/CDN</td><td>Edge massif, protection API</td></tr>
<tr><td><strong>Fortinet FortiWeb</strong></td><td>Appliance/virtuel</td><td>ML, intégration Fortinet</td></tr>
<tr><td><strong>ModSecurity</strong></td><td>Open source (module)</td><td>Moteur SecRules + OWASP CRS</td></tr>
<tr><td><strong>Coraza</strong></td><td>Open source (Go)</td><td>Successeur ModSecurity, Caddy/Envoy</td></tr>
</table>
</div>
<div class="card" style="margin-top:1rem">
<h4>Bonnes pratiques</h4>
<ul style="font-size:.85rem;padding-left:1.2rem;line-height:1.85">
<li>Démarrer en <strong>detection only</strong>, tuner, puis bloquer</li>
<li>Traiter les faux positifs par <strong>exclusions ciblées</strong>, jamais en désactivant le moteur</li>
<li>Monter les <strong>Paranoia Levels</strong> progressivement</li>
<li>Garder le WAF et le <strong>CRS à jour</strong>, activer le virtual patching pour les CVE critiques</li>
<li>Exporter les logs vers le <strong>SIEM/SOC</strong> et alerter sur les pics de score</li>
<li>Tester régulièrement avec des outils (nuclei, WAF bypass) et des pentests</li>
<li>Ne jamais s'appuyer sur le WAF seul : <strong>défense en profondeur</strong> + code sécurisé</li>
</ul>
</div>
</section>
<section id="quiz">
<h2>Quiz — WAF</h2>
<div id="quiz-container"></div>
<div id="quiz-score"></div>
</section>
<script>
function showTab(id){document.querySelectorAll('section').forEach(s=>s.classList.remove('active'));document.querySelectorAll('.tab-btn').forEach(b=>b.classList.remove('active'));document.getElementById(id).classList.add('active');event.target.classList.add('active')}
const quizData=[
{q:"À quelle couche du modèle OSI un WAF opère-t-il principalement ?",opts:["Couche 3 (réseau / IP)","Couche 4 (transport / TCP)","Couche 7 (application / HTTP)","Couche 2 (liaison)"],a:2},
{q:"Quelle différence majeure entre un WAF et un firewall réseau classique ?",opts:["Le WAF filtre par IP et port uniquement","Le WAF inspecte le contenu applicatif HTTP, le firewall réseau raisonne IP/ports","Aucune, ce sont des synonymes","Le firewall réseau bloque les injections SQL"],a:1},
{q:"Que vise principalement un WAF dans l'OWASP Top 10 ?",opts:["A04 Insecure Design","A02 Cryptographic Failures","A03 Injection (SQLi, XSS…)","A08 Data Integrity"],a:2},
{q:"Quel modèle de détection autorise uniquement ce qui est explicitement connu comme bon ?",opts:["Modèle négatif (blacklist)","Modèle positif (whitelist)","Modèle par signatures","Détection par anomalie"],a:1},
{q:"Quel est le principal inconvénient du modèle négatif (signatures) ?",opts:["Trop de faux positifs","Inefficace contre les 0-day et variantes inédites","Trop lent à déployer","Incompatible avec HTTPS"],a:1},
{q:"Comment fonctionne l'anomaly scoring du OWASP CRS ?",opts:["Il bloque à la première signature","Chaque règle ajoute des points ; blocage au-delà d'un seuil","Il chiffre les requêtes suspectes","Il redirige tout vers un honeypot"],a:1},
{q:"Quel mode de déploiement WAF ne peut PAS bloquer activement le trafic ?",opts:["Reverse proxy inline","WAF cloud/CDN","Out-of-band (SPAN/monitoring)","WAF embarqué"],a:2},
{q:"Qu'est-ce que le RASP par rapport à un WAF ?",opts:["Un WAF cloud","Un agent dans l'application qui voit le contexte d'exécution","Un format de règles","Un protocole de chiffrement"],a:1},
{q:"Que charge-t-on dans le moteur ModSecurity pour qu'il bloque réellement des attaques ?",opts:["Un certificat TLS","Le OWASP Core Rule Set (CRS)","Un fichier OpenAPI","Une base GeoIP"],a:1},
{q:"À quoi servent les Paranoia Levels (PL) du CRS ?",opts:["Régler le niveau d'agressivité (couverture vs faux positifs)","Définir le port d'écoute","Choisir l'algorithme de chiffrement","Limiter la bande passante"],a:0},
{q:"Qu'est-ce que le virtual patching ?",opts:["Mettre à jour le firmware du WAF","Une règle WAF bloquant l'exploitation d'une CVE avant correctif applicatif","Sauvegarder la configuration","Migrer vers le cloud"],a:1},
{q:"Quelle opération est essentielle pour résister aux techniques d'évasion d'encodage ?",opts:["Augmenter la RAM","La normalisation / canonicalisation (transformations t:) avant comparaison","Bloquer tout le pays","Désactiver le HTTPS"],a:1},
{q:"Quelle est la démarche recommandée pour mettre un WAF en production ?",opts:["Bloquer immédiatement au PL4","Detection only → tuner les faux positifs → blocking → monter le PL","Désactiver le scoring","Tout autoriser puis observer"],a:1},
{q:"Quel projet open source en Go est le successeur de ModSecurity ?",opts:["Coraza","Nginx","Envoy","Suricata"],a:0}
];
let answers=new Array(quizData.length).fill(null);
function buildQuiz(){const c=document.getElementById('quiz-container');c.innerHTML=quizData.map((q,i)=>`<div class="quiz-q"><p>${i+1}. ${q.q}</p>${q.opts.map((o,j)=>`<div class="quiz-opt" onclick="answer(this,${i},${j})">${o}</div>`).join('')}</div>`).join('')}
function answer(el,qi,oi){const parent=el.parentElement;if(parent.querySelector('.correct,.wrong'))return;answers[qi]=oi;const correct=quizData[qi].a;parent.querySelectorAll('.quiz-opt').forEach((o,j)=>{if(j===correct)o.classList.add('correct');else if(j===oi&&oi!==correct)o.classList.add('wrong')});if(answers.every(a=>a!==null)){const score=answers.filter((a,i)=>a===quizData[i].a).length;const sc=document.getElementById('quiz-score');sc.style.display='block';sc.innerHTML=`Score : ${score}/${quizData.length} ${score>=11?'Excellent !':score>=8?'Bien !':'À revoir'}`}}
buildQuiz();
</script>
</body>
</html>