mirror of
https://github.com/macintoshplus/doc-fr.git
synced 2026-03-24 08:52:09 +01:00
239 lines
7.4 KiB
XML
239 lines
7.4 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
<!-- EN-Revision: 91570644fbbe4d23e79908e1a04c4c4d003fe587 Maintainer: yannick Status: ready -->
|
|
<!-- Reviewed: yes -->
|
|
|
|
<chapter xml:id="security.filesystem" xmlns="http://docbook.org/ns/docbook">
|
|
<title>Sécurité des fichiers</title>
|
|
<simpara>
|
|
<acronym>PHP</acronym> est soumis aux règles de sécurité
|
|
intrinsèques de la plupart des systèmes serveurs :
|
|
il respecte notamment les droits des fichiers et des dossiers.
|
|
Une attention particulière doit être portée aux
|
|
fichiers ou dossiers qui sont accessibles à tout le monde, afin de
|
|
s'assurer qu'ils ne divulguent pas d'informations critiques.
|
|
</simpara>
|
|
<simpara>
|
|
Puisque <acronym>PHP</acronym> a été fait pour permettre aux utilisateurs
|
|
d'accéder aux fichiers, il est possible de créer un
|
|
script <acronym>PHP</acronym> qui vous permet de lire des fichiers tels que <filename>/etc/password</filename>,
|
|
de modifier les connexions ethernet, lancer des impressions de documents,
|
|
etc. Cela implique notamment que vous devez vous assurer que les fichiers
|
|
manipulés par les scripts sont bien ceux qu'il faut.
|
|
</simpara>
|
|
<simpara>
|
|
Considérez le script suivant, où l'utilisateur indique
|
|
qu'il souhaite effacer un fichier dans son dossier racine. Nous
|
|
supposons que <acronym>PHP</acronym> est utilisé comme interface web pour
|
|
gérer les fichiers, et que l'utilisateur Apache est
|
|
autorisé à effacer les fichiers dans le dossier racine des
|
|
utilisateurs.
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Une erreur de vérification de variable conduit à un gros problème</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
// Efface un fichier dans un dossier racine
|
|
$username = $_POST['user_submitted_name'];
|
|
$userfile = $_POST['user_submitted_filename'];
|
|
$homedir = "/home/$username";
|
|
|
|
unlink("$homedir/$userfile");
|
|
|
|
echo "Ce fichier a été effacé !";
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
Étant donné que le nom de l'utilisateur et le nom du fichier sont fournis, des intrus peuvent
|
|
envoyer un nom d'utilisateur et un nom de fichier autres que les leurs, et effacer des
|
|
documents dans les comptes des autres utilisateurs.
|
|
Dans ce cas, vous souhaiterez utiliser une autre forme d'identification.
|
|
Considérez ce qui pourrait se passer si les utilisateurs passent
|
|
<literal>../etc/</literal> et <literal>passwd</literal> comme arguments!
|
|
Le code serait exécuté tel que :
|
|
<example>
|
|
<title>Une attaque du système de fichiers!</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
// Efface un fichier n'importe où sur le disque dur,
|
|
// où l'utilisateur PHP a accès. Si PHP a un accès root :
|
|
$username = $_POST['user_submitted_name']; // "../etc"
|
|
$userfile = $_POST['user_submitted_filename']; // "passwd"
|
|
$homedir = "/home/$username"; // "/home/../etc"
|
|
|
|
unlink("$homedir/$userfile"); // "/home/../etc/passwd"
|
|
|
|
echo "Ce fichier a été effacé !";
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
Il y a deux mesures primordiales à prendre pour éviter
|
|
ces manoeuvres :
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
Limiter les permissions de l'utilisateur web <acronym>PHP</acronym>.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Vérifier toutes les variables liées aux chemins et aux fichiers
|
|
qui sont fournis.
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
Voici un script renforcé :
|
|
<example>
|
|
<title>Une vérification renforcée</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
// Efface un fichier sur le disque où l'utilisateur a le droit d'aller
|
|
$username = $_SERVER['REMOTE_USER']; // utilisation d'un mécanisme d'identification
|
|
$userfile = basename($_POST['user_submitted_filename']);
|
|
$homedir = "/home/$username";
|
|
|
|
$filepath = "$homedir/$userfile";
|
|
|
|
if (file_exists($filepath) && unlink($filepath)) {
|
|
$logstring = "$filepath effacé\n";
|
|
} else {
|
|
$logstring = "Échec lors de l'effacement de $filepath\n";
|
|
}
|
|
|
|
$fp = fopen("/home/logging/filedelete.log", "a");
|
|
fwrite($fp, $logstring);
|
|
fclose($fp);
|
|
|
|
echo htmlentities($logstring, ENT_QUOTES);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
Cependant, même cette technique n'est pas sans faille.
|
|
Si votre système d'identification permet aux utilisateurs
|
|
de créer leur propre login, et qu'un utilisateur choisi
|
|
le login <literal>../etc/</literal>, le système est de nouveau exposé. Pour
|
|
cette raison, vous pouvez essayez d'écrire un script renforcé :
|
|
<example>
|
|
<title>Vérification renforcée de noms de fichiers</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$username = $_SERVER['REMOTE_USER']; // utilisation d'un mécanisme d'identification
|
|
$userfile = $_POST['user_submitted_filename'];
|
|
$homedir = "/home/$username";
|
|
|
|
$filepath = "$homedir/$userfile";
|
|
|
|
if (!ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD', $userfile)) {
|
|
die("Mauvais utilisateur/nom de fichier");
|
|
}
|
|
|
|
// etc...
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Suivant votre système d'exploitation, vous devrez protéger
|
|
un grand nombre de fichiers, notamment les entrées de périphériques,
|
|
(<literal>/dev/</literal> ou <literal>COM1</literal>), les fichiers de
|
|
configuration (fichiers <literal>/etc/</literal> et
|
|
<literal>.ini</literal>), les lieux de stockage d'informations
|
|
(<literal>/home/</literal>, <literal>My Documents</literal>), etc.
|
|
Pour cette raison, il est généralement plus sûr d'établir une
|
|
politique qui interdit TOUT sauf ce que vous autorisez.
|
|
</para>
|
|
<sect1 xml:id="security.filesystem.nullbytes">
|
|
<title>Issue lors de l'utilisation des octets nuls</title>
|
|
<simpara>
|
|
Comme <acronym>PHP</acronym> utilise des fonctions C pour les opérations sous-jacentes,
|
|
notamment au niveau du système de fichiers, il peut gérer les octets nuls
|
|
d'une façon inattendue. Sachant que les octets nuls dénotent la
|
|
fin d'une chaîne de caractères en C, certaines fonctions vont donc
|
|
considérer ces chaînes jusqu'à la première occurrence d'un octet nul.
|
|
|
|
L'exemple suivant présente un code vulnérable qui montre ce problème :
|
|
</simpara>
|
|
<example>
|
|
<title>Script vulnérable aux octets nuls</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$file = $_GET['file']; // "../../etc/passwd\0"
|
|
if (file_exists('/home/wwwrun/' . $file . '.php')) {
|
|
// file_exists retournera true sachant que le fichier /home/wwwrun/../../etc/passwd existe
|
|
include '/home/wwwrun/' . $file . '.php';
|
|
// le fichier /etc/passwd sera inclu
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Ainsi, toute chaîne utilisée dans des opérations sur le système de fichiers
|
|
doit toujours être validée proprement. Voici une meilleure solution de
|
|
l'exemple précédent :
|
|
</para>
|
|
<example>
|
|
<title>Validation correcte de l'entrée</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$file = $_GET['file'];
|
|
|
|
// Whitelisting possible values
|
|
switch ($file) {
|
|
case 'main':
|
|
case 'foo':
|
|
case 'bar':
|
|
include '/home/wwwrun/include/' . $file . '.php';
|
|
break;
|
|
default:
|
|
include '/home/wwwrun/include/main.php';
|
|
}
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</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:"~/.phpdoc/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
|
|
-->
|