vendredi 25 septembre 2026

À propos

Contact

Sécurité

WAF et fail2ban : protéger WordPress avant même que PHP ne s’exécute

Un pare-feu applicatif et fail2ban bloquent une attaque avant qu'elle n'atteigne votre code. Voici comment les deux se complètent sur un site WordPress.

Par Clément Hadrot • 27 septembre 2022 • 5 min de lecture • Aucun commentaire
WAF et fail2ban : protéger WordPress avant même que PHP ne s'exécute

Toutes les protections vues jusqu’ici, nonces, échappement, capacités, permission_callback, agissent une fois que la requête est arrivée jusqu’au code PHP de WordPress. C’est déjà tard : chaque requête, même bloquée ensuite, a consommé du temps CPU, potentiellement révélé une information dans un message d’erreur, ou fait partie d’une salve de milliers de tentatives similaires. Un pare-feu applicatif et un outil comme fail2ban agissent en amont, avant ou pendant l’exécution, avec une logique complémentaire à celle du code.

Ces deux outils ne jouent pas le même rôle et sont souvent confondus. Comprendre leur différence permet de choisir la bonne combinaison selon l’infrastructure du projet, qu’il s’agisse d’un hébergement mutualisé, d’un VPS géré en direct ou d’une infrastructure derrière un CDN.

Ce qu’est un WAF, concrètement

Un WAF, ou Web Application Firewall, analyse chaque requête HTTP selon un ensemble de règles avant de la laisser atteindre l’application. Il peut fonctionner à deux niveaux : en amont du serveur, sous forme de service réseau ou de CDN comme Cloudflare, ou directement sur le serveur, sous forme de module comme ModSecurity avec le jeu de règles OWASP Core Rule Set.

Un WAF applicatif reconnaît des motifs caractéristiques d’une attaque : une tentative d’injection SQL dans un paramètre d’URL, une signature de scan automatisé, une charge utile typique d’une faille connue sur une extension WordPress populaire. Il bloque la requête avant même que WordPress ne la charge, ce qui économise des ressources serveur et referme certaines failles zero-day le temps qu’un correctif officiel sorte.

Les limites d’un WAF mal calibré

Un WAF trop strict génère des faux positifs : un client qui colle un texte contenant des guillemets et des apostrophes dans un formulaire de contact peut se voir bloqué parce que la requête ressemble, de loin, à une tentative d’injection. C’est pour cette raison que le déploiement d’un nouveau jeu de règles WAF mérite toujours une phase de test en mode détection seule avant le passage en blocage actif.

L'essentiel à retenir : Un WAF filtre les requêtes selon des règles avant qu'elles atteignent PHP ; fail2ban bannit une IP après un nombre défini d'échecs de connexion ; Les deux se combinent, ils ne se remplacent pas
  • Commencer en mode détection ou journalisation, jamais en blocage direct
  • Surveiller les faux positifs pendant au moins une à deux semaines
  • Exclure explicitement les routes REST légitimes qui manipulent du contenu riche, comme l’éditeur de blocs

fail2ban : bannir sur la répétition d’échecs

fail2ban fonctionne différemment : il surveille les fichiers de journal du serveur, repère un motif d’échec répété, comme plusieurs tentatives de connexion infructueuses sur wp-login.php en peu de temps, et bannit temporairement l’adresse IP source au niveau du pare-feu du système, généralement via iptables ou nftables.

# /etc/fail2ban/filter.d/wordpress-auth.conf
[Definition]
failregex = ^<HOST> .* "POST .*wp-login\.php.*" 200
ignoreregex =

# /etc/fail2ban/jail.local
[wordpress-auth]
enabled  = true
port     = http,https
filter   = wordpress-auth
logpath  = /var/log/nginx/access.log
maxretry = 5
findtime = 600
bantime  = 3600

Ce type de règle repère une tentative de connexion, mais ne distingue pas nativement un succès d’un échec dans les journaux d’accès standards. En pratique, il est souvent plus fiable de journaliser les échecs de connexion directement depuis WordPress via le hook wp_login_failed, dans un fichier de log dédié que fail2ban peut surveiller avec un motif précis.

add_action( 'wp_login_failed', function ( $username ) {
    error_log(
        sprintf( '[wp-auth-fail] user=%s ip=%s', $username, $_SERVER['REMOTE_ADDR'] ),
        3,
        '/var/log/wordpress/auth-fail.log'
    );
} );

Où placer chaque protection

Le WAF et fail2ban interviennent à des moments différents du cycle de vie d’une requête, ce qui justifie de les utiliser ensemble plutôt que l’un à la place de l’autre.

OutilMoment d’actionBon pour
WAFAvant l’exécution de PHP, requête par requêteBloquer des motifs d’attaque connus, absorber un scan massif
fail2banAprès répétition d’un comportement dans les journauxBannir une IP qui insiste sur wp-login.php ou XML-RPC

Un banissement n’est jamais définitif ni infaillible

Une IP bannie par fail2ban peut appartenir à un réseau d’entreprise partagé par des dizaines d’employés légitimes, ou changer de main le lendemain sur un fournisseur d’accès qui pratique l’IP dynamique. C’est pourquoi la durée de bannissement (bantime) doit rester raisonnable, quelques heures dans la majorité des cas, et pourquoi une liste blanche d’adresses de confiance, comme celle du bureau ou de l’agence, évite de se bloquer soi-même un lundi matin.

Je recommande toujours de tester le bannissement sur sa propre IP en environnement de test avant de le déployer en production. Rien n’est plus frustrant que de se faire bannir de son propre site un vendredi à 18 heures.

En résumé

Un WAF filtre le contenu des requêtes selon des règles, fail2ban sanctionne un comportement répété observé dans les journaux : les deux interviennent avant que le code applicatif de WordPress ne soit sollicité, ce qui en fait un complément précieux à tout le travail de durcissement effectué dans le code lui-même. Aucun des deux ne dispense de corriger les failles à la source, mais ensemble, ils réduisent considérablement la surface d’attaque exposée au quotidien.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi