I. Définition▲
Les tableaux superglobaux (dits aussi autoglobaux) sont une nouveauté de PHP 4.2.0, les versions antérieures n'en possèdent pas.
De façon générale, une variable superglobale est automatiquement disponible dans tous les environnements d'exécution. Elle a donc une portée globale.
Un environnement d'exécution possède son propre espace de variables. Pour connaître une variable dans plusieurs environnements, il faut la déclarer à l'aide du mot réservé global.
Par exemple, une fonction ne connait pas les variables du script, pour y remédier, on déclare celles que l'on souhaite utiliser dans la fonction avec global.
Exemple :
II. Utilisation▲
Les tableaux superglobaux ne peuvent être utilisés qu'avec la version PHP 4.2.0 (et supérieures).
En pratique, une variable superglobale est simplement disponible dans tout contexte d'utilisation, que ce soit dans le script, dans une méthode de classe, dans une fonction… sans avoir à utiliser la directive global.
Il n'est pas possible (pour l'instant du moins) de créer soi-même des variables superglobales, on ne peut qu'utiliser celles déjà existantes comme définies dans la Liste des tableaux superglobaux.
Ces variables sont des tableaux associatifs. C'est-à-dire qu'à une clé est associée une valeur pouvant être un nombre, une chaîne de caractères, un tableau… Les clés de ces tableaux sont les noms des variables qu'ils référencent.
Exemple :
Comme les tableaux superglobaux remplacent d'anciennes variables obsolètes, mais toujours présentes, ces dernières peuvent encore être utilisées. Dans ce cas, ne pas oublier la directive global.
III. Liste des tableaux superglobaux▲
Ces tableaux ne sont disponibles que sur les serveurs équipés de la version 4.2.0 et suivantes de PHP. Pour les versions antérieures, il faut utiliser les variables dites obsolètes du tableau suivant.
À noter que certaines variables peuvent être simultanément disponibles dans plusieurs tableaux superglobaux à la fois. Par exemple, le tableau $GLOBALS reprend chacune des variables disponibles dans tous les autres tableaux superblobaux. Autre exemple, un paramètre passé dans l'URL à un script sera référencé dans $_GET et dans $_REQUEST.
Nom |
Description |
Nom obsolète |
---|---|---|
$GLOBALS |
Contient toutes les variables disponibles dans l'environnement d'exécution global. |
- |
$_SERVER |
Contient les variables fournies par le serveur web. |
$HTTP_SERVER_VARS |
$_GET |
Contient les variables fournies en paramètre au script via la méthode GET du protocole HTTP. |
$HTTP_GET_VARS |
$_POST |
Contient les variables fournies par un formulaire via la méthode POST du protocole HTTP. |
$HTTP_POST_VARS |
$_COOKIES |
Contient les variables fournies par les cookies via le protocole HTTP. |
$HTTP_COOKIE_VARS |
$_FILES |
Contient les variables fournies suite à un chargement de fichier par un formulaire via la méthode POST du protocole HTTP. |
$HTTP_POST_FILES |
$_ENV |
Contient les variables fournies par l'environnement. Ce peut être des variables du Shell sous lequel s'exécute PHP, les variables CGI… |
$HTTP_ENV_VARS |
$_REQUEST |
Contient les variables fournies au script par n'importe quel mécanisme. |
- |
$_SESSION |
Contient les variables de la session en cours dans le script. |
$HTTP_SESSION_VARS |
IV. Liste des variables du serveur▲
Ces variables sont référencées dans le tableau superglobal $_SERVER.
Nom |
Description |
---|---|
argv |
Tableau des arguments passés au script dans le cas où celui-ci est lancé en ligne de commande depuis un Shell. |
argc |
Nombre de paramètres passés au script (dans le cas ligne de commande). |
DOCUMENT_ROOT |
Racine à partir de laquelle est exécuté le script. |
PHP_SELF |
Nom du fichier du script en cours par rapport au DOCUMENT_ROOT. |
REQUEST_METHOD |
Méthode de la requête invoquée pour accéder à la page. Avec le protocole HTTP/1.0, les méthodes possibles sont : GET, POST, HEAD, PUT. |
REQUEST_URI |
URI (Uniform Resource Identifier) qui a été fournie pour accéder à la page. |
QUERY_STRING |
Question posée au script (si elle existe). Ce sont les paramètres passés au script. |
SCRIPT_FILENAME |
Chemin absolu jusqu'au script courant. |
SCRIPT_NAME |
Nom du script courant. Utilisé dans le champ method des formulaires pour que le script s'appelle lui-même. |
PATH_TRANSLATED |
Chemin de la page dans le système de fichiers réel du serveur. Est différent du chemin virtuel traduit pour l'extérieur. |
GATEWAY_INTERFACE |
Numéro de révision de l'interface CGI du serveur. |
SERVER_NAME |
Nom du serveur qui exécute le script. Ce peut-être un hôte virtuel. Tel que défini par la directive VIRTUAL_HOST d'Apache. |
SERVER_SOFTWARE |
Chaîne de caractères d'identification du serveur. Contenu du champ Server de l'entête HTTP. Par exemple : Apache/1.3.9 (Unix) Debian/GNU. |
SERVER_PROTOCOL |
Nom et révision du protocole utilisé pour transférer au client la page issue du script. En général : HTTP/1.0 ou HTTP/1.1. |
SERVER_ADMIN |
Identifiant de l'administrateur du serveur tel que défini par la directive SERVER_ADMIN d'Apache. |
SERVER_PORT |
Numéro de port utilisé sur le serveur. Traditionnellement, vaut 80. |
SERVER_SIGNATURE |
Chaîne de caractères contenant le numéro de version du serveur ainsi que le nom d'hôte virtuel. |
HTTP_ACCEPT |
Contenu du champ Accept de l'entête HTTP. C'est la liste des types MIME. Par exemple : text/html, application/xml, image/gif. |
HTTP_ACCEPT_CHARSET |
Contenu du champ Accept-Charset de l'entête HTTP. C'est le type d'encodage des caractères utilisés. |
HTTP_ACCEPT_ENCODING |
Contenu du champ Accept-Encoding de l'entête HTTP. C'est le type d'encodage des données utilisées. C'est en général de la compression. Par exemple : gzip. |
HTTP_ACCEPT_LANGUAGE |
Contenu du champ Accept-Language de l'entête HTTP. C'est la langue utilisée. Par exemple : fr. |
HTTP_CONNECTION |
Contenu du champ Accept-Connection de l'entête HTTP. C'est le type de la connexion établie entre le client et le serveur (persistante ou non), par exemple : Keep-Alive ou close. |
HTTP_HOST |
Contenu du champ Host de l'entête HTTP en cas de virtual hosting. |
HTTP_REFERER |
Adresse de la page qui a conduit le client à la page courante. |
HTTP_USER_AGENT |
Contenu du champ User-Agent de l'entête HTTP. C'est le nom et la version du navigateur utilisé par le client pour consulter la page en cours. Ainsi que le système d'exploitation et autres informations. Par exemple : Mozilla/5.0 Galeon/1.0.2 (X11;Linux i686; U;) Gecko/20011224. |
REMOTE_ADDR |
Adresse IP du client qui demande la page. |
REMOTE_PORT |
Le numéro de port utilisé sur la machine cliente pour établir la communication avec le serveur. |
Script de départ |
---|
echo « <form action=\ »« .$_SERVER[ »SCRIPT_NAME« ]. »\« method=\ »POST\« > »; |
Script d'arrivée |
echo « Vous êtes ».$_POST[« nom »].« . »; |
V. Portée des variables référencées▲
On a vu qu'à partir de PHP 4.2.0 les variables référencées dans les tableaux superglobaux ne sont accessibles que par l'intermédiaire de ces tableaux. Auparavant, les variables référencées pouvaient être accédées directement, via un global si nécessaire (dans les fonctions et méthodes).
Ce changement repose sur un paramétrage par défaut du fichier de configuration php.ini qui a été changé. Le paramètre register_global était à On, en PHP 4.2.0 il passe à Off par défaut. Mais il est toujours possible de le changer manuellement afin de revenir à la situation antérieure ou les variables référencées par ces tableaux superglobaux étaient directement accessibles.
Avec register_global = On, appel de la page page.php?id=41&nom=robert : |
Affiche : Sélectionnez 1. 2.
|
VI. Pourquoi des tableaux superglobaux ?▲
Pourquoi avoir introduit cette nouveauté dans PHP 4.2.0 ? Tout simplement pour des raisons de sécurité.
Non pas que PHP lui-même comporte des failles de sécurité (en fait si, mais ce n'est pas le sujet de cet article), mais les webdesigners qui programment en PHP ne font pas toujours suffisamment attention à ce qu'ils écrivent. Permettant ainsi aux internautes malveillants d'induire le script en erreur ou de lui faire faire des choses qui n'étaient pas prévues.
Voici un petit exemple, notre script script.php va inclure un fichier de configuration via une commande include() qui contient par exemple les informations nécessaires (login, mot de passe, nom de la base) pour se connecter à une base de données MySQL. Le nom de ce fichier est normalement passé en paramètre via un formulaire (méthode GET ou POST).
Script.php :
2.
3.
4.
<?php
include($config_file
);
...
?>
Un petit malin pourrait avoir l'idée d'aller regarder le code source HTML de votre formulaire formulaire.php.
Libre à lui, à partir de là, d'exécuter votre script d'arrivée sans passer par l'intermédiaire du formulaire, et en lui passant des paramètres en argument.
Adresse tapée dans le navigateur par le hacker :
script.
php?
config_file=/
etc/
passwd
Ainsi votre script a été détourné pour afficher le fichier de mot de passe du serveur ! Il connait maintenant tous les utilisateurs de votre système (les mots de passe sont généralement cryptés).
Les include() préfixés ou suffixés par une chaîne de caractères constante ne sont pas mieux lotis.
Dans l'exemple suivant, un chemin relatif permet la remontée dans le système de fichiers.
2.
script.
php?
config_file=../../../
etc/
passwd
include("
common/config/
$config_file
"
);
Dans l'exemple suivant, une chaîne de caractères terminée par le caractère spécial de fin de chaîne %00 dit à PHP d'ignorer le suffixe « inc ».
2.
script.
php?
config_file=../../
etc/
passwd%
00
include("
myfiles/
"
.
$config_file
.
"
inc
"
);
Comment remédier à ces attaques ? En étant plus rigoureux dans sa programmation ! L'exemple suivant montre une méthode sûre.
Dans cet exemple, on vérifie que le nom de fichier reçu par le script appartient à une liste prédéterminée, si tel est le cas, on l'inclut. Sinon, c'est qu'il y a un problème !
Il existe de nombreuses fonctions travaillant sur les fichiers qui sont susceptibles d'être détournées (inclusion, ouverture, exécution de fichier) : require(), include(), include_once(), require_once(), file(), readfile(), fpassthru(), exec(), fopen()…
Il est donc nécessaire d'être très vigilant lors de la programmation en PHP et de deviner quelles sont toutes les actions malveillantes susceptibles d'être exécutées à travers vos scripts. Il s'agit donc d'être particulièrement paranoïaque et de protéger toutes les variables en les vérifiant systématiquement.
D'ailleurs ce problème n'est pas réservé aux fichiers. Toutes les autres variables sont concernées. Ainsi les id de sessions peuvent être falsifiées, les id de message à supprimer d'un forum aussi…
Alors, au lieu de faire démesurément confiance aux variables créées automatiquement dans l'espace d'exécution (par global_register) à partir des paramètres passés au script, on utilise les tableaux globaux $HTTP_ENV_VARS, $HTTP_GET_VARS $HTTP_POST_VARS, $HTTP_COOKIE_VARS, $HTTP_SERVER_VARS et $HTTP_SESSION_VARS (créés automatiquement par la directive de configuration track_vars mise à On).
Ainsi, utiliser $HTTP_POST_VARS[« config_file »] permet de se prémunir contre les attaques précédentes.
Par contre cette relative sécurité peut être détournée par un hacker qui enregistre sur son ordinateur votre formulaire, en modifie le code pour changer le <input type=« hidden » name=« config_file » value=« config_bd.php » /> en <input type=« hidden » name=« config_file » value=« /etc/passwd%00 » /> et valider le formulaire pour vous pirater !
Depuis PHP 4.2.0 ces tableaux globaux sont devenus obsolètes. Et il faut alors utiliser les tableaux superglobaux.
VII. Liens▲
VII-A. Tableaux superglobaux▲
Sur PHP.net :
VII-B. Sécurité▲
Pour de plus amples informations sur cette question de sécurité, je vous recommande la lecture de cet article de Thomas Oertli : Secure Programming in PHP (en anglais).
Un autre document très intéressant, traduit en français celui-là, Exploitation des vulnérabilités avec les applications PHP de Shaun Clowes SecureReality.