Saltar a contenido

LFI al Descubierto: De la Inclusión Local a la Ejecución Remota de Comandos (RCE)

La vulnerabilidad de Local File Inclusion (LFI) no se limita únicamente a la inclusión de archivos locales. En manos de un atacante experimentado puede convertirse en un vector de ataque crítico, escalable a una situación de ejecución remota de comandos (RCE). Este artículo explora cómo los atacantes aprovechan esta vulnerabilidad para comprometer servidores y qué medidas puedes implementar para proteger tu aplicación y tu infraestructura.

¿Qué es Local File Inclusion (LFI)?

La vulnerabilidad de Local File Inclusion (LFI) se produce cuando un servidor web incluye archivos locales basándose en datos proporcionados por el usuario. Este comportamiento puede aprovecharse a fin de leer archivos no accesibles desde el lado cliente y causar comportamientos inesperados en la aplicación.

Impacto de las LFI

Las vulnerabilidades LFI pueden generar serios problemas de seguridad en un servidor web, incluyendo:

  • Acceso no autorizado a archivos sensibles y Robo de información: Un atacante puede leer archivos de configuración y credenciales almacenadas en el sistema.
  • Ejecución de código malicioso: Mediante técnicas avanzadas dependientes de la situación un atacante podría llegar a ejecutar código arbitrario en el contexto del servidor.

Ejemplo de LFI Básico

Imaginemos una aplicación web desarrollada en PHP:

LFI básico
Aplicación Web.

Tenemos una barra de búsqueda donde podemos buscar cualquier archivo. La aplicación web estaría usando un código similar a este:

<?php
  $file = $_GET['file'];
  if (isset($file)){
    include($file);
  }
?>

Este código espera un parámetro file que contendrá el archivo que le pasemos al formulario de búsqueda. Si en el formulario ponemos un archivo como hi.php, la variable contendrá dicha cadena, haciendo referencia al fichero hi.php en el mismo directorio que el archivo de la aplicación web.

Si realizamos la búsqueda, la URL de nuestra web cambiará a:

http://dominio.com/pruebas/index.php?archivo=hi.php
Resultado de aplicar LFI básico
Resultado de aplicar LFI básico.

Como prueba de concepto, intentamos acceder al archivo que contiene la configuración de los usuarios en sistemas Linux, el fichero /etc/passwd. Como la entrada del parámetro file no está sanitizada, un atacante podría escribir lo siguiente en la URL de la aplicación web:

http://dominio.com/pruebas/index.php?archivo=/etc/passwd
Accesso al fichero /etc/passwd
Acceso al fichero /etc/passwd.

Esto supone un grave error de seguridad, no ya por la revelación de nombres de usuarios e información interna del servidor si no por que el atacante podría acceder acceder a otros archivos del sistema como la configuración de servicios, el historial de comandos o claves SSH.

Para prevenir esto, podríamos realizar una sanitización de la entrada que recibe el parámetro file:

<?php
  $file = $_GET['file'];
  if (isset($file)){
    include("/var/www/html" . $file);
  }
?>
Acceso al fichero /etc/passwd restringido
Acceso al fichero /etc/passwd restringido.

Con este cambio, el acceso a los ficheros que no están contenidos en la ruta /var/www/html está restringido, aumentando levemente la seguridad en nuestro servidor. Sin embargo, esta mitigación no está completa, ya que existen otras técnicas que permiten eludir este tipo de mitigación, como veremos a continuación.

LFI con Path Traversal

Ahora, consideremos una aplicación web más robusta, donde los payloads básicos para LFI no funciona, ya que la web contiene este código:

<?php
  $file = $_GET['file'];
  if (isset($file)){
    include("/var/www/html". $file);
  }
?>

Esta protección impide acceder a cualquier archivo fuera del directorio especificado. Sin embargo, esta restricción puede ser eludida mediante Path Traversal.

El Path Traversal, también conocido como Directory Traversal, es una técnica para acceder a archivos y directorios fuera del directorio permitido por la aplicación web. Se logra utilizando secuencias como ../ para subir niveles en el sistema de archivos.

Si una aplicación tiene un filtro que solo restringe archivos en su directorio de trabajo, se puede usar Path Traversal junto con LFI para acceder a archivos del sistema. Por ejemplo:

https://dominio.com/pruebas/index.php?file=../../../../../../../../../../../etc/passwd
Acceso al fichero /etc/passwd del servidor
Acceso al archivo /etc/passwd del servidor.

Este tipo de ataque es muy peligroso cuando se combina con LFI, ya que puede permitir a un atacante acceder a archivos críticos del sistema, incluyendo configuraciones, credenciales y registros de actividad del servidor. Además, es común escalar estos ataques a una ejecución remota de comandos, ya sea realizando un ataque de LogPoisoning o incluyendo una Web Shell en el servidor.

De LFI a RCE (Remote Code Execution)

La transición de una vulnerabilidad de Local File Inclusion (LFI) a Remote Code Execution (RCE) es una técnica avanzada que los atacantes pueden emplear para comprometer un sistema por completo. Estos métodos son bastante dependientes del lenguaje en el que se escribe la aplicación y de configuraciones especificas del servidor, los métodos más comunes para lograr pasar de un LFI a RCE son los siguientes:

Inclusión de archivos de registro con inyección de código (Log Poissoning)

Si el servidor web registra las solicitudes en archivos de log accesibles, un atacante puede inyectar código malicioso en dichos registros y luego incluirlos mediante LFI. Por ejemplo:

  1. El atacante envía una solicitud maliciosa que inyecta código PHP en los logs del servidor:
curl -A "<?php system('whoami'); ?>" http://dominio.com

Aquí, el código PHP se inyecta en el archivo de logs del servidor web (por ejemplo, /var/log/apache2/access.log).

  1. Luego, utiliza LFI para incluir el archivo de log:
http://dominio.com/pruebas/index.php?file=../../../../../../var/log/apache2/access.log

Esto ejecutará el código PHP inyectado, permitiendo al atacante ejecutar comandos en el servidor.

Fichero logs de Apache
Acceso a los logs de acceso de Apache via LFI.

Como se puede observar al final del log, se refleja que hemos accedido al directorio especificado. Esto significa que el contenido de la variable proporcionada en la URL ha sido procesado por el servidor, permitiendo al atacante visualizar información sensible o ejecutar código malicioso si el archivo incluido contiene instrucciones ejecutables.

De igual manera y dependiendo del log que podamos leer se puede inyectar el código a ejecutar en los logs del servicio web (a través del User-Agent por ejemplo), en los logs del SSH (mediante el nombre de usuario) e incluso en logs custom de la aplicación mediante diversos parámetros.

¿Qué ocurre exactamente?

  • PHP usa include() para interpretar el archivo especificado.
  • Al incluir el log, se encuentra con una línea que contiene <?php system('id'); ?>.
  • PHP ejecuta esa línea como si fuera parte del código original.
  • El resultado del comando id se muestra en la respuesta HTTP.

Inclusión de Sesiones PHP

Cuando PHP almacena datos de sesión en archivos (configuración predeterminada), estos se guardan en un directorio definido por session.save_path en el archivo php.ini. Si un atacante obtiene acceso a estos archivos mediante Local File Inclusion (LFI), puede inyectar y ejecutar código malicioso.

Flujo de Ataque

  1. Inyección de Código en la Sesión:
    El atacante inicia una sesión y modifica su contenido para incluir código PHP:
<?php
 session_start();
 $_SESSION['malicioso'] = "<?php system('id'); ?>";
?>

Esto guarda el payload en el archivo de sesión (ej: /var/lib/php/sessions/sess_abc123).

  1. Explotación mediante LFI:
    Si el servidor permite incluir archivos fuera del directorio raíz:
    url http://dominio.com/index.php?file=../../../../var/lib/php/sessions/sess_abc123 El código PHP inyectado se ejecutará, permitiendo ejecutar comandos como id.

¿Por qué son Sensibles los Archivos de Sesión?

  • Ubicación Accesible: Por defecto, PHP almacena sesiones en directorios como /var/lib/php/sessions (Linux) o C:\Windows\Temp (Windows). Si estos archivos están dentro del alcance del servidor web (ej: DocumentRoot), podrían ser incluidos mediante LFI.
  • Formato de Almacenamiento: Los archivos de sesión contienen datos en texto plano con el formato. Si el valor incluye código PHP sin sanitizar, se ejecutará al ser incluido.

Mitigaciones

La prevención de vulnerabilidades como Local File Inclusion (LFI) requiere un enfoque integral que combine buenas prácticas de desarrollo, configuraciones seguras del servidor y monitoreo constante. Las mitigaciones no solo deben enfocarse en evitar la explotación inicial, sino también en limitar el impacto de un posible ataque. A continuación, se presentan estrategias clave para proteger tus aplicaciones y sistemas frente a LFI a su posible escalada a Remote Code Execution (RCE) y prevenir la inclusion de sesiones en PHP.

Mitigaciones para prevenir LFI a RCE

Para evitar que una vulnerabilidad de LFI escale a RCE, se deben implementar las siguientes medidas:

  1. Validación estricta de entradas:

    Utilizar listas blancas para limitar los archivos que pueden ser incluidos, además de rechazar caracteres como ../, y otros que permitan Path Traversal.

    • Listas Blancas (Whitelisting):

    • Concepto: Permite solo un conjunto específico de archivos o rutas que son consideradas seguras.

    • Ejemplo: Si tu aplicación necesita incluir solo archivos .php desde un directorio específico, define una lista blanca que solo permita esos archivos.
    <?php
    $allowed_files = [
        'home.php',
        'about.php',
        'contact.php'
    ];
    
    $file = $_GET['file'];
    
    if (in_array($file, $allowed_files)) {
        include('/var/www/html/pages/' . $file);
    } else {
        echo "Archivo no permitido.";
    }
    ?>
    

    En este ejemplo, solo los archivos home.php, about.php y contact.php pueden ser incluidos. Cualquier otro archivo será rechazado.

    • Rechazar Caracteres Peligrosos:

      • Concepto: Bloquea caracteres y secuencias que facilitan el Path Traversal y otras manipulaciones.
      • Ejemplo: Eliminar o rechazar secuencias como ../, ..\\, y otros caracteres especiales.
    <?php
    function sanitizePath($input) {
        // Decodificar URL primero para evitar bypass con caracteres codificados
        $input = urldecode($input);
    
        // Eliminar secuencias de traversal en todas sus variantes
        $input = str_replace(['../', '..\\', '.../', '....//'], '', $input);
    
        // Eliminar caracteres no permitidos (solo letras, números, guiones y puntos)
        $input = preg_replace('/[^a-zA-Z0-9\-\.\/]/', '', $input);
    
        return $input;
    }
    
    $file = sanitizePath($_GET['file']);
    $basePath = '/var/www/html/pages/';
    $fullPath = realpath($basePath . $file . '.php');
    
    // Validación final con realpath()
    if ($fullPath && strpos($fullPath, $basePath) === 0) {
        include($fullPath);
    } else {
        echo "Acceso denegado: Ruta no válida.";
    }
    ?>
    

    Realizar una combinación de sanitización proactiva, validación estricta de caracteres y comprobación con realpath() cierra múltiples vectores de ataque. Sin embargo, las listas blancas siguen siendo la estrategia más robusta contra LFI.

  2. Deshabilitar funciones peligrosas:

    Configurar allow_url_include=Off y allow_url_fopen=Off en php.ini y deshabilitar funciones como system(), exec(), shell_exec(), y similares.

    • allow_url_include y allow_url_fopen:

    • Concepto: Estas directivas permiten incluir archivos desde URLs remotas. Deshabilitarlas previene la inclusión de código desde fuentes externas, reduciendo el riesgo de RCE.

    • Configuración: En el archivo php.ini, asegúrate de que estén configuradas como Off:

      allow_url_include = Off
      allow_url_fopen = Off
      
    • Deshabilitar Funciones Críticas:

      • Concepto: Funciones como system(), exec(), shell_exec(), passthru() y popen() permiten la ejecución de comandos del sistema. Deshabilitarlas o restringir su uso impide que los atacantes ejecuten código arbitrario.
      • Configuración: En el archivo php.ini, utiliza la directiva disable_functions:
      disable_functions = system,exec,shell_exec,passthru,popen,proc_open,curl_exec,curl_multi_exec,parse_ini_file,show_source
      

    Esto deshabilita las funciones listadas, impidiendo su uso en el código PHP.

  3. Aislar archivos sensibles:

    Almacenar archivos de configuración, logs y sesiones fuera del directorio accesible por la aplicación web.

    • Concepto: Almacena archivos de configuración, logs y sesiones fuera del directorio raíz accesible por la web.
    • Ejemplo:

    • Logs: Guarda los archivos de log en un directorio como /var/log/app/ que no sea accesible directamente a través de la web.

    • Configuración: Almacena los archivos de configuración en un directorio como /etc/app/ y asegúrate de que el usuario del servidor web no tenga permisos de lectura.
    • Sesiones: Configura PHP para guardar las sesiones en un directorio seguro fuera del alcance del servidor web, como /var/lib/php/sessions/.

    En el archivo php.ini:

    session.save_path = "/var/lib/php/sessions"
    

    Asegúrate de que solo el usuario del sistema tenga acceso a este directorio.

  4. Configurar permisos adecuados:

    Restringir los permisos de lectura y escritura en archivos y directorios críticos.

    • Concepto: Restringe los permisos de lectura y escritura en archivos y directorios críticos.
    • Ejemplo:

    • Utiliza chmod para configurar los permisos de los archivos. Por ejemplo, para un archivo de configuración:

      chmod 600 /etc/app/config.ini
      chown root:root /etc/app/config.ini
      

      Esto da permisos de lectura y escritura solo al usuario root.

    • Directorios:

      chmod 700 /var/log/app/
      chown www-data:www-data /var/log/app/
      

      Esto da permisos de lectura, escritura y ejecución al usuario www-data, que es el usuario del servidor web, y restringe el acceso a otros usuarios.

  5. Monitorear y auditar:

    Revisar regularmente los logs del servidor para detectar actividades sospechosas e implementar herramientas de detección de intrusos (IDS) para identificar intentos de explotación.

    • Revisar Logs del Servidor:

    • Concepto: Analiza regularmente los logs del servidor web y de la aplicación para detectar patrones sospechosos, errores inusuales o intentos de acceso a archivos no autorizados.

    • Ejemplo: Busca en los logs patrones como:

      • Intentos de acceder a archivos sensibles (/etc/passwd, archivos de configuración).
      • Errores de inclusión de archivos.
      • Solicitudes con caracteres sospechosos (../).
    • Implementar un WAF (Web Application Firewall):

    • Concepto: Utiliza un firewall de aplicaciones web (WAF) para proteger aplicaciones expuestas a internet contra ataques como Path Traversal, inyección de código y otras amenazas comunes.

    • Ejemplo: Configura un WAF como ModSecurity o servicios en la nube como Cloudflare para filtrar y bloquear solicitudes maliciosas.

    Estas herramientas son ideales para proteger aplicaciones web en entornos expuestos a internet, proporcionando una capa adicional de seguridad.

Mitigaciones para prevenir inclusion de sesiones en PHP

  1. Mover Archivos de Sesión Fuera del Alcance del Servidor Web:
    Configurar session.save_path en php.ini para usar un directorio no accesible desde la web:
session.save_path = "/var/secure/sessions"

Asegurar permisos: chmod 600 /var/secure/sessions.

  1. Validación Estricta en LFI:
    Usar listas blancas y sanitización de rutas:
$allowed = ['home', 'about'];
if (!in_array($_GET['file'], $allowed)) die("Acceso denegado");
  1. Sanitizar Datos de Sesión:
    Validar y filtrar entradas antes de almacenarlas en $_SESSION:
$_SESSION['usuario'] = htmlspecialchars($input);
  1. Configurar open_basedir:
    Restringir el acceso a directorios específicos:
open_basedir = /var/www/html:/var/secure/sessions
  1. Usar Almacenamiento Alternativo:
    Cambiar el manejador de sesiones a bases de datos o memoria:
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://127.0.0.1:6379');

Conclusión

La vulnerabilidad de Local File Inclusion (LFI) es un recordatorio de cómo una mala gestión de las entradas del usuario puede convertirse en un vector de ataque crítico. Aunque puede parecer una falla menor, su combinación con técnicas avanzadas como Path Traversal o Log Poisoning puede escalar rápidamente a una ejecución remota de comandos (RCE), comprometiendo por completo la seguridad de un sistema.

La clave para mitigar este tipo de vulnerabilidades radica en la implementación de buenas prácticas de desarrollo seguro, como la validación estricta de entradas, el uso de listas blancas, la configuración adecuada del servidor y la desactivación de funciones peligrosas. Además, el monitoreo constante y la auditoría de los sistemas son esenciales para detectar y prevenir intentos de explotación.

En última instancia, la seguridad no es un estado, sino un proceso continuo. Adoptar un enfoque proactivo y mantener una mentalidad de mejora constante es fundamental para proteger tus aplicaciones y tu infraestructura frente a amenazas como LFI.

Stay safe. Stay smart. Stay secure.