4 minute read

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>
    

    Laboratorio

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.

Textos

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.

/etc/passwd

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.

id_rsa

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.php
  • english 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.

id_rsa

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).

etc_passwd

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).

null_byte_etc_passwd_result

Nota: Las versiones de PHP anteriores a la 5.5 son vulnerables a la inyección de bytes nulos (null bytes).