Comment sécuriser ton site WordPress avec le fichier .htaccess ?

Publié le 
31 décembre 2020

Comment sécuriser ton site WordPress avec le fichier .htaccess ?

Dans cet article tu vas voir comment sécuriser ton site Wordpress avec le fichier .htaccess (qui vient de "hypertext access"). En effet, il est important de prendre du temps d'appliquer quelques règles simples de sécurité pour être sûr que ton site ne soit pas compromis. 

Voici quelques règles de sécurité qui tu pourras appliquer à ton site internet. Pour cela tu devras t'assurer tout d'abord, que ton hébergeur te permette de modifier le fichier .htaccess

Ce fichier de configuration n'existe que sur Apache, donc pas la peine de le chercher sur Nginx ou LiteSpeed par exemple. 

Avant tout, pense à effectuer un backup de ton site WordPress et de ta BDD, avant de modifier quoi que ce soit. Et si tu as un site de développement teste dessus, avant de faire ces modifications sur ton site en production. Enfin, à chaque modification, vérifie bien que tout ton site fonctionne bien, avant de mettre en place de nouvelles règles. 

Il existe sur internet des générateurs de fichier htaccess.

À quoi sert le fichier .htaccess ?  

Le fichier .htaccess permet de configurer ton serveur Web Apache. Il te servira à affiner des développements supplémentaires non prévus par certaines plateformes, à renforcer certains paramètres de sécurité sur certaines zones de son site, et à optimiser certains aspects de ton hébergement (organisation personnelle)  ou de ton site internet.

Afin d’avoir une vue plus synthétique, j’ai regroupé dans 5 pouvoirs du fichier htaccess. Ces exemples sont prêts à l'emploi, mais restent à personnaliser selon ta configuration.

  • Sécurité
  • Serveur
  • Site (performance)
  • SEO
  • Expérience Utilisateur (UX)

1. Performances de ton serveur

Limiter le nombre de connexions simultanées

MaxClients < nombre-de-connexions>

Configuration de la Timezone de ton serveur

# SetEnv TZ Continent/Pays
SetEnv TZ France/Paris

2. Performances de ton site

Augmenter la mémoire PHP

L’utilisation d’applications PHP est soumise à une limite de mémoire causée par les scripts PHP sur ton serveur. Cette mémoire peut être augmentée en fonction des besoins en utilisant la directive suivante :

# PHP Memory Limit php_value memory_limit 256M

Permettre la compression

<ifModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/x-javascript
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4.0[678] no-gzip
BrowserMatch bMSIE !no-gzip !gzip-only-text/html
</ifModule>

Utiliser le cache navigateur pour accélérer le chargement de ton site

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg « access 1 year »
ExpiresByType image/jpeg « access 1 year »
ExpiresByType image/gif « access 1 year »
ExpiresByType image/png « access 1 year »
ExpiresByType text/css « access 1 month »
ExpiresByType application/pdf « access 1 month »
ExpiresByType text/x-javascript « access 1 month »
ExpiresByType application/x-shockwave-flash « access 1 month »
ExpiresByType image/x-icon « access 1 year »
ExpiresDefault « access 2 days »
</IfModule>

Définir la police des documents de ton site

Les accents peuvent poser des problèmes si aucun codage de caractère n'existe. Pour cela, tu dois spécifier au fichier .htaccess, quel codage doit être utilisé pour chaque document type. Avec la directive suivante tu utiliseras le codage UTF-8 pour tous les documents (html, css, php, etc.) :

# Définir le codage de caractères
AddDefaultCharset utf-8

Si seuls quelques types de documents doivent être définis par codage, utilise cette directive :

# Définir le codage de caractères pour certains fichiers 
AddDefaultCharset utf-8 .css .htm .html .xhtml .php 

3. Expérience Utilisateur (UX)

Les redirections

un des usages du fichier .htaccess est de rédiger des pages , que cela soit sur ton même site, ou sur un autre.  Tout d'abord : rediriger une vieille page vers une nouvelle sur le même site internet : 

RewriteEngine on

Redirect 301 /old.html /new.html

Rediriger une vieille page vers une nouvelle sur un autre site : 

RewriteEngine on

Redirect 301 /old.html http://autresite/new.html

Rediriger toutes les archives d'un répertoire à un autre :

RewriteEngine on

Redirect 301 /docs/ http://new.example.com/docs/

Rediriger à une page toutes les pages d'un répertoire :

RewriteOptions inherit

RewriteEngine On

RewriteRule ^(.*)$ https://page.html [R=301,L]

Rediriger un site sans WWW, vers des adresses avec WWW :

RewriteEngine on

RewriteCond %{HTTP_HOST} ^example.com [NC]

RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]

La même action antérieure, mais sans spécifier le nom de domaine et utiliser HTTPS et HTTPS :

ewriteCond %{HTTPS} off

RewriteCond %{HTTP_HOST} !^www.(.*)$ [NC]

RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

 

RewriteCond %{HTTPS} on

RewriteCond %{HTTP_HOST} !^www.(.*)$ [NC]

RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]

Rediriger un site avec WWW à des adresses sans WWW :

RewriteEngine on

rewritecond %{http_host} ^www.norfipc.com [nc]

rewriterule ^(.*)$ http://norfipc.com/$1 [r=301,nc]

La même action antérieure, mais sans spécifier le nom de domaine :

RewriteCond %{HTTP_HOST} ^www.(.+)$ [NC]

RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

La même chose, mais pour rediriger et utiliser HTTP et HTTPS

RewriteCond %{HTTPS} off

RewriteCond %{HTTP_HOST} ^www.(.*)$ [NC]

RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

 

RewriteCond %{HTTPS} on

RewriteCond %{HTTP_HOST} ^www.(.*)$ [NC]

RewriteRule ^(.*)$ https://%1/$1 [R=301,L]

Utiliser HTTPS sur tout un site. Il y a 2 options :

RewriteCond %{HTTPS} !on

RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

RewriteCond %{SERVER_PORT} 80

RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

Rediriger automatiquement le visiteur en HTTPS quand il visite le site en HTTP

RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.votredomaine.fr/$1 [R,L]

Créer et utiliser des pages d'erreur personnalisées

Devant une erreur d'accès à ton site internet, tes usagers recevront une page d'erreur prédéterminée codée . L'idéal est de créer ta propre page d'erreur personnalisée (avec ta charte graphique) avec une explication détaillée dans chaque cas d'erreur, la page d'erreur 404 est fondamentale. 

ErrorDocument 404 / introuvable404.html
#Pour les autres types d'erreurs :
ErrorDocument 403/ nonautorise500.html ErrorDocument 500 / erreur500.html

Redirection vers une page de maintenance

Remplacer la page dénommée maintenance.html par la page que sur laquelle tu souhaites rediriger le visiteur avec l’adresse IP voulue ( note la redirection 302 pour éviter l’indexation de cette page temporaire).

#On active le rewriting
RewriteEngine on
RewriteCond %{REQUEST_URI} !/maintenance.html$
RewriteCond %{REMOTE_ADDR} !^123.123.123.123
RewriteRule $ /maintenance.html [R=302,L]

Protège ton site WordPress avec ton fichier .htaccess

Protection des fichier importants du Core de WordPress

<FilesMatch "^.*(error_log|wp-config.php|php.ini|.[hH][tT][aApP].*)$">
Order deny,allow
Deny from all
</FilesMatch>

Protection du fichier .htaccess lui-même

#htaccess file
<files .htaccess>
order allow,deny
deny from all
</files> 

Protéger un fichier en particulier

# protéger  monfichier.php
<files monfichier.php>
order allow,deny
deny from all
</files>

Protéger un fichier de ton site par un mot-de-passe

<Files secure.php>
AuthType Basic
AuthName « Prompt »
AuthUserFile /home/path/.htpasswd
Require valid-user
</Files>

Protéger un répertoire de ton site par un mot-de-passe

La façon la plus sûre de protéger l'accès à un répertoire complet de ton serveur, pour que l'on puisse y accéder seulement avec un login et un mot-de-passe, est d'utiliser la directive "AuthConfig".

Pour cela, 2 actions seront nécessaires :

  1. créer un fichier .htpasswd (il peut avoir un autre nom) qui contienne le nom de l'usager et son mot-de-passe. Sauvegarde ce fichier dans un répertoire qui ne soit pas accessible depuis le web. Tu peux utiliser une service en ligne pour créer ton fichier .htpasswd
  2. créer un fichier .htaccess dans le répertoire qui tu souhaites protéger, avec le code suivant :
AuthType Basic
AuthName "Ce repertoire est protégé"
AuthUserFile /chemin/.htpasswd
Require valid-user

Interdire le Hotlinking d'images

Le Hotlinking permet à une tierce personne d’utiliser l’adresse d’un fichier publié sur ton site Internet, le plus souvent une image, et de l’afficher sur un autre site sans l’enregistrer sur son propre serveur. Cela entraîne une augmentation du volume de données sur ton site (le site d’origine), sans que tu ne puisses rien faire. La solution est de bloquer ces liens grâce à la directive suivante :

RewriteEngine on 
RewriteCond %{HTTP_REFERER} !^$ 
RewriteCond %{HTTP_REFERER} !^http:// www.ton-domaine/.*$ [NC] [OR]
RewriteCond %{HTTP_REFERER} !^http://www.ton-domaine/.*$ [NC] [OR]
RewriteRule .*.(gif|GIF|jpg|JPG|bmp|BMP|wav|mp3|wmv|avi|mpeg)$ - [F]

Tu peux également autoriser Google Images, certains bots ou réseaux sociaux, en mettant cette directive : 

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?norfipc.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?google.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?bing.com [NC]
#Permettre l'accès par URL RewriteCond %{HTTP_REFERER} !^$
#Permettre l'accès des moteurs de recherche RewriteCond %{HTTP_REFERER} !google. [NC] RewriteCond %{HTTP_REFERER} !search?q=cache [NC] RewriteCond %{HTTP_REFERER} !msn. [NC] RewriteCond %{HTTP_REFERER} !yahoo. [NC]
#Permettre l'accès de robots RewriteCond %{HTTP_USER_AGENT} !googlebot [NC] RewriteCond %{HTTP_USER_AGENT} !msnbot [NC]
#Permittre l'accès de réseaux sociaux RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?pinterest.com [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?tumblr.com [NC] RewriteRule .(jpg|jpeg|png|gif)$ - [NC,F,L]

Changer la page Index d'un répertoire

Par défaut, le fichier index d’un répertoire est index.html, index.htm ou index.php. Si tu veux que ce soit un autre fichier, rajoute cette ligne :

DirectoryIndex about.html 

Par exemple, si tu veux utiliser la page accueil.html comme page d’index, utilise la ligne suivante :

 
DirectoryIndex accueil.html

Protection contre les injections via des scripts malveillants du March

RewriteEngine On
RewriteCond %{QUERY_STRING} (<|%3C).*script malveillant.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|[|%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]

Accepter l'accès à un dossier du serveur que pour 1 IP

#Plusieurs adresses IP sont possibles , avec une instruction par ligne.
AuthUserFile /dev/null
AuthGroupFile /dev/null
AuthName « Example Access Control »
AuthType Basic
<LIMIT GET>
order deny,allow
deny from all
allow from xx.xx.xx.xx
</LIMIT>

Désactiver le XML RPC2 

This is a block of text. Double-click this text to edit it.
# Block WordPress xmlrpc.php requests
<Files xmlrpc.php>
order deny,allow
 deny from all
 allow from xxx.xxx.xxx.xxx
</Files>

Attaque par énumération d'utilisateurs

C'est quand un hacker essaye de trouver les identifiants de connexion des utilisateurs d'un système (nom d'utilisateur à la fin d'une URL WordPress ou dans l'URL d'une page d'archive. avec le nom d'utilisateur il aura déjà 50% de chance de se connecter à ton site, il ne lui restera plus qu'à trouver ton mot-de-passe. 

Pour cela, un hacker tentera d’entrer un certain nombre de noms d’utilisateurs et observera le comportement de l’application pour déterminer si un identifiant est valide ou non ( temps de réponse différents, message d’erreur différent et plus généralement toute différence au niveau réponse HTTP).

Le hacker pourra par exemple essayer de trouver des adresses email ou des personnes liées à sa cible sur des moteurs de recherche ou sur les réseaux sociaux. Donc attention de bien avoir un identifiant qui ne soit pas de type "admin", "mon nom", "mon adresse mail",etc.

Formulaire de connexion : Par exemple, en essayant de se connecter à WordPress, on aura le message "mot de passe incorrect", ce qui veut dire que l'identifiant tapé est bien existant, mais que son mot-de-passe ne l'est pas. Pour corriger cette vulnérabilité sur un formulaire de connexion (WordPress ou autre), il faut simplement faire en sorte que le message d’erreur renvoyé par l’application soit le même, quelle que soit la source du problème (nom d’utilisateur ou mot de passe).

Réinitialisation du mot-de-passe : Le problème se pose également sur la réinitialisation du mot-de-passe de connexion, pour cela il faut retourner un message du style « Si votre compte existe bien, un lien de réinitialisation de mot de passe vous sera envoyé dans quelques instants", que le compte existe ou pas. Cependant, si l’application envoie l’email de réinitialisation directement lorsque l’utilisateur valide son formulaire, un temps de latence plus grand sera observé si l’adresse email existe (si elle n’existe pas, cet envoi n’aura pas lieu). La solution est de faire en sorte que les emails ne soient pas envoyés directement lors du clic sur le bouton mais soit mis en attente et envoyés par un autre processus qui tournerait par exemple en tache planifiée toutes les X minutes.

Formulaire de création de compte : Comme pour le formulaire de récupération du mot-de-passe,  il arrive souvent que les applications web informent les utilisateurs lorsqu’un identifiant est déjà existant, avec un message du genre "l'adresse email existe déjà". Sinon, tu auras plutôt un message du genre "votre compte a été créé, vous allez recevoir un email de confirmation dans quelques instants". 

Les énumérations d'utilisateurs de connexion restent une trop grande source d’information pour de potentiels attaquants.

Pour les archives d'auteur, fais le test en mettant ton "URL/?author=1". Surprise, ça te mettra sûrement le nom "Admin" en plus. Voilà la moitié du travail du hacker est effectuée. 

 

RewriteCond %{REQUEST_URI} !^/wp-admin [NC]
RewriteCond %{QUERY_STRING} author=d RewriteRule ^ /? [L,R=301]

Ce code doit être placé après la ligne "RewriteEngine On" et avant la ligne "RewriteBase /"

Cela fera une redirection 301 et redirigera vers la page d'accueil. 

Désactiver la signature du serveur Apache

Une fois la directive ServerSignature à Off, le serveur n’affiche plus aucune information sur les pages d’erreur.

# désactiver signature de ton serveur
ServerSignature Off

Restreindre l'accès aux fichiers de Plugins et de Thèmes

Aujourd'hui la majorité des plugins et thèmes n'ont pas besoin d'accès direct aux fichiers PHP dans leurs répertoires. La première partie du code fera que quand un hacker tente d'accéder à "monsite/wp-content/plugins, il aura une erreur 404 de page non-trouvée. Ce code est uniquement pour les fichiers PHP, par pour les autres fichiers statiques.

# Restraint l'accès aux fichiers PHP des répertoires de plugins et de thèmes
RewriteRule wp-content/plugins/(.*.php)$ - [R=404,L]
RewriteRule wp-content/themes/(.*.php)$ - [R=404,L]

# Si tu as besoin d'exclure cretains plugins à cette règle, colle ce code juste avant 
# la règle précédente et remplace avec tes fichiers de plugins ou répertoires à exclure RewriteCond %{REQUEST_URI} !^/wp-content/plugins/file/to/exclude.php RewriteCond %{REQUEST_URI} !^/wp-content/plugins/directory/to/exclude/

Ce code doit être placé après la ligne "RewriteEngine On" et avant la ligne "RewriteBase /".

Limiter la taille en upload de téléchargement

# limité à  10mb
LimitRequestBody 10240000

Empêcher l'exécution et le téléchargement dans /wp-content 

Typiquement, tu as besoin que le répertoire d'uploads ait les accès en écriture pour le serveur web, pour y uploader des images et du contenu pour les mettre dans tes pages. Cependant, tu as besoin d'empêcher que des fichiers PHP soit ajoutés dans ton répertoire d'uploads. Par défaut, quand tu créé du contenu à travers le WP Admin Dashboard, WordPress a déjà une option de sécurité qui ne va permettre l'upload de fichiers PHP à travers le WP Admin Dashboard. Mais si tu as un thème ou un plugin mal écrit, un hacker pourra profiter de cette faille pour y injecter des fichiers PHP dans ton répertoire wp-content/uploads. 

Créé un fichier ".htaccess" dans le répertoire "wp-content/" de ton site (et non dans le fichier .htaccess à la racine de ton site) et ajoutes-y cette règle qui va interdire l'upload de fichier PHP dans ton dossier /wp-content :

# Desactiver l'upload de fichier PHP dans /wp-content
<Files "*.php"> Order Deny,Allow Deny from All </Files>

Tu peux également n'accepter que certains types d'extensions avec ce genre de code :

# Desactiver l'upload de fichier avec 
des extensions autre que Order deny,allow Deny from all <Files ~ ".(xml|css|js|jpe?g|png|gif
|pdf|docx|rtf|odf|zip|rar)$"> Allow from all </Files>

Désactiver l'accès aux répertoires

Par défaut, les serveurs Apache permettent l'exploration des fichiers et des répertoires. Pour éviter cela, il suffit d'ajouter ce bout de code dans ton fichier .htaccess

# disable directory browsing
Options All -Indexes

Bloquer l'accès à /wp-includes

Le dossier /wp-includes/ de WordPress contient les fichiers essentiels au bon fonctionnement de WordPress. 

# Bloquer l'accès à /wp-includes/
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>

Restreindre l'accès au fichier wp-config.php

Le fichier wp-config.php contient des données essentielles pour ton site WordPress (nom de base de données, login utilisateurs, …). Il faudra donc protéger ce fichier via le bout de code suivant à placer dans le fichier .htaccess

# Restreindre l'accès au fichier wp-config.php
<files wp-config.php>
order allow,deny
deny from all
</files>

Limiter l'accès à WP-Admin

Il faut que tu évites les bots d'attaquer le wp-admin de ton site. 

ErrorDocument 401 monsite.fr/index.php?error=404
ErrorDocument 403 monsite.fr/index.php?error=404

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{HTTP_REFERER} !^http://(.*)?monsite.fr [NC]
RewriteCond %{REQUEST_URI} ^(.*)?wp-login.php(.*)$ [OR]
RewriteCond %{REQUEST_URI} ^(.*)?wp-admin$
RewriteRule ^(.*)$ - [F]
</IfModule>

Supprimer les fichiers inutiles

Tu dois penser à supprimer les fichiers d'installation de WordPress, après installation ils ne te serviront plus. 

readme.html
/wp-admin/install.php
wp-config-sample.php

Prévenir les injections SQL : scripts malicieux

Les hackers qui essayent d’infecter ton site internet WordPress vont tenter de changer les variables GLOBALS et REQUEST. Cela sert à éviter les injections SQL que peuvent réaliser un hacker sur ton site, pour y installer un malware. 

# Prevenir l'injection de script malicieux
Options +FollowSymLinks RewriteEngine On RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR] RewriteCond %{QUERY_STRING} GLOBALS(=|[|%[0-9A-Z]{0,2}) [OR] RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2}) RewriteRule ^(.*)$ index.php [F,L]

Sécuriser les Headers HTTP

Cela sert à éviter les scripts ou les injections malicieuses de JavaScript

#Ce code demande au navigateur de n'utiliser que des codes
#qui viennent de ton site WordPress : header('Access-Control-Allow-Headers:X-WP-Nonce'); header('Content-Security-Policy: default-src self'); #Code pour éviter qu'un hacker n'utilise tout ton code pour
#le copier sur un site et se faire passer pour toi: header('X-Frame-Options: SAMEORIGIN'); #Code pour prévenir du cross-site-attack (XSS attacks) header('X-XSS-Protection: 1; mode=block'); header('X-Content-Type-Options: nosniff'); #Force le navigateur à n'utiliser que le HTTPS: header('Strict-Transport-Security:max-age=31536000; includeSubdomains; preload'); # Code qui protège et sécurise tes cookies : demande au navigateur de croire
# uniquement les cookies envoyés par ton serveur
@ini_set('session.cookie_httponly', true); @ini_set('session.cookie_secure', true); @ini_set('session.use_only_cookies', true);

Bloquer des IP 

Si tu remarques que des personnes essayent de se connecter à ton site pour te hacker ou des bots, tu peux les bloquer grâce à leur adresse IP. 

# Bloquer des adresses IP
# Remplacer IP_ADDRESS_* avec l'adresse que vous voulez

# Pour bloquer uniquement une IP
Deny from 192.168.1.7
# Pour bloquer toutes les IP en 192.168
Deny from 192.168

# Pour bloquer un domaine
Deny from [email protected]

# Si tu souhaites bloquer tout le monde, sauf une IP
order deny,allow deny from all Allow from 192.168.1.7

Fichier htaccess et SEO

Rediriger WWW vers non WWW et vice versa

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www.yourblogname.com [NC]
RewriteRule ^(.*)$ http://yourblogname.com/$1 [L,R=301]
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^yourblogname.com [NC]
RewriteRule ^(.*)$ http://www.yourblogname.com/$1 [L,R=301]
Proudly designed with Oxygen, the world's best visual website design software
chevron-up-circle
linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram