Sécuriser Wordpress : le login (wp-login.php et xmlrpc.php)

WordPress est le CMS le plus utilisé par les SEO. Bien au-delà, c’est le CMS le plus utilisé au monde ! De fait, c’est malheureusement aussi le plus sujet aux attaques. Je vous indique ici ma manière de parer les tentatives de login indésirables.

Quiconque a déjà regardé ses logs après avoir installé un WordPress s’est rendu compte de tout ce qui traine sur le web. Il ne faut généralement pas attendre bien longtemps après la mise en ligne d’un site pour voir des tentatives de connexion sur /wp-login.php ou /xmlrpc.php. Il s’agit souvent de bots un peu bêtes et pas très agressifs, mais vous avez quand même là une belle porte ouverte prête à laisser rentrer ceux qui s’en donnent les moyens !

Bloquer les IP indésirables

La première chose à faire est de limiter les tentatives de connexion. Pour cela, le plus simple est d’installer une extension comme l’excellent Limit Login Attempts Reloaded (LLAR). La version gratuite rend déjà de fiers services. Elle va bloquer des IP après une ou plusieurs tentatives de connexion pendant un temps que vous aurez déterminé. Cette simple extension limite donc déjà drastiquement le risque d’attaque par force brute sur votre WordPress.

Elle a aussi l’avantage de faire prendre conscience du risque, car elle garde en mémoire toutes les tentatives de connexion (d’autant qu’elle peut aussi prévenir par email lorsqu’une IP est bloquée). Il n’est pas rare de bloquer plus de 100 IP par jour sur un site moyen avec cette extension !

Sécuriser l’accès à /wp-admin/

Personnellement, ces centaines de tentatives de connexion par jour ne me rassurent pas, même si les IP en cause finissent par être bloquées par LLAR. J’aime bien ajouter une couche de sécurité supplémentaire pour tout simplement éviter les tentatives.

Pour cela, le moyen le plus simple est de demander un mot de passe HTTP pour accéder à /wp-admin/ (et à /wp-login.php, on va y venir).

Apache propose une solution simple. Il faut tout d’abord créer un fichier .htaccess et le placer dans /wp-admin/. Ce fichier devra contenir quelques lignes :

AuthType Basic
AuthName "Espace sécurisé"
AuthUserFile "/home/site/public_html/wp-admin/.passwd"
require valid-user

AuthUserFile doit contenir le chemin vers un fichier contenant le nom d’utilisateur et le mot de passe. On y revient dans une seconde, mais sachez que ce chemin doit être un chemin absolu. Il faut donc partir de la racine / de votre serveur. 

Sur des hébergements mutualisés, c’est parfois un peu compliqué à déterminer. Le plus simple est alors d’utiliser la fonction php realpath pour l’afficher. Un simple fichier contenant ce code devrait vous renseigner sur l’emplacement où il se trouve sur le serveur :

<?php
echo realpath('./');
?>

Il faut maintenant créer le fichier contenant le nom d’utilisateur et le mot de passe. Dans le .htaccess dont je donne l’exemple plus haut, je l’ai appelé .passwd et je l’ai placé dans le répertoire /wp-admin/, mais il peut se trouver n’importe où sur le serveur (à condition d’être accessible à l’utilisateur qui fait tourner Apache). Rien ne s’oppose donc à utiliser le même fichier pour des installations de WordPress différentes.

Pour générer le contenu de ce fichier, le plus simple est d’utiliser un générateur de fichier de password Apache. Il en existe plusieurs en ligne. Je trouve celui de web2generators bien pratique. Générez le fichier .passwd et placez le tout simplement dans /wp-admin/.

Votre /wp-admin/ est maintenant sécurisé, mais ce n’est pas fini !

Étendre la protection à wp-login.php

La véritable page de connexion WordPress ne se trouve pas dans le répertoire /wp-admin/, il s’agit en fait du fichier /wp-login.php. Se trouvant à la racine du site, il n’est pas sécurisé par le mot de passe HTTP que nous venons de définir (le risque est cependant limité du fait de la sécurisation de toutes les fonctions sensibles dans /wp-admin/).

Pour sécuriser le fichier wp-login.php avec le même user/password que précédemment, il faut éditer le fichier .htaccess à la racine du site. Attention à laisser intacte ce qui se trouve entre # BEGIN WordPress et # END WordPress. Au cas où ça ne serait pas assez clair, il s’agit du code que WordPress utilise pour gérer l’accès aux URLs de votre site. C’est à la fin de ce fichier que vous pouvez ajouter un code comme celui-ci pour inclure le fichier wp-login.php dans la protection que vous avez créé pour /wp-admin/ :

<FilesMatch "wp-login.php">
AuthUserFile "/home/site/public_html/wp-admin/.passwd"
AuthType Basic
AuthName "Secure File"
Require valid-user
</FilesMatch>

AuthUserFile doit là aussi contenir le chemin absolu vers votre fichier de mot de passe.

Les connexions « classiques » à votre WP sont maintenant doublement sécurisées. Selon mon expérience, cette simple opération diminue les tentatives de connexions indésirables de… 100% ou presque ! Ça serait toutefois dommage de s’arrêter là parce que WordPress laisse encore une porte grande ouverte avec l’usage de XML-RPC.

Désactiver XML-RPC

XML-RPC est un protocole permettant d’appeler des fonctions sur un système distant. WordPress utilisait ce mécanisme avant de passer à une API REST plus moderne. XML-RPC est cependant encore activé avant tout pour des raisons de compatibilité. Sauf quelques rares cas, vous pouvez désactiver l’interface XML-RPC sans souci. C’est surtout recommandé pour des raisons de sécurité, car elle permet de s’authentifier comme via la page de login !

WordPress utilise un fichier wp_xmlrpc.php à la racine du site pour utiliser ce protocole. Le plus simple est d’y interdire l’accès en ajoutant ces lignes au fichier .htaccess situé à la racine du site (le même que l’on a modifié pour sécuriser l’accès à wp-login.php) :

<Files "xmlrpc.php">
Require all denied
</Files>

Votre WordPress est maintenant beaucoup plus sécurisé contre les attaques par login. C’est un premier pas important, mais ce n’est qu’une étape pour sécuriser WordPress.

En particulier, limiter les tentatives de connexion ne vous dispense pas de maintenir votre système à jour ! Sécuriser le login ne vous immunise en rien contre les failles éventuellement présentes dans votre version de WordPress ou dans l’une de vos extensions. Pour cela, le mot-clé à retenir : update !