-
Notifications
You must be signed in to change notification settings - Fork 164
Expand file tree
/
Copy pathfilesystem.xml
More file actions
238 lines (213 loc) · 7.43 KB
/
filesystem.xml
File metadata and controls
238 lines (213 loc) · 7.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: 91570644fbbe4d23e79908e1a04c4c4d003fe587 Maintainer: lacatoire 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 permet de lire des fichiers tels que <filename>/etc/passwd</filename>,
de modifier les connexions ethernet, lancer des impressions de documents,
etc. Cela implique notamment qu'il faut s'assurer que les fichiers
manipulés par les scripts sont bien ceux qu'il faut.
</simpara>
<simpara>
Dans le script suivant, 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, il est préférable d'utiliser une autre forme d'identification.
Il faut considérer 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 manœuvres :
<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 le système d'identification permet aux utilisateurs
de créer leur propre login, et qu'un utilisateur choisit
le login <literal>../etc/</literal>, le système est de nouveau exposé. Pour
cette raison, il est possible 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 le système d'exploitation, il faudra protéger
un grand nombre de fichiers, notamment les entrées de périphériques,
(<filename>/dev/</filename> ou <filename>COM1</filename>), les fichiers de
configuration (fichiers <filename>/etc/</filename> et
<literal>.ini</literal>), les lieux de stockage d'informations
(<filename>/home/</filename>, <filename>My Documents</filename>), etc.
Pour cette raison, il est généralement plus sûr d'établir une
politique qui interdit TOUT sauf ce qui est autorisé.
</para>
<sect1 xml:id="security.filesystem.nullbytes">
<title>Problèmes liés aux 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 inclus
}
?>
]]>
</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'];
// Liste blanche des valeurs possibles
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
-->