ModSecurity ajoute une couche de filtrage applicatif devant vos sites web. Il ne remplace ni les mises à jour, ni une configuration Apache propre, ni un pare-feu réseau. En revanche, il peut bloquer ou journaliser des requêtes clairement suspectes avant qu’elles n’atteignent WordPress, PHP, un CMS ancien ou une application maison.
L’ancien tutoriel utilisait Debian Squeeze, des backports manuels et les règles Atomicorp/ASL. Cette méthode a fait son temps. Aujourd’hui, la base saine consiste à installer ModSecurity avec les paquets Debian/Ubuntu, puis à utiliser l’OWASP Core Rule Set.
ModSecurity, à quoi ça sert ?
ModSecurity est un WAF, pour Web Application Firewall. Il analyse les requêtes HTTP et peut détecter, journaliser ou bloquer des comportements suspects.
Il peut notamment aider contre :
- les injections SQL ;
- les attaques XSS ;
- les tentatives de local file inclusion ;
- les remote file inclusions ;
- les payloads malformés ;
- certaines attaques contre les formulaires ;
- les scans automatisés trop bruyants ;
- les requêtes qui ciblent des failles connues.
Le point important : ModSecurity a besoin de règles. Sans règles utiles, c’est surtout un moteur qui attend qu’on lui donne du travail. Et comme tout outil de sécurité, il peut aussi produire des faux positifs. Donc on l’installe, on observe, on ajuste, puis on bloque. Pas l’inverse.
ModSecurity 2 ou ModSecurity 3 ?
Le sujet peut vite devenir confus, donc simplifions.
- ModSecurity 2.9.x reste très utilisé avec Apache via le module
security2_module. - ModSecurity 3 repose sur
libmodsecurityet des connecteurs séparés pour Apache, Nginx ou d’autres serveurs. - Sur Debian/Ubuntu avec Apache, le chemin le plus simple passe généralement par
libapache2-mod-security2.
Ce tutoriel privilégie donc l’approche paquetée Debian/Ubuntu. Elle est moins sexy qu’une compilation à la main, mais elle se maintient mieux. Et sur un serveur de production, “moins sexy mais maintenable” gagne souvent par KO.
Installer ModSecurity et OWASP CRS sur Apache
Sur Debian ou Ubuntu, commencez par mettre les dépôts à jour :
sudo apt update
Installez ensuite ModSecurity pour Apache et le Core Rule Set :
sudo apt install libapache2-mod-security2 modsecurity-crs
Activez le module Apache si nécessaire :
sudo a2enmod security2
Vérifiez que le module est chargé :
sudo apachectl -M | grep security
Vous devriez obtenir une ligne proche de celle-ci :
security2_module (shared)
Avant de recharger Apache, testez toujours la configuration :
sudo apachectl configtest
Si tout va bien :
sudo systemctl reload apache2
Activer le moteur ModSecurity
Selon la distribution, le fichier recommandé peut déjà exister sous cette forme :
/etc/modsecurity/modsecurity.conf-recommended
S’il n’existe pas encore en version active, copiez-le :
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
Ouvrez ensuite le fichier :
sudo nano /etc/modsecurity/modsecurity.conf
Repérez la directive SecRuleEngine. Pour commencer prudemment, utilisez le mode détection :
SecRuleEngine DetectionOnly
Ce mode journalise les alertes sans bloquer les requêtes. C’est le meilleur point de départ sur un site existant, surtout avec WordPress, WooCommerce, un espace membre ou des formulaires complexes.
Après une phase d’observation et de réglage, vous pourrez passer en mode blocage :
SecRuleEngine On
Évitez de passer directement en blocage sur un site de production actif. Sinon, le WAF risque de confondre vos vrais visiteurs avec des gremlins. Et parfois, il aura tort.
Charger OWASP Core Rule Set
Le paquet modsecurity-crs installe les règles OWASP CRS dans un répertoire système. Selon Debian ou Ubuntu, l’inclusion peut déjà être préparée.
Contrôlez les fichiers disponibles :
dpkg -L modsecurity-crs | less
Vous trouverez généralement les règles sous :
/usr/share/modsecurity-crs/
Sur beaucoup d’installations, Apache charge CRS via un fichier du type :
/usr/share/modsecurity-crs/owasp-crs.load
Vérifiez aussi la configuration Apache liée à ModSecurity :
grep -R "modsecurity-crs\|owasp-crs\|security2" /etc/apache2 /etc/modsecurity 2>/dev/nullLangage du code : JavaScript (javascript)
Si rien n’inclut CRS, créez un fichier dédié :
sudo nano /etc/apache2/conf-available/modsecurity-crs.conf
Ajoutez :
<IfModule security2_module>
IncludeOptional /usr/share/modsecurity-crs/owasp-crs.load
</IfModule>Langage du code : HTML, XML (xml)
Activez ensuite cette configuration :
sudo a2enconf modsecurity-crs
sudo apachectl configtest
sudo systemctl reload apache2
Ne copiez pas les règles à la main dans /etc/apache2/modsecurity.d/ comme dans les vieux tutoriels. Vous perdriez les mises à jour propres du paquet et vous pourriez créer des doublons de règles.
Configurer CRS sans massacrer les fichiers du paquet
OWASP CRS utilise un fichier de configuration principal souvent nommé :
crs-setup.confLangage du code : CSS (css)
Selon le paquet, vous pouvez trouver un exemple avec :
sudo find /usr/share/modsecurity-crs /etc/modsecurity -name '*crs*setup*' -printLangage du code : PHP (php)
Si un fichier recommandé existe, copiez-le vers un emplacement local avant modification. Par exemple :
sudo cp /usr/share/modsecurity-crs/crs-setup.conf.example /etc/modsecurity/crs-setup.conf
Adaptez ensuite l’inclusion si votre distribution ne le fait pas déjà. Le principe reste simple : les fichiers fournis par les paquets restent intacts, vos réglages locaux vivent dans /etc/modsecurity/ ou /etc/apache2/conf-available/.
Cette séparation évite le grand classique : “j’ai mis à jour le paquet, et mes modifications ont disparu”. Le serveur n’a pas trahi. Il a juste suivi les règles du packaging.
Commencer avec un niveau de paranoia raisonnable
CRS peut fonctionner avec différents niveaux de paranoia. Plus le niveau augmente, plus les règles deviennent strictes. Et plus les faux positifs deviennent probables.
Pour un site WordPress classique, commencez en douceur :
setvar:'tx.paranoia_level=1'Langage du code : JavaScript (javascript)
Le niveau 1 suffit souvent à bloquer ou détecter beaucoup de bruit automatisé sans transformer votre site en bunker qui refuse ses propres habitants.
Ne passez pas au niveau 2 ou plus sans logs propres, exclusions ciblées et vraie phase de test. Sur WooCommerce, certains formulaires, endpoints AJAX ou appels REST peuvent déclencher des règles trop strictes.
Tester ModSecurity sans casser le site
Après installation, testez avec une requête volontairement suspecte. Depuis le serveur, vous pouvez lancer :
curl -I "http://localhost/?test=<script>alert(1)</script>"Langage du code : HTML, XML (xml)
En mode DetectionOnly, la requête ne sera pas forcément bloquée. C’est normal. L’objectif est d’abord de vérifier que ModSecurity journalise l’événement.
Surveillez les logs Apache :
sudo tail -f /var/log/apache2/error.logLangage du code : JavaScript (javascript)
Et les logs d’audit ModSecurity si activés :
sudo tail -f /var/log/apache2/modsec_audit.logLangage du code : JavaScript (javascript)
Le chemin exact peut varier selon la distribution et votre configuration. Retrouvez-le avec :
grep -R "SecAuditLog" /etc/modsecurity /etc/apache2 2>/dev/nullLangage du code : JavaScript (javascript)
Lire une alerte ModSecurity
Une alerte ModSecurity contient généralement plusieurs informations utiles :
- l’adresse IP du client ;
- l’URL demandée ;
- l’identifiant de règle ;
- le message de règle ;
- la phase de traitement ;
- la donnée qui a déclenché l’alerte ;
- l’action appliquée ;
- le score d’anomalie CRS.
Ce sont ces informations qui permettent d’ajuster proprement. Ne désactivez pas ModSecurity à la première alerte gênante. Identifiez la règle, l’URL, le paramètre concerné, puis créez une exclusion ciblée.
Passer de DetectionOnly à On
Avant de passer en blocage, testez les parcours importants du site :
- connexion WordPress ;
- édition d’un article ;
- upload d’un média ;
- soumission des formulaires ;
- recherche interne ;
- API REST WordPress ;
- admin-ajax.php ;
- commande WooCommerce ;
- paiement ;
- webhooks ;
- espace client ;
- imports CSV ;
- tâches cron HTTP.
Si les logs restent propres, passez à :
SecRuleEngine On
Puis rechargez Apache :
sudo apachectl configtest
sudo systemctl reload apache2
Gardez les logs sous surveillance après l’activation. Un WAF se règle avec du trafic réel, pas avec de l’optimisme.
Créer une exclusion ciblée
Le mauvais réflexe consiste à désactiver une règle globalement. Le bon réflexe consiste à limiter l’exclusion à une URL, un paramètre ou un contexte précis.
Créez un fichier local pour vos exclusions :
sudo nano /etc/modsecurity/wordpress-exclusions.conf
Exemple fictif : désactiver une règle précise uniquement pour un paramètre donné sur une URL donnée :
<LocationMatch "^/wp-admin/admin-ajax\.php$">
SecRuleRemoveById 941100
</LocationMatch>Langage du code : HTML, XML (xml)
Cet exemple n’est pas une recommandation universelle. Il illustre la logique : on retire une règle uniquement là où elle casse un flux légitime.
Ajoutez ensuite l’inclusion si nécessaire dans votre configuration Apache ou ModSecurity :
IncludeOptional /etc/modsecurity/wordpress-exclusions.conf
Puis testez :
sudo apachectl configtest
sudo systemctl reload apache2
La bonne exclusion est chirurgicale. La mauvaise exclusion ressemble à “désactiver le WAF pour tout WordPress”. Autant installer une porte blindée et laisser les clés sous le paillasson.
ModSecurity avec WordPress
WordPress fonctionne bien derrière ModSecurity, mais certains points doivent être testés avec soin :
/wp-admin/admin-ajax.php;/wp-json/;- l’éditeur de blocs ;
- les sauvegardes de brouillons ;
- les formulaires de contact ;
- les champs HTML ou JSON ;
- les imports ;
- les constructeurs de pages ;
- les plugins de sécurité ;
- les plugins multilingues ;
- WooCommerce et ses webhooks.
Sur un site WooCommerce, testez impérativement le tunnel de commande. Un faux positif sur le paiement coûte plus cher qu’un joli score de sécurité dans un terminal.
Si votre priorité est de protéger WordPress contre l’énumération d’utilisateurs, complétez ce WAF avec une règle dédiée côté serveur : Bloquer complètement l’énumération des utilisateurs WordPress avec Nginx ou Apache.
ModSecurity derrière Cloudflare ou un reverse proxy
Si Apache se trouve derrière Cloudflare, HAProxy, Nginx ou un autre reverse proxy, corrigez d’abord l’adresse IP réelle du visiteur. Sinon, ModSecurity verra surtout l’IP du proxy.
Avec Apache, cela passe généralement par mod_remoteip. Exemple :
sudo a2enmod remoteip
Puis une configuration adaptée à votre proxy. Pour Cloudflare, les plages IP doivent rester à jour. Ne mettez pas une vieille liste copiée depuis un forum en 2017 et oubliée dans un coin.
Ensuite seulement, analysez les logs ModSecurity. Une alerte sans vraie IP client est moins utile, surtout si vous voulez corréler avec fail2ban, Apache, WordPress ou un CDN.
Coupler ModSecurity avec fail2ban
ModSecurity bloque ou journalise des requêtes applicatives. fail2ban peut ensuite bannir temporairement les IP qui déclenchent trop d’alertes. Le duo peut être efficace, à condition de ne pas bannir les IP du reverse proxy.
Avant toute intégration fail2ban, vérifiez donc :
- que les logs contiennent la vraie IP client ;
- que les faux positifs sont maîtrisés ;
- que les règles ne bannissent pas Googlebot, Stripe, PayPal ou votre CDN ;
- que les webhooks légitimes ne déclenchent pas d’alerte en boucle.
Pour une approche serveur plus large, l’article Comment sécuriser efficacement votre serveur SSH avec SSH-Audit complète bien ce travail côté accès distant.
Performance : attention au coût des règles
Un WAF inspecte des requêtes. Il consomme donc du CPU et de la mémoire. L’impact dépend du trafic, du nombre de règles, du niveau de paranoia, de la taille des requêtes et des pages dynamiques.
Sur un petit site vitrine, l’impact peut rester discret. Sur un WooCommerce très actif, un back-office lourd ou une API très sollicitée, surveillez les temps de réponse après activation.
Commandes utiles :
sudo apachectl -M | grep security
sudo journalctl -u apache2 --since "1 hour ago"
sudo tail -f /var/log/apache2/error.log
sudo tail -f /var/log/apache2/modsec_audit.log
top
htopLangage du code : JavaScript (javascript)
Si vous auditez un site WordPress, vous pouvez aussi compléter avec Auditer les problèmes de performance WordPress avec wp profile.
Mettre à jour les règles CRS
Si vous utilisez les paquets Debian/Ubuntu, les règles CRS se mettent à jour avec le système :
sudo apt update
sudo apt upgrade
Contrôlez les versions installées :
dpkg-query -W libapache2-mod-security2 modsecurity-crs
Évitez de mélanger paquets système, règles téléchargées à la main et copies locales non suivies. C’est le meilleur moyen de créer des doublons, des erreurs de syntaxe et des configurations impossibles à maintenir.
Désactiver ModSecurity pour un vhost précis
Il peut arriver qu’un site précis ne supporte pas encore ModSecurity. Dans ce cas, ne désactivez pas tout le module globalement si les autres sites en bénéficient.
Dans le vhost concerné, vous pouvez désactiver le moteur :
<VirtualHost *:443>
ServerName exemple.test
<IfModule security2_module>
SecRuleEngine Off
</IfModule>
</VirtualHost>Langage du code : HTML, XML (xml)
Ce n’est pas idéal, mais c’est parfois utile pendant une migration. Documentez ce choix et revenez ensuite à une configuration plus fine.
Dépannage courant
Apache ne redémarre plus après activation
Lancez d’abord :
sudo apachectl configtest
Puis consultez les logs :
sudo journalctl -u apache2 --since "10 minutes ago"
sudo tail -n 100 /var/log/apache2/error.logLangage du code : JavaScript (javascript)
Les causes fréquentes : double inclusion des règles CRS, fichier local mal placé, directive non supportée, faute de syntaxe dans une exclusion ou règle copiée depuis une ancienne version.
Une page WordPress renvoie 403
Cherchez l’identifiant de règle dans les logs ModSecurity. Ensuite, créez une exclusion ciblée pour l’URL ou le paramètre fautif. Ne désactivez pas tout CRS pour une seule règle un peu nerveuse.
Le checkout WooCommerce casse
Repassez temporairement en DetectionOnly, reproduisez la commande, puis analysez les logs. Vérifiez aussi les webhooks des moyens de paiement. Stripe, PayPal et les transporteurs n’aiment pas les WAF réglés au marteau.
Les logs sont énormes
Réduisez le bruit avec une configuration d’audit raisonnable, corrigez les faux positifs récurrents et ajoutez une rotation de logs correcte. Un WAF qui remplit le disque devient lui-même un problème de production.
Checklist d’installation propre
- Installer
libapache2-mod-security2etmodsecurity-crs. - Activer le module Apache
security2. - Vérifier avec
apachectl -M. - Activer
modsecurity.conf. - Commencer avec
SecRuleEngine DetectionOnly. - Charger OWASP Core Rule Set sans copier les règles à la main.
- Tester les parcours critiques du site.
- Lire les logs ModSecurity.
- Créer des exclusions ciblées.
- Passer à
SecRuleEngine Onaprès validation. - Surveiller les erreurs 403, les webhooks et les performances.
- Mettre à jour ModSecurity et CRS avec les paquets système.
Articles liés sur SkyMinds
Pour compléter la sécurisation d’un serveur Apache ou WordPress, ces guides peuvent vous aider :
- Bloquer complètement l’énumération des utilisateurs WordPress avec Nginx ou Apache
- Comment sécuriser efficacement votre serveur SSH avec SSH-Audit
- Serveur : migration vers Ubuntu 26.04 LTS depuis Ubuntu 24.04 LTS
- Mise à jour du serveur vers Ubuntu 24.04 LTS
- Auditer les problèmes de performance WordPress avec wp profile
- Installer PHP 8.5 sous Ubuntu Server
FAQ
ModSecurity remplace-t-il un pare-feu comme nftables ou iptables ?
Non. ModSecurity travaille au niveau HTTP et applicatif. Un pare-feu réseau filtre les ports, les IP et les flux. Les deux outils sont complémentaires.
Faut-il activer ModSecurity directement en mode blocage ?
Non, pas sur un site existant. Commencez avec SecRuleEngine DetectionOnly, testez les vrais parcours utilisateurs, corrigez les faux positifs, puis passez en mode blocage.
OWASP CRS suffit-il pour protéger WordPress ?
OWASP CRS ajoute une bonne couche de défense générique, mais il ne remplace pas les mises à jour WordPress, les plugins maintenus, les permissions correctes, les sauvegardes et une configuration serveur propre.
Pourquoi ModSecurity bloque-t-il une requête légitime ?
Une règle peut confondre un contenu légitime avec un payload suspect. Lisez les logs, identifiez l’ID de règle et créez une exclusion ciblée pour l’URL ou le paramètre concerné.
Puis-je utiliser ModSecurity avec Cloudflare ?
Oui. Configurez d’abord Apache pour récupérer la vraie IP client via mod_remoteip. Sinon, vos logs ModSecurity afficheront surtout les IP Cloudflare, ce qui complique les analyses et les bannissements.
ModSecurity ralentit-il Apache ?
Oui, il ajoute un coût de traitement. L’impact dépend du trafic, du nombre de règles, du niveau de paranoia et des requêtes inspectées. Mesurez avant et après activation, surtout sur WooCommerce ou les API.




Merci pour ce billet. Installé en quelques minutes sur une Squeeze.
J’ai eu par contre une erreur à l’étape 3 au moment de recharger la configuration d’apache et lors de l’installation des dernières règles de mod security
Il suffit de remplacer la variable REQBODY_ERROR par REQBODY_PROCESSOR_ERROR dans /etc/apache2/modsecurity.d/00_asl_z_antievasion.conf
Report a typoMerci pour cette solution n47 !
Report a typoSalut Matt,
Que du bonheur sur ton site!
Je viens de mettre en place ce tutoriel (les mains dans le dos), sur une nouvelle acquisition, un dédié ovh.
Dans la série « Unknown variable ».
En voici une autre.
# service apache2 restart
Syntax error on line 490 of /etc/apache2/modsecurity-rules/10_asl_rules.conf:
Error creating rule: Unknown variable: MATCHED_VARS
Action ‘configtest’ failed.
The Apache error log may have more information.
failed!
#
Il suffit de se rendre en ligne 490, et changer la variable MATCHED_VARS par MATCHED_VAR.
Opération à effectué également pour les lignes :
Syntax error on line 540 of /etc/apache2/modsecurity-rules/10_asl_rules.conf
Syntax error on line 1187 of /etc/apache2/modsecurity-rules/10_asl_rules.conf
Syntax error on line 1187 of /etc/apache2/modsecurity-rules/10_asl_rules.conf
Syntax error on line 2853 of /etc/apache2/modsecurity-rules/10_asl_rules.conf
Syntax error on line 2865 of /etc/apache2/modsecurity-rules/10_asl_rules.conf
Ben voilà, c’est dit …
J’t’en serre cinq, à tantôt …
Report a typoMerci loreleil !
J’ai eu la même erreur en mettant les règles à jour. C’est étrange qu’ils ne la corrigent pas.
Report a typoHello Matt,
Pour ma part, c’est à la fin de l’étape 1 que ça a bogué!
Sous Ubu 12, apache ne trouve pas libxml2.so.2.
Donc —> vi /etc/apache2/mods-enabled/mod-secrity.load et remplacer le chemin LoadFile /usr/lib/libxml2.so.2 par LoadFile /usr/lib/i286-linux-gnu/libxml2.so.2.
Et viva la musica!
Report a typoMerci Argile pour cette solution !
Report a typoSalut tlm, j’ai corrigé comme vous les erreurs, mais j’en ai encore :s,
pouvez-vous m’aider?
Syntax error on line 66 of /etc/apache2/modsecurity.d/70_asl_csrf_experimental.conf:
Error creating rule: Unknown variable: UNIQUE_ID
Action ‘configtest’ failed.
Merci d’avance !
Report a typoSalut skiti,
Vérifie que le module
Report a typounique_idsoit bien activé dans Apache :Bonjour,
Merci pour ce tuto.
J’ai le même soucis que skiti, et j’ai pourtant bien activé le module unique_id.
Je suis sous squeeze.
Merci d’avance
Même souci que Math, Unknown variable: UNIQUE_ID.
Bonjour,
Cela est dû au nouveau fichier (70_asl_csrf_experimental.conf) qui n’est pas vraiment stable :
Personnellement, je ne l’ai pas installé. Je suis sous Squeeze également.
Report a typoSalut,
Concernant cette erreur:
Pour l’heure, il suffit de commenter les lignes suivantes, suivit d’un restart.
À bientôt Matt … ^¿^
Report a typoMerci loreleil ! :)
J’ai préféré ne pas utiliser le fichier mais on peut bien sûr commenter les lignes qui posent problèmes (tout en sachant qu’il faudra refaire les changements à la prochaine mise à jour).
Report a typoBonjour,
J’ai suivi le tuto, ca affiche toujours l’erreur 404, et les logs error.log:
et:
sachant que le mode php5 est desactive, je travaille avec suphp et suexec
merci a vous
Report a typoBonjour Fred,
Les règles experimental et paranoid sont très instables : elles cassent pas mal de choses et causent beaucoup de faux-positifs.
A ta place, je les désactiverai. C’est ce que j’ai fait chez moi, je n’ai pas vraiment le temps de les débugger (et elles changent d’une version à l’autre).
Report a typoBeaucoup d’erreurs avec ce mod ! La rétro-compatibilité de certaines règles laisse à désirer !
Report a typoSalut,
Juste pour te signaler que les regles atomicorp ne sont plus dispo :( il ne les propose plus. C’est devenu payant, tu aurais une solution alternative ?
cheer
Report a typoSalut Majeri,
Merci pour le suivi, je n’avais pas vu que les règles Atomicorp n’étaient plus disponible!
Je viens de modifier l’article utiliser les règles du projet OWASP ModSecurity Core Rule Set (CRS), qui ont l’air d’être mises à jours plus régulièrement.
Report a typoMerci pour le tutorial.
Report a typoJe pensais que mod security etait deploye par defaut sur tous les serveurs apache.
Merci pour ce tuto très clair :)
Report a typo