LFI to RCE via phpinfo() Race Condition
Arsenal completo de comandos en la cheatsheetUn LFI (inclusión de fichero local) permite leer ficheros, pero por sí solo no ejecuta código. La técnica clásica para convertirlo en RCE cuando PHP tiene file_uploads = On aprovecha un detalle: al recibir un multipart/form-data, PHP guarda el fichero subido en un temporal (/tmp/phpXXXXXX) antes de que el script decida qué hacer con él, y lo borra en cuanto la petición termina. El fichero existe solo durante milisegundos.
El puente es una página que exponga phpinfo(). Su salida imprime la variable $_FILES y, con ella, el tmp_name exacto del temporal que se acaba de crear. La cadena de ataque es una condición de carrera:
- Enviar por
POSTa la página conphpinfo()unmultipartcuyo fichero contenga una webshell. - En la misma respuesta, leer el
tmp_namequephpinfo()filtra. - Incluir ese
tmp_namea través del LFI antes de que PHP lo borre.
Si el LFI ejecuta el temporal como PHP, la webshell corre y ya se puede lanzar la reverse shell. Hacerlo a mano es difícil por la ventana tan estrecha; se automatiza con un bucle que sube y trata de incluir sin parar, o directamente con el exploit público de referencia (phpinfolfi.py de Insomnia Security), que abre muchos hilos para ganar la carrera:
python2.7 phpinfolfi.py <ip> 80 100 # 100 hilos en paraleloRequisitos. Un LFI que incluya y ejecute el fichero apuntado, file_uploads = On (por defecto en PHP) y una página que revele phpinfo() para filtrar el tmp_name. No hace falta un directorio de subida accesible: el temporal de /tmp basta.
Cómo detectarlo. La firma es un volumen anómalo de peticiones en muy poco tiempo (cientos por segundo) alternando POST multipart a la página de phpinfo() con GET al parámetro del LFI apuntando a /tmp/php...: el patrón de fuerza bruta de la race condition es evidente en el log de acceso, y un WAF que correlacione ráfagas + inclusión de rutas /tmp/ lo bloquea. En el host, el proceso web incluyendo un temporal de /tmp/phpXXXXXX y lanzando sh/bash justo después es la confirmación (auditd/Sysmon for Linux). Que una página exponga phpinfo() es ya la exposición previa a auditar.
Defensa. No exponer nunca phpinfo() en producción, desactivar file_uploads si no se usa y sanear el parámetro del include para que no acepte rutas arbitrarias. Nace de un LFI y comparte objetivo con la subida de webshell.
Máquinas donde se aplica
- Infovore 1VulnHub