Index des CoursChapitre précedentChapitre 17

Security

 

PHP est un langage puissant et l'interpréteur, qu'il soit inclus dans le serveur web ou bien compilé en version CGI, est capable d'accéder aux fichiers, d'exécuter des commandes et d'ouvrir des connexions réseaux. Toutes ces propriétés rendent le serveur web non sécurisé. Le langage PHP a été pensé afin d'être un langage beaucoup plus sécurisé pour écrire des CGI que le Perl ou le langage C, de plus une sélection rigoureuse des options de compilation et d'exécution vous permettront d'obtenir un équilibre parfaite entre liberté et sécurité.

Etant donné qu'il y a de nombreux moyens d'utiliser le langage PHP, il y a de nombreuses directives de configuration afin d'en contrôler le comportement. Un grand nombre d'options permettent d'utiliser le PHP dans de nombreuses situations, mais cela signifie aussi qu'il y a certaines combinaisons d'options de compilation et d'exécution qui amènent le serveur a être non sécurisé. Ce chapitre explique comme les différentes options de configurations peuvent être combinées, tout en conservant une sécurité maximum.

Version binaire CGI

Attaques possibles

L'option d'utiliser le PHP comme un binaire CGI vient la plupart du temps du fait de ne pas vouloir l'utiliser comme un module du serveur web, (comme Apache), ou bien que vous souhaitez l'utiliser en combinaison d'un wrapper CGI afin de créer un environnement de script sécurisé (en utilisant des techniques de chroot ou setuid). Une telle décision signifie habituellement que vous installez votre exécutable dans le répertoire cgi-bin de votre serveur web. CERT advisory CA-96.11 recommende effectivement de placer l'interpréteur à l'intérieur du répertoire cgi-bin. Même si le binaire PHP peut être utilisé comme interpréteur indépendant, PHP a été pensé afin de rendre impossible les attaques que ce type d'installation induit.

La requête dans une url après le point d'interrogation (?) est envoyée à l'interpréteur comme une ligne de commande par l'interface CGI. Habituellement, l'interpréteur ouvre le fichier spécifié et l'exécute.

Lorsqu'il est invoqué comme binaire CGI, le PHP refuse d'interpréter les arguments de la ligne de commande.

Le "path information" dans l'url, situé juste après le nom du binaire PHP, /secret/doc.html est utilisé par convention pour spécifier le nom du fichier qui doit être ouvert et interprété par le programe CGI. Habituellement, des directives de configuration du serveur web (pour le serveur Apache: Action) sont utilisées pour rediriger les requêtes pour obtenir un document http://ma.machine/secret/script.php3 par l'interpréteur PHP. Dans une telle configuration, le serveur web vérifie d'abord si il a accès au répertoire /secret, et après cette vérification redirige la requête vers http://ma.machine/cgi-bin/php/secret/script.php3. Malheureusement, si la requète est faite directement sous cette forme, aucune vérification d'accès n'est faite par le serveur web pour le fichier /secret/script.php3, mais uniquement pour le fichier /cgi-bin/php. De cette manière, n'importe quel utilisateur qui peut accéder au fichier /cgi-bin/php peut aussi accéder au document protégés sur le serveur web.

Avec le PHP, l'option de compilation --enable-force-cgi-redirect et les options d'exécution doc_root et user_dir peuvent être utilisées pour prévenir ce genre d'attaques, si des restrictions d'accès sont appliquées sur les documents du serveur. Voir ci-dessous pour des explications plus complètes sur les différentes combinaisons.

Cas 1: Tous les fichiers sont publics

Si votre serveur n'a aucun document dont l'accès est restreint par un mot de passe ou un système de vérification de l'adresse IP, vous n'avez aucun besoin de ce type de configuration. Si votre serveur web ne permet pas les redirections, ou si votre serveur web n'a aucun besoin de communiquer avec le binaire PHP de manière sécurisée, vous pouvez utiliser l'option de compilation --disable-force-cgi-redirect . Vous devez quand même vérifier qu'aucun script ne fait appel au PHP, de manière directe, http://ma.machine/cgi-bin/php/dir/script.php3 ou bien de manière indirecte, par redirection, http://ma.machine/dir/script.php3.

Les redirections peuvent être configurées dans les fichiers de configuration d'Apache en utilisant les directives "AddHandler" et "Action" (voir ci-dessous).

Cas 2: Utilisation de la directive de compilation --enable-force-cgi-redirect

Cette option de compilation prévient quiconque d'appeler directement un script avec l'url http://ma.machine/cgi-bin/php/secretdir/script.php3. Dans ce cas là, PHP parsera le fichier uniquement si il y a eu redirection.

Habituellement, le serveur web Apache réalise une redirection grâce aux directives suivantes :

Action php3-script /cgi-bin/php

AddHandler php3-script .php3

Cette option a uniquement été testée avec Apache; et compte sur Apache pour affecter la variable d'environnement non-standart REDIRECT_STATUS pour les requêtes redirigées. Dans le cas où votre serveur web ne supporte pas le renseignement du PHP, pour savoir si la requête a été redirigée ou non, vous ne pouvez pas utiliser cette option de compilation. Vous devez alors utiliser une des autres manières pour utiliser la version binaire CGI du PHP, comme exposé ci-dessous.

Cas 3: Utilisation du "doc_root" ou du "user_dir"

Ajouter un contenu interactif dans votre serveur web, comme des scripts ou des exécutables, est souvent considéré comme une pratique non-sécurisée. Si, par erreur, le script n'est pas exécuté mais affiché comme une page HTML classique, il peut en résulter un vol de propriété intellectuelle ou des problèmes de sécurité à propos des mots de passe notamment. Donc, la plupart des administrateurs préfèrent mettre en place un répertoire spécial pour les scripts qui est uniquement accessible par le biais du binaire CGI du PHP, et donc, tous les fichiers de ce répertoire seront interprétés et non affichés tels quel.

Aussi, si vous ne pouvez pas utiliser la méthode présentée ci-dessus, il est nécessaire de mettre en place un répertoire "doc_root" différent de votre répertoire "document root" de votre serveur web.

Vous pouvez utiliser la directive doc_root dans le fichier de configuration , ou vous pouvez affecter la variable d'environnement PHP_DOCUMENT_ROOT. Si cette variable d'environnement est affectée, le binaire CGI du PHP construira toujours le nom de fichier à ouvrir avec doc_root et le "path information" de la requête, et donc vous serez sûr qu'aucun script n'est exécuté en dehors du répertoire prédéfinit. (à l'exception du répertoire désigné par la directive user_dir Voir ci-dessous).

Une autre option possible ici est la directive user_dir . Lorsque la directive n'est pas activée, seulement les fichiers contenues dans le répertoire doc_root peuvent être ouverts. Ouvrir un fichier possédant l'url http://ma.machine/~user/doc.php3 ne correspond pas à l'ouverture d'un fichier sous le répertoire racine de l'utilisateur mais à l'ouverture du fichier ~user/doc.php3 sous le repertoire "doc_root" (oui, un répertoire comment par un tilde [~]).

Si la directive "user_dir" est activée à la valeur public_php par exemple, une requête du type http://ma.machine/~user/doc.php3 ouvrira un fichier appelé doc.php3 sous le répertoire appelé public_php sous le répertoire racine de l'utilisateur. Si le répertoire racine des utilisateurs est /home/user, le fichier exécuté sera /home/user/public_php/doc.php3.

user_dir et doc_root sont deux directives totalement indépendantes et donc vous pouvez contrôler l'accès au répertoire "document root" séparément des répertoires "user directory".

Cas 4: L'exécutable PHP à l'extérieur de l'arborescence du serveur

Une solution extrêmement sécurisée consiste à mettre l'exécutable PHP à l'extérieur de l'arborescence du serveur web. Dans le répertoire /usr/local/bin, par exemple. Le problème de cette méthode est que vous aurez à rajouter la ligne suivante :

#!/usr/local/bin/php

dans tous les fichiers contenant des tags PHP. Vous devrez aussi rendre le binaire PHP exécutable. Dans ce cas-là, traitez le fichier exactement comme si vous aviez un autre script écrit en Perl ou en sh ou en un autre langage de script qui utilise #! comme mécanisme pour lancer l'interpréteur lui-même.

Pour que l'exécutable PHP prenne en compte les variables d'environnement PATH_INFO et PATH_TRANSLATED correctement avec cette configuration, vous devez utiliser l'option de compilation --enable-discard-path .

Module Apache

Lorsque le PHP est compilé en tant que module Apache, ce module hérite des permissions accordées à l'utilisateur faisant tourner Apache ( par défaut, l'utilisateur "noboby").

 

Chapitre précedentIndex des Cours

Révisé le :23-Jan-2008| ©2008 www.technologuepro.com