Files
doc-fr/security/cgi-bin.xml
Damien Seguy 2bffbe55a0 minor spelling mistakes
git-svn-id: https://svn.php.net/repository/phpdoc/fr/trunk@257608 c90b9560-bf6c-de11-be94-00142212c4b1
2008-04-15 18:25:25 +00:00

264 lines
12 KiB
XML

<?xml version="1.0" encoding="iso-8859-1"?>
<!-- $Revision: 1.16 $ -->
<!-- EN-Revision: 1.5 Maintainer: yannick Status: ready -->
<!-- Reviewed: no -->
<chapter xml:id="security.cgi-bin" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Binaires CGI</title>
<sect1 xml:id="security.cgi-bin.attacks">
<title>Faiblesses connues</title>
<simpara>
Utiliser PHP comme un <acronym>CGI</acronym> exécutable vient
la majorité du temps du fait que l'on ne veut pas l'utiliser comme un module
du serveur web, (comme Apache), ou bien que l'on souhaite l'utiliser en
combinaison d'un <acronym>CGI</acronym> complémentaire, 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.
<link xlink:href="&url.cert;">CERT CA-96.11</link> recommande effectivement
de ne placer aucun interpréteur à l'intérieur du répertoire
cgi-bin. Même si le programme 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.
</simpara>
<itemizedlist>
<listitem>
<simpara>
Accès au système de fichier :
<filename role="url">http://ma.machine/cgi-bin/php?/etc/passwd</filename>
</simpara>
<simpara>
Lorsque la requête est passée dans une url, après le point
d'interrogation (?), elle 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.
</simpara>
<simpara>
Lorsqu'il est invoqué comme exécutable CGI, PHP refuse
d'interpréter les arguments de la ligne de commande.
</simpara>
</listitem>
<listitem>
<simpara>
Accès d'un document web sur le serveur :
<filename role="url">http://my.host/cgi-bin/php/secret/doc.html</filename>
</simpara>
<simpara>
Le "path information" dans l'url, situé juste après le nom
de l'exécutable PHP, <filename role="uri">/secret/doc.html</filename> est
utilisé par convention pour spécifier le nom du fichier
qui doit être ouvert et interprété par le programe
<acronym>CGI</acronym>. Habituellement, des directives de configuration
du serveur web (pour le serveur Apache : Action) sont utilisées pour
rediriger les requêtes afin d'obtenir un document
<filename role="url">http://my.host/secret/script.php</filename> par
l'interpréteur PHP. Dans une telle configuration, le serveur web
vérifie d'abord s'il a accès au répertoire
<filename role="uri">/secret</filename>, et après cette
vérification redirige la requête vers
<filename role="url">http://my.host/cgi-bin/php/secret/script.php</filename>.
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 <filename role="uri">/secret/script.php</filename>,
mais uniquement pour le fichier <filename role="uri">/cgi-bin/php</filename>.
De cette manière, n'importe quel utilisateur qui peut accéder
au fichier <filename role="uri">/cgi-bin/php</filename> peut aussi
accéder aux documents protégés sur le serveur web.
</simpara>
<simpara>
Avec PHP, l'option de compilation
<link linkend="configure.enable-force-cgi-redirect">--enable-force-cgi-redirect</link>
et les options d'exécution <link linkend="ini.doc-root">doc_root</link>
et <link linkend="ini.user-dir">user_dir</link> 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.
</simpara>
</listitem>
</itemizedlist>
</sect1>
<sect1 xml:id="security.cgi-bin.default">
<title>Cas 1 : Tous les fichiers sont publics</title>
<simpara>
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
<link linkend="configure.enable-force-cgi-redirect">--disable-force-cgi-redirect</link>.
Vous devez quand même vérifier qu'aucun script ne fait appel
au PHP, de manière directe,
<filename role="php">http://my.host/cgi-bin/php/dir/script.php</filename>
ou bien de manière indirecte, par redirection,
<filename role="php">http://my.host/dir/script.php</filename>.
</simpara>
<simpara>
Les redirections peuvent être configurées dans les fichiers
de configuration d'Apache en utilisant les directives "AddHandler" et
"Action" (voir ci-dessous).
</simpara>
</sect1>
<sect1 xml:id="security.cgi-bin.force-redirect">
<title>
Cas 2 : Utilisation de la directive de compilation
--enable-force-cgi-redirect
</title>
<simpara>
Cette option de compilation prévient quiconque d'appeler
directement un script avec l'url
<filename role="php">http://my.host/cgi-bin/php/secretdir/script.php</filename>.
Dans ce cas-là, PHP analysera le fichier uniquement s'il y a eu redirection.
</simpara>
<simpara>
Habituellement, le serveur web Apache réalise une redirection
grâce aux directives suivantes :
</simpara>
<programlisting role="apache-conf">
<![CDATA[
Action php-script /cgi-bin/php
AddHandler php-script .php
]]>
</programlisting>
<simpara>
Cette option a uniquement été testée avec Apache et
compte sur Apache pour affecter la variable d'environnement non-standard
<envar>REDIRECT_STATUS</envar> pour les requêtes redirigées.
Dans le cas où votre serveur web ne supporte pas le renseignement
de 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 méthodes
d'exploitation de la version binaire CGI de PHP, comme exposé ci-dessous.
</simpara>
</sect1>
<sect1 xml:id="security.cgi-bin.doc-root">
<title>Cas 3 : Utilisation du "doc_root" ou du "user_dir"</title>
<simpara>
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 majorité des administrateurs
préfèrent mettre en place un répertoire
spécial pour les scripts qui soit uniquement accessible par le biais
du binaire CGI de PHP, et donc, tous les fichiers de ce répertoire
seront interprétés et non affichés tels quels.
</simpara>
<simpara>
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.
</simpara>
<simpara>
Vous pouvez utiliser la directive <link linkend="ini.doc-root">doc_root</link>
dans le <link linkend="configuration.file">fichier de configuration</link>,
ou vous pouvez affecter la variable d'environnement
<envar>PHP_DOCUMENT_ROOT</envar>. Si cette variable d'environnement
est affectée, le binaire <acronym>CGI</acronym> de PHP construira
toujours le nom de fichier à ouvrir avec <parameter>doc_root</parameter>
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éfini (à l'exception du répertoire
désigné par la directive <parameter>user_dir</parameter>
Voir ci-dessous).
</simpara>
<simpara>
Une autre option possible ici est la directive
<link linkend="ini.user-dir">user_dir</link>. Lorsque la directive n'est pas
activée, seuls les fichiers contenus dans le répertoire
<parameter>doc_root</parameter> peuvent être ouverts.
Ouvrir un fichier possédant l'url
<filename role="url">http://my.host/~user/doc.php</filename> ne correspond
pas à l'ouverture d'un fichier sous le répertoire racine de
l'utilisateur mais à l'ouverture du fichier
<filename role="uri">~user/doc.php</filename> sous le répertoire
"doc_root" (oui, un répertoire commence par un tilde
[<literal>~</literal>]).
</simpara>
<simpara>
Si la directive "user_dir" est activée à la valeur
<filename role="dir">public_php</filename> par exemple, une requête
du type <filename role="url">http://my.host/~user/doc.php</filename>
ouvrira un fichier appelé <filename>doc.php</filename> sous le
répertoire appelé <filename role="dir">public_php</filename>
sous le répertoire racine de l'utilisateur.
Si le répertoire racine des utilisateurs est
<filename role="dir">/home/user</filename>, le fichier exécuté
sera <filename>/home/user/public_php/doc.php</filename>.
</simpara>
<simpara>
<parameter>user_dir</parameter> et <parameter>doc_root</parameter> 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".
</simpara>
</sect1>
<sect1 xml:id="security.cgi-bin.shell">
<title>
Cas 4 : L'exécutable PHP à l'extérieur de l'arborescence du serveur
</title>
<para>
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
<filename role="dir">/usr/local/bin</filename>, par exemple.
Le problème de cette méthode est que vous aurez à
rajouter la ligne suivante :
<example>
<title>Ligne d'invocation de PHP</title>
<programlisting role="cgi">
<![CDATA[
#!/usr/local/bin/php
]]>
</programlisting>
</example>
dans tous les fichiers contenant des balises 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 <literal>#!</literal> comme
mécanisme pour lancer l'interpréteur lui-même.
</para>
<para>
Pour que l'exécutable PHP prenne en compte les variables
d'environnement <envar>PATH_INFO</envar> et
<envar>PATH_TRANSLATED</envar> correctement avec cette configuration,
vous devez utiliser l'option de compilation
<link linkend="configure.enable-discard-path">--enable-discard-path</link>.
</para>
</sect1>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"../../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->