Local File Inclusion (LFI) & Null Bytes
La inclusión de archivos es una vulnerabilidad común de las aplicaciones web, que puede ser fácilmente pasada por alto como parte de la funcionalidad de la aplicación.
Los lenguajes del lado del servidor como PHP o JSP pueden incluir dinámicamente scripts externos, reduciendo el tamaño total del script y simplificando el código, pero si esta lógica de inclusión no se implementa correctamente, los atacantes pueden incluir archivos tanto locales como remotos, lo que puede conducir a la divulgación del código fuente, la exposición de datos sensibles y la ejecución de código bajo ciertas condiciones.
¿Como encontrarlo?
El lugar más común donde se encuentran las vulnerabilidades LFI es dentro de los motores de plantillas. Esto se debe a que los sitios web quieren mantener una gran mayoría del sitio web igual cuando se navega entre páginas, como el encabezado, la barra de navegación y el pie de página ya que sin la generación de páginas dinámicas, todas las páginas del servidor tendrían que ser modificadas cuando se hicieran cambios en cualquiera de esas secciones.
Por ejemplo, a menudo verá un parámetro como /index.php?page=about
, que lo que hace es mantener la estética de la pagina web pero incluyendo el contenido que tiene about, en este caso.
Otro lugar común es dentro de los idiomas y se podría ver de la siguiente manera index.php?lang=en
.
¿Porque funciona?
Esta vulnerabilidad existe cuando una aplicación web incluye un archivo confiando totalmente en lo que un usuario proporcione como entrada, es decir sin tomar las medidas necesarias a la hora de incluir un archivo local.
Laboratorio
Para poder poner en practica todo lo mencionado antes simularemos un sitio web muy básico que nos permitirá en base a lo que escojamos ver un texto en un cierto idioma.
Nota: Para realizar los siguientes pasos se deberá contar con privilegios adecuados
o ser el usuario root
.
1. Habilitar un servicio web
service apache2 start
2. Ubicar nuestro sitio web
En mi caso creare una carpeta llamada lfi donde depositare los archivos necesarios para esta practica.
cd /var/www/html/
mkdir lfi
cd /var/www/html/lfi
Nota: No es necesario crear la carpeta lfi
, pero si debes alojar tus archivos en la ruta /var/www/html/
.
3. Crear los archivos necesarios
Para este ejemplo yo creare 3 archivos:
-
index.php
que sera el sitio web principal.<html> <head> <title>LFI</title> <?php echo "<br><pre>"; $language=$_GET['language']; include($language); echo "</pre>"; ?> </head> <form method="GET" > <select name="language"> <option>english</option> <option>spanish</option> </select> <input type="submit" value="Enviar"/></td> </form> </html>
-
spanish
que simulara un contenido en español.<h1>Texto en español</h1>
-
english
que simulara un contenido en inglés.<h1>Text in English</h1>
Explotación
Una vez realizado todo lo anterior debemos dirigirnos a http://localhost/lfi/index.php
en mi caso.
Ahí podremos observar nuestro sitio web y su funcionalidad para incluir archivos, en este "caso"
para el idioma.
Como sabemos que este servicio web esta incluyendo archivos locales de la maquina, podríamos probar si podemos incluir archivos distintos a los del idioma (english, spanish)
en este caso.
Un archivo común a enumerar en maquinas linux es el /etc/passwd
y en maquinas windows el C:\Windows\boot.ini
.
Como hemos visto, somos capaces de enumerar otros archivos locales del servidor web que no
pertenecen o no tienen nada que ver son el servicio web.
Nota: En este punto podrías enumerar archivos críticos dependiendo el servicio web, como por ejemplo para Apache Tomcat el archivo tomcat-users.xml
, para WordPress el archivo wp-config.php
.
Para este ejemplo simularemos un entorno de usuario muy mal configurado
y en base al resultado anterior podemos saber que usuarios existen en el sistema, para los cuales podríamos intentar listar archivos que les pertenezca y nos permita ingresar al sistema por ejemplo llaves ssh
.
Nota: Si esta llave esta almacenada en la máquina dentro del fichero authorized_keys
con ella podríamos ingresar a la máquina.
Null Bytes
Para poder ver como funciona el uso de los Null Bytes
deberemos modificar ligeramente nuestros archivos y su contenido.
-
index.php
<html> <head> <title>LFI</title> <?php echo "<br><pre>"; $language=$_GET['language']; include($language . ".php"); echo "</pre>"; ?> </head> <form method="GET" > <select name="language"> <option>english</option> <option>spanish</option> </select> <input type="submit" value="Enviar"/></td> </form> </html>
spanish
Renombrar por spanish.phpenglish
Renombrar por english.php
Una vez hecho esto si volvemos a tratar de listar los archivos anteriores nos daremos cuenta que esta vez no
los podremos listar, esto se debe a que al momento de incluir archivos nuestra aplicación esta concatenando la extensión .php
, es decir si le pasamos como parámetro spanish
el resultado seria spanish.php
, si le pasamos /etc/passwd
el resultado seria /etc/passwd.php
y así sucesivamente con lo que le pasemos como parámetro.
Si deseamos visualizar el archivo /etc/passwd
no lo podremos hacer ya que sabemos que se nos concatenara la extensión .php
y el resultado de eso nos dará un archivo que no existe (/etc/passwd.php)
.
Para esos casos necesitaremos el null byte que nos permitirá omitir la verificación de la extensión gracias a que el servidor ignorara todo aquello después del byte nulo (null byte)
.
Por ejemplo en nuestro caso al pasar como entrada index.php?language=/etc/passwd%00
el servidor lo estaría interpretando de la siguiente manera include("/etc/passwd%00.php")
ignorando todo después de %00
(null byte).
Nota: Las versiones de PHP anteriores a la 5.5 son vulnerables a la inyección de bytes nulos (null bytes)
.