Sécurité des systèmes informatiques/Sécurité informatique/Serveur HTTP

L'avènement du protocole HTTP et du Web, étroitement associée à l'explosion de l'utilisation d'Internet, a été une nouvelle étape du développement de l'utilisation de l'informatique et des réseaux par un nombre grandissant d'utilisateurs (voir ci-contre et les données actualisées[1]). Au cœur de cette fonction se trouve bien évidemment le serveur HTTP lui-même, et notamment une de ses implémentations les plus répandues : le logiciel libre Apache.

De plus en plus d'applications s'appuient aussi sur le protocole HTTP et les serveurs associés pour gérer les interactions avec leurs utilisateurs. Ces applications Web vont parfois jusqu'à réimplémenter au-dessus du protocole HTTP des infrastructures de fonctionnement complètes (par exemple de type RPC avec SOAP) qui mettent le serveur HTTP au cœur de leur exécution.

Évolution du nombre de sites Web 1995-2004 (source Netcraft)

La sécurité des serveurs Web (c'est à dire des serveurs HTTP et HTTPS) est donc devenu un enjeu majeur. Dans cette section, nous essayons d'en aborder certains aspects concrets, sans nous soucier de la sécurité sur le Web au sens large, mais pour mettre l'accent sur les fonctions du logiciel présent au centre du système et dont les paramètres et les fonctions de sécurité nous semblent malgré tout assez méconnues et pas toujours bien maîtrisées.

D'abord, stricto senso, notamment du point de vue réseau il faut faire la distinction entre le serveur HTTP (TCP/80) et le serveur HTTPS (TCP/443). Il s'agit en général du même programme, offrant souvent un accès aux mêmes données, mais en utilisant soit une connexion TCP conventionnelle, soit une connexion incluse dans SSL/TLS. Ce dernier protocole offre des fonctions de sécurité avancées pour les communications point à point entre client et serveur, pouvant aller jusqu'à une authentification mutuelle utilisant des techniques de cryptographie asymétrique avec des longueurs de clefs supérieures à 1024 bits et une protection de l'intégrité et de la confidentialité de la communication avec des algorithmes symétriques variés et des longueurs de clefs de session tout à fait acceptable (56, 64 ou 128 bits). Toutes les possibilités de SSL/TLS ne sont généralement pas exploitées dans les configurations courantes, notamment l'authentification du client.

Pourtant, pour la sélection des utilisateurs, on peut envisager deux grandes approches, avec des niveaux de protection bien différents :

  • La sélection peut-être basée sur des plages d’adresses IP, à l'instar des contrôles effectués par un firewall. Le serveur HTTP(S) décide d'autoriser l'accès à une URL particulière en fonction de l'adresse du client.
  • Via HTTPS seulement, la sélection peut également s'appuyer sur un certificat X.509 présenté par le navigateur client (relié au certificat du serveur) et l'identité garantie par ce certificat.

En ce qui concerne les URL (ou plus généralement les ensembles d'URL) accessibles via un serveur, la sélection des destinations et de la manière dont on peut y accéder peut s'effectuer également de deux grandes manières :

  • soit en s'appuyant sur le chemin d’accès (URL ou nom dans le système de fichier) ;
  • soit en analysant le type d’extension de l'URL accédée (par exemple .html pour des fichiers simples, .php, .jsp, .asp pour des pages dynamiques, etc.).

S'agissant des pages dites « dynamiques », celles-ci sont obtenues non pas par un simple accès au système de fichiers, mais par l'exécution d'un programme secondaire générant la page. Ce programme est parfois exécuté dans le contexte même du processus du serveur, lequel doit alors pré-charger ou se lier dynamique à des exécutables externes adaptés (des modules). La maîtrise des extensions dynamiques, de leur présence ou de leur absence et de leurs configurations spécifiques, est un point important de la sécurité du serveur HTTP. Beaucoup de serveurs incluent certainement des modules dynamiques dont ils n'ont pas besoin, et offrent donc des fonctions d'accès inutilisées et presque inconnues de leurs administrateurs.

On le voit, les serveurs HTTP sont des composants logiciels plus complexes qu'il n'y paraît ou en tout cas dont l'environnement d'exécution est complexe. La sécurité du serveur peut passer par un meilleur contrôle du processus serveur lui-même au niveau du système d'exploitation visant à limiter les débordements possibles via ce processus. On peut alors envisager deux grandes voies pour mieux contrôler ce processus critique :

  • l'utilisation de techniques de confinement (notamment sous Unix via chroot - un effort notamment réalisé dans OpenBSD) ;
  • la mise en place réfléchie de restrictions d'accès en lien avec le système de fichiers (arborescences www bien limitées et au contenu validé).

Apache 1.3

modifier
Répartitions des principaux serveurs (source Netcraft)

Le serveur HTTP librement disponible du projet Apache est une des principales implémentations de serveur HTTP utilisée dans la pratique (voir graphique).

En parcourant un fichier de configuration standard d'Apache, notamment ceux de la distribution Debian GNU/Linux dont le fonctionnement est très réfléchi, on distingue un certain nombre de directives qu'il semble souhaitable de contrôler dans la perspective de la sécurité du service.

Les fichiers de configuration d'Apache sont nommés par défaut httpd.conf, access.conf et srm.conf (on rencontre également le nom apache.conf à la place du premier, et la présence d'un fichier nommé modules.conf est aussi assez fréquente pour isoler les directives de chargement des modules). Les différents fichiers sont normalement associés à des directives différentes. Toutefois, ces fichiers ne sont pas les seuls pouvant être impliqués dans la configuration complète : le langage de configuration est modulaire via l'utilisation de directives Include et cette modularité est souvent mise à profit pour isoler les directives de configuration des modules dans des fichiers séparés.

Dans le fichier principal par défaut (httpd.conf en général) dont nous présentons certains extraits ici, les directives mentionnées en commentaire (débutant par un #) indiquent les valeurs par défaut utilisées par Apache en l'absence de la directive (supprimer simplement le # n'a donc normalement aucun effet sur le serveur).

Certaines directives concernent la configuration réseau fondamentale, c'est à dire l'adresse IP et le port TCP de la socket ouverte par le serveur lors de son démarrage. Les directives BindAddress et Port permettent d'indiquer l'adresse IP et le numéro de port à utiliser. Mais la première est obsolète et devrait être éliminée dans la version 2.0 d'Apache. Listen est une forme plus moderne permettant de spécifier en une seule fois les paramètres réseau du port de communication, en séparant l'adresse IP et le numéro de port par : . En l'absence d'adresse IP spécifiée (ou si BindAddress * est utilisé) le serveur Apache écoutera sur toutes les adresses IP disponibles, y compris des adresses virtuelles ou des adresses correspondant à plusieurs cartes réseau. C'est notamment dans ces deux cas qu'une directive explicite est souhaitable pour éviter les confusions. Des directives Listen explicites sont également indispensables (éventuellement sous la forme Port) pour démarrer un serveur Apache fournissant un ou plusieurs services sur un ou des ports différents du port HTTP standard (80).

#Listen 3000
#Listen 12.34.56.78:80
#BindAddress *
Port 80

Le fonctionnement du serveur Apache est largement basé sur les possibilités offertes par une architecture logicielle modulaire. La plupart des fonctions additionnelles du serveur sont fournies par des modules. Même certaines qui paraissent naturelles du point de vue de l'utilisateur sont en fait des extensions par rapport aux services élémentaires fournis par le serveur HTTP (comme le contrôle d'accès, SSL/TLS, les programmes CGI externes, ou certaines directives de configuration comme les alias de chemins d'accès). Ces modules sont chargés par Apache quand il rencontre une directive LoadModule dans le fichier de configuration. Ces directives arrivent assez tôt dans la configuration car elles peuvent étendre le langage de configuration en offrant de nouvelles directives. L'identification précise de tous les modules chargés par Apache est cruciale du point de vue de la sécurité, car c'est elle qui permet de savoir quel est exactement le périmètre fonctionnel offert par un serveur particulier. Par exemple, avec les directives suivantes, le serveur Apache, outre qu'il est un serveur HTTP, offre également : des fonctions permettant d'exécuter des programmes externes (CGI) générant des pages Web (mod_cgi), un interpréteur intégré du langage PHP (libphp4), des directives de contrôle d'accès (mod_access) et une directive de configuration permettant de définir des Alias (mod_alias) de chemin d'accès pour les URL (pour repositionner différentes parties du système de fichiers dans l'arbre des documents accessibles ou permettre la redirection des URL).

LoadModule cgi_module /usr/lib/apache/1.3/mod_cgi.so
# LoadModule asis_module /usr/lib/apache/1.3/mod_asis.so
LoadModule alias_module /usr/lib/apache/1.3/mod_alias.so
LoadModule access_module /usr/lib/apache/1.3/mod_access.so
LoadModule php4_module /usr/lib/apache/1.3/libphp4.so

Les directives User et Group permettent de définir l'identifiant utilisateur et l'identifiant du groupe (UID et GID sous Unix) que doivent posséder les processus serveurs (démons httpd). Le processus initial d'Apache s'exécute en effet généralement avec les droits du super-utilisateur (root sous Unix) afin d'initialiser les ports de communication nécessaires situés sur des ports TCP privilégiés, mais les processus serveurs répondant aux requêtes des navigateurs peuvent eux s'exécuter avec des identifiants non-privilégiés. Dans l'exemple suivant, ceux-ci vont s'exécuter avec des UID et GID dédiées nommées www-data.

User www-data
Group www-data

Compte tenu de la modularité du logiciel et de la possibilité pour les modules de fournir de nouvelles directives de configuration, des éléments de configuration conditionnelle sont disponibles, notamment via la directive <IfModule>. Sa syntaxe est particulière car elle nécessite, pour délimiter des blocs, des marqueurs de début et de fin comme dans l'exemple ci-après. Ces directives permettent d'écrire des portions de configuration valides même si le module concerné n'est pas chargé au démarrage (via une directive LoadModule). Elles sont surtout intéressantes pour préparer certains paramétrages dans une configuration type dans le cas où la mise en place des modules concernés est décidée ultérieurement suivant les besoins des utilisateurs du serveur Web. L'activation ou la désactivation d'un ou plusieurs modules peut alors être envisagée avec une relative sérénité durant l'exploitation. Dans l'exemple que nous prenons, le module mod_status est un module permettant d'afficher des informations internes concernant le serveur Apache lui-même. À priori, cette information n'est pas nécessaire aux utilisateurs normaux du site (c'est une information surtout intéressante pour ses administrateurs) et il serait également nécessaire de limiter l'accès à ces informations.

<IfModule mod_status.c>
  ExtendedStatus On
</IfModule>

Outre les directives de configuration conditionnelle, la directive Include permet de choisir une configuration modulaire, séparée en plusieurs fichiers. Les exemples ci-dessous illustrent le principe de la distribution Debian dans laquelle des portions de configuration d'Apache concernant exclusivement certaines applications Web sont en fait localisées aux côtés des fichiers de configuration de l'application elle-même. Chacun de ces fichiers contient des paramétrages du serveur HTTP (notamment des règles de contrôle d'accès) appliqués uniquement à la portion de l'arborescence des documents correspondant à l'application concernée.

Include /etc/phpmyadmin/apache.conf
Include /etc/phpgroupware/apache.conf

Afin d'adapter les paramètres aux besoins des différentes parties de l'arborescence des documents accessibles, Apache offre un certain nombre de directives que nous qualifions de « contexte ».

<Directory> et <DirectoryMatch>
<Files> et <FilesMatch>
<Location> et <LocationMatch>
<VirtualHost>

Ces directives qui servent comme <IfModule> à identifier des blocs de lignes permettent d'appliquer des paramètres uniquement dans certains contextes : soit pour l'accès à certaines répertoires du système de fichier (<Directory> et <DirectoryMatch>), soit pour l'accès à certains fichiers (<Files> et <FilesMatch>), soit pour des accès effectués via certaines URL (<Location> et <LocationMatch>). Par ailleurs, Apache offre la possibilité de définir des serveurs virtuels via la directive <VirtualHost> et de leur appliquer des règles de configuration spécifiques. Ceux-ci se comportent comme des serveurs indépendants associés à des noms de domaine différents tandis qu'ils correspondent en fait seulement à des parties différentes de l'arborescence de documents d'un même serveur Apache (les différents noms de domaine doivent toutefois pointer vers une même machine - généralement via un alias DNS).

Le contrôle des chemins d’accès (via les répertoires) permet ainsi de proposer des configurations de ce type :

<Directory />
    Options SymLinksIfOwnerMatch
    AllowOverride None
</Directory>
…
<Directory /var/www/>
 Options Indexes Includes FollowSymLinks MultiViews
 AllowOverride None
 Order allow,deny
    Allow from all
</Directory>
…
<Directory /home/*/public_html>
    AllowOverride FileInfo AuthConfig Limit
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    <Limit GET POST OPTIONS PROPFIND>
        Order allow,deny
        Allow from all
    </Limit>
    <Limit PUT DELETE PATCH PROPPATCH MKCOL COPY MOVE LOCK UNLOCK>
        Order deny,allow
        Deny from all
    </Limit>
</Directory>

Dans cet exemple, le répertoire par défaut (racine /) se voit d'abord affecté une configuration très restrictive. Le répertoire /var/www est rendu accessible à tous, un certain nombre d'options sont également activées. Les répertoires public_html des utilisateurs (/home/*/public_html) sont aussi rendus accessibles à tous mais les utilisateurs peuvent modifier les règles de contrôle d'accès s'ils le souhaitent car la directive AllowOverride le leur permet (via des fichiers .htaccess). Par contre, les requêtes autorisées vers ces zones gérées directement par les utilisateurs sont limitées à des accès simples de consultation HTTP.

Le contrôle des noms de fichiers permet de traiter certains cas particuliers d'autorisation. Ainsi par exemple, pour interdire la consultation via le serveur HTTP des fichiers .htaccess permettant (éventuellement) de modifier les autorisations d'accès localement dans une zone du système de fichiers, la directive suivante peut être utilisée.

<Files ~ "^\.ht">
    Order allow,deny
    Deny from all
</Files>

En combinant l'utilisation des alias (directive Alias) et le contrôle d'accès basé sur l'URL utilisée par le navigateur (directive Location), il est possible d'autoriser à certains clients particuliers l'accès à des zones du système de fichiers qui ne sont pas directement visible dans l'arborescence des documents normale (/var/www dans nos exemples). Par exemple, voici comment rendre accessible la documentation installée sur le système de fichiers dans /usr/share/doc via une URL du type http://mon.serveur/doc/. S'agissant de fichiers normaux (par exemple des fichiers textes), la gestion automatique d'index listant le contenu des répertoires est évidemment utile dans ce cas (directive Options Indexes).

Alias /doc/ /usr/share/doc/
<Location /doc>
  order deny,allow
  deny from all
  allow from 127.0.0.0/255.0.0.0
  allow from AA.BB.CC.0/255.255.XX.0
  Options Indexes FollowSymLinks MultiViews
</Location>

Voici comment permettre l'exécution de pages dynamiques (générées via des programmes en langage Perl) dans une arborescence spécifique de la zone du système de fichiers consacrée au Web. C'est la directive Options +ExecCGI qui permet l'exécution de programmes externes du type CGI, les programmes eux-mêmes étant exécutés par le handler spécifique au langage Perl (fournit par le module mod_perl s'il est chargé).

# If the perl module is installed, this will be enabled.
<IfModule mod_perl.c>
  Alias /perl/ /var/www/perl/
  <Location /perl>
    SetHandler perl-script
    PerlHandler Apache::Registry
    Options +ExecCGI
  </Location>
</IfModule>

Voici maintenant des exemples d'utilisation des directives de configuration que nous avons vues dans l'objectif de réaliser un contrôle d'accès à des pages dynamiques installées dans une arborescence spécifique (a priori non-publique) via des chemins d’accès. Il s'agit là de permettre d'utiliser l'interface de visualisation de Prelude-IDS écrite en Perl nommée Piwi.

# For Prelude PIWI
Alias /piwi /home/xxxx/prelude/piwi
ScriptAlias /piwi /home/xxxx/prelude/piwi
<DirectoryMatch /home/xxxx/prelude/piwi/>
 order allow,deny
 allow from all
 Options +ExecCGI
 AddHandler cgi-script .pl
 DirectoryIndex index.pl
</DirectoryMatch>

Ce type de configuration d'une application Web est celui utilisé par la distribution Debian qui permet aussi d'isoler dans des fichiers de configuration secondaires les paramètres associés à une application Web par ailleurs installée dans une zone privée du système de fichiers. Cette approche nous semble intéressante du point de vue de la sécurité, car elle permet vraiment de s'appuyer sur les directives de contrôle d'accès disponibles via le module mod_access pour gérer les autorisations d'accès à chaque application avec une bonne granularité et sans craindre trop d'interactions entre les différentes applications. Voici donc un exemple de fichier de configuration secondaire pour une application Web (PHPGroupware) sur ce système : /etc/phpgroupware/apache.conf

Alias /phpgroupware /usr/share/phpgroupware
<Directory /usr/share/phpgroupware/>
       Options +FollowSymLinks
       AllowOverride None
       order allow,deny
       allow from all
       DirectoryIndex index.html index.php
       <IfModule mod_php3.c>
               php3_magic_quotes_gpc On
               php3_track_vars On
               php3_include_path .:/etc/phpgroupware
       </IfModule>
       <IfModule mod_php4.c>
               php_flag magic_quotes_gpc On
               php_flag track_vars On
               php_flag session.save_path /var/tmp/phpgroupware
               php_value include_path .:/etc/phpgroupware
       </IfModule>
</Directory>

On notera également sur cet exemple la gestion simultanée de paramètres de configuration pour deux versions du module mod_php.

Apache et SSL (Apache-SSL ou Apache+mod_ssl)

modifier

On notera qu'Apache n'inclut pas dans la distribution de base du logiciel l'implémentation du protocole HTTPS, utilisant SSL/TLS6. L'installation d'un serveur HTTPS nécessite l'utilisation d'une des deux principales variantes d'Apache incluant le support de HTTPS :

  • Apache+mod_ssl : implémentation utilisant un module d'Apache nommé mod_ssl pour fournir le protocole HTTPS en s'appuyant sur l'implémentation OpenSSL de SSL/TLS.
  • Apache-SSL[2] : une implémentation d'origine plus ancienne focalisée sur la stabilité du logiciel mais également basée sur Apache et sur SSLeay/OpenSSL.

Le premier correspond à une division du développement du premier, maintenant suffisamment ancienne pour que les deux implémentations soient désormais réellement différentes.

Références

modifier