Introduction
Un site web est exposé en permanence à des centaines d'attaques automatisées : injections SQL, XSS, bots cherchant des CVE WordPress, etc.
ModSecurity intercepte les requêtes HTTP/S et les évalue contre un jeu de règles avant de les passer à votre application. Couplé au OWASP Core Rule Set (CRS), vous bloquez :
- SQLi (SQL injection)
- XSS (Cross-site scripting)
- RFI / LFI (Remote / Local File Inclusion)
- Command injection
- Scanners (Nikto, sqlmap, etc.)
- Exploits CVE connus (Log4Shell, Heartbleed, etc.)
Prérequis
- Nginx installé (1.18+)
- VPS Debian / Ubuntu
- Accès root
Étape 1 : Installation
sudo apt update
sudo apt install -y libmodsecurity3 libmodsecurity-dev nginx-module-modsecurity
Activez le module dans /etc/nginx/nginx.conf :
load_module modules/ngx_http_modsecurity_module.so;
http {
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
# ...
}
Étape 2 : Configuration de base
sudo mkdir -p /etc/nginx/modsec
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf
sudo nano /etc/nginx/modsec/modsecurity.conf
Changez SecRuleEngine :
SecRuleEngine DetectionOnly
⚠️ Démarrez en DetectionOnly (log uniquement) pour identifier les faux positifs avant de passer en On (bloquant).
Étape 3 : Installer OWASP CRS
cd /etc/nginx/modsec
sudo git clone https://github.com/coreruleset/coreruleset.git
sudo cp coreruleset/crs-setup.conf.example coreruleset/crs-setup.conf
Étape 4 : main.conf
sudo nano /etc/nginx/modsec/main.conf
Include /etc/nginx/modsec/modsecurity.conf
Include /etc/nginx/modsec/coreruleset/crs-setup.conf
Include /etc/nginx/modsec/coreruleset/rules/*.conf
Étape 5 : Tester et activer
sudo nginx -t
sudo systemctl reload nginx
Test SQLi :
curl "http://votre-site.fr/?id=1' OR '1'='1"
Vérifiez les logs :
sudo tail -f /var/log/modsec_audit.log
Vous devriez voir l'attaque détectée.
Étape 6 : Tuner les faux positifs
Pendant quelques jours, laissez en DetectionOnly et analysez les logs :
sudo grep -E "MATCHES|Detected" /var/log/modsec_audit.log | head
Pour exclure une règle pour un site spécifique :
sudo nano /etc/nginx/sites-available/mon-site
server {
location /admin/ {
modsecurity_rules '
SecRuleRemoveById 941100
SecRuleRemoveById 942100
';
}
}
Ou globalement, créez /etc/nginx/modsec/coreruleset/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf :
SecRule REQUEST_URI "@beginsWith /api/" "id:1001,phase:1,nolog,allow,ctl:ruleRemoveById=920420"
Étape 7 : Activer le mode blocage
Une fois les faux positifs réglés :
sudo nano /etc/nginx/modsec/modsecurity.conf
SecRuleEngine On
sudo systemctl reload nginx
ModSecurity bloque maintenant en HTTP 403.
Étape 8 : Niveaux d'agressivité (Paranoia Level)
CRS supporte 4 niveaux (1-4) :
- PL1 : règles essentielles, peu de faux positifs (défaut)
- PL2 : plus stricte
- PL3 : strict, beaucoup de FP probables
- PL4 : paranoid, à réserver à des contextes critiques
sudo nano /etc/nginx/modsec/coreruleset/crs-setup.conf
SecAction "id:900000,phase:1,nolog,pass,t:none,setvar:tx.paranoia_level=2"
Étape 9 : Anomaly scoring
CRS utilise un système de score. Chaque règle déclenchée ajoute des points. Quand le score dépasse un seuil, la requête est bloquée :
SecAction "id:900110,phase:1,nolog,pass,t:none,
setvar:tx.inbound_anomaly_score_threshold=5,
setvar:tx.outbound_anomaly_score_threshold=4"
Réduisez le seuil pour être plus strict (3 au lieu de 5).
Étape 10 : Personnaliser les règles
Bloquer une IP :
SecRule REMOTE_ADDR "@ipMatch 1.2.3.4" "id:1000,phase:1,deny,status:403"
Bloquer un User-Agent :
SecRule REQUEST_HEADERS:User-Agent "@contains sqlmap" "id:1001,phase:1,deny,status:403"
Rate-limit sur /login :
SecAction "id:1002,phase:1,nolog,pass,initcol:ip=%{REMOTE_ADDR},chain"
SecRule REQUEST_URI "@beginsWith /login" "chain"
SecAction "id:1003,setvar:ip.attempts=+1,expirevar:ip.attempts=60"
SecRule IP:attempts "@gt 5" "id:1004,deny,status:429"
Étape 11 : Performance
ModSecurity ajoute 5-15ms par requête en moyenne. Pour optimiser :
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
Limitez le scan à certaines requêtes :
location / {
modsecurity on;
}
location /static/ {
modsecurity off; # bypass pour assets statiques
}
Étape 12 : Monitoring
Comptez les blocages par jour :
sudo grep "Access denied" /var/log/nginx/error.log | wc -l
Top des règles déclenchées :
sudo grep "Matched" /var/log/modsec_audit.log | grep -oP 'id "\d+"' | sort | uniq -c | sort -rn | head
Top des IPs bloquées :
sudo grep "deny" /var/log/nginx/error.log | grep -oP 'client: \S+' | sort | uniq -c | sort -rn | head
Dépannage
"modsecurity: SecRuleEngine On - failed"
Syntaxe invalide dans une règle. Vérifiez :
sudo nginx -t
L'erreur précise quelle règle.
Trop de faux positifs
Revenez en DetectionOnly, analysez les patterns, ajustez via exclusions ciblées (par URL ou par règle ID).
Performance dégradée
Désactivez le scan du body pour les gros uploads :
location /upload {
modsecurity_rules '
SecRequestBodyAccess Off
';
}
Logs trop verbeux
SecAuditLogParts ABCFHZ
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
Ne log que les requêtes pertinentes.
Commandes utiles
sudo nginx -t # tester config
sudo systemctl reload nginx # recharger
sudo tail -f /var/log/modsec_audit.log # logs audit
sudo tail -f /var/log/nginx/error.log # erreurs nginx
sudo grep "id \"941100\"" /var/log/modsec_audit.log # tracer une règle
# Updater CRS
cd /etc/nginx/modsec/coreruleset
sudo git pull
sudo systemctl reload nginx
Conclusion
ModSecurity + OWASP CRS bloque la majorité des attaques web automatisées sans modifier votre application. Avantages :
- Couverture des CVE web courantes
- Mises à jour gratuites via OWASP
- Logs détaillés pour analyse
- Performance acceptable (<15ms)
Pour aller plus loin :
- Combinez avec Fail2ban pour bloquer durablement les IPs récidivistes
- Utilisez CrowdSec pour de l'intelligence collaborative
- Pour du SaaS, considérez aussi NAXSI (alternative plus légère)
Ressources
- ModSecurity : https://github.com/owasp-modsecurity/ModSecurity
- OWASP CRS : https://coreruleset.org
- Documentation CRS : https://coreruleset.org/docs/
- Liste de règles : https://github.com/coreruleset/coreruleset/tree/v4.0/dev/rules


















