Format d'impression
Le bug PHP Array
Auteur/Traducteur : frog-man@phpsecure.info
Date de création : 19 Janvier 2003
Dernière modification : 19 Janvier 2003
Vu 22535 fois

References :
Prévénez l'auteur si vous en connaissez !

  Je vais ici expliquer un bug du langage PHP et ses éventuelles conséquences pour la sécurité d'un site web.
  Le bug en question a été testé sur les versions 4.1.0 et 4.2.0 de PHP. Ce texte sera mis à jour quand
  de nouveaux tests seront fait.
 
  Explication du bug :
  °°°°°°°°°°°°°°°°°°°°
 
  Imaginons un fichier (file.php) de ce type :
 
  ------------------------------------------
  <?
  if (isset($HTTP_COOKIE_VARS["var"])){
  echo "COOKIE";
  }elseif (isset($HTTP_GET_VARS["var"])){
  echo "GET";
  }elseif (isset($HTTP_POST_VARS["var"])){
  echo "POST";
  }elseif (isset($var)){
  echo "LOCAL";
  }else{
  echo "IS NOT SET";
  }
  ?>
  ------------------------------------------
 
  Ce fichier affichera la façon dont la variable $var a été définie : dans un cookie, par une url, par un formulaire POST,
  en local dans le script ou pas du tout.
  Concretement :
 
  Pour afficher COOKIE :
 
  --------------------------------------------
  <?
  setcookie("var","1");
  echo "<script>location='file.php';</script>";
  ?>
  --------------------------------------------
 
  Pour afficher GET :
  Dans le webbrowser, simplement taper http://[website]/file.php?var=1
 
  Pour afficher POST :
 
  -------------------------------------------
  <form action="file.php" method="POST">
  <input type="hidden" name="var" value="1">
  <input type="Submit" value="Go">
  </form>
  -------------------------------------------
 
 
  Pour afficher LOCAL :
 
  --------------------
  <?
  $var="1";
  include("file.php");
  ?>
  --------------------
 
  La méthode que nous allons utiliser pour présenter le bug est la GET.
  Pour afficher GET, on a donc vu qu'on pouvait utiliser l'url http://[website]/file.php?var=1.
  Mais on pourrait aussi l'obtenir si $var était un tableau : http://[website]/file.php?var[]=1.
  On a donc toujours GET, mais la variable est 'Array'.
  Le bug est le suivant : si on définit $var comme Array dans l'url mais qu'on ne referme pas le crochet, donc
  qu'on tape une url du type :
  http://[website]/file.php?var[=1
  On aura alors comme résultat "LOCAL".
 
  Un résultat logique aurait bien sûr été GET, ou même IS NOT SET. Le résultat obtenu nous apprend donc que si une
  variable est définie dans une url par 'variable[', elle n'est considérée ni comme venant d'une url, ni comme
  venant d'un formulaire, ni comme venant d'un cookie.
 
  Si on execute alors
  echo $var;
  on aura comme résultat la string 'Array'.
 
  Conséquence sur la sécurité :
  °°°°°°°°°°°°°°°°°°°°°°°°°°°°°
 
  La sécurité qui est alors mise en doute est quelque chose dans ce genre :
 
  -------------------------------------------------------------------------------------------------------
  if (isset($HTTP_COOKIE_VARS["var"]) || isset($HTTP_GET_VARS["var"]) || isset($HTTP_POST_VARS["var"])) {
  die("You're not authorized to do that."); }
  -------------------------------------------------------------------------------------------------------
 
  Un exemple concret (pass.php) :
 
  -------------------------------------------------------------------------------------------------------
  if (isset($HTTP_COOKIE_VARS["var"]) || isset($HTTP_GET_VARS["var"]) || isset($HTTP_POST_VARS["var"])) {
  die("You're not authorized to do that.");
  }else{
 
  if ($admin_pass==$pass){
  $var=1;
  }
 
  if (isset($var)){
  print $admin_pass;
  }else{
  die("You're not admin.");
  }
 
  }
  -------------------------------------------------------------------------------------------------------
 
  Ici, il suffirait de taper l'url http://[target]/pass.php?var[=1 pour se voir afficher le password admin.
  Evidemment c'est un exemple très simplifié et primaire, mais c'est le principe, et ce n'est pas loin
  de la vérité pour beaucoup de scripts.
 
  Un autre exemple (file2.php):
 
  -------------------------------------------------------------------------------------------------------
  if (isset($HTTP_COOKIE_VARS["inc"]) || isset($HTTP_GET_VARS["inc"]) || isset($HTTP_POST_VARS["inc"])) {
  die("You're not authorized to do that.");
  }else{
  include($inc."/config.inc");
  }
  -------------------------------------------------------------------------------------------------------
 
  Ici, l'url http://[target]/file2.php?inc[=1 fera afficher une erreur d'inclusion, car tentera d'inclure le fichier
  Array/config.inc, qui n'existe pas.
  En plus d'une faille Path Disclosure (révélation de path), l'attaqueur verra l'emplacement d'un fichier clef.
 
  Solution :
  °°°°°°°°°°
 
  1) Mettre register_globals=OFF, au lieu de vérifier si il y a une variable COOKIE, GET ou POST.
  2) Télécharger les dernières versions de PHP.
 
 
(copyleft) 2001 webmaster@phpsecure.info 19-mar-2001 16:33:02 GMT &Ext