# LFI2RCE a través de la espera eterna
Aprende hacking en AWS de cero a héroe con htARTE (Experto en Equipos Rojos de AWS de HackTricks)! Otras formas de apoyar a HackTricks: * Si deseas ver tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF** Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)! * Obtén el [**swag oficial de PEASS & HackTricks**](https://peass.creator-spring.com) * Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family) * **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Comparte tus trucos de hacking enviando PRs a los** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositorios de github.
## Información Básica Por defecto, cuando se carga un archivo en PHP (incluso si no se espera), generará un archivo temporal en `/tmp` con un nombre como **`php[a-zA-Z0-9]{6}`**, aunque he visto algunas imágenes de docker donde los archivos generados no contienen dígitos. En una inclusión de archivo local, **si logras incluir ese archivo cargado, obtendrás RCE**. Ten en cuenta que por defecto **PHP solo permite cargar 20 archivos en una única solicitud** (configurado en `/etc/php//apache2/php.ini`): ``` ; Maximum number of files that can be uploaded via a single request max_file_uploads = 20 ``` ### Técnica de espera eterna En esta técnica **solo necesitamos controlar una ruta relativa**. Si logramos cargar archivos y hacer que la **LFI nunca termine**, tendremos "suficiente tiempo" para **realizar fuerza bruta en los archivos cargados** y **encontrar** cualquiera de los que se hayan subido. **Ventajas de esta técnica**: - Solo necesitas controlar una ruta relativa dentro de una inclusión - No requiere nginx ni un nivel inesperado de acceso a archivos de registro - No requiere un zero day para causar una falla de segmentación - No requiere una divulgación de ruta Los **principales problemas** de esta técnica son: - Necesidad de que un archivo específico (o archivos) esté presente (puede haber más) - La **enorme** cantidad de nombres de archivo potenciales: **56800235584** - Si el servidor **no está utilizando dígitos**, la cantidad total potencial es: **19770609664** - Por defecto, **solo se pueden cargar 20 archivos** en una **sola solicitud**. - El **número máximo de trabajadores en paralelo** del servidor utilizado. - Esta limitación junto con las anteriores puede hacer que este ataque dure demasiado - **Tiempo de espera para una solicitud de PHP**. Idealmente, esto debería ser eterno o debería finalizar el proceso de PHP sin eliminar los archivos temporales cargados; de lo contrario, también será un dolor Entonces, ¿cómo puedes **hacer que una inclusión de PHP nunca termine**? Simplemente incluyendo el archivo **`/sys/kernel/security/apparmor/revision`** (**desafortunadamente no disponible en contenedores Docker**). Inténtalo simplemente llamando: ```bash php -a # open php cli include("/sys/kernel/security/apparmor/revision"); ``` ## Apache2 Por defecto, Apache soporta **150 conexiones concurrentes**, siguiendo [https://ubiq.co/tech-blog/increase-max-connections-apache/](https://ubiq.co/tech-blog/increase-max-connections-apache/) es posible aumentar este número hasta 8000. Sigue esto para usar PHP con ese módulo: [https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04](https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04). Por defecto, (como puedo ver en mis pruebas), un **proceso PHP puede durar eternamente**. Hagamos algunos cálculos: * Podemos usar **149 conexiones** para generar **149 \* 20 = 2980 archivos temporales** con nuestra webshell. * Luego, usar la **última conexión** para **bruteforce** posibles archivos. * A una velocidad de **10 solicitudes/s** los tiempos son: * 56800235584 / 2980 / 10 / 3600 \~= **530 horas** (50% de probabilidad en 265h) * (sin decimales) 19770609664 / 2980 / 10 / 3600 \~= 185h (50% de probabilidad en 93h) {% hint style="warning" %} ¡Ten en cuenta que en el ejemplo anterior estamos **haciendo un DoS completo a otros clientes**! {% endhint %} Si el servidor Apache se mejora y pudiéramos abusar de **4000 conexiones** (la mitad del número máximo). Podríamos crear `3999*20 = 79980` **archivos** y el **número** se reduciría a alrededor de **19.7h** o **6.9h** (10h, 3.5h 50% de probabilidad). ## PHP-FMP Si en lugar de usar el módulo php regular para apache para ejecutar scripts PHP la **página web está utilizando** **PHP-FMP** (esto mejora la eficiencia de la página web, por lo que es común encontrarlo), hay algo más que se puede hacer para mejorar la técnica. PHP-FMP permite **configurar** el **parámetro** **`request_terminate_timeout`** en **`/etc/php//fpm/pool.d/www.conf`**.\ Este parámetro indica la cantidad máxima de segundos **cuando** **la solicitud a PHP debe terminar** (infinito de forma predeterminada, pero **30s si el parámetro está descomentado**). Cuando una solicitud está siendo procesada por PHP durante el número indicado de segundos, es **eliminada**. Esto significa que si la solicitud estaba subiendo archivos temporales, porque el **procesamiento de php se detuvo**, esos **archivos no se eliminarán**. Por lo tanto, si puedes hacer que una solicitud dure ese tiempo, puedes **generar miles de archivos temporales** que no se eliminarán, lo que **acelerará el proceso de encontrarlos** y reducirá la probabilidad de un DoS a la plataforma al consumir todas las conexiones. Entonces, para **evitar un DoS** supongamos que un **atacante solo usará 100 conexiones** al mismo tiempo y el tiempo máximo de procesamiento por PHP-FMP (`request_terminate_timeout`**)** es **30s**. Por lo tanto, la cantidad de **archivos temporales** que se pueden generar **por segundo** es `100*20/30 = 66.67`. Luego, para generar **10000 archivos** un atacante necesitaría: **`10000/66.67 = 150s`** (para generar **100000 archivos** el tiempo sería **25min**). Luego, el atacante podría usar esas **100 conexiones** para realizar un **bruteforce de búsqueda**. Suponiendo una velocidad de 300 req/s, el tiempo necesario para explotar esto es el siguiente: * 56800235584 / 10000 / 300 / 3600 \~= **5.25 horas** (50% de probabilidad en 2.63h) * (con 100000 archivos) 56800235584 / 100000 / 300 / 3600 \~= **0.525 horas** (50% de probabilidad en 0.263h) Sí, es posible generar 100000 archivos temporales en una instancia de tamaño mediano de EC2:
{% hint style="warning" %} Ten en cuenta que para activar el tiempo de espera sería **suficiente incluir la página LFI vulnerable**, para que entre en un bucle de inclusión eterno. {% endhint %} ## Nginx Parece que por defecto Nginx soporta **512 conexiones paralelas** al mismo tiempo (y este número puede mejorarse).