Bienvenue sur www[/gris].STUDENT-DESIGNER.[gris]com

Annonces


Affichage du tutoriel

Tutoriaux Tutoriaux > Programmation > PHP / MYSQL > Sécurité > Gérer les failles de register_globals
Créé le Mardi 8 Aout 2006 par manu

Gérer les failles de register_globals

Vous avez codé quelques scripts, peut-être même un espace "sécurisé" pour vos membres. Vous avez peut-être entendu parlé des failles de sécurité des variables globales sans réellement comprendre pourquoi ? Nous allons voir quels problèmes causent ces variables globales en état "On" et comment mettre en place un espace membre simple sécurisé.

Nous verrons aussi comment désactiver cette fonction, soit directement dans le fichier de configuration de PHP si vous avez votre propre serveur. Si vous avez un hébergement mutualisé, comme free par exemple, et que vous n'avez pas accès au php.ini je vais vous donner des astuces pour neutraliser ces variables globales :D

ouvrir Chapitre 1 : Les variables globales

Qu'est ce qui peut bien se cacher derrière ce nom barbare de variable globale[/b] ? Et bien les variables globales regroupent en fait toutes les variables dont la source provient de "l'extérieur", que l'on nomme [b]variables d'environnement[/b] ou [b]superglobales[/b]. C'est à dire qu'elles stockent les valeurs de [b]$_GET[/b], [b]$_POST[/b], [b]$_COOKIE[/b], [b]$_SERVER.

[alinea]Dans les anciennes versions de PHP, ces variables étaient accessibles de manière globale[/b]. Je vais vous donner un exemple ne paniquez pas, c'est en faite simple à comprendre ! Quand le [b]register_globals[/b] est activé, les variables provenant de $_GET['variable'], $_POST['variable'], $_COOKIE['variable'] ou $_SERVER['variable'] sont accessibles avec [b]$variable[/b], ce qui simplifie l'écriture. Mais, nous allons le voir, cette écriture entraine des [b]problèmes de sécurité.

<?php
//Ces deux écritures entrainent le même resultat lorsque register_global est à On
echo $_GET['login'];
echo 
$login;
?>

[/alinea]

ouvrir Chapitre 2 : Démonstration de la faille

Le chapitre précédent était purement théorique et vous n'avez peut-être pas encore compris les soucis qu'entrainaient ces variables globales. Nous allons donc illustrer cela par un exemple d'exploitation de cette faille.

Nous avons donc dit dans le chapitre précédent que le nom d'un champ de formulaire devenait automatiquement une variable PHP. La valeur d'un champ de ce type :

Code :

<input type="text" name="champ" />


peut-être lu par php de cette facon :



<?php
echo "Voici notre variable :".$champ;
?>



Et ceci fonctionne aussi bien par un formulaire envoyé par la méthode post[/b] que [b]get. De même si vous avez un cookie qui porte comme nom $_COOKIE['mon_nom'], vous pouvez y acceder grâce à la variable $mon_nom.



Cela peut vous paraître pratique et vous donner envie de l'utiliser mais sachez que cette méthode peut entrainer des confusions. Vous pouvez avoir dans votre formulaire HTML un champ qui se nomme "login" et avoir aussi une variable $login dans le fichier php qui traite votre formulaire. Une variable risque alors d'écraser l'autre et de créer un disfonctionnement dans votre script. Et ce genre de "bug" est difficile à déloger ...

Nous allons maintenant parler sécurité, puisque c'est le vif du sujet. Voici un code que l'on peut penser opérationnel, sans risque de dévoiler une information à un petit fouineur :D (je pars du principe que le registrer_globals est encore sur On). Et pourtant non, cherchez l'erreur !


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=windows-1250">
  <meta name="generator" content="PSPad editor, www.pspad.com">
  <title>Cette page de login n'est pas sécurisée</title>
  </head>
  <body>
    <h1>Voici ce qui peut se passer si register_globals = On</h1>
    <form action="<?php echo $_SERVER['PHP_SELF']?>" method="post">
      Entrez votre mot de passe : <input type="password" name="pass">
      <input type="submit" value="Valider" />
    </form>
    <?php
    
//Traitement du formulaire
    
if ($pass == "coucou"){
      
$session_utilisateur=true;
    }
    
    
//Espace privé
    
if ($session_utilisateur) {
      
//Le mot de passe est correct
      //Merci à http://k4lipk4.free.fr pour la citation 
      
echo "<br /><h4>Bienvenue dans votre espace privé</h4><p>L'enfer ne peut attaquer les paiiens (Rimbaud) </p>";
    }
    
?>
    
  </body>
</html>



Ce code est en fichier joint de ce chapitre et testable ici. Vous n'avez toujours pas deviné ou ce situait la faille ? Alors retrouvons nous au chapitre suivant !

ouvrir Chapitre 3 : Explication de la faille

Nous avons travaillé avec une variable qui sert de clée pour "activer" la zone privée. Cette variable je l'ai appelée $session_utilisateur[/b] dans mon script. Celle ci passe à [b]TRUE si le mot de passe est correct. Un petit rappel pourra vous rafraichir l'esprit :

<?php
    
//Traitement du formulaire
    
if ($pass == "coucou"){
      
$session_utilisateur=true;
    }
?>



La variable $session_utilisateur[/b] n'a pas été [b]initialisée et là est l'erreur. Ainsi n'importe qui peut accéder à l'espace privé sans avoir le mot de passe. Comment ? me diriez vous.

Et bien si vous avez suivi vous devriez me répondre d'une voix clair et spontannée "en rajoutant ?session_utilisateur=1 dans l'url[/i]". Je donne 1 comme valeur à [i]session_utilisateur car 1 est l'équivalent de TRUE et 0 de FALSE. Essayez donc sur le script de demonstration : ?session_utilisateur=1

Vous voyez maintenant le problème qui se pose, n'importe qui peut agir sur vos variables ! Si vous ne pouvez pas passer register_globals à Off veuillez bien à initialiser vos variables. Il suffisait de mettre :


<?php
//initialisation de la variable
//En haut de code
$session_utilisateur=false;
?>

ouvrir Chapitre 4 : Les tableaux $_GET et $_POST

Je vous conseille vivement de désactiver register_globals et d'utiliser plutôt les tableaux $_GET[/b] et [b]$_POST.

[ul]

  • Toutes les données de formulaires envoyées via method="post" sont enregistrée dans le tableau $_POST.

  • Toutes les données de formulaires envoyées via method="get" se trouvent dans le tableau $_GET. Vous trouverez donc tous les paramètres passés dans l'url contenu dans ce tableau.
  • [/ul]

    Peut-être utilisiez vous déja les tableaux $_POST et $_GET et c'est trsè bien. Vous n'avez pas pour autant perdu votre temps en lisant ce tutoriel. Je pense qu'il est important de comprendre pourquoi on ne doit pas utiliser les variables globales et pourquoi, au cas ou, il vaut mieux toujours initialiser ses variables. Voyons maintenant comment désactiver le register_globals.

    ouvrir Chapitre 5 : Régler register_globals sur Off

    Je le répète encore, je vous conseille vivement de désactiver register_globals. Pour ce faire, deux cas de figure s'offre à nous : soit vous avez un serveur dédié ou encore vous travaillez en local, soit vous êtes sur un serveur mutualisé et vous ne pouvez pas modifier le php.ini.

    1. Possibilité de modifier le php.ini

    Le plus simple pour savoir ou se trouve le fichier php.ini[/b] est d'afficher un [b]phpinfo() qui affiche de nombreuses informations sur la configuration de PHP. Copiez le code suivant dans un fichier php et affichez le depuis votre serveur.

    <?php
    phpinfo
    ();
    ?>


    Repérez la ligne Configuration File (php.ini) Path et vous aurez dans la colonne de droite l'adresse du fichier php.ini sur votre serveur.


    Editez maintenant votre php.ini[/b], recherchez la ligne [b]register_globals et remplacer le On en Off. Enregistrez votre fichier et redémarrez votre serveur apache. Voila les variables globales sont désactivées.

    2. Aucun accès au php.ini

    Je pensais pouvoir vous proposer une solution simple pour désactiver les register_globals[/b] sans modifier le php.ini avec la fonction [b]ini_set. Cette fonction permet de modifier, jusqu'à la fin de l'exécution du script, la configuration de PHP. Par exemple pour modifier l'option "display_errors" de php (qui affiche ou non les erreurs de vos scripts PHP), vous pouvez faire :

    <?php
    //Ce code placé en haut de page cachera toutes les erreurs de votre script php
    ini_set('display_errors',0);
    ?>


    Malheureusement on ne peut pas intervenir sur register_globals à partir de cette fonction. Voici donc deux autres possibilités :



    Première solution : par le biais de la fonction ini_get()[/b], qui lit les valeurs de configuration, on retrouve les valeurs entrées en GET ou en POST en parcourant le tableau [b]$_REQUEST. Ensuite nous supprimons toutes les variables globales :


    <?php
    //Astuce trouvée sur un article du journal du net
    //Si le register_globals est activé
    if (@ini_get('register_globals')) {
      
    //Alors on scannes toutes les variables provenant de $_POST, $_GET, $_ENV, $_COOKIE, $_SESSION
      
    foreach ($_REQUEST as $clef => $valeur);
        
    //Enfin unset permet de supprimer les variables globales provenant de $_POST, $_GET, $_ENV, $_COOKIE, $_SESSION
        
    unset($GLOBALS[$clef]);
      }
    ?>



    Deuxième solution : par le biais d'un fichier .htaccess[/b]. Créez un fichier texte sur votre disque dur, puis renommez le en [b]a.htaccess (sous windows on ne peut pas créer de fichier .htaccess). Editez le et coller le code suivant dedans :

    Code :

    php_value register_globals 1


    Enregistrez votre fichier et déposez le à la racine de votre ftp. Enfin, renommez le en .htaccess[/b]. Voila le .htaccess maintient donc l'état de [b]register_globals[/b] à [b]Off.

    Conlusion

    Vous pouvez maintenant constater qu'une fois register_globals à Off, l'astuce d'accéder à la zone d'administration par une variable en GET ne fonctionne plus : ?session_utilisateur=1.

    Si toutefois vous deviez laisser activé register_globals[/b], faites bien attention à [b]initialiser vos variables.

    Commentaires

    Auteur

    Soyez le premier à commenter ce tutorial.

    Page : -
    Tutoriaux Tutoriaux > Programmation > PHP / MYSQL > Sécurité > Gérer les failles de register_globals

    Derniers inscrits