Utilisation des variables super-globales
Avertissement
Cette fonctionnalité est OBSOLÈTE à partir de PHP 5.3.0 et a été
SUPPRIMÉE à partir de PHP 5.4.0.
L'une des évolutions les plus controversées de PHP a été
le changement de valeur par défaut de la directive PHP
register_globals, qui est
passée de On à Off en PHP
» 4.2.0.
Beaucoup d'applications dépendaient de cette directive, et de nombreux
programmeurs ne savaient même pas qu'elle existait, et supposaient
que c'était le fonctionnement normal de PHP. Cette page explique
comment on peut écrire du code peu sécuritaire en utilisant
cette directive. Gardez bien en tête que cette directive,
par elle-même, n'est pas un trou de sécurité, mais qu'elle
facilite leur création.
Lorsqu'elle est activée, register_globals
va injecter vos scripts avec toutes sortes de variables,
comme les variables issues des formulaires HTML. Ceci, couplé au fait
que PHP ne requiert pas d'initialisation de variable signifie que la
programmation de script peu sûr est possible. Ce fut une décision
difficile de la communauté PHP, mais finalement, il a été décidé
de désactiver par défaut cette variable. Lorsqu'elle est active,
le programmeur ne sait pas exactement d'où provient le contenu de la
variable, et ne peut que faire des suppositions. Les variables internes
définies dans le script sont mélangées avec les données envoyées par les
utilisateurs, et en désactivant register_globals,
on empêche cela. Voyons avec un exemple le fonctionnement de
register_globals :
Exemple #1 Exemple de mauvaise utilisation de register_globals
<?php
// $authorized = true uniquement si l'utilisateur est identifié
if (authenticated_user()) {
$authorized = true;
}
// Comme nous n'avons pas initialisé $authorized avec false, cette dernière
// peut être définie via register_globals, comme avec l'URL GET auth.php?authorized=1
// Tout le monde peut facilement être reconnu comme identifié!
if ($authorized) {
include "/donnees/critiques/data.php";
}
?>
Lorsque register_globals est activé, la logique ci-dessus peut être prise
en défaut. Lorsque register_globals est désactivée
$authorized ne peut plus être assignée via la requête, et
le script est maintenant sûr, même s'il reste recommandé de toujours
initialiser ses variables. Par exemple, dans notre programme ci-dessus, nous
pourrions ajouter $authorized = false
. En faisant cela,
le script peut fonctionner avec register_globals on ou off, car les
utilisateurs seront par défaut non-identifiés.
Un autre exemple implique les sessions.
Lorsque register_globals est activé, on peut aussi utiliser
$username dans notre exemple, mais, encore une fois, vous
devez garder en tête que $username peut aussi provenir
d'autres biais, tels que GET (via l'URL).
Exemple #2 Exemple d'abus de sessions avec register_globals on ou off
<?php
// Nous ne savons pas d'où provient $username mais nous savons que
// $_SESSION contient les données de session
if (isset($_SESSION['username'])) {
echo "Bonjour <strong>{$_SESSION['username']}</strong>";
} else {
echo "Bonjour <strong>visiteur</strong><br />";
echo "Voulez-vous vous identifier?";
}
?>
Il est même possible de prendre des mesures préventives, pour
être alerté lorsqu'une tentative d'usurpation est faite. Si vous savez
à l'avance de quelle variable le nom d'utilisateur doit provenir, vous
pouvez vérifier si les données que vous manipulez sont d'une origine
contrôlée. Même si cela ne garantit pas que les données ne puissent être
falsifiées, cela complique la tache du faussaire. Si vous ne vous
préoccupez pas de l'origine des données, vous pouvez utiliser la variable
$_REQUEST qui contient un mélange de données GET, POST
et COOKIE. Voyez aussi la section du manuel concernant les
variables de sources externes à
PHP.
Exemple #3 Détection simple de fausses variables
<?php
if (isset($_COOKIE['MAGIC_COOKIE'])) {
// MAGIC_COOKIE provient d'un cookie.
// Assurez-vous de valider les données du cookie!
} elseif (isset($_GET['MAGIC_COOKIE']) || isset($_POST['MAGIC_COOKIE'])) {
mail("admin@example.com", "Tentative possible d'attaque", $_SERVER['REMOTE_ADDR']);
echo "Alerte sécurité, l'admin a été prévenu.";
exit;
} else {
// MAGIC_COOKIE ne provient pas de REQUEST
}
?>
Bien sur, désactiver l'option register_globals ne signifie pas que votre
code est sécuritaire. Pour chaque donnée reçu, vous devez appliquer un
maximum de validations. Vérifiez toujours les données de votre visiteur,
et initialisez vos variables! Pour vérifier les variables non-initialisées,
voyez la fonction error_reporting(), qui peut afficher
les erreurs de niveau E_NOTICE
.
Pour des informations sur l'émulation de register_globals
On ou Off, voyez la FAQ.