-
Notifications
You must be signed in to change notification settings - Fork 167
Expand file tree
/
Copy pathcgi-bin.xml
More file actions
259 lines (250 loc) · 12.2 KB
/
cgi-bin.xml
File metadata and controls
259 lines (250 loc) · 12.2 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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: 87d3bf2e9ea7da5abbeca3e60ea7cf7abfa6f7f3 Maintainer: lacatoire Status: ready -->
<!-- Reviewed: yes Maintainer: pmartin -->
<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 exécutable <acronym>CGI</acronym> est une possibilité
pour les cas où l'on ne veut pas l'utiliser comme un module
du serveur web (comme Apache), ou bien lorsque l'on souhaite l'utiliser en
combinaison avec un gestionnaire <acronym>CGI</acronym> complémentaire, afin de
créer un environnement de script sécurisé (en utilisant
des techniques de <command>chroot</command> ou <command>setuid</command>).
Une telle décision signifie habituellement que l'exécutable
<command>php</command> sera installé dans le répertoire du serveur web <filename class="directory">cgi-bin</filename>.
Le conseil de sécurité CERT <link xlink:href="&url.cert;">CA-96.11</link> recommande
de ne pas placer d'interpréteurs dans le répertoire <filename class="directory">cgi-bin</filename>.
Même si le binaire <command>php</command> peut être utilisé comme interpréteur autonome,
PHP est conçu pour prévenir les attaques que cette configuration peut rendre possibles :
</simpara>
<itemizedlist>
<listitem>
<simpara>
Accès au système de fichiers :
<filename role="url">http://my.host/cgi-bin/php?/etc/passwd</filename>
</simpara>
<simpara>
Lorsque la requête est passée dans une url, après le point
d'interrogation (<literal>?</literal>), 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, <command>php</command> refuse
d'interpréter les arguments de la ligne de commande.
</simpara>
</listitem>
<listitem>
<simpara>
Accès à n'importe quel 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 programme
<acronym>CGI</acronym>. Habituellement, des directives de configuration
du serveur web (pour le serveur Apache : <literal>Action</literal>) sont utilisées pour
rediriger des requêtes vers des documents comme
<filename role="url">http://my.host/secret/script.php</filename> vers
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 redirige ensuite 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 à n'importe quel document protégé sur le serveur web.
</simpara>
<simpara>
Avec PHP, les options d'exécution
<link linkend="ini.cgi.force-redirect">cgi.force_redirect</link>,
<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'attaque, 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 : Seuls les fichiers publics sont servis</title>
<simpara>
Si le serveur n'a aucun document dont l'accès n'est pas restreint
par un mot de passe ou un système de vérification de l'adresse
IP, ce type de configuration n'est pas nécessaire. Si le serveur web
ne permet pas les redirections, ou s'il n'a aucun besoin de
communiquer avec le binaire PHP de manière sécurisée,
il est possible d'activer la directive INI
<link linkend="ini.cgi.force-redirect">cgi.force_redirect</link>.
Il faut tout de même s'assurer que les scripts PHP ne dépendent pas d'un appel
de manière directe comme <filename role="php">http://my.host/cgi-bin/php/dir/script.php</filename>,
ou de manière indirecte, par redirection, <filename role="php">http://my.host/dir/script.php</filename>.
</simpara>
<simpara>
Avec Apache, les redirections peuvent être configurées en utilisant les directives <literal>AddHandler</literal>
et <literal>Action</literal> (voir ci-dessous).
</simpara>
</sect1>
<sect1 xml:id="security.cgi-bin.force-redirect">
<title>
Cas 2 : Utilisation de la directive
<literal>cgi.force_redirect</literal>
</title>
<simpara>
La directive de configuration <link
linkend="ini.cgi.force-redirect">cgi.force_redirect</link>
évite qu'un appel direct à <command>php</command> avec une URL comme <filename
role="php">http://my.host/cgi-bin/php/secretdir/script.php</filename> ne soit possible.
À la place, PHP analysera le fichier uniquement s'il y a eu redirection.
</simpara>
<simpara>
Habituellement, la redirection est effectuée grâce aux directives suivantes dans la
configuration du serveur Apache :
</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ù le serveur web ne supporte aucune manière d'indiquer si la requête a été
redirigée ou non, cette option de
compilation ne pourra pas être utilisée. Il faudra 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, comme des scripts ou des exécutables, dans les répertoires
de documents du serveur web, est parfois considéré comme une
pratique non-sécurisée. Si, à cause d'une erreur de configuration, le script n'est pas
exécuté mais affiché comme une page HTML classique,
il peut en résulter une fuite de propriété intellectuelle
ou d'informations liées à la sécurité, comme, typiquement, des mots de passe.
En conséquence, un bon nombre d'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, ce qui signifie que tous les fichiers de ce répertoire
seront interprétés et jamais affichés tels quels.
</simpara>
<simpara>
De plus, s'il n'est pas possible d'utiliser la méthode
qui permet de s'assurer que les requêtes ne sont pas redirigées,
comme présentée ci-dessus, il est nécessaire de mettre
en place un répertoire de scripts "doc_root" différent du
répertoire "document root" du serveur web.
</simpara>
<simpara>
Pour indiquer la racine des scripts PHP, il est possible d'utiliser la directive
<link linkend="ini.doc-root">doc_root</link> dans le
<link linkend="configuration.file">fichier de configuration</link>,
ou il est possible d'affecter la variable d'environnement
<envar>PHP_DOCUMENT_ROOT</envar>. Si cette information
est renseigné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, ce qui garantit
qu'aucun script ne sera 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 <parameter>user_dir</parameter>
n'est pas spécifié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 correspondra
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
<parameter>doc_root</parameter> (oui, un nom de répertoire commençant par un tilde
[<literal>~</literal>]).
</simpara>
<simpara>
Si la directive <parameter>user_dir</parameter> est activée, par exemple à la valeur
<filename role="dir">public_php</filename>, une requête
du type <filename role="url">http://my.host/~user/doc.php</filename>
ouvrira un fichier appelé <filename>doc.php</filename> dans le
répertoire appelé <filename role="dir">public_php</filename>
sous le répertoire racine de l'utilisateur.
Si le répertoire racine de l'utilisateur 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 il est donc possible de
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 : Exécutable PHP à l'extérieur de l'arborescence du serveur
</title>
<para>
Une solution extrêmement sécurisée est de
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 seul véritable inconvénient de cette méthode est qu'il faudra
rajouter une ligne comme celle-ci :
<informalexample>
<programlisting>
<![CDATA[
#!/usr/local/bin/php
]]>
</programlisting>
</informalexample>
au début de chaque fichier contenant des balises PHP. Il faudra aussi rendre les
scripts PHP exécutables. En somme, le fichier doit être traité
exactement comme tout 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,
la directive INI
<link linkend="ini.cgi.discard-path">cgi.discard_path</link>
doit être activée.
</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:"~/.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
-->