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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
function printLink($link) {
global $color;
echo "<a style=\"color:$color;\" href=\"$link\">Visitez $link !</a>";
}
$color = "yellow";
printLink("http://www.developpez.com")

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 :

 
Sélectionnez
1.
2.
3.
4.
5.
function printLink($link) {
echo "<a style=\"color:".$GLOBALS["color"].";\" href=\"$link\">Visitez $link !</a>";
}
$color = "yellow";
printLink("http://www.developpez.com")

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\« > »;
echo « <input type=\ »text\« name=\ »nom\« /> »;
echo « <input type=\ »submit\« /> »;
echo « </form> »;

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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
<?php
 function afficher() {
  global $nom
  echo "Vous êtes ".$nom;
 }
 echo "$id, $nom";
 afficher();
?>

Affiche :

 
Sélectionnez
1.
2.
41, robert
Vous êtes robert

Avec register_global = Off, appel de la page page.php?id=41&nom=robert :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
<?php
 function afficher() {
  echo "Vous êtes ".$_GET["nom"];
 }
 echo $_GET["id"].", ".$_GET["nom"];
 afficher();
?>

Affiche :

 
Sélectionnez
1.
2.
41, robert
Vous êtes robert

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 :

 
Sélectionnez
1.
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.

 
Sélectionnez
1.
2.
<form action="script.php" method="POST">
<input type="hidden" name="config_file" value="config_bd.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 :

 
Sélectionnez
1.
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.

 
Sélectionnez
1.
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 ».

 
Sélectionnez
1.
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.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
<?php
 $files = array{"config_db.php", "config_user.php", "config_forum.php"}
 if(in_array($config_file,$files)) {
  require($config_file);
 } else {
  echo "C'est pas beau de pirater les sites web !";
 }
?>

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

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.