reseau social

Comment gérer correctement les magic-quotes

Un article de ToutProgrammer.com.

Les magic_quotes sont une fonctionnalité de PHP qui risque d'introduire des failles de sécurité importantes dans vos scripts si elles sont mal utilisées. Guillaume BOUCHARD propose une approche pour utiliser efficacement les magic_quotes.

Sommaire

[modifier] Introduction

Les magic-quotes sont deux options de PHP accessibles dans le php.ini et qui gèrent les chaines de caractères. Mais leur utilisation devient complètement anarchique et même dangereuse quand l'on ne sait pas s'en servir.

[modifier] Présentation des options

L'option magic_quotes_runtime permet, si elle est activée, d'échapper tous les caractères spéciaux des chaines provenant de fichiers ou de base de données.

Exemple:

  1. <?php
  2. // le fichier contient la chaîne "aujourd'hui"
  3.  
  4. $fp = fopen('url','r') ;
  5. $file = fread('$fp,128);
  6.  
  7. // magic_quote_runtime sur off
  8. echo $file; // renverra "aujourd'hui"
  9.  
  10. // magic_quote_runtime sur on
  11. echo $file; // renvera "aujourd\'hui";
  12.  
  13. ?>

L'option magic_quotes_gpc permet, si elle est activée, d'échapper tous les caractères spéciaux des chaînes provenant de Get, Post ou Cookie.

Exemple:

  1. <?php
  2.  
  3. // Vous venez de remplir un formulaire avec un champs nommé 'champs' qui
  4. // contient "aujourd'hui"
  5.  
  6. // magic_quote_gpc sur off
  7. echo $_POST['champs']; // renverra "aujourd'hui"
  8.  
  9. // magic_quote_gpc sur on
  10. echo $_POST['champs']; // renverra "aujourd\'hui"
  11.  
  12. ?>

[modifier] Le problème des 'injections SQL'

Les injections SQL c'est la possibilité d'exécuter une requête SQL différente de celle prévue par le programmeur.

Exemple:

  1. <?php
  2.  
  3. // requête SQL typique d'une interface utilisateur
  4. $sql = "SELECT * FROM user_tbl WHERE login = '".$login."' AND password = '".$password."';
  5.  
  6. ?>


Note
Le SELECT * n'est pas recommandé. Et pour une sécurité optimale, l'on optera pour un password crypté en MD5.

Cette requête semble inoffensive en utilisation normale :

  1. <?php
  2.  
  3. $login = 'guillaume';
  4. $password = 'sauce_tomate';
  5.  
  6. ?>

La requête est donc SELECT * FROM user_tbl WHERE login = 'guillaume' AND password = 'sauce_tomate'.

Maintenant, modifions un peu nos valeurs :

  1. <?php
  2.  
  3. $login = 'guillaume';
  4. $password = "' OR password LIKE '%";
  5.  
  6. ?>

La requête est donc SELECT * FROM user_tbl WHERE login = 'guillaume' AND password = OR password LIKE '%' et la ligne est quand même sélectionnée alors que le password n'est pas correct. Tout ceci aurait pu être évité si les quotes (') avaient été échappées.

[modifier] Utilisation des magic_quotes

Nous avons donc vu qu'il était nécessaire d'échapper toutes chaînes de caractères en entrée de base de données et que les magic_quotes le font gentiment pour nous quand elles sont à on. Mais cela pose quand même des problèmes.

En premier lieu, les chaînes générées par PHP et qui ne viennent pas de l'extérieur (base, fichier, formulaire) ne sont pas échappées et il peut devenir anarchique de savoir si une chaine vient de l'extérieur ou de l'intérieur. De plus, les affichages doivent tous être nettoyés et cela devient rébarbatif. Pour finir, les slashes peuvent fausser les traitements car ils allongent les chaînes.

En conclusion, il est plus simple de désactiver les magic_quotes et de penser à ajouter soit même les slashes lors d'une requête SQL via la fonction addslashes().

[modifier] Réglages des magic_quotes

La technique la plus simple est de modifier directement dans le php.ini en mettant les valeurs de magic_quotes_gpc et magic_quote_runtime à off, mais il est rare d'avoir accès au php.ini.

Le seconde solution et d'utiliser Apache et les fichiers .htaccess et la directive php_flag.

php_flag magic_quotes_gpc off
php_flag magic_quotes_runtime off

Mais encore, certains hébergements n'autorisent pas cette utilisation, il va donc falloir faire autrement.

[modifier] Réglages via php

Pour les magic_quotes_runtime, cela n'est pas extrêmement dur via la fonction set_magic_quotes_runtime().

  1. <?php
  2. ?>

En ce qui concerne magic_quotes_gpc, cela se complique car il n'y a pas de fonction pour faire cela 'à la volée', il va donc falloir faire une boucle se chargeant de nettoyer les variables.

Les variables concernées sont $_POST, $_COOKIE, $_GET, $_REQUEST, $_SERVER, $_FILES.

  1. <?php
  2.  
  3. # On n'exécute la boucle que si nécessaire
  4.  
  5. # Définition de la fonction récursive.
  6. function remove_magic_quotes(&$array)
  7. {
  8. foreach($array as $key => $val){
  9.  
  10. # Si c'est un array, recurssion de la fonction, sinon suppression des slashes
  11. if(is_array($val)){
  12. remove_magic_quotes($array[$key]);
  13. } else if(is_string($val)){
  14. $array[$key] = stripslashes($val);
  15. }
  16. }
  17. }
  18.  
  19. # Appel de la fonction pour chaque variables.
  20. # Notes, vous pouvez enlevez celle d'on vous ne vous servez pas.
  21. # Personnellement, j'enlève $_REQUEST et $_FILES
  22.  
  23. remove_magic_quotes($_POST);
  24. remove_magic_quotes($_GET);
  25. remove_magic_quotes($_REQUEST);
  26. remove_magic_quotes($_SERVER);
  27. remove_magic_quotes($_FILES);
  28. remove_magic_quotes($_COOKIE);
  29. }
  30. ?>

Ce script est à appeler avant tout autre action, via la fonction require().

[modifier] Conclusion

Maintenant, vous ne devez pas oublier d'échapper toutes les chaines dans les requêtes SQL, mais c'est la seul chose à laquelle vous devrez penser, le script se charge du reste. L'autre avantage c'est que si jamais votre hébergement change de réglages, vous êtes compatible, c'est ce que l'on appelle la portabilitée.

[modifier] Historique de l'article

Cet article, réalisé par Guillaume BOUCHARD, a été publié pour la première fois sur son blog puis sur le site ToutProgrammer.com (1ème version) le 16 mars 2004.