WAF open source : protéger ses applications web avec OWASP CRS (Coraza et ModSecurity)
Déployer un WAF open source (Coraza, ModSecurity) avec OWASP CRS : paranoia levels, exclusions ciblées par endpoint et tuning anti faux positifs pour PME.
Une PME qui expose une application web se pose tôt ou tard la même question : faut-il mettre un WAF SaaS américain devant son site, ou existe-t-il une alternative crédible, auto-hébergée, dont on garde la maîtrise ? La réponse existe depuis longtemps dans l'écosystème open source, avec OWASP Core Rule Set (CRS) comme moteur de règles de référence. Le vrai sujet n'est pas de savoir si un WAF open source peut bloquer une injection SQL (il le peut très bien), mais de savoir comment le régler sans se noyer sous les faux positifs dès la première semaine de production.
Pourquoi un WAF devant vos applications
Un WAF (Web Application Firewall) intercepte les requêtes HTTP avant qu'elles n'atteignent le code applicatif. Trois familles d'attaques sont bloquées à ce niveau, avant même d'entrer dans la logique métier :
- Injections SQL : une requête contenant
UNION SELECT,OR 1=1ou des fonctions de temporisation (SLEEP(),BENCHMARK()) est reconnue par sa forme, indépendamment du framework applicatif derrière. - Cross-Site Scripting (XSS) : des balises
<script>, des gestionnaires d'événements (onerror=,onload=) ou des encodages suspects dans les paramètres sont détectés avant d'être réfléchis dans une page. - Path traversal : des séquences
../../../etc/passwdou des tentatives d'accès à des chemins sensibles sont filtrées au niveau de l'URL, sans dépendre de la validation (parfois absente) du code métier.
L'intérêt d'un filtrage en amont, c'est qu'il protège aussi le code que vous n'avez pas eu le temps de corriger : une dépendance vulnérable, un endpoint legacy, une librairie qui ne sera patchée que le mois prochain. Le WAF ne remplace pas la correction du code, il achète du temps pendant que la dette technique se résorbe.
Coraza ou ModSecurity : deux moteurs, un même langage de règles
Deux moteurs open source portent aujourd'hui OWASP CRS :
ModSecurity est le moteur historique, écrit en C, intégré comme module Apache puis NGINX. Il a fait ses preuves pendant quinze ans, mais son horizon est clair : le connecteur NGINX n'est plus maintenu de façon active et le projet vit désormais en mode maintenance, avec une fin de vie qui se rapproche. Le déployer aujourd'hui pour un nouveau projet revient à bâtir sur une fondation qui ne recevra plus d'évolutions majeures.
Coraza est l'alternative montante : un moteur écrit en Go, pensé cloud-native dès le départ, packagé comme bibliothèque, module NGINX ou proxy WASM. Son atout central est la compatibilité SecLang à 100 pourcent avec ModSecurity : les règles OWASP CRS v4 s'exécutent sans traduction ni réécriture. Migrer de ModSecurity vers Coraza ne veut pas dire réapprendre un langage de règles, cela veut dire changer de moteur d'exécution sous un jeu de règles inchangé.
# docker-compose.yml (extrait) : Coraza en sidecar devant une app
services:
waf:
image: caddy:2-alpine
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./crs:/etc/crs
ports:
- "443:443"
app:
image: monapp:latest
expose:
- "8080"Pour une PME qui construit aujourd'hui, Coraza est le choix par défaut : même couverture de règles CRS, moteur activement développé, empreinte plus légère à l'exécution.
Les paranoia levels CRS : le curseur entre sécurité et faux positifs
OWASP CRS expose quatre niveaux de paranoïa (PL1 à PL4). Plus le niveau monte, plus de règles s'activent, et plus le taux de faux positifs augmente en proportion :
- PL1 : couverture large des attaques évidentes, taux de faux positifs très bas. C'est le niveau de démarrage recommandé pour toute mise en production.
- PL2 : règles additionnelles contre des techniques d'évasion plus subtiles. Faux positifs plus fréquents sur des applications qui manipulent des données proches de patterns d'attaque (formulaires riches, éditeurs de texte).
- PL3 et PL4 : niveaux de durcissement maximal, réservés à des périmètres à très forte sensibilité, avec un budget de tuning conséquent en face.
CRS fonctionne en anomaly scoring : chaque règle qui matche ajoute des points à un score cumulé sur la requête, et le blocage n'intervient que si ce score dépasse un seuil configuré. Cette logique est essentielle à comprendre, car elle change la façon de traiter les faux positifs. On ne cherche pas à empêcher une règle de matcher, on cherche à empêcher que ce match compte pour une requête légitime précise.
# crs-setup.conf (extrait)
SecAction \
"id:900000,\
phase:1,\
pass,\
t:none,\
setvar:tx.paranoia_level=1,\
setvar:tx.inbound_anomaly_score_threshold=5,\
setvar:tx.outbound_anomaly_score_threshold=4"
Démarrer en PL1 avec les seuils par défaut, mesurer sur du trafic réel pendant deux à quatre semaines, puis monter progressivement si le contexte l'exige : c'est la trajectoire qui évite la tempête de faux positifs à J1.
Le piège central : exclure une règle sans désarmer tout le CRS
C'est l'erreur la plus fréquente, et la plus coûteuse en sécurité. Un formulaire de contact remonte un faux positif sur une règle XSS parce qu'un champ « commentaire » contient légitimement des caractères < ou >. Le réflexe naturel est de désactiver la règle en question globalement :
# A NE PAS FAIRE : désactive la règle pour TOUTES les requêtes, tous endpoints confondus
SecRuleRemoveById 941100
Cette approche ouvre un trou de sécurité sur l'ensemble du périmètre pour corriger un problème localisé à un seul endpoint et un seul paramètre. La bonne pratique consiste à cibler l'exclusion avec SecRuleUpdateTargetById, qui retire un paramètre précis de l'inspection d'une règle, sans toucher au reste du trafic :
# A FAIRE : la règle 941100 reste active partout, sauf sur ce paramètre précis
SecRuleUpdateTargetById 941100 "!ARGS:comment"
Autre variante utile, l'exclusion par chemin, quand le faux positif est propre à un endpoint entier plutôt qu'à un paramètre :
<LocationMatch "/api/v1/rich-text-editor">
SecRuleRemoveById 941100 941160
</LocationMatch>
La différence entre les deux approches est celle qui sépare un WAF réglé d'un WAF contourné. Chaque exclusion doit être documentée (quelle règle, quel endpoint, quel paramètre, pourquoi), versionnée dans le dépôt de configuration, et revue périodiquement : une exclusion oubliée trois ans plus tard sur un endpoint qui a changé de fonction est une porte dérobée qui ne dit pas son nom.
Déployer le WAF comme du code
Un WAF open source n'a de valeur que s'il est intégré à la chaîne de livraison comme n'importe quel composant applicatif. Concrètement :
- Positionnement : devant NGINX (module natif), devant Envoy (filtre WASM), ou en Ingress Kubernetes (Coraza s'intègre nativement comme Ingress Controller). Le choix dépend de l'infrastructure existante, pas l'inverse.
- WAF-as-code : le jeu de règles CRS, les seuils de paranoïa et les exclusions vivent dans un dépôt Git, avec revue de code sur chaque modification, exactement comme une politique de pare-feu réseau.
- Test avant mise en production : chaque changement de règle est rejoué sur un corpus de trafic légitime capturé en production (requêtes réelles, anonymisées) avant tout déploiement. C'est la seule façon de prouver qu'une modification ne casse rien pour les utilisateurs réels, plutôt que de le découvrir après coup dans les tickets de support.
# Exemple : test de non-régression avant déploiement
coraza-testsuite run --ruleset ./crs --corpus ./traffic-samples/legitimate.har \
--fail-on-blockUn WAF qui bloque en silence sans que personne ne rejoue les changements sur du trafic réel finit toujours par être désactivé en urgence un vendredi soir, ce qui annule tout le bénéfice initial.
En résumé
Un WAF open source basé sur Coraza (ou ModSecurity en transition) et OWASP CRS offre une protection réelle contre les injections SQL, le XSS et le path traversal, sans dépendance à un fournisseur SaaS. La clé n'est pas le moteur, elle est dans la méthode : démarrer en PL1 avec l'anomaly scoring, cibler les exclusions règle par règle et endpoint par endpoint plutôt que désactiver globalement, et traiter la configuration comme du code testé avant chaque mise en production.
C'est exactement ce travail de tuning que nous livrons prêt à l'emploi dans le pack de règles WAF durcies : des exclusions déjà validées sur des corpus de trafic légitime, pour réduire la charge de faux positifs sans rouvrir la porte que le CRS est censé fermer.
Articles liés
GPTBot, ClaudeBot et Bytespider aspirent votre contenu et votre bande passante. Comment les bloquer avec des règles WAF sans toucher à Googlebot ni casser votre SEO.
Microsoft a montré qu'un prompt suffit à lancer calc.exe via Semantic Kernel. CVE-2026-26030 transforme l'injection en RCE. Comment tester ses agents IA.
Une fuite mémoire NetScaler configuré en IdP SAML rejoue le scénario CitrixBleed : vol de jetons, contournement MFA, DragonForce. Voici le virtual patching WAF.
Détection credential stuffing e-commerce WAF : fingerprinting JA4, seuils par ASN et réponse graduée pour bloquer les bots sans casser les clients CGNAT.