Sécuriser son serveur WordPress

Il existe de nombreux tutoriels consacrés à ce sujet, je ne vais donc faire que survoler le sujet. Mon objectif est surtout de rappeler des règles simples.

Le serveur

Si vous faites de l’autohébergement complet, le serveur est chez vous. Il faut donc sécuriser la machine d’un point de vue physique et logiciel. J’ai fait le choix d’une machine virtuelle dédiée uniquement au fonctionnement du service WordPress. Elle est située sur un NAS Synology permettant de faire fonctionner des machines virtuelles. Ce NAS est en hauteur (pour échapper aux coups de balais ou de serpillières) et branché sur un onduleur électrique pour l’isoler des micro-coupures, des variations de tension et des coupures électriques de moins d’une demi heure.

La machine virtuelle (que j’appellerai “le serveur” dans la suite de ce billet) est une Debian 11 minimaliste (sans interface graphique) avec ssh. Un snapshot à chaud du serveur est pris chaque jour par le virtualiseur du Synology, et un “apt update && apt upgrade -y” (yolo) est lancé automatiquement chaque jour. Les vrais admin utiliseront plutôt un cron-apt ou unattended-upgrades.

Le virtualiseur Synology permet aussi de créer un clone du serveur à partir d’un snapshot et de l’exporter au format OVA. Je fais cela de temps en temps (manuellement) pour disposer d’un fichier qui suivra ensuite toute la procédure de sauvegarde 3-2-1 des autres fichiers du NAS. C’est plus pour reconstruire rapidement un serveur en cas de problème, puisque les contenus WordPress seront sauvegardés de manière spécifique (voir plus loin).

Les services qui tournent sur le serveur sont protégés par un pare-feu local (ufw) qui vient compléter celui du NAS Synology, celui du routeur ER-X de mon réseau et celui de la box fournie par mon FAI (nous vivons dans un monde formidable).

Il y a un seul utilisateur local, en plus de root, et celui-ci est configuré pour accéder au serveur en ssh avec une authentification par clef SSH. Les mots de passe font 32 caractères, comprennent des majuscules, des minuscules, des chiffres et des caractères spéciaux classiques et français. Ils sont générés aléatoirement par KeePass et y sont stockés, ainsi que les clefs SSH et tout ce qui relèvera de la sécurité de ce serveur (les codes 2FA par exemple, voir plus loin). Vous trouverez plus de détails techniques, sur ce lien : https://www.digitalocean.com/community/tutorials/initial-server-setup-with-debian-11

Installation du CMS

Il faut ensuite installer apache2, php8, mariadb et pour finir WordPress. Vous trouverez tous les détails techniques, sur ces liens (kudos à leurs auteurs):
https://cloudinfrastructureservices.co.uk/install-wordpress-on-debian-10-11/
https://www.linuxcapable.com/how-to-install-wordpress-with-lamp-stack-on-debian-11-bullseye/

N’oubliez pas le passage sur la commande “mysql_secure_installation”, ni la génération des sels dans wp-config.php grâce au site https://api.wordpress.org/secret-key/1.1/salt/

Certificats SSL

Il faut maintenant mettre en place vos certificats SSL pour accéder à votre nouveau serveur en https. Pour ma part, ayant en tête d’utiliser les différents services de Cloudflare, j’ai suivi ce tuto : https://devanswers.co/configure-cloudflare-origin-ca-apache/

Les fichiers .htaccess

Plutôt qu’un cours sur les fichiers .htaccess, voici le contenu de ceux que j’utilise :

.htaccess à la racine du site WordPress (le répertoire où l’on trouve les répertoire wp-admin, wp-content et wp-includes

#Blocage de la visibilité du fichier wp-config.php
<Files wp-config.php>
order allow,deny
deny from all
</Files>
#Fin du blocage

#Blocage de la visibilité du fichier xmlrpc.php
<Files xmlrpc.php>
Order Allow,Deny
Deny from all
</Files>
#Fin du blocage

#Interdiction de visualisation des repertoires du site :
Options All -Indexes

# Protéger .htaccess et .htpasswds
<Files ~ "^.*\.([Hh][Tt][AaPp])">
order allow,deny
deny from all
satisfy all
</Files>

# Protections diverses (XSS, clickjacking et MIME-Type sniffing)
<ifModule mod_headers.c>
Header set X-XSS-Protection "1; mode=block"
Header always append X-Frame-Options SAMEORIGIN
Header set X-Content-Type-Options nosniff
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</ifModule>

# Redirection vers HTTPS 
RewriteEngine On
RewriteCond %{SERVER_PORT} ^80$ [OR]
RewriteCond %{HTTPS} =off
RewriteRule ^(.*)$ https://zythom.fr/$1 [R=301,L]

# Redirection du www vers non-www en HTTPS
RewriteCond %{HTTP_HOST} ^www\.zythom\.fr [NC]
RewriteRule ^(.*)$ https://zythom.fr/$1 [R=301,L]

.htaccess dans wp-admin (attention, une fois en place, vous ne pourrez accéder à l’interface d’administration WordPress que depuis ces adresses IP) :

order deny,allow
deny from all
# IP de la maison
allow from W1.X1.Y1.Z1
# IP de la ligne de secours
allow from W2.X2.Y2.Z2
# IP locales
allow from 192.168.N1.M1
allow from 192.168.N2.M2

.htaccess dans wp-content :

# Bloque les accès directs aux fichiers PHP (Merci à Sucuri)
<FilesMatch "\.(?i:php)$">
  <IfModule !mod_authz_core.c>
    Order allow,deny
    Deny from all
  </IfModule>
  <IfModule mod_authz_core.c>
    Require all denied
  </IfModule>
</FilesMatch>

.htaccess dans wp-includes :

# Bloque les accès directs aux fichiers PHP (Merci à Sucuri)
<Files wp-tinymce.php>
allow from all
</Files>
<FilesMatch "\.(?i:php)$">
  <IfModule !mod_authz_core.c>
    Order allow,deny
    Deny from all
  </IfModule>
  <IfModule mod_authz_core.c>
    Require all denied
  </IfModule>
</FilesMatch>
<Files wp-tinymce.php>
  Allow from all
</Files>
<Files ms-files.php>
  Allow from all
</Files>

Les plugins WordPress

Il existe de nombreux modules d’extension qui font la richesse de l’écosystème WordPress mais également son danger : je vous conseille de minimiser le nombre de plugins et de veiller à leurs mises à jour régulière.

Le premier plugin que je vous recommande permet justement la mise à jour des tous les plugins : il s’agit de Companion Auto Update.

Le plugin suivant vous permet de mettre en place l’authentification multi facteurs sur votre site (indispensable) : Two-Factor.

Un pare-feu dédié à WordPress viendra compléter les différentes barrières déjà mises en place : NinjaFirewall.

J’aime beaucoup le concept de protection communautaire associé au produit Crowdsec que vous pourrez installer en suivant ce billet : https://www.it-connect.fr/comment-proteger-son-site-wordpress-avec-crowdsec/

Enfin, la sauvegarde de vos billets, commentaires, thèmes et plugins pourra se faire simplement avec le plugin UpdraftPlus qui m’a déjà sauvé la vie.

J’ajouterai deux plugins dans ma revue de sécurité car ils aident beaucoup le blogueur à survivre aux spammeurs (j’ai installé les deux qui fonctionnent très bien en parallèle) : Akismet Anti-Spam et Antispam Bee.

Voilà ce que j’ai mis en place. En parler diminue déjà la sécurité, mais comme le partage, lui, augmente la sécurité, n’hésitez pas à me faire part de vos conseils et recommandations en commentaire.

2 réflexions sur « Sécuriser son serveur WordPress »

  1. Bonjour,
    Merci pour ce partage.
    Il me semblait que WordPress maintenait à jour les plugins depuis quelques versions alors je ne comprend pas l’utilité de Companion Auto Update ?

    De mon coté j’utilise :
    Wordfence Security : un firewall applicatif
    hCaptcha : à la place de reCaptcha
    Site Kit by Google : pour le référencement et les statistiques Google
    Statify : pour des statistiques ultra simples

    (attention : je ne suis pas un spécialiste WordPress et mon blog est plus à titre expérimental)

  2. Bonjour,

    Je me permets quelques remarques sur la configuration d’Apache pour WordPress.
    Interdire l’accès à certaines ressource se fait depuis un bon moment avec les directives Require :
    Require all denied
    Le blocage de l’accès aux fichiers .htacces et .htpasswd est déjà présent dans la configuration par défaut d’Apache. Sous Debian dans le fichier apache2.conf :

    Require all denied

    L’en tête HTTP X-XSS-Protection devrait être au contraire désactivée :
    Header set X-XSS-Protection “0”

    On peut économiser le coût des réécritures pour forcer le HTTPS simplement avec :
    Redirect permanent / https://zythom.fr/

    Autres mesures de sécurité, ou plutôt de limitation des dommages en cas d’accès frauduleux :
    – interdiction de l’exécution des scripts PHP dans les dossiers comme wp-content/uploads :

    SetHandler none

    – interdiction de modifier les fichiers du WordPress depuis l’interface d’administration en mettant dans le fichier wp-config.php :
    define(‘DISALLOW_FILE_EDIT’, true);

Les commentaires sont fermés.