Sécuriser WordPress avec .htaccess

Sécuriser WordPress doit être la première préoccupation après l’installation d’un site sur un hébergement. Cet article présente des directives à ajouter au fichier .htaccess pour protéger son site.

Ne croyez pas que votre site n’intéresse pas les pirates de l’Internet. Leurs attaques sont systématiques, et ils exploitent toutes les failles qu’ils peuvent trouver. En prenant le contrôle de votre site, ils peuvent modifier l’affichage de certaines pages, l’utiliser pour envoyer des spams ou créer des liens pour améliorer leur référencement. Bilan, votre site risque d’être bloqué par votre hébergeur ou banni par les moteurs de recherche en plus de faire de vous le complice involontaire d’escrocs, mafieux et autres terroristes. Autant tout faire pour éviter ce type de conséquences.

À noter : le codex WordPress consacre une page à la façon de sécuriser un site WordPress (en anglais).

Haut de page

Généralités sur le fichier .htaccess

Un article de présentation du fichier .htaccess est disponible dans la documentation Apache. Retenez notamment que :

  • si vous avez accès à la configuration du serveur (ce qui n’est généralement pas le cas sur un hébergement mutualisé), il vaut mieux insérer les directives dans un fichier de configuration d’Apache,
  • les directives contenues dans un fichier .htaccess situé dans un répertoire s’appliquent à ce répertoire mais aussi aux répertoires de niveau inférieur.

Où se situe le fichier htaccess ?

Le fichier .htaccess se situe notamment dans le répertoire racine du site. Dans ce cas, les directives s’appliquent à l’ensemble du site. Il est possible d’avoir aussi des fichiers .htaccess dans certains sous-répertoires afin que les directives ne s’appliquent qu’à une partie du site.

Sécuriser WordPress - Fichier .htaccess situé à la racine du site
Sécuriser WordPress – Fichier .htaccess situé à la racine du site

Créer, modifier et transférer le fichier .htaccess

Si vous avez personnalisé des permaliens, WordPress a inséré des directives dans un fichier .htaccess qu’il a éventuellement créé.

Le fichier .htaccess est un fichier texte qui peut être créé et modifié avec un éditeur de texte (pas un traitement de texte comme Microsoft Word qui va inclure du formatage incompréhensible par Apache). Le codage UTF8 sans BOM, celui utilisé pour les fichiers WordPress, convient aussi pour le fichier .htaccess.

Sécuriser WordPress - Encodage de .htaccess dans Notepad++
Sécuriser WordPress – Encodage de .htaccess dans Notepad++

Pour transférer un fichier .htaccess vers un hébergement, vous pouvez utiliser un client FTP comme FileZilla :

Sécuriser WordPress - Transférer un fichier.htaccess sur un serveur hébergé avec FileZilla
Sécuriser WordPress – Transférer un fichier.htaccess sur un serveur hébergé avec FileZilla

À noter :

  • si vous n’êtes pas familier des directives du fichier « .htaccess », je vous conseille de lire d’abord l’article Redirections d’adresses HTTP pour WordPress,
  • si en testant des modifications celles-ci ne semblent ne pas fonctionner, penser à forcer le rechargement de la page testée en tapant en même temps sur les touches   CTRL  et   F5 . Sinon, il se peut que l’affichage s’effectue depuis le cache mémoire de votre navigateur, sans solliciter Apache,
  • certaines erreurs peuvent conduire au blocage brutal du serveur Apache; personne ne pourra accéder au site tant que l’erreur n’aura pas été corrigée ! Soyez donc très prudent, testez si possible en local vos modifications avant de les reporter sur le site de production :

    Sécuriser WordPress - Une erreur dans htaccess peut rendre le serveur inutilisable
    Sécuriser WordPress – Une erreur dans htaccess peut rendre le serveur inutilisable

La suite de cet article propose des directives à insérer dans des fichiers .htaccess. Vous pouvez utiliser un générateur de directives pour mieux comprendre comment les créer.

Haut de page

Protéger fichiers et répertoires

Ne pas afficher le contenu des répertoires

Par défaut, si l’adresse internet correspond à un répertoire, Apache affiche la liste des fichiers qu’il contient. Par exemple, « https://dfarnier.fr/mon/contenu/plugins » permet d’afficher la liste des extensions (plugins) installées  sur le site WordPress. C’est fournir des informations utiles pour qui voudrait pirater le site, et c’est totalement inutile à qui veut le consulter. Le code ci-dessous permet d’empêcher cet affichage du contenu des répertoires :

# empêcher la lecture des répertoires
<IfModule mod_autoindex.c>
Options -Indexes
</IfModule>
Empêcher l'affichage du contenu des répertoires

Voici désormais ce qui s’affichera en réponse à une requête http correspondant à l’adresse d’un répertoire :

Sécuriser WordPress - La liste des fichiers contenus dans le répertoire demandé ne s'affiche plus
Sécuriser WordPress – La liste des fichiers contenus dans le répertoire demandé ne s’affiche plus

Ne pas afficher wp-config.php

Le fichier « wp-config.php » contient des informations sensibles, à commencer par les codes de connexion à la base de données. Les directives ci-dessous interdisent son accès depuis internet :

# interdire lecture de wp-config.php
<Files wp-config.php>
Order Deny,Allow
Deny from All
</Files>
Empêcher l'affichage du fichier config.php depuis internet

À partir de ce moment, toute personne saisissant l’url du fichier « wp-config.php » dans la barre d’adresse de son navigateur se verra retourné un message du type :

Sécuriser WordPress - wp-config.php rendu inaccessible depuis internet
Sécuriser WordPress – wp-config.php rendu inaccessible depuis internet

À savoir : WordPress recherche le fichier wp-config.php dans le répertoire racine et dans le répertoire directement parent. Un bon moyen de le protéger, consiste à le déplacer un cran au-dessus dans la hiérarchie des répertoires, là où les pirates ne vont pas d’abord le rechercher.
Cette protection devient particulièrement efficace si le site est situé dans le répertoire qui représente la racine Internet pour Apache. Ce répertoire est souvent appelé « www ». En plaçant le site dans ce répertoire et le fichier wp-config.php un  niveau au-dessus, on est assuré qu’Apache n’affichera jamais le contenu du fichier wp-config.php sur Internet.

Sécuriser WordPress - Déplacer wp-config.php en dehors de la zone Internet du serveur Apache
Sécuriser WordPress – Déplacer wp-config.php en dehors de la zone Internet du serveur Apache

Attention : ne laissez pas traîner non plus d’anciennes versions du wp-config.php dont vous avez modifié le nom. Regardez cet extrait d’une attaque réelle où le pirate recherche différentes variantes :

Sécuriser WordPress - Recherche ancien fichier config.php
Sécuriser WordPress – Recherche ancien fichier config.php

Protéger des fichiers sensibles

Protéger les fichiers « techniques »

Voici des directives qui permettent d’empêcher la lecture des fichiers « .htaccess », « .htpasswd » (pour les mots de passe), « .ini » et « .log » depuis Internet :

# empêcher la lecture des fichiers sensibles
# reconnus par leur exension
<FilesMatch "\.(htaccess|htpasswd|ini|log)$">
Order Deny,Allow
Deny from All
</FilesMatch>
Protéger les fichiers ayant certaines extensions

Protéger les fichiers de programmes

Les répertoires « includes » et « wp-admin/includes » contiennent des fichiers de programme de WordPress. Il n’y a pas de raison que ces fichiers soient lus via Internet.

Voici des directives à insérer dans le fichier .htaccess situé à la racine du site :

# empêcher l'exécution des fichiers dans les répertoires
# wp-admin/includes' et wp-includes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F]
RewriteRule ^wp-includes/theme-compat/ - [F]
</IfModule>
Bloquer la lecture des fichiers contenus dans des répertoires includes
  • [F] est un drapeau Apache qui veut dire Interdit (Forbidden ). Quand la requête HTTP s’adresse à un fichier correspondant à la « RewriteRule », Apache renvoie l’erreur « 403 »,
  • [S=3] permet de ne pas traiter les 3 directives suivantes si le fichier demandé n’est pas situé dans le répertoire « wp-includes » situé à la racine.

Autoriser la lecture du fichier wp- tinymce.php

« Tinymce » est l’éditeur qui permet de rédiger les articles et pages. Son bon fonctionnement nécessite que le fichier wp-tinymce.php soit accessible depuis Internet. Les directives suivantes sont à insérer dans un fichier .htaccess situé dans le répertoire wp-includes :

Sécuriser WordPress - Fichier .htaccess dans le répertoire wp-includes
Sécuriser WordPress – Fichier .htaccess dans le répertoire wp-includes
<Files wp-tinymce.php>
allow from all
</Files>
Autoriser l'exécution via Internet du fichier wp-tinymce.php situé dans wp-includes

On remarque le fonctionnement en cascade des fichiers .htaccess :

  • celui situé à la racine du site interdit la lecture via Internet des fichiers « .php » dans tous ses sous-répertoires,
  • mais comme celui situé dans le sous-répertoire « wp-includes » autorise la lecture du fichier « wp-tinymce.php », ce fichier situé dans un sous-répertoire de « wp-includes » pourra être lu.
Haut de page

Bannir des adresses dangereuses

Vous avez détecté une adresse IP correspondant à une tentative d’accès malintentionnée. Vous souhaitez l’empêcher d’accéder à votre site avant qu’elle ne réussisse une intrusion. Utilisez le code suivant, en modifiant les adresses IP :

<Limit GET POST>
order allow,deny
deny from 123.45.67.89
deny from 98.76.54.32
allow from all
</Limit>
Bannir une liste d'adresses IP

Il est aussi possible :

  • de bloquer des plages d’adresses. Par exemple, pour bloquer les adresses commençant par « 123.45.67 », ajouter la ligne  : deny from 123.45.67,
  • de bloquer plusieurs adresses en les indiquant sur la même ligne séparées par un caractère blanc ( exemple : deny from 123.45.67.89 98.76.54.32),
  • de bloquer des domaines. Par exemple, pour bloquer le domaine »domaine.tld », ajouter la ligne : deny from domaine.tld (exemple : deny from dfarnier.fr).

La documentation Apache indique que : « Les directives Allow, Deny, et Order fournies par le module mod_access_compat sont obsolètes, et sont appelées à disparaître dans les versions futures. Il est donc déconseillé de les utiliser, et de se fier aux tutoriels qui recommandent leur utilisation.  »

Il faut se méfier de cette recommandation, car la version d’Apache installée sur un hébergement n’est pas forcément à jour. Voici un code qui doit fonctionner quelle que soit la version d’Apache que vous utilisez :

# Bannir certaines adresses IP
# version Apache à partir de 2.3
<IfModule authz_core_module>
<RequireAll>
Require all granted
Require not ip 123.45.67.89
</RequireAll>
</IfModule>

# Bannir certaines adresses IP
# version Apache avant 2.3
<IfModule !authz_core_module>
<Limit GET POST>
order allow,deny
deny from 123.45.67.89
allow from all
</Limit>
</IfModule>
Bannir des adresses IP quelle que soit la version d'Apache

Quelques explications :

IfModule authz_core_module>…. IfModule>

  • les directives situées entre IfModule et /IfModule ne seront exécutées que si le module authz_core_module est installé (la version d’Apache doit être au moins la 2.3)

<RequireAll> … RequireAll>

  • les directives contenues entre RequireAll et /RequireAll devront toutes être vérifiées pour qu’Apache continue à analyser le fichier .htaccess. Si une directive n’est pas vérifiée, Apache refusera l’accès

Require all granted

  • indique que, par défaut, toutes les requêtes http sont acceptées

Require not ip 123.45.67.89

  • les requêtes http provenant de l’adresse IP « 123.45.67.89 »  sont rejetées ( autrement dit, l’accès au site est refusé),
  • vous pouvez ajouter autant de lignes « Require not » que nécessaire,
  • vous pouvez mettre plusieurs adresses IP sur la même directive en les séparant par des caractères blancs ( exemple : Require not ip 123.45.67.89 98.76.54.32),
  • il est aussi possible de filtrer en fonction du nome de domaine (voir des exemples dans la documentation Apache)

Comment repérer les adresses à bannir ?

Les accès douteux peuvent être identifiés dans le fichier journal ( ou fichier log ) qui retrace toutes les demandes d’accès (requêtes HTTP). Pour l’hébergement que j’utilise, ce sont les logs « web » :

Sécuriser WordPress - Accéder aux logs http
Sécuriser WordPress – Accéder aux logs http

Une fois le fichier log ouvert, rechercher la chaîne «  404  » (blanc + 4 + 0 + 4 + blanc) qui permet de retrouver les demandes d’accès à des pages non trouvées par le serveur HTTP. On trouve par exemple ceci :

Sécuriser WordPress - Repérer une tentative de piratage
Sécuriser WordPress – Repérer une tentative de piratage
  1. le  404  trouvé se situe après l’indication du protocole utilisé (HTTP/1.1); il s’agit du code HTTP indiquant que la page demandée n’a pas été trouvée par le serveur HTTP,
  2. l’adresse demandée et non trouvée est « wp-content/plugins/wysija-newsletters/readme.txt »
  3. l’adresse IP du demandeur est « 185.13.38.146 »

Ce n’est pas parce qu’une adresse n’est pas trouvée qu’il faut immédiatement bannir l’adresse IP du demandeur. Mais en cherchant « wysija-newsletters/readme.txt » dans un moteur de recherche, on découvre qu’il s’agit d’une vulnérabilité connue du plugin « mailpoet » dont l’ancien nom était « wysija ».
Comme je n’utilise pas cette extension pour mon site, une telle requête n’a pas de raison d’être. Je préfère bannir l’IP car, si cette attaque ne peut pas aboutir, l’assaillant peut lancer d’autres attaques qui pourraient finir par lui permettre de pénétrer mon site.

Il est utile de rechercher régulièrement dans vos logs les requêtes ayant abouti à une réponse « 404 ».
Certaines peuvent correspondre à des adresses de votre site qui ont disparues (suite à un renommage d’article par exemple). Dans ce cas, il faut envisager de mettre en place une redirection permanente.
D’autres erreurs 404 correspondront à des tentatives d’intrusion dans votre site pour lesquelles vous bannirez les adresses IP.

Haut de page

Limiter l’accès à l’administration du site

Le code suivant permet de réserver l’accès à l’administration via Internet à un nombre limité d’adresses IP; il doit être placé dans un fichier .htaccess situé dans le répertoire « wp-admin »  :

# Bloquer l'accès à l'administration en dehors de quelques adresses IP
order deny,allow
deny from all
allow from 123.45.67.89
allow from 98.76.54.321
Limiter l'accès à l'administration

Avertissement : ceci ne peut être utile que si les utilisateurs devant accéder à l’administration (administrateurs, rédacteurs..) :

  • sont en nombre limité,
  • ont des adresses IP qui sont fixes ou ne changent pas souvent,
  • n’ont pas besoin d’accéder à l’administration lorsqu’ils sont en déplacement.

Dans le cas contraire, vous allez devoir modifier en permanence le fichier .htaccess, ce qui représente chaque fois un risque faire tomber votre site.

Attention : le fichier « admin-ajax.php » qui se trouve dans le répertoire « wp-admin » doit être accessible dès lors qu’un thème ou une extension utilise le fonctionnement en ajax (Asynchronous JavaScript and XML).  Voici un code qui permet d’autoriser explicitement l’accès au fichier « admin-ajax.php » (à placer dans le fichier .htaccess situé dans le répertoire wp-admin) :

 # Autoriser les accès à wp-admin/admin-ajax.php
<Files admin-ajax.php>
    Order allow,deny
    Allow from all
    Satisfy any
</Files>
Permettre l'accès à tous du programme admin-ajax.php
Haut de page

Bloquer l’exécution des programmes php dans uploads

Le répertoire « uploads » est utilisé pour le chargement des fichiers médias. Il peut représenter une porte d’entrée permettant à un pirate de télécharger des fichiers de programmes sur votre site puis de les exécuter.

Il n’y a aucune raison dans le fonctionnement de WordPress de vouloir exécuter un fichier php situé dans le répertoire « uploads ». Voici comment l’empêcher.

Le fichier « uploads » se trouve dans le répertoire « wp-content, » au même niveau que les fichiers de thèmes et d’extensions (plugins); dans l’exemple ci-dessous, pour améliorer la sécurité, nous avons remplacé le répertoire « wp-content » par le répertoire « contenu » :

Le sous-répertoire uploads se trouve dans le même répertoire que les sous-répertoires "themes" et "plugins"
Situer le répertoire « uploads »

Dans le répertoire « uploads » créer un fichier « .htaccess » :

le fichier .htaccess doit apparaître dans le répertoire uploads
htaccess créé dans uploads

Ajouter les directives suivantes dans le fichier « .htaccess » :

<Files *.php>
Deny from all
</Files>
Bloquer l'exécution des programmes php dans uploads

Haut de page

Une réflexion sur « Sécuriser WordPress avec .htaccess »

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.