Mod security

De wiki.nexiat.fr
Aller à la navigation Aller à la recherche
Fiche express
Type WAF (pare-feu applicatif web), moteur de règles
Génération actuelle v3 (libModSecurity + connecteurs)
Jeu de règles de référence OWASP Core Rule Set (CRS)
Licence Apache License 2.0
Voir aussi Nginx · Certbot · Securiser nginx

ModSecurity (souvent désigné par son nom de module historique mod_security / mod_security2) est un moteur de pare-feu applicatif web (Web Application Firewall, WAF) open source, multiplateforme, qui inspecte le trafic HTTP(S) en temps réel afin de détecter et de bloquer les attaques applicatives (injection SQL, XSS, traversée de chemin, etc.). Le moteur est généralement couplé à l'OWASP Core Rule Set (CRS), le jeu de règles de référence, qui fournit la couverture de détection effective.

Le projet, créé par Ivan Ristić en 2002, a été maintenu par Breach Security puis Trustwave SpiderLabs, avant d'être transféré à la Fondation OWASP en février 2024. Il est désormais publié sous le nom OWASP ModSecurity (dépôt github.com/owasp-modsecurity) et licencié sous Apache License 2.0.

Vue d'ensemble

ModSecurity ne « connaît » aucune attaque par lui-même : c'est un moteur d'exécution de règles. On lui fournit des règles écrites dans le langage SecRules (les siennes, ou plus généralement le CRS), il les applique à chaque transaction HTTP et déclenche des actions (journaliser, refuser, rediriger…) selon les correspondances.

Trois fonctions principales :

  • Surveillance et contrôle d'accès en temps réel sur le trafic HTTP entrant et sortant ;
  • Journalisation complète du trafic (audit logging) à des fins d'analyse et de forensic ;
  • Durcissement applicatif (virtual patching) : corriger une vulnérabilité par une règle WAF sans toucher au code de l'application.

Architecture : v2 (module Apache) vs v3 (libModSecurity)

C'est le point le plus important à comprendre, car les deux générations coexistent et n'ont pas la même architecture.

ModSecurity v2 (mod_security2) ModSecurity v3 (libModSecurity)
Nature Module Apache natif, embarqué dans httpd Bibliothèque C++ autonome (libmodsecurity), indépendante du serveur
Serveur web Apache uniquement (couplage fort) Apache, Nginx, IIS via des connecteurs séparés
Couplage serveur Le module est le pont avec Apache Le serveur dialogue avec la lib via un connecteur (ex. ModSecurity-nginx, ModSecurity-apache)
Statut Maintenu (branche 2.9.x, ex. 2.9.12) Génération recommandée (branche 3.0.x, ex. 3.0.14)
Réécriture Code historique Apache-centré Réécriture complète, multiplateforme

Dans le modèle v3, le moteur de règles est décorrélé du serveur web. Chaque connecteur (ModSecurity-nginx, etc.) a son propre cycle de vie et n'embarque que ce qui est nécessaire.

<mermaid> flowchart LR

   subgraph V2["ModSecurity v2 (Apache)"]
       A2[Client HTTP] --> B2[Apache httpd]
       B2 --> C2[mod_security2
moteur intégré] C2 --> D2[Application] end subgraph V3["ModSecurity v3 (libModSecurity)"] A3[Client HTTP] --> B3[Nginx / Apache / IIS] B3 --> C3[Connecteur
ex. ModSecurity-nginx] C3 --> E3[libmodsecurity
moteur de règles] E3 --> C3 C3 --> D3[Application] end

</mermaid>

Fonctionnement

Les cinq phases de traitement

ModSecurity découpe chaque transaction HTTP en cinq phases. Toute règle s'attache à une phase via l'action phase:. C'est ce qui détermine à quel moment du cycle de vie de la requête la règle est évaluée et quelles données sont alors disponibles.

Phase Nom Données disponibles
1 Request headers Méthode, URI, en-têtes de requête
2 Request body Corps de la requête (formulaires, JSON, XML, fichiers)
3 Response headers En-têtes de réponse générés par l'application
4 Response body Corps de la réponse (fuite de données, messages d'erreur…)
5 Logging Phase finale, non disruptive : journalisation uniquement

L'essentiel de la détection des attaques entrantes se fait en phases 1 et 2 ; la détection de fuites et le data leakage en phases 3 et 4.

<mermaid> flowchart TD

   R[Requête HTTP entrante] --> P1[Phase 1
Request Headers] P1 --> P2[Phase 2
Request Body] P2 --> APP[Application web] APP --> P3[Phase 3
Response Headers] P3 --> P4[Phase 4
Response Body] P4 --> P5[Phase 5
Logging] P5 --> RESP[Réponse au client] P1 -. blocage possible .-> BLOCK[Action disruptive
deny / redirect / drop] P2 -. blocage possible .-> BLOCK

</mermaid>

Modèles de sécurité

  • Modèle négatif (blacklist) : on laisse tout passer sauf ce qui ressemble à une attaque connue. C'est l'approche du CRS. Souple, mais sujet aux contournements et aux faux positifs.
  • Modèle positif (whitelist) : on n'accepte que ce qui est explicitement reconnu comme valide. Très robuste, mais coûteux à maintenir ; adapté aux applications stables et peu évolutives.

Le langage SecRules

Une règle suit la structure :

SecRule VARIABLES "OPERATEUR" "ACTIONS"

Exemple — refuser une requête contenant une balise <script> dans n'importe quel paramètre :

SecRule ARGS "@rx <script>" \
    "id:1000,\
    phase:2,\
    t:none,t:urlDecode,t:lowercase,\
    deny,status:403,\
    log,msg:'Tentative XSS détectée',\
    tag:'attack-xss',severity:'CRITICAL'"

Les quatre briques :

  • Variables / collections — ce que l'on inspecte : ARGS, REQUEST_HEADERS, REQUEST_URI, REQUEST_FILENAME, REQUEST_BODY, RESPONSE_BODY, REMOTE_ADDR, FILES, ainsi que les collections persistantes TX (transaction), IP, SESSION, GEO.
  • Opérateurs (préfixés @) — comment on compare : @rx (regex), @pm / @pmFromFile (recherche multi-motifs), @eq, @ge, @streq, @beginsWith, @contains, @ipMatch, @detectSQLi, @detectXSS, @validateByteRange.
  • Transformations (préfixées t:) — normalisation avant comparaison, pour contrer l'évasion : t:none, t:lowercase, t:urlDecode, t:htmlEntityDecode, t:compressWhitespace, t:normalizePath. Elles s'enchaînent.
  • Actions — quoi faire :
    • disruptives : deny, drop, redirect, pass, allow, block ;
    • de flux : chain (enchaîner des conditions en ET logique), skip, skipAfter ;
    • de métadonnée : id (obligatoire et unique), phase, msg, tag, severity, ver ;
    • de variable : setvar, capture ;
    • non disruptives : log / nolog, auditlog / noauditlog, ctl (modifier le moteur à la volée pour la transaction en cours).

OWASP Core Rule Set (CRS)

Le CRS est le jeu de règles génériques de référence pour ModSecurity. Il couvre le Top Ten OWASP (injections SQL, XSS, LFI/RFI, fixation de session…) et constitue, en pratique, ce qui rend un déploiement ModSecurity utile.

Versions à connaître :

  • CRS 4.x : branche actuelle (ex. 4.27.0), architecture à plugins. La 4.25.0 est la première version LTS de la branche 4.
  • CRS 3.3.x : version majeure précédente. Fin de support prévue T3 2026 — toute installation encore en 3.3 doit planifier sa migration.

Score d'anomalie (anomaly scoring)

Depuis le CRS 3, le mode par défaut n'est plus le blocage règle-par-règle mais le score d'anomalie collaboratif :

  1. Chaque règle qui correspond n'ajoute pas un blocage immédiat : elle incrémente un score dans TX selon sa sévérité (CRITICAL = 5, ERROR = 4, WARNING = 3, NOTICE = 2).
  2. À la fin de la phase, le score cumulé est comparé à un seuil (par défaut 5 en entrée, 4 en sortie).
  3. Si le seuil est dépassé, la transaction est bloquée.

L'intérêt : une requête qui déclenche plusieurs petites règles « suspectes » est bloquée, alors qu'une seule correspondance faible ne l'est pas — ce qui réduit fortement les faux positifs.

<mermaid> flowchart TD

   REQ[Requête] --> R1[Règle CRS A
+3] REQ --> R2[Règle CRS B
+5] REQ --> R3[Règle CRS C
+2] R1 --> SUM[Score cumulé TX] R2 --> SUM R3 --> SUM SUM --> T{Score >= seuil
par défaut 5 ?} T -->|Oui| DENY[Blocage] T -->|Non| PASS[Laisser passer]

</mermaid>

Niveaux de paranoïa (paranoia levels)

Le CRS gradue son agressivité de PL1 (par défaut, peu de faux positifs) à PL4 (détection maximale, beaucoup de faux positifs, réservé aux environnements très sensibles avec tuning poussé). En CRS 4, le réglage se fait via tx.blocking_paranoia_level et tx.detection_paranoia_level dans crs-setup.conf.

Installation

v2 — module Apache

# Debian/Ubuntu
apt install libapache2-mod-security2
a2enmod security2
# Le fichier de recommandations sert de base de configuration
cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
systemctl restart apache2

v3 — connecteur Nginx

Sur Nginx, ModSecurity v3 s'installe via libmodsecurity + le module ModSecurity-nginx (souvent fourni par le paquet libnginx-mod-http-modsecurity), puis on l'active dans le bloc serveur :

modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;

Kubernetes — ingress-nginx

Dans un cluster (RKE2, par exemple), l'ingress-nginx controller embarque ModSecurity v3 + CRS. On l'active par annotations ou via la ConfigMap du contrôleur :

# Annotations sur l'Ingress
nginx.ingress.kubernetes.io/enable-modsecurity: "true"
nginx.ingress.kubernetes.io/enable-owasp-core-rules: "true"
nginx.ingress.kubernetes.io/modsecurity-snippet: |
  SecRuleEngine On
  SecAuditEngine RelevantOnly

C'est l'approche idéale pour mutualiser un WAF en frontal de plusieurs services derrière un même ingress.

Configuration de base

Le cœur de la configuration tient en quelques directives, généralement dans modsecurity.conf :

# Activation : Off | On | DetectionOnly
SecRuleEngine DetectionOnly

# Inspection du corps de requête (indispensable pour la phase 2)
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072

# Inspection du corps de réponse (détection de fuites)
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml application/json

# Journal d'audit
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLog /var/log/modsec_audit.log
SecAuditLogParts ABIJDEFHKZ
SecAuditLogType Serial

# Action par défaut des règles
SecDefaultAction "phase:2,log,auditlog,pass"

Management et exploitation

C'est la partie qui occupe le plus de temps dans la durée. Un WAF se gère, il ne s'installe pas une fois pour toutes.

Cycle de mise en production : DetectionOnly d'abord

Ne jamais passer directement en SecRuleEngine On en production. Le déroulé recommandé :

  1. Déployer en SecRuleEngine DetectionOnly : les règles évaluent et journalisent, mais ne bloquent rien.
  2. Laisser tourner sur du trafic réel (jours/semaines) et collecter les correspondances.
  3. Analyser les déclenchements : distinguer vraies attaques et faux positifs (requêtes légitimes bloquées à tort).
  4. Écrire les exclusions nécessaires (voir ci-dessous).
  5. Basculer en SecRuleEngine On une fois le bruit maîtrisé.

<mermaid> flowchart LR

   A[DetectionOnly] --> B[Collecte
des logs] B --> C{Faux
positifs ?} C -->|Oui| D[Écrire
exclusions] D --> B C -->|Non / maîtrisés| E[SecRuleEngine On] E --> F[Supervision
continue] F --> C

</mermaid>

Tuning des faux positifs

Quatre leviers, du plus large au plus chirurgical :

  • Retirer une règle entière (statique, dans la conf) :
SecRuleRemoveById 920350
SecRuleRemoveByTag "attack-protocol"
  • Retirer une règle à l'exécution, conditionnée à un contexte (URL, paramètre…) :
SecRule REQUEST_URI "@beginsWith /api/upload" \
    "id:10000,phase:1,pass,nolog,ctl:ruleRemoveById=920350"
  • Exclure une cible précise d'une règle (le plus chirurgical, à privilégier) :
SecRuleUpdateTargetById 942100 "!ARGS:description"
  • Plugins d'exclusion CRS : pour les applications connues (WordPress, Drupal, Nextcloud…), le CRS 4 fournit des plugins d'exclusion prêts à l'emploi, à déposer dans le répertoire plugins/.

Règle d'or : préférer toujours l'exclusion la plus ciblée possible (une cible sur une URL donnée) plutôt que de désactiver une règle globalement.

Journal d'audit

Le journal d'audit est structuré en sections lettrées, sélectionnées par SecAuditLogParts :

Partie Contenu
A En-tête de l'entrée (obligatoire)
B En-têtes de requête
C Corps de requête
E Corps de réponse
F En-têtes de réponse
H Pied de page (règles déclenchées, infos moteur)
I Alternative compacte à C
J Informations sur les fichiers téléversés
K Liste de toutes les règles ayant correspondu
Z Borne finale (obligatoire)

SecAuditLogType peut être Serial (tout dans un fichier, simple mais verrouillage sous forte charge) ou Concurrent (un fichier par transaction, requis pour expédier vers un collecteur distant).

Supervision et intégration SIEM

En exploitation, les journaux ModSecurity ont vocation à être centralisés, pas relus à la main. Schéma type :

  1. Le moteur écrit l'audit log (idéalement en JSON, supporté en v3) ;
  2. Un agent de collecte (Fluent Bit, Promtail…) expédie les lignes ;
  3. Stockage et indexation (par ex. Loki) ;
  4. Visualisation et alerting (Grafana) ;
  5. Règles de détection (par ex. Sigma) pour lever des alertes sur les patterns d'attaque récurrents.

Cela permet de corréler les déclenchements WAF avec le reste de la télémétrie sécurité et de distinguer un balayage opportuniste d'une attaque ciblée.

Mises à jour

Deux composants à maintenir séparément :

  • Le moteur (libmodsecurity / module) : à tenir à jour pour les CVE — plusieurs ont été corrigées sur la branche 3.0.x en 2025 (DoS, gestion d'erreur, fuites mémoire). Surveiller les releases OWASP ModSecurity.
  • Le CRS : à mettre à jour régulièrement (nouvelles détections, correctifs de contournements). Attention : toute montée de version CRS peut introduire de nouveaux faux positifs → retester en DetectionOnly avant de rebasculer.

Pièges et bonnes pratiques

  • Coût en performance : un CRS complet augmente sensiblement la consommation CPU/mémoire (évaluation des règles + journalisation). Mesurer avant/après, surtout sur les corps volumineux.
  • Faux positifs : c'est le principal motif d'abandon. Les applications dynamiques (éditeurs riches, page builders, API REST) déclenchent facilement des règles. D'où le passage obligé par DetectionOnly.
  • Limites de taille de corps : un corps qui dépasse SecRequestBodyLimit n'est pas inspecté → angle mort exploitable. Accompagner d'une règle qui refuse au-delà de la limite.
  • Le WAF n'est pas une excuse : c'est une couche de défense en profondeur, pas un substitut au durcissement applicatif (mises à jour, authentification, validation côté serveur).
  • Versionner sa configuration : conf moteur, crs-setup.conf et fichiers d'exclusions doivent vivre en Git, déployés de façon reproductible.

Voir aussi

  • Nginx — serveur web pouvant être protégé par ModSecurity v3
  • Certbot — TLS, complémentaire au WAF
  • Securiser nginx — durcissement Nginx

Liens externes