.htaccess et sécurité

mercredi 2 mars 2011
par Loki
popularité : 46%

Sur les serveurs Apache, le fichier .htaccess est un fichier de configuration qui vous permet de définir un certain nombre de règles de fonctionnement de votre site web, (comme la réécriture ou la redirection d’URL) ou de modifier certains paramètres configurés par votre hébergeur pour Apache (httpd.conf) ou pour PHP (php.ini ou php5.ini).

Je n’aborderai dans cet article que les directives directement liées à la sécurité, et pouvant être facilement mises en oeuvre quelque soit le langage de script ou le CMS que vous utilisiez.

Commençons par les directives les plus simples et qu’on devrait voir dans tout fichier .htaccess.

Petite précision utile : on peut placer un fichier .htaccess dans chaque répertoire, mais les directives placées dans le .htaccess à la racine du site s’appliquent par défaut à l’ensemble des sous-répertoires sauf si autrement spécifié au niveau d’un sous-répertoire par un autre fichier .htaccess.

Protéger un fichier spécifique des yeux indiscrets :

Pour interdire l’accès à un fichier sensible, comme le fichier .htaccess lui-même, mais aussi le fichier php.ini, utiliser la directive FilesMatch :

<FilesMatch "^(\.htaccess|php\.ini|php5\.ini)">
Deny from all
</FilesMatch>

Chaque CMS possède des fichiers spécifiques qu’il est bon de protéger de cette manière : pour WordPress par exemple, le fichier wp-config.php, mais aussi le simple fichier readme.html qui peut donner des indications sur la version de WordPress utilisée.

<FilesMatch "^(wp-config\.php|install\.php|\.htaccess|php\.ini|php5\.ini|readme\.html)">
Deny from all
</FilesMatch>

Le fichier .htaccess livré avec Drupal utilise déjà cette directive de manière très exhaustive, mais rien n’empêche de la compléter.

# Protect files and directories from prying eyes.
<FilesMatch "\.(engine|inc|info|install|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl|svn-base)$|^(code-style\.pl|Entries.*|Repository|Root|Tag|Template|all-wcprops|entries|format)$">
 Order allow,deny
</FilesMatch>

Empêcher l’affichage du contenu d’un répertoire

Le moyen le plus simple d’empêcher l’affichage du contenu des répertoires de votre site est d’utiliser la directive suivante.

Options -Indexes

Si un répertoire particulier nécessite l’affichage de son contenu (comme un répertoire de FTP publique par exemple) il suffira de mettre une directive Options +Indexes dans le fichier .htaccess de ce répertoire.

Modifier les paramètres de PHP

Le paramètrage de PHP s’effectue au moyen des fichiers de configuration httpd.conf et php.ini et c’est là qu’idéalement devraient être réglés les paramètres de sécurité. Si vous êtes sur un hébergement mutualisé, vous n’avez sûrement pas accès au fichier php.ini du serveur mais certains hébergeurs vous permettront de créer un fichier php.ini dans votre le racine de votre site.

Si ce n’est pas le cas, certains de ces paramètres peuvent être modifiés au niveau du fichier .htaccess, en utilisant les directives php_flag ou php_value (sauf si PHP est installé en « mode CGI »).

  • php_flag n’est utilisable que sur les paramètres booléens pouvant être activés (On) ou désactivés (Off)

  • php_value quand à lui permet d’indiquer une valeur précise, mais peut sans problème être utilisé en lieu et place de php_flag.

Exemple : « php_value register_globals 0 » est l’équivalent de « php_flag register_globals off ».

Les paramètres de sécurité suivants sont modifiables au niveau .htaccess et je vous conseille fortement de le faire :

php_value magic_quotes_gpc       0
php_value register_globals           0

Si l’ajout de ces directives provoquent une erreur serveur, c’est que PHP tourne en mode CGI, et n’est pas installé en tant que module. Renseignez-vous avant, ou faite comme Drupal et conditionnez-vos directives comme ci-dessous :

# PHP 4, Apache 1.
<IfModule mod_php4.c>
 php_value magic_quotes_gpc            0
 php_value register_globals                0
 php_value session.auto_start              0
 php_value mbstring.http_input            pass
 php_value mbstring.http_output           pass
 php_value mbstring.encoding_translation   0
</IfModule>

# PHP 4, Apache 2.
<IfModule sapi_apache2.c>
 php_value magic_quotes_gpc                0
 php_value register_globals                0
 php_value session.auto_start              0
 php_value mbstring.http_input             pass
 php_value mbstring.http_output            pass
 php_value mbstring.encoding_translation   0
</IfModule>

# PHP 5, Apache 1 and 2.
<IfModule mod_php5.c>
 php_value magic_quotes_gpc                0
 php_value register_globals                0
 php_value session.auto_start              0
 php_value mbstring.http_input             pass
 php_value mbstring.http_output            pass
 php_value mbstring.encoding_translation   0
</IfModule>

Le fichier php.ini permet de modifier bien d’autres paramètres de sécurité importants qui ne sont pas accessibles par .htaccess mais ce n’est pas l’objet de cet article. Toutefois, je vous recommande le paramétrage ci-dessous, suite à une expérience pénible avec l’hébergeur GoDaddy.

Fichier php.ini (ou php5.ini) :

disable_functions = dl,system,exec,passthru,shell_exec
allow_url_fopen = 0
allow_url_include = 0

Prévenir les injections SQL ou les attaques XSS

Ce n’est pas la panacée universelle, mais ces quelques directives devraient filtrer un grand nombre d’attaques classiques. C’est l’une des méthodes utilisées par le plugin BulletProof Security pour WordPress, mais elle est applicable sans problème à la plupart des sites PHP.

<IfModule mod_rewrite.c>
 RewriteEngine on
# placez vos propres règles de réécriture en tête, afin qu'elles ne soient pas
# accidentellement filtrées par les règles suivantes.


#########################
# FILTER REQUEST METHODS
#########################

RewriteCond %{REQUEST_METHOD} ^(HEAD|TRACE|DELETE|TRACK) [NC]
RewriteRule ^(.*)$ - [F,L]

#########################
# QUERY STRING EXPLOITS
#########################

riteCond %{QUERY_STRING} \.\.\/ [NC,OR]
RewriteCond %{QUERY_STRING} boot\.ini [NC,OR]
RewriteCond %{QUERY_STRING} tag\= [NC,OR]
RewriteCond %{QUERY_STRING} ftp\:  [NC,OR]
RewriteCond %{QUERY_STRING} http\:  [NC,OR]
RewriteCond %{QUERY_STRING} https\:  [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*iframe.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|%3D) [NC,OR]
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} ^(.*)cPath=http://(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)/self/(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(\[|\]|\(|\)|<|>).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(globals|encode|localhost|loopback).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(execute|exec|sp_executesql|request|select|insert|union|declare|drop|delete|create|alter|update|order|char|set|cast|convert|meta|script|truncate).* [NC]
RewriteRule ^(.*)$ - [F,L]
</IfModule>

Commentaires

Navigation

Articles de la rubrique

  • .htaccess et sécurité