Les failles de type RFI (Remote File Include) et LFI (Local File Include) sont les conséquences d’une trop grande confiance envers ses utilisateurs. En fait, tout programmeur web pense avant tout à la rapidité et à la facilité de navigation pour un utilisateur lambda venant visiter le site. Il ne faut surtout pas oublier l’utilisateur gzeta qui ne vient pas pour visiter le site mais pour essayer d’en tirer profit. La fonction php include() permet d’inclure ce qui est contenu dans n’importe quel autre fichier dans une page web. Notre site est une illustration typique de ce type de fonction. En réalité, le site est construit à partir d’une seule page qui appelle dynamiquement les articles et en place le contenu en son centre. Dans notre cas, ce mécanisme est quelque peu masqué mais de manière générale il l’est beaucoup moins. On le remarque notamment avec des URLs de la forme ?page=XXX.
De cette manière, il n’est pas nécessaire de réécrire le code de présentation et des menus dans chaque page du site, mais seulement dans notre page principale qui ensuite inclut elle-même tous les articles. L’inclusion est effectuée, puis interprétée, c’est-à-dire que si on inclut une page contenant du code, il sera interprété comme s’il faisait partie de la page originale, celà est particulièrement pratique quand une portion de code se répète plusieurs fois dans différentes pages d’un site. Seulement, quand cette fonction est utilisée sans trop prendre garde à ce que l’utilisateur pourrait faire, elle peut permettre un DoS (Denial of Service, c’est-à-dire le plantage du serveur) ou même l’éxécution de code arbitraire côté serveur. Cette faille est l’une des plus dangereuses car elle donne réellement un accès complet au serveur. Comme exemple de la manière dont cette faille peut être exploitée, nous pensons que la démonstration suivante parle d’elle-même.
Un petit exemple
Voici le code de deux pages web écrites en PHP : index.php et accueil.php. Ceci est codé de sorte à ce que n’importe quel utilisateur sollicitant l’index se verra afficher l’accueil. La fonction include() est utilisée, considérant l’extension future du site :
- <? // index.php - Bases Hacking Index Page
- if ($_GET["url"] == "") header("Location: ./?url=accueil.php"); ?> //S'il n'y a pas d'url spécifiée, afficher l'accueil
- <html>
- <head>
- <div align="center"><h1>Bases Hacking</h1></div>
- <title>Faille de type PHP include</title> </head>
- <body>
- <img src="../images/penguinroot.gif">
- <? $url = $_GET["url"];
- include($url); ?>
- </body>
- </html>
< !—>
- <br>
- <br>
- <div style="text-align: justify;">
- <font size="-1">
- Notre but avec ce site est d'introduire le grand public à l'état d'esprit des hackers. Pour ce, nous allons essayer de vous apprendre les techniques fondamentales du vrai hacking, de l'exploitation des failles classiques du web (xss, include, sql injection...), à l'injection de shellcode en mémoire (buffer overflow, ou BoF), en passant par la redirection des flux réseaux (ARP Poisoning) ou les méthodes de crackage des clés WEP qui sécurisent vos réseaux Wifi. Nous essaierons de vous faire pénétrer dans ce que Jon Erikson a dénommé "l'art de l'exploitation". <br>N'est pas un hacker qui sait "deface" un site web. Hacker, c'est tout d'abord avoir des bases solides en informatique généraliste et surtout savoir réfléchir, s'adapter à de nouvelles situations et innover. Bien sûr, pour combattre le hack, il faut tout simplement le connaître aussi bien que les acteurs du hack eux-mêmes. Pouvoir sécuriser un site, un serveur, un ordinateur personnel, c'est avant tout savoir quelles failles sont susceptibles d'exister et comment elles sont exploitables afin de les combler.<br>
- Nous espérons susciter des vocations vers ce monde malheureusement trop peu connu et diffusé qu'est la sécurité informatique.
- <br>Bon voyage en notre compagnie,
- </div>
- </font>
Nous allons donc vous expliquer le but de ces pages avec quelques screenshots qui parlent d’eux-mêmes. Tout d’abord, voici ce que l’on voit en sollicitant le site :
Nous allons maintenant essayer d’inclure une page extérieure au site, par exemple, en ajoutant http://www.google.com/intl/xx-hacker/ à l’url et voir ce qui se passe :
Ce qui se passe est très édifiant : la page de google apparaît sur le site (sans les images qui n’existent pas dans notre répertoire).
Ainsi, un attaquant peut tout à fait écrire sur un autre site un script php qui demande de réécrire l’index du site, ou de changer l’extension des scripts du site (pour qu’ils ne soient pas interprétés et que le code soit visible). En incluant la page de son script, l’attaquant a un accès complet au serveur et peut faire ce qu’il veut dans la limite des droits du serveur Web, par exemple deface le site web ou encore accéder aux éventuelles bases de données, aux mots de passe, etc..
Dans ce cas, la faille est dite RFI car il est possible d’inclure du contenu distant. De manière générale, les failles sont plutôt de type LFI (inclusion de fichier local) et vont permettre par exemple de consulter tous les fichiers du serveur ou d’inclure des fichiers malveillants que l’attaquant aura pu déposer au préalable. D’ailleurs, selon certaines configuration, un code de type include("/blabla/".$page.".php") ; peut rester vulnérable à l’inclusion locale en injectant un caractère de fin de chaîne, le byte 0 (ou NULL-byte). Par exemple, demande la page page=test.txt%00 reviendrait au même que l’inclusion de /blabla/test.txt, permettant de ne pas appliquer la restriction d’extension php souhaitée. Une autre façon d’utilier les LFI est décrite dans l’article sur le directory traversal.
Il y a cependant une autre façon, moins connue, d’exploiter ce type de faille : resolliciter la page qui inclut les autres. Ainsi, la page va s’inclure à l’infini, provoquant à la longue (et en multipliant les requêtes de ce type) le plantage du serveur web, ou Déni de Service :
Cette exploitation est intéressante car elle ne nécessite pas l’accès à un site extérieur (qui peut être très facilement bloqué). Un court article de recommandations de programmation Web sécurisée vous donnera plus d’informations sur les bonnes pratiques permettant d’éviter ce genre de failles.
Server-side includes
Cet autre type d’include n’est pas très courant car obsolète mais permet de bien comprendre les mécanismes mis en jeu. Il concerne donc les fichiers de type shtml. Beaucoup de gens les confondent avec les fichiers xhtml (eXtensible HyperText Markup Language) qui eux ne sont qu’une redéfinition standard du HTML. Ces fichiers s’appellent Server-side HTML et sont une facilité pour les développeurs qui veulent pouvoir exécuter des commandes systèmes. En effet, la majorité des serveurs analysent ce type de page avant de les rendre au client et y interprètent certaines données.
Par exemple, prenons le fichier SHTML suivant :
Lors de l’analyse du fichier, le serveur Web va apercevoir les marqueurs de code embarqué () et va interpréter ce qu’il trouvera au milieu. Dans notre cas, il exécutera la commande echo `ls -l /tmp/test`.
Au final, le navigateur recevra donc une page Web avec comme titre "Test SSI" et comme contenu quelque chose du genre "-rw-r—r— 1 root root 0 aoû 31 22:12 /tmp/test" si le fichier existe bien. Ce genre de système peut être bien pratique sur certains portails personnalisés par exemple où l’on veut extraire directement des données du serveur. C’était en réalité un embryon de développement dynamique orienté Web. Mais comme toute technologie désuette, il y en a encore qui l’utilisent aujourd’hui, coûts de migration obligent.
Ce langage est capable d’effectuer des tests de condition ou encore d’inclure d’autres fichiers. On a pu voir des portails qui généraient à la demande un fichier client.shtml contenan un code du type
<!--#exec cmd="echo `ls -l /home/client`" -->
Dans ce cas, on peut imaginer s’inscrire sur le portail avec comme nom de client && cat /etc/passwd. La commande exécutée, vous l’avez compris, serait transformée en ls -l /home/ && cat /etc/passwd, ce qui aura pour effet de concaténer à la suite du listage du répertoire /home/ le contenu du fichier /etc/passwd, contenant la liste des utilisateurs sur les systèmes UNIX.
Vous l’aurez compris, ce genre de problème n’est pas courant mais permet selon moi de commencer à appréhender les insécurités que peuvent ramener l’exécution dynamique et surtout les interactions avec l’utilisateur.
Nous ne détaillerons pas plus ce point mais je vous invite à essayer de reproduire ce scénario, ce qui permettra en premier lieu une bonne compréhension des composants mis en jeu et d’autre part un aperçu ne serait-ce que minimal de la configuration d’un serveur Web.
Au final, ce cas est spécial car la variable dynamique est déjà à l’intérieur d’un script. Mais toute donnée dynamique amenée à être écrite dans un fichier .shtml est potentiellement dangereuse si elle est remplacée par du code interprétable entre balises. Nous aurons l’occasion d’étudier plus tard le Cross-Site Scripting mettant bien plus en avant les danger de la présentation de contenu dynamique originant de l’utilisateur dans une page Web.
De manière générale, cette fonctionnalité est désactivée par défaut (il suffit par exemple sous Apache2.x d’ajouter le module include à la liste des modules chargés).