Apache est un serveur web très populaire, performant, et sa conception modulaire le dote d'une grande richesse fonctionnelle. Découvrez comment le sécuriser et le rôle de ses modules.
Il est très facile de découvrir quel serveur tourne sur un site web comme le montre l'exemple suivant :
$ telnet localhost 80 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. HEAD / HTTP/1.0 HTTP/1.1 200 OK Date: Sat, 02 Jun 2001 13:11:40 GMT Server: Apache/1.3.14 (Unix) (Red-Hat/Linux) PHP/4.0.3pl1 mod_perl/1.24 Connection: close Content-Type: text/html Connection closed by foreign host.
Un pirate apprend que le serveur Apache tourne sous une
distribution RedHat et que les langages Perl et PHP sont actifs. On
limite la divulgation d'information en insérant dans le fichier de
configuration, /etc/httpd/conf/httpd.conf
pour une
RedHat, la ligne ServerTokens Prod
.
Ainsi, la bannière Server: Apache/1.3.14 (Unix) (Red-Hat/Linux)
PHP/4.0.3pl1 mod_perl/1.24
se limite à Server:
Apache
. Cette option n'apparaît pas toujours dans le fichier de
configuration (enfin, c'est le cas pour ma RedHat et ma Mandrake...),
alors ajoutez-la rapidement.
Cela ne suffit toujours pas à masquer la version d'Apache : si vous
demandez une page inexistante, Apache renvoie une page d'erreur
404
avec en bas de la page, le message
Apache/1.3.14 Server at www.mon-serveur.org Port 80
qui révèle
la version du serveur d'Apache. Pour empêcher cela, il faut désactiver
l'insertion de la signature du serveur avec la commande
ServerSignature Off
. Utiliser ErrorDocument 404
/missing.html
pour définir votre propre page d'erreur
404
.
De façon à limiter la portée des attaques de type Denial of
Service, il est
conseillé de limiter le nombre de connexions simultanées
MaxClients
et en particulier le nombre de connexions
persistantes MaxKeepAliveRequests
. Celles-ci sont
apparues avec la norme
HTTP 1.1. Elles permettent d'effectuer des requêtes successives lors de la
même connexion, ce qui augmente les performances du serveur.
L'utilisation d'un timeout empêche les connexions sans fin.
Exemple pour un petit serveur :
MaxClients 150 KeepAlive On MaxKeepAliveRequests 100 KeepAliveTimeout 5
Apache permet la définition de Virtual Host, c'est-à-dire que le même serveur peut héberger, y compris sur une même adresse IP, plusieurs sites différenciés par leur nom. Pour limiter les risques liés à une panne des serveurs DNS ou à des manipulations frauduleuses, il convient de définir le VirtualHost par une adresse IP puis de préciser son nom.
<VirtualHost 194.57.201.103> ServerName www.esiea.fr ... </VirtualHost>
Apache permet de définir ses propres formats LogFormat
pour les enregistrements dans les fichiers de log.
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent
Ensuite, on enregistre les informations de log précisées par le format dans le fichier de son choix
CustomLog /var/log/httpd/access_log common
.
Suivant l'utilisation de ces fichiers de logs
(reporting,...), il peut être intéressant de faire apparaître le nom des
machines se connectant au serveur web au lieu de leur adresse
IP : HostnameLookups On
active la résolution inverse.
La gestion des accès est effectuée par le module
mod_access
. On manipule principalement trois catégories
d'objets :
Directory
désigne un répertoire du serveur ;
Location
une arborescence du serveur web ;
Files
un fichier.
Voici un exemple un peu farfelu extrait
du manuel d'Apache, qui autorise la consultation du répertoire
/docroot
aux personnes utilisant le brower
KnockKnock/2.0
. Si vous voulez restreindre la
consultation d'une partie de votre site aux personnes n'utilisant pas
I.E., vous n'aurez pas trop de difficultés =:-)
BrowserMatch ^KnockKnock/2.0 let_me_in <Directory /docroot> order deny,allow deny from all allow from env=let_me_in </Directory>
Plus sérieusement, il est fortement conseillé de tout interdire par défaut :
<Directory /> Order deny,allow Deny from all </Directory>
Ensuite, il ne reste qu'à valider l'accès aux répertoires correspondant aux sites
Order
indique dans quel ordre les directives
deny
et allow
sont évaluées. Deny from
all
interdit l'accès depuis partout. On aurait pu
indiquer un nom de machine, un nom de domaine, une adresse IP, un
couple IP/masque de réseau.
Options
contrôle
FollowSymLinks
/SymLinksIfOwnerMatch
;
ExecCGI
;
Includes
et
IncludesNOEXEC
;
Indexes
en l'absence
de celles-ci ;
MultiViews
.
All
regroupe les différentes options sauf
MultiViews
, None
supprime les options.
MultiViews
redirige une demande pour
index.html
vers index.html.en
ou index.html.fr
selon la préférence signalée par le
navigateur au serveur web.
Il est important d'être le plus restrictif possible par défaut, je conseille de n'autoriser que le suivi des liens symboliques où liens et destinations ont le même propriétaire :
<Directory /> Options SymLinksIfOwnerMatch AllowOverride None </Directory />
Un pirate pouvant écrire dans un répertoire du serveur web, par
exemple via un partage NFS, peut en profiter pour accéder au fichier
/etc/passwd
via un lien symbolique si l'option
FollowSymLinks
est présente, Includes
ou
ExecCGI
permet d'exécuter des programmes... En un mot,
soyez prudent.
La directive AllowOverride
peut prendre n'importe quel
paramètre qu'aurait pris Options
.
Le module mod_auth
permet de protéger l'accès à un
répertoire par mot de passe. En pratique, c'est souvent utiliser pour
filtrer les accès à un sous-répertoires d'une page personnelle.
<Directory /home/*/public_html> AllowOverride AuthConfig Options SymLinksIfOwnerMatch </Directory>ou pour bloquer l'accès à un répertoire déterminé
<Location "/private"> Options None AllowOverride None AuthName "restricted stuff" AuthType Basic AuthUserFile "/etc/httpd/.passwd" require valid-user </Location>
Dans le cas des pages personnelles /home/*/public_html
des utilisateurs, l'accès est déterminé par un fichier
.htaccess
que peut utiliser ou non un utilisateur, le nom du fichier même est défini dans la section générale de la
configuration du serveur. Ce fichier protége l'accès au répertoire dans lequel il est placé ainsi que l'accès aux sous-répertoires.
AllowOverride AuthConfig
permet à ce fichier d'être pris en compte.
Par précaution, il faut empêcher un utilisateur de les récupérer via le web :
AccessFileName .htaccess <Files ~ "^\.ht"> Order deny,allow Deny from all </Files>Si on veut pouvoir définir explicitement des exceptions pour les fichiers
.htpipo
par exemple, il faut spécifier l'ordre allow
puis deny
pour que l'autorisation prime sur l'interdiction.
Le fichier .htaccess
contient les mêmes champs que
pour le répertoire /private
de l'exemple, c'est-à-dire un
nom qui apparaîtra sur la fenêtre de demande d'identification
(AuthName
), la méthode d'identification
(AuthType
), le fichier de mot de passe
(AuthUserFile
) et enfin require
valid-user
:
AuthName "my restricted stuff" AuthType Basic AuthUserFile "/home/titi/.htpasswd" require valid-user
Le serveur Apache s'articule sur un ensemble de modules qu'il convient de restreindre au strict nécessaire.
Les SSI ont déjà été présentés lors du sixième article sur la
programmation sécurisée. Il s'agit d'un vestige de l'époque où les
Perl et PHP n'avaient pas encore fait leurs apparitions. Il est
fortement conseillé de le supprimé ou de ne l'activé qu'avec prudence
Options +IncludesNOEXEC
ou Options
+Includes
.
Le module mod_perl
a été le résultat d'une intégration
plus poussée des scripts CGI écrits en Perl. Il permet de meilleures
performances qu'un script CGI classique. En terme de sécurité, il
présente des risques identiques.
PHP a été conçu spécifiquement pour la programmation web en tenant
compte d'impératif de sécurité. Il est grandement paramétrable. Il est
conseillé de définir les options suivantes dans son fichier de
configuration /etc/php.ini
. safe_mode
surveille les fichiers accédés et interdit l'usage de commande à
risque, expose_php
contrôle l'affichage de sa banner,
max_execution_time
et memory_limit
limite
les risques de DoS, magic_quotes_gpc
ajoute des quotes
pour les données reçues des GET/POST et des cookies. Enfin, souvent
oublié en production, il faut éviter l'affichage des lignes fautives
lorsque les scripts PHP plantent.
safe_mode = On expose_php = Off max_execution_time = 30 ; Maximum execution time of each script, in seconds memory_limit = 8M magic_quotes_gpc = On display_errors = Off [SQL] sql.safe_mode = On
Il faut limiter leur présence à des répertoires bien déterminés,
ils sont alors autorisés par un Options +ExecCGI
sur la
base d'un répertoire particulier.
Les utilisateurs du serveur peuvent bien souvent publier leurs
pages dans leur répertoire public_html
, configuré via le
paramètre UserDir public_html
. De façon à éviter une
mauvaise surprise, root n'est pas autorisé à faire de
même : UserDir disabled root
.
La directive DirectoryIndex
définit les pages d'index
souvent index.html
ou index.php3
et en
l'absence de celle-ci, le module mod_autoindex
en génère
une si l'option Indexes
est présente. Les index peuvent
aider un pirate à découvrir d'anciennes versions de script, un backup
du site ou d'autres documents sensibles.
Le serveur web est lancé par l'utilisateur root ce qui lui permet d'utiliser le port privilégié 80, ensuite il prend l'identité d'un utilisateur sans pouvoir apache ou nobody.
User apache Group apache
Le problème est que les scripts s'exécutent tous avec le même id
(i.e. le même propriétaire). En conséquence, ils peuvent interférer
entre eux. Le programme suexec
permet d'utiliser des
User/Group différents
pour chaque virtual host de façon à séparer les utilisateurs. En
contrepartie, un pirate disposant du compte apache
est capable
d'utiliser ce programme pour corrompre d'autres comptes, c'est pour cela
qu'il n'est pas actif par défaut. Il faut lire très attentivement la
documentation.
Il est déjà compilé sur une RedHat mais pas forcément activé,
il suffit alors d'un chmod u+s /usr/sbin/suexec
pour le rendre actif.
ls -l /usr/sbin/suexec -r-s--x--- 1 root apache 10976 Mar 29 19:52 /usr/sbin/suexec
# httpd -l Compiled-in modules: http_core.c mod_so.c suexec: enabled; valid wrapper /usr/sbin/suexec
J'espère vous avoir donné suffisamment d'éléments pour sécuriser
votre serveur Apache, sinon n'hésitez pas à consulter le manuel :
si vous avez des difficultés à vous y retrouver, un grep
peut vous aider.