Aller au contenu

15. Durcissement de la sécurité WordPress

WordPress alimente plus de 40 % de tous les sites web sur Internet, ce qui en fait une cible privilégiée pour les attaquants. Cette section couvre les mesures de sécurité essentielles pour protéger votre installation WordPress contre les menaces courantes.

Les mesures de sécurité de ce guide suivent une approche de défense en profondeur, implémentant plusieurs couches de protection :

  1. Isolation : Séparer les sites WordPress en utilisant des utilisateurs dédiés et des pools PHP-FPM
  2. Contrôle d’accès : Restreindre l’accès au système de fichiers et définir les permissions appropriées
  3. Chiffrement : Implémenter SSL/TLS avec des paramètres de sécurité optimaux
  4. Filtrage des requêtes : Bloquer les requêtes malveillantes avant qu’elles n’atteignent WordPress
  5. Durcissement de l’application : Limiter les fonctionnalités WordPress qui pourraient être exploitées

En implémentant ces mesures, vous réduirez significativement la surface d’attaque de votre installation WordPress et rendrez beaucoup plus difficile la compromission de votre site par les attaquants.

15.2. Surveillance de la sécurité avec les journaux

Section intitulée « 15.2. Surveillance de la sécurité avec les journaux »

Avant d’implémenter des mesures de sécurité, il est important de comprendre comment surveiller votre serveur pour détecter les activités suspectes.

Les journaux Nginx fournissent des informations précieuses sur les requêtes vers votre site web, y compris les tentatives d’attaque potentielles :

# Naviguer vers le répertoire des journaux Nginx
cd /var/log/nginx
# Lister les fichiers journaux disponibles
ls
# Afficher le contenu d'un fichier journal spécifique
sudo cat access_example.com.log
# Afficher les journaux avec pagination pour les gros fichiers
sudo less error_example.com.log

Recherchez des schémas comme des tentatives de connexion échouées répétées, des méthodes HTTP inhabituelles ou des requêtes vers des fichiers PHP inexistants, qui pourraient indiquer des tentatives d’attaque.

15.3. Séparation des sites avec des pools PHP - Partie 1

Section intitulée « 15.3. Séparation des sites avec des pools PHP - Partie 1 »

15.3.1. Création d’un utilisateur dédié pour WordPress

Section intitulée « 15.3.1. Création d’un utilisateur dédié pour WordPress »

Un principe de sécurité clé est d’exécuter WordPress sous un compte utilisateur dédié plutôt que l’utilisateur www-data par défaut. Cela offre une meilleure isolation et un meilleur contrôle.

Commencez par créer un utilisateur dédié pour votre site WordPress :

# Créer un nouvel utilisateur pour votre site WordPress
sudo useradd wordpress_user

15.3.2. Configuration des permissions de groupe utilisateur

Section intitulée « 15.3.2. Configuration des permissions de groupe utilisateur »

Configurez les relations de groupe appropriées pour permettre au serveur web et à votre utilisateur spécifique au site d’accéder aux fichiers nécessaires :

# Ajouter www-data au groupe de l'utilisateur WordPress
sudo usermod -a -G wordpress_user www-data
# Ajouter l'utilisateur WordPress au groupe www-data
sudo usermod -a -G www-data wordpress_user
# Si nécessaire, ajouter votre utilisateur admin au groupe de l'utilisateur WordPress
sudo usermod -a -G wordpress_user admin_username

Cette configuration crée une isolation appropriée tout en maintenant les permissions d’accès nécessaires.

15.4. Séparation des sites avec des pools PHP - Partie 2

Section intitulée « 15.4. Séparation des sites avec des pools PHP - Partie 2 »

Par défaut, tout le traitement PHP passe par un seul pool PHP-FPM. La création d’un pool dédié pour chaque site WordPress offre une meilleure isolation de sécurité et un meilleur contrôle des ressources.

15.4.1. Création d’un pool PHP-FPM spécifique au site

Section intitulée « 15.4.1. Création d’un pool PHP-FPM spécifique au site »
# Naviguer vers le répertoire de configuration des pools PHP-FPM
cd /etc/php/8.3/fpm/pool.d/
# Créer une nouvelle configuration de pool en copiant celle par défaut
sudo cp www.conf example.com.conf
# Modifier la nouvelle configuration de pool
sudo vim example.com.conf

Modifiez le fichier de configuration du pool avec ces paramètres orientés sécurité :

; Changer le nom du pool de 'www' au nom de votre site
[example]
; Définir l'utilisateur et le groupe à votre utilisateur spécifique au site
user = wordpress_user
group = wordpress_user
; Utiliser un fichier socket spécifique au site
listen = /run/php/php8.3-fpm-example.com.sock
; Définir les limites de ressources
rlimit_files = 15000
rlimit_core = 100
; Désactiver l'affichage des erreurs mais activer la journalisation
php_flag[display_errors] = off
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/log/fpm-php.example.com.log

Ajoutez ces directives pour sécuriser davantage le socket PHP-FPM :

; Définir la propriété et les permissions du socket
listen.owner = www-data
listen.group = www-data
listen.mode = 0600

Ces paramètres :

  • Restreignent l’accès au socket uniquement à l’utilisateur du serveur web
  • Empêchent les autres utilisateurs du système de se connecter à votre pool PHP-FPM
# Créer le fichier journal
sudo touch /var/log/fpm-php.example.com.log
# Définir la propriété appropriée
sudo chown wordpress_user:www-data /var/log/fpm-php.example.com.log
# Définir les permissions appropriées
sudo chmod 660 /var/log/fpm-php.example.com.log
# Recharger PHP-FPM pour appliquer les modifications
sudo systemctl reload php8.3-fpm
# Vérifier le chemin du socket dans votre configuration
sudo grep "listen = /" example.com.conf

15.4.6. Mise à jour de Nginx pour utiliser le nouveau pool PHP-FPM

Section intitulée « 15.4.6. Mise à jour de Nginx pour utiliser le nouveau pool PHP-FPM »

Modifiez votre bloc serveur Nginx pour utiliser le nouveau socket PHP-FPM :

# Modifier la configuration Nginx de votre site
sudo vim /etc/nginx/sites-available/example.com.conf

Trouvez la section de traitement PHP et mettez à jour la directive fastcgi_pass :

location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock;
include /etc/nginx/includes/fastcgi_optimize.conf;
}

Appliquez les modifications :

# Tester la configuration Nginx
sudo nginx -t
# Recharger Nginx si le test est réussi
sudo systemctl reload nginx

La propriété et les permissions des fichiers sont critiques pour la sécurité de WordPress. L’objectif est de permettre à WordPress de fonctionner normalement tout en restreignant l’accès aux fichiers sensibles.

Pour un équilibre entre sécurité et fonctionnalité, utilisez ces permissions :

# Définir la propriété à l'utilisateur WordPress
sudo chown -R wordpress_user:wordpress_user /var/www/example.com/public_html/
# Définir les permissions des répertoires à 770 (propriétaire et groupe : lecture, écriture, exécution)
sudo find /var/www/example.com/public_html/ -type d -exec chmod 770 {} \;
# Définir les permissions des fichiers à 660 (propriétaire et groupe : lecture et écriture)
sudo find /var/www/example.com/public_html/ -type f -exec chmod 660 {} \;
# Définir wp-config.php en lecture seule pour le propriétaire
sudo chmod 400 /var/www/example.com/public_html/wp-config.php

Pour une sécurité maximale (peut nécessiter des ajustements pour certaines extensions) :

# Définir la propriété à l'utilisateur WordPress
sudo chown -R wordpress_user:wordpress_user /var/www/example.com/public_html/
# Définir les permissions des répertoires à 550 (propriétaire et groupe : lecture et exécution)
sudo find /var/www/example.com/public_html/ -type d -exec chmod 550 {} \;
# Définir les permissions des fichiers à 440 (propriétaire et groupe : lecture)
sudo find /var/www/example.com/public_html/ -type f -exec chmod 440 {} \;
# Autoriser l'écriture dans le répertoire wp-content pour les mises à jour et les téléchargements
sudo find /var/www/example.com/public_html/wp-content/ -type d -exec chmod 770 {} \;
sudo find /var/www/example.com/public_html/wp-content/ -type f -exec chmod 660 {} \;

15.6. Limiter l’accès au système de fichiers avec PHP open_basedir

Section intitulée « 15.6. Limiter l’accès au système de fichiers avec PHP open_basedir »

La directive open_basedir restreint les fichiers auxquels PHP peut accéder, empêchant les attaquants d’accéder aux fichiers en dehors de votre installation WordPress.

15.6.1. Configuration des répertoires temporaires PHP

Section intitulée « 15.6.1. Configuration des répertoires temporaires PHP »

Commencez par créer un répertoire temporaire dédié pour votre site WordPress :

# Créer un répertoire temporaire
cd /var/www/example.com/
sudo mkdir tmp/
# Définir la propriété et les permissions appropriées
sudo chown wordpress_user:wordpress_user tmp/
sudo chmod 770 tmp/

15.6.2. Configuration de la restriction open_basedir

Section intitulée « 15.6.2. Configuration de la restriction open_basedir »

Modifiez la configuration de votre pool PHP-FPM pour ajouter la directive open_basedir :

# Modifier la configuration du pool PHP-FPM
sudo vim /etc/php/8.3/fpm/pool.d/example.com.conf

Ajoutez ces lignes à la configuration :

; Définir des répertoires temporaires personnalisés
php_admin_value[upload_tmp_dir] = /var/www/example.com/tmp/
php_admin_value[sys_temp_dir] = /var/www/example.com/tmp/
; Restreindre l'accès aux fichiers PHP à des répertoires spécifiques
php_admin_value[open_basedir] = /var/www/example.com/public_html/:/var/www/example.com/tmp/

Appliquez les modifications :

# Recharger PHP-FPM
sudo systemctl reload php8.3-fpm

15.6.3. Désactivation des fonctions PHP dangereuses

Section intitulée « 15.6.3. Désactivation des fonctions PHP dangereuses »

Restreignez les fonctions PHP qui pourraient être utilisées à des fins malveillantes :

; Désactiver les fonctions PHP potentiellement dangereuses
php_admin_value[disable_functions] = shell_exec, opcache_get_configuration, opcache_get_status, disk_total_space, diskfreespace, dl, exec, passthru, pclose, pcntl_alarm, pcntl_exec, pcntl_fork, pcntl_get_last_error, pcntl_getpriority, pcntl_setpriority, pcntl_signal, pcntl_signal_dispatch, pcntl_sigprocmask, pcntl_sigtimedwait, pcntl_sigwaitinfo, pcntl_strerror, pcntl_waitpid, pcntl_wait, pcntl_wexitstatus, pcntl_wifcontinued, pcntl_wifexited, pcntl_wifsignaled, pcntl_wifstopped, pcntl_wstopsig, pcntl_wtermsig, popen, posix_getpwuid, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid, posix_setuid, posix_uname, proc_close, proc_get_status, proc_nice, proc_open, proc_terminate, show_source, system

15.7. Installer et configurer des certificats SSL GRATUITS - Partie 1

Section intitulée « 15.7. Installer et configurer des certificats SSL GRATUITS - Partie 1 »

Le chiffrement HTTPS est essentiel pour la sécurité de WordPress. Let’s Encrypt fournit des certificats SSL gratuits qui sont reconnus par tous les navigateurs majeurs.

Certbot est un outil qui automatise le processus d’obtention et de renouvellement des certificats Let’s Encrypt :

# Mettre à jour les listes de paquets
sudo apt update
# Installer Certbot et le plugin Nginx
sudo apt install certbot python3-certbot-nginx

Utilisez le plugin webroot pour obtenir un certificat sans interrompre votre site web :

# Obtenir un certificat pour votre domaine
sudo certbot certonly --webroot -w /var/www/example.com/public_html/ -d example.com -d www.example.com

Suivez les invites pour terminer le processus d’émission du certificat.

15.8. Installer et configurer des certificats SSL GRATUITS - Partie 2

Section intitulée « 15.8. Installer et configurer des certificats SSL GRATUITS - Partie 2 »

Pour renforcer la sécurité de votre implémentation SSL/TLS, créez un fichier de paramètres Diffie-Hellman fort :

# Créer le répertoire SSL
cd /etc/nginx/
sudo mkdir ssl/
cd ssl/
# Générer les paramètres DH (cela peut prendre quelques minutes)
sudo openssl dhparam -out dhparam.pem 2048

15.8.2. Création de la configuration SSL spécifique au site

Section intitulée « 15.8.2. Création de la configuration SSL spécifique au site »

Créez un fichier de configuration pour les certificats SSL de votre site :

# Créer le fichier de configuration des certificats SSL
sudo vim /etc/nginx/ssl/ssl_certs_example.com.conf

Ajoutez le contenu suivant :

# Chemins des certificats
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Certificat de stapling SSL
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

15.9. Installer et configurer des certificats SSL GRATUITS - Partie 3

Section intitulée « 15.9. Installer et configurer des certificats SSL GRATUITS - Partie 3 »

Créez un fichier de configuration SSL global avec des paramètres de sécurité optimaux :

# Créer le fichier de configuration SSL global
sudo vim /etc/nginx/ssl/ssl_all_sites.conf

Ajoutez le contenu suivant :

# CONFIGURATION RESULTAT EN NOTE A+ SUR SSLLABS.COM
# MISE A JOUR DES DIRECTIVES POUR MAINTENIR LA NOTE A+ - VERIFIER LA DATE
# DATE: OCTOBER 2024
# CACHE SSL ET PROTOCOLES
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 180m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# ssl_ciphers doit etre sur une seule ligne, ne pas repartir sur plusieurs lignes
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
# resolver defini sur Cloudflare
# timeout peut etre defini jusqu'a 30s
resolver 1.1.1.1 1.0.0.1;
resolver_timeout 15s;
ssl_session_tickets off;
# EN-TETES HSTS
add_header Strict-Transport-Security "max-age=31536000;" always;
# Apres avoir configure TOUS vos sous-domaines - commentez la ligne ci-dessus et decommentez la directive ci-dessous
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains;" always;
# Activer QUIC et HTTP/3
ssl_early_data on;
add_header Alt-Svc 'h3=":$server_port"; ma=86400';
add_header x-quic 'H3';
quic_retry on;

Mettez à jour votre bloc serveur Nginx pour utiliser HTTPS :

# Modifier la configuration Nginx de votre site
sudo vim /etc/nginx/sites-available/example.com.conf

Ajoutez un bloc serveur pour rediriger HTTP vers HTTPS :

# Redirection HTTP vers HTTPS
server {
listen 80;
server_name example.com www.example.com;
# Redirection permanente 301
return 301 https://example.com$request_uri;
}

Configurez le bloc serveur HTTPS :

# Bloc serveur HTTPS
server {
# Activer SSL, HTTP/2 et HTTP/3
listen 443 ssl;
http2 on;
# Support HTTP/3
listen 443 quic reuseport;
http3 on;
server_name example.com www.example.com;
# Inclure les fichiers de configuration SSL
include /etc/nginx/ssl/ssl_certs_example.com.conf;
include /etc/nginx/ssl/ssl_all_sites.conf;
# Reste de votre configuration serveur...
}

Appliquez les modifications :

# Tester la configuration Nginx
sudo nginx -t
# Recharger Nginx si le test est réussi
sudo systemctl reload nginx

Vérifiez que votre configuration SSL fonctionne correctement :

# Tester la redirection HTTP vers HTTPS
curl -I http://example.com
# Tester la connexion HTTPS
curl -I https://example.com

Vous pouvez également tester votre configuration SSL avec des outils en ligne :

15.9.4. Configuration du renouvellement automatique des certificats

Section intitulée « 15.9.4. Configuration du renouvellement automatique des certificats »

Les certificats Let’s Encrypt expirent après 90 jours, le renouvellement automatique est donc essentiel :

# Modifier le crontab root
sudo crontab -e

Ajoutez les lignes suivantes :

# Renouveler les certificats deux fois par mois et recharger Nginx
00 1 14,28 * * certbot renew --force-renewal --deploy-hook "systemctl reload nginx" >> /var/log/certbot-renew.log 2>&1

Définissez les permissions appropriées pour le fichier journal :

# Créer le fichier journal s'il n'existe pas
sudo touch /var/log/certbot-renew.log
# Définir les permissions appropriées
sudo chmod 644 /var/log/certbot-renew.log

15.10. Durcissement des en-têtes de réponse HTTP

Section intitulée « 15.10. Durcissement des en-têtes de réponse HTTP »

Les en-têtes de sécurité HTTP aident à protéger votre site contre diverses attaques comme le XSS, le clickjacking et le reniflage de type de contenu.

15.10.1. Création d’une configuration d’en-têtes de sécurité

Section intitulée « 15.10.1. Création d’une configuration d’en-têtes de sécurité »

Créez un fichier de configuration pour les en-têtes de sécurité :

# Créer le fichier de configuration des en-têtes de sécurité
cd /etc/nginx/includes/
sudo vim http_headers.conf

Ajoutez le contenu suivant :

# Politique de référent
# Contrôle la quantité d'informations de référent incluse dans les requêtes
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Options de type de contenu
# Empêche les navigateurs de deviner le type MIME d'une réponse
add_header X-Content-Type-Options "nosniff" always;
# Options de cadre
# Protège contre le clickjacking en empêchant votre page d'être affichée dans un cadre
add_header X-Frame-Options "sameorigin" always;
# Protection XSS
# Active le filtre de script intersite (XSS) dans les navigateurs
add_header X-XSS-Protection "1; mode=block" always;
# Politique de permissions
# Contrôle quelles fonctionnalités et API du navigateur peuvent être utilisées
add_header Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=self,payment=()" always;

15.10.2. Création d’une configuration d’en-têtes de mise en cache et de sécurité

Section intitulée « 15.10.2. Création d’une configuration d’en-têtes de mise en cache et de sécurité »

Pour le contenu statique, créez une configuration combinant mise en cache et en-têtes de sécurité :

# Créer le fichier de configuration des en-têtes de mise en cache et de sécurité
sudo vim /etc/nginx/includes/browser_caching_security_headers.conf

Ajoutez le contenu suivant :

# Activer la mise en cache du navigateur
expires 30d;
etag on;
if_modified_since exact;
add_header Pragma "public" always;
add_header Cache-Control "public, no-transform" always;
# Inclure les en-têtes de sécurité
include /etc/nginx/includes/http_headers.conf;
# Désactiver la journalisation d'accès pour le contenu statique
access_log off;

15.10.3. Implémentation des en-têtes de sécurité

Section intitulée « 15.10.3. Implémentation des en-têtes de sécurité »

Ajoutez les en-têtes de sécurité à votre bloc serveur Nginx :

# Modifier la configuration Nginx de votre site
sudo vim /etc/nginx/sites-available/example.com.conf

Ajoutez la directive d’inclusion au-dessus du bloc location de traitement PHP :

# Inclure les en-têtes de sécurité
include /etc/nginx/includes/http_headers.conf;

Appliquez les modifications :

# Tester la configuration Nginx
sudo nginx -t
# Recharger Nginx si le test est réussi
sudo systemctl reload nginx

15.11. Utilisation des directives Nginx pour protéger WordPress

Section intitulée « 15.11. Utilisation des directives Nginx pour protéger WordPress »

Nginx peut être configuré pour bloquer l’accès aux fichiers WordPress sensibles et prévenir les vecteurs d’attaque courants.

15.11.1. Création des directives de sécurité WordPress

Section intitulée « 15.11.1. Création des directives de sécurité WordPress »

Créez un fichier de configuration pour les directives de sécurité WordPress :

# Créer le fichier de directives de sécurité WordPress
cd /etc/nginx/includes/
sudo vim nginx_security_directives.conf

Ajoutez le contenu suivant :

# Refuser l'accès aux fichiers WordPress sensibles
location = /wp-config.php { deny all; }
location = /wp-admin/install.php { deny all; }
location ~* /readme\.html$ { deny all; }
location ~* /readme\.txt$ { deny all; }
location ~* /licence\.txt$ { deny all; }
location ~* /license\.txt$ { deny all; }
location ~ ^/wp-admin/includes/ { deny all; }
location ~ ^/wp-includes/[^/]+\.php$ { deny all; }
location ~ ^/wp-includes/js/tinymce/langs/.+\.php$ { deny all; }
location ~ ^/wp-includes/theme-compat/ { deny all; }
# Désactiver l'exécution PHP dans les répertoires potentiellement dangereux
location ~* ^/wp\-content/uploads/.*\.(?:php[1-7]?|pht|phtml?|phps)$ { deny all; }
location ~* ^/wp\-content/plugins/.*\.(?:php[1-7]?|pht|phtml?|phps)$ { deny all; }
location ~* ^/wp\-content/themes/.*\.(?:php[1-7]?|pht|phtml?|phps)$ { deny all; }
# Désactiver l'accès au fichier de surcharge PHP du site
location = /.user.ini { deny all; }
# Filtrer les méthodes de requête suspectes
if ( $request_method ~* ^(TRACE|DELETE|TRACK)$ ) { return 403; }
# Filtrer les chaînes de requête suspectes dans l'URL
set $susquery 0;
if ( $args ~* "\.\./" ) { set $susquery 1; }
if ( $args ~* "\.(bash|git|hg|log|svn|swp|cvs)" ) { set $susquery 1; }
if ( $args ~* "etc/passwd" ) { set $susquery 1; }
if ( $args ~* "boot\.ini" ) { set $susquery 1; }
if ( $args ~* "ftp:" ) { set $susquery 1; }
if ( $args ~* "(<|%3C)script(>|%3E)" ) { set $susquery 1; }
if ( $args ~* "mosConfig_[a-zA-Z_]{1,21}(=|%3D)" ) { set $susquery 1; }
if ( $args ~* "base64_decode\(" ) { set $susquery 1; }
if ( $args ~* "%24&x" ) { set $susquery 1; }
if ( $args ~* "127\.0" ) { set $susquery 1; }
if ( $args ~* "(globals|encode|request|localhost|loopback|request|insert|concat|union|declare)" ) { set $susquery 1; }
if ( $args ~* "%[01][0-9A-F]" ) { set $susquery 1; }
# Exceptions pour les fonctionnalités WordPress légitimes
if ( $args ~ "^loggedout=true" ) { set $susquery 0; }
if ( $args ~ "^action=jetpack-sso" ) { set $susquery 0; }
if ( $args ~ "^action=rp" ) { set $susquery 0; }
if ( $http_cookie ~ "wordpress_logged_in_" ) { set $susquery 0; }
if ( $http_referer ~* "^https?://maps\.googleapis\.com/" ) { set $susquery 0; }
if ( $susquery = 1 ) { return 403; }
# Bloquer les injections SQL courantes
set $block_sql_injections 0;
if ($query_string ~ "union.*select.*\(") { set $block_sql_injections 1; }
if ($query_string ~ "union.*all.*select.*") { set $block_sql_injections 1; }
if ($query_string ~ "concat.*\(") { set $block_sql_injections 1; }
if ($block_sql_injections = 1) { return 403; }
# Bloquer les injections de fichiers
set $block_file_injections 0;
if ($query_string ~ "[a-zA-Z0-9_]=http://") { set $block_file_injections 1; }
if ($query_string ~ "[a-zA-Z0-9_]=(\.\.//?)+") { set $block_file_injections 1; }
if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") { set $block_file_injections 1; }
if ($block_file_injections = 1) { return 403; }
# Bloquer les exploits courants
set $block_common_exploits 0;
if ($query_string ~ "(<|%3C).*script.*(>|%3E)") { set $block_common_exploits 1; }
if ($query_string ~ "GLOBALS(=|\[|\%[0-9A-Z]{0,2})") { set $block_common_exploits 1; }
if ($query_string ~ "_REQUEST(=|\[|\%[0-9A-Z]{0,2})") { set $block_common_exploits 1; }
if ($query_string ~ "proc/self/environ") { set $block_common_exploits 1; }
if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|\%3D)") { set $block_common_exploits 1; }
if ($query_string ~ "base64_(en|de)code\(.*\)") { set $block_common_exploits 1; }
if ($block_common_exploits = 1) { return 403; }
# Bloquer le spam
set $block_spam 0;
if ($query_string ~ "\b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)\b") { set $block_spam 1; }
if ($query_string ~ "\b(erections|hoodia|huronriveracres|impotence|levitra|libido)\b") { set $block_spam 1; }
if ($query_string ~ "\b(ambien|blue\spill|cialis|cocaine|ejaculation|erectile)\b") { set $block_spam 1; }
if ($query_string ~ "\b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)\b") { set $block_spam 1; }
if ($block_spam = 1) { return 403; }
# Bloquer les agents utilisateurs malveillants
set $block_user_agents 0;
if ($http_user_agent ~ "Indy Library") { set $block_user_agents 1; }
if ($http_user_agent ~ "libwww-perl") { set $block_user_agents 1; }
if ($http_user_agent ~ "GetRight") { set $block_user_agents 1; }
if ($http_user_agent ~ "GetWeb!") { set $block_user_agents 1; }
if ($http_user_agent ~ "Go!Zilla") { set $block_user_agents 1; }
if ($http_user_agent ~ "Download Demon") { set $block_user_agents 1; }
if ($http_user_agent ~ "Go-Ahead-Got-It") { set $block_user_agents 1; }
if ($http_user_agent ~ "TurnitinBot") { set $block_user_agents 1; }
if ($http_user_agent ~ "GrabNet") { set $block_user_agents 1; }
# Bloquer les outils de scan de sécurité courants
if ($http_user_agent ~ "dirbuster") { set $block_user_agents 1; }
if ($http_user_agent ~ "nikto") { set $block_user_agents 1; }
if ($http_user_agent ~ "sqlmap") { set $block_user_agents 1; }
if ($http_user_agent ~ "fimap") { set $block_user_agents 1; }
if ($http_user_agent ~ "nessus") { set $block_user_agents 1; }
if ($http_user_agent ~ "whatweb") { set $block_user_agents 1; }
if ($http_user_agent ~ "Openvas") { set $block_user_agents 1; }
if ($http_user_agent ~ "jbrofuzz") { set $block_user_agents 1; }
if ($http_user_agent ~ "libwhisker") { set $block_user_agents 1; }
if ($http_user_agent ~ "webshag") { set $block_user_agents 1; }
if ($http_user_agent ~ "Acunetix") { set $block_user_agents 1; }
if ($block_user_agents = 1) { return 403; }

15.11.2. Implémentation des directives de sécurité WordPress

Section intitulée « 15.11.2. Implémentation des directives de sécurité WordPress »

Ajoutez les directives de sécurité à votre bloc serveur Nginx :

# Modifier la configuration Nginx de votre site
sudo vim /etc/nginx/sites-available/example.com.conf

Ajoutez la directive d’inclusion au-dessus du bloc location de traitement PHP :

# Inclure les directives de sécurité WordPress
include /etc/nginx/includes/nginx_security_directives.conf;

Appliquez les modifications :

# Tester la configuration Nginx
sudo nginx -t
# Recharger Nginx si le test est réussi
sudo systemctl reload nginx

15.11.3. Autoriser l’exécution PHP pour des fichiers d’extensions spécifiques

Section intitulée « 15.11.3. Autoriser l’exécution PHP pour des fichiers d’extensions spécifiques »

Certaines extensions nécessitent l’exécution PHP dans le répertoire des extensions. Puisque nous avons bloqué l’exécution PHP dans ce répertoire pour des raisons de sécurité, nous devons l’autoriser sélectivement pour les fichiers d’extensions légitimes.

Vérifiez d’abord que l’exécution PHP est bloquée dans le répertoire des extensions :

# Créer un fichier PHP de test dans le répertoire des extensions
cd /var/www/example.com/
sudo vim public_html/wp-content/plugins/test.php

Ajoutez ce contenu au fichier de test :

<?php
phpinfo();
?>

Lorsque vous essayez d’accéder à ce fichier dans votre navigateur (https://example.com/wp-content/plugins/test.php), vous devriez recevoir une erreur 403 Forbidden, confirmant que l’exécution PHP est bloquée.

Autoriser des fichiers d’extensions spécifiques

Section intitulée « Autoriser des fichiers d’extensions spécifiques »

Pour autoriser l’exécution PHP pour des fichiers d’extensions spécifiques, ajoutez un bloc location pour chaque fichier :

# Modifier la configuration Nginx de votre site
sudo vim /etc/nginx/sites-available/example.com.conf

Ajoutez un bloc location pour chaque fichier d’extension nécessitant l’exécution PHP :

# Autoriser l'exécution PHP pour des fichiers d'extensions spécifiques
location = /wp-content/plugins/specific-plugin/file.php {
allow all;
include snippets/fastcgi-php.conf;
fastcgi_param HTTP_HOST $host;
fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock;
include /etc/nginx/includes/fastcgi_optimize.conf;
}

Appliquez les modifications :

# Tester la configuration Nginx
sudo nginx -t
# Recharger Nginx et redémarrer PHP-FPM
sudo systemctl reload nginx && sudo systemctl restart php8.3-fpm

N’oubliez pas de supprimer le fichier de test :

# Supprimer le fichier PHP de test
sudo rm /var/www/example.com/public_html/wp-content/plugins/test.php

Le hotlinking se produit lorsque d’autres sites web créent des liens directs vers vos images ou fichiers, consommant votre bande passante. Empêchez cela avec Nginx :

# Modifier la configuration Nginx de votre site
sudo vim /etc/nginx/sites-available/example.com.conf

Ajoutez ce qui suit à votre bloc serveur :

# Empêcher le hotlinking des images
location ~* \.(jpg|jpeg|png|gif|webp|svg)$ {
valid_referers none blocked server_names *.example.com example.com;
if ($invalid_referer) {
return 403;
}
# Inclure la mise en cache du navigateur pour les images
include /etc/nginx/includes/browser_caching_security_headers.conf;
}

15.13. Stopper les attaques par force brute - Limitation de débit Nginx

Section intitulée « 15.13. Stopper les attaques par force brute - Limitation de débit Nginx »

La limitation de débit aide à prévenir les attaques par force brute en limitant le nombre de requêtes qu’un client peut effectuer dans une période donnée.

Commencez par ajouter la zone de limitation de débit à votre configuration Nginx principale :

# Modifier la configuration Nginx principale
cd /etc/nginx/
sudo vim nginx.conf

Ajoutez ce qui suit au contexte http :

# Zone de limitation de débit pour WordPress
limit_req_zone $binary_remote_addr zone=wp:10m rate=30r/m;

Cela crée une zone de 10 Mo nommée “wp” qui limite les clients à 30 requêtes par minute.

15.13.2. Création d’une configuration de limitation de débit

Section intitulée « 15.13.2. Création d’une configuration de limitation de débit »

Créez un fichier de configuration pour la limitation de débit du login WordPress et XML-RPC :

# Créer le fichier de configuration de limitation de débit
cd /etc/nginx/includes/
sudo vim rate_limiting.conf

Ajoutez le contenu suivant :

# Limiter le débit de la page de connexion WordPress
location = /wp-login.php {
limit_req zone=wp burst=20 nodelay;
limit_req_status 444;
include snippets/fastcgi-php.conf;
fastcgi_param HTTP_HOST $host;
fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock;
include /etc/nginx/includes/fastcgi_optimize.conf;
}
# Limiter le débit du XML-RPC WordPress (souvent utilisé dans les attaques par force brute)
location = /xmlrpc.php {
limit_req zone=wp burst=20 nodelay;
limit_req_status 444;
include snippets/fastcgi-php.conf;
fastcgi_param HTTP_HOST $host;
fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock;
include /etc/nginx/includes/fastcgi_optimize.conf;
}

15.13.3. Implémentation de la limitation de débit

Section intitulée « 15.13.3. Implémentation de la limitation de débit »

Ajoutez la configuration de limitation de débit à votre bloc serveur Nginx :

# Modifier la configuration Nginx de votre site
sudo vim /etc/nginx/sites-available/example.com.conf

Ajoutez la directive d’inclusion :

# Inclure la configuration de limitation de débit
include /etc/nginx/includes/rate_limiting.conf;

Appliquez les modifications :

# Tester la configuration Nginx
sudo nginx -t
# Recharger Nginx si le test est réussi
sudo systemctl reload nginx

WordPress permet aux administrateurs de modifier les fichiers de thèmes et d’extensions directement depuis le tableau de bord d’administration. Cela peut être un risque de sécurité si un attaquant obtient l’accès à votre compte administrateur.

15.14.1. Désactivation des modifications de fichiers dans wp-config.php

Section intitulée « 15.14.1. Désactivation des modifications de fichiers dans wp-config.php »

Modifiez votre fichier wp-config.php pour désactiver les modifications de fichiers :

# Modifier wp-config.php
sudo vim /var/www/example.com/public_html/wp-config.php

Ajoutez la ligne suivante avant le commentaire “That’s all, stop editing!” :

/* Désactiver les modifications de fichiers */
define('DISALLOW_FILE_MODS', true);

Appliquez les modifications :

# Recharger PHP-FPM
sudo systemctl reload php8.3-fpm

15.15. Restriction des privilèges utilisateur de la base de données

Section intitulée « 15.15. Restriction des privilèges utilisateur de la base de données »

L’utilisateur de la base de données WordPress ne devrait avoir que les privilèges nécessaires à son fonctionnement, et non un accès complet à la base de données.

15.15.1. Limitation des privilèges utilisateur de la base de données

Section intitulée « 15.15.1. Limitation des privilèges utilisateur de la base de données »

Connectez-vous à votre serveur MariaDB et restreignez les privilèges de l’utilisateur de la base de données WordPress :

# Se connecter à MariaDB
sudo mysql -u root -p

Exécutez ces commandes SQL :

-- Révoquer tous les privilèges
REVOKE ALL PRIVILEGES ON wordpress_db.* FROM 'wordpress_user'@'localhost';
-- Accorder uniquement les privilèges nécessaires
GRANT SELECT, INSERT, UPDATE, DELETE ON wordpress_db.* TO 'wordpress_user'@'localhost';
-- Appliquer les modifications
FLUSH PRIVILEGES;

Quittez la console MariaDB :

EXIT;

L’API REST WordPress peut être une cible pour les attaquants. Par défaut, elle est accessible à tous, mais nous pouvons restreindre l’accès aux utilisateurs authentifiés uniquement.

15.16.1. Restriction de l’accès à l’API REST

Section intitulée « 15.16.1. Restriction de l’accès à l’API REST »

Ajoutez le code suivant au fichier functions.php de votre thème ou à une extension personnalisée :

/**
* Restreindre l'API REST aux utilisateurs authentifiés
*/
function restrict_rest_api_to_authenticated_users($access) {
// Si non authentifié, bloquer l'accès
if (!is_user_logged_in()) {
return new WP_Error('rest_api_restricted', 'REST API access is restricted to authenticated users.', array('status' => 401));
}
// Sinon, autoriser l'accès
return $access;
}
add_filter('rest_authentication_errors', 'restrict_rest_api_to_authenticated_users');

Pour une couche de sécurité supplémentaire, vous pouvez également restreindre l’accès à l’API REST au niveau Nginx :

# Modifier la configuration Nginx de votre site
sudo vim /etc/nginx/sites-available/example.com.conf

Ajoutez le bloc location suivant :

# Restreindre l'API REST WP
location /wp-json/ {
# Autoriser l'accès uniquement si connecté ou depuis des IP spécifiques
if ($http_cookie !~* "wordpress_logged_in_") {
# Autoriser des IP spécifiques (remplacez par votre IP)
allow 192.168.1.1;
# Bloquer tous les autres
deny all;
}
# Continuer le traitement de la requête
try_files $uri $uri/ /index.php?$args;
}

Appliquez les modifications :

# Tester la configuration Nginx
sudo nginx -t
# Recharger Nginx si le test est réussi
sudo systemctl reload nginx

Un pare-feu applicatif web (WAF) fournit une couche de sécurité supplémentaire en filtrant et surveillant le trafic HTTP entre une application web et Internet.

ModSecurity est un WAF open source qui peut être intégré à Nginx :

# Installer ModSecurity et les dépendances
sudo apt update
sudo apt install -y libmodsecurity3 libmodsecurity-dev nginx-module-security

Créez une configuration de base ModSecurity :

# Créer le répertoire de configuration ModSecurity
sudo mkdir -p /etc/nginx/modsec
# Télécharger le jeu de règles OWASP Core Rule Set
sudo git clone https://github.com/coreruleset/coreruleset /etc/nginx/modsec/coreruleset
# Créer le fichier de configuration ModSecurity
sudo vim /etc/nginx/modsec/modsec.conf

Ajoutez le contenu suivant :

# Configuration de base ModSecurity
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml application/json
SecResponseBodyLimit 1024
# Inclure le jeu de règles OWASP Core Rule Set
Include /etc/nginx/modsec/coreruleset/crs-setup.conf
Include /etc/nginx/modsec/coreruleset/rules/*.conf

Modifiez votre configuration Nginx pour activer ModSecurity :

# Modifier la configuration Nginx principale
sudo vim /etc/nginx/nginx.conf

Ajoutez ce qui suit au contexte http :

# Charger le module ModSecurity
load_module modules/ngx_http_modsecurity_module.so;

Modifiez le bloc serveur de votre site :

# Modifier la configuration Nginx de votre site
sudo vim /etc/nginx/sites-available/example.com.conf

Ajoutez les directives ModSecurity à votre bloc serveur :

# Activer ModSecurity
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/modsec.conf;

Appliquez les modifications :

# Tester la configuration Nginx
sudo nginx -t
# Recharger Nginx si le test est réussi
sudo systemctl reload nginx

En implémentant ces mesures de sécurité, vous avez considérablement durci votre installation WordPress contre les menaces courantes. N’oubliez pas que la sécurité est un processus continu et que vous devez :

  1. Mettre régulièrement à jour le noyau WordPress, les thèmes et les extensions
  2. Surveiller vos journaux pour détecter les activités suspectes
  3. Effectuer des audits de sécurité réguliers
  4. Conserver des sauvegardes de votre site et de votre base de données
  5. Rester informé des nouvelles menaces de sécurité et des bonnes pratiques