Otra plataforma en donde he tenido la oportunidad de colaborar es en esta llamada VulNyx, de la cual ya he tenido la oportunidad de hablarles. En este caso les traigo mi primera máquina construida y elaborada para compartir con los «players» de esta hambrienta y despierta comunidad. Aquí mis anotaciones para resolver la VM y el motivo por el que se me ocurrió configurarlas.

Después de descargarnos la VM la levantamos mediante VirtualBox. Recibiremos una vista como esta:

Escaneamos el segmento de red con el que trabajamos habitualmente e identificamos la VM recientemente encendida:

Ya enfocados en la VM y su dirección IP, realizamos un escaneo de puertos y servicios de la siguiente forma:
sudo nmap -sS -sV -p- 15.15.15.6

Tenemos 4 puertos TCP abiertos, partiremos nuestra revisión desde el menor al mayor, dejando por el momento de lado el puerto TCP 22, entendiendo que se trata del canal de administración de la VM.
En el puerto TCP 80 tenemos una aplicación en un servidor web Apache:

Además de identificar el sistema operativo mediante la presentación por defecto de la aplicación web, intentaremos averiguar si existe algún contenido adicional, para ello haremos fuzzing de directorios y ficheros:

Podemos hacer validaciones adicionales en este servicio, sin embargo como autor de la VM ya os adelanto que no se me ocurrió nada más dejar por aquí. Vayamos entonces a por el próximo servicio.
Nos debería llamar la atención a priori que el servicio FTP no se encuentra en su número de puerto por defecto, eso podría ser un indicio, pero como «players» habituales que somos, esto no nos debería distraer. Partiremos el análisis realizando, gracias a los scripts de Nmap, validaciones básicas del servicio:
sudo nmap -sS -sV -p 2121 -sC 15.15.15.6

De esta forma conseguiremos evidenciar que el acceso mediante usuario anónimo está habilitado en este servicio FTP. Por tanto inmediatamente produciremos dicho acceso, dada la condición:

Dado el fichero identificado (users.list
), lo descargamos y revisamos:

Por si acabo, también probaremos el acceso con el otro usuario (dejando la contraseña vacía por ahora, a ver si canta la flauta):
hydra -L users.list -p '' ftp://15.15.15.6 -s 2121

Pues, solo hemos llegado hasta aquí. Es momento de saltar de puerto.
Ya en el puerto TCP 8090, volvemos a tener una aplicación web, en este caso presenta el siguiente aspecto (ojo!):

Dado el presente formulario, será muy tentador validar algún tipo de inyección (¿a que si player?)

En este caso, he sido un poco «cabroncete» y he intentado colar un típico mensaje indicio de SQLi (SQL Injection), pero amigo, a veces tus ojos te pueden engañar…

Viendo la petición con detenimiento parece que todo lo que insertemos en el parámetro user
será inmediatamente reflejado en la respuesta, entonces nos debería mosquear cuanto menos el mensaje recibido.
Lo que si identificaremos rápidamente, gracias a la carencia en la sanitización de la entrada, es que este campo es vulnerable a XSS (Cross-Site Scripting):

Bien, volvemos a la necesidad de identificar ficheros y directorios en esta aplicación web.
gobuster dir -w /usr/share/wordlists/dirb/common.txt -u http://15.15.15.6:8090/

Pero en este caso, dada las condiciones de la aplicación web, se nos «dificulta» la identificación, como vemos en el mensaje de error anterior.
Para sortear esta situación emplearemos el operador --exclude-length
:
gobuster dir -w /usr/share/wordlists/dirb/common.txt -u http://15.15.15.6:8090/ --exclude-length 329

De esta forma identificaremos un primer fichero PHP. A continuación su vista:

Es momento de profundizar en esta labor, pero esta vez lo haremos a través de un diccionario algo más grande (con mas de 220000 registros) y la poderosa herramienta ffuf (más ágil que gobuster):
ffuf -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://15.15.15.6:8090/FUZZ.php -fs 329

El fichero PHP validation.php
ya lo teníamos identificado, sin embargo el fichero PHP secret.php
es una novedad, veamos su vista a través del navegador:

Este mensaje algo enigmático, también lo he descrito a fin producir algo de aliento al player, espero haberlo conseguido…
Si adicionalmente revisamos el código fuente, también nos haremos con una pieza extra del puzzle:

Pero ojo con esto, según el feedback de algunos players, es común pensar en que el descubrimiento del parámetro que se precisa, pasa por fuzzearlo, esto «nada más lejos de la realidad», si optamos por ello, seguramente nos eternizaremos… Por tanto veamos el camino correcto que asumí en la construcción inicial de la VM.
Si observamos nuevamente las cabeceras HTTP de respuesta de la aplicación web, la tecnología que está detrás de dicha aplicación web, debería llamar nuestra atención:

Revisando la documentación oficial de PHP identificaremos prontamente que la versión con la que contamos en el aplicativo, es una versión bastante antigua:

Por tanto, googleando deberíamos ser capaces de identificar debilidades conocidas en esta versión de PHP:

Uno de los resultados más relevantes será este estudio que nos presentan desde el equipo de ProjectDiscovery a través de la siguiente entrada en su blog:

Ya os he traído a esta casa (el blog de Infayer), una entrada pormenorizada en español, para aprovechar esta debilidad: «Divulgación de código fuente mediante PHP-CLI«, del cual básicamente tendré en cuenta los siguiente aspectos:
Será importante no tomar las actualizaciones del «Content-Length» en las peticiones que hagamos al servidor, por tanto en el propio repeater de Burp Suite la desmarcaremos:

Tomando en cuenta el modelo de petición que debemos hacer para llegar a revelar el código fuente de los ficheros PHP localizados anteriormente, observamos que en el caso del index.php
, el formulario es claramente una «farsa» (lo siento por los que os hayáis entretenido más de la cuenta en este punto).

Observemos también la lectura del fichero info.php
:

Y lo más relevante aún, veamos nuestro fichero secret.php
:

Ahora entendéis el porqué era una locura fuzzear este parámetro (como que es una cadena, prácticamente inadivinable).
Pero ahora ya reconociéndola, será momento de ponerla en práctica para llegar al contenido del fichero secret.txt
ubicada en el directorio del superusuario.

Aquí también muchos os habéis atascado, y tirasteis por el lado musical de la estrofa (lo mismo he sido muy ambiguo, sorry por ello!), pero de lo que se trata aquí es de hacernos con dicho texto y tratar de obtener un diccionario de palabras del mismo. Para los más «jugones» seguro que estaréis pensado en el fabuloso CeWL y no vais mal encaminados, para ello ejecutaremos algo como esto:
cewl http://15.15.15.6:8090/secret.php?fbd94d1aa64007cbb89b9c0156ac23edba23f7fd57b2d765e4e88712ee642739

Pero llegados a este punto, no nos será suficiente, ahora veremos el motivo. Os recomiendo emplear lo que aventuradamente bautice como el «primo vitaminado» de CeWL, en este caso la herramienta CeWLeR y que emplearemos de forma similar a su predecesor:
cewler http://15.15.15.6:8090/secret.php?fbd94d1aa64007cbb89b9c0156ac23edba23f7fd57b2d765e4e88712ee642739

Ahora que tenemos 2 diccionarios, observemos las diferencias:

Observemos la efectividad de cada uno si lo empleamos en Hydra mismamente:
hydra -l kohanic -P dic.txt ftp://15.15.15.6 -s 2121

Como se observa, los resultados del diccionario generado con CeWLeR nos será mucho más efectivo que el generado con CeWL, dado que este segundo solo coge palabras separadas, sin tomar en cuenta que puedan estar unidas por algún carácter especial, en el caso de darse, las divide y pues, para este caso, no nos será válido sus resultados. Sin embargo CeWLeR respecta dichas palabras y aunque arroje menos resultados (en números totales lógicamente), logrará mantener dichos caracteres especiales que unen nuestras palabras, como fueron observadas en origen.
Una vez identificadas las credenciales del usuario kohanic
es momento de volver a conectar por FTP:

Aquí nos encontraremos con un directorio llamado DB
, cuyo contenido será inmediatamente sustraído:

Llegados a este punto, al contar con un fichero KDBX (extensión reconocida de KeePass), más un volcado (intuiblemente del proceso), podríamos comprender que es «blanco y en botella«, por tanto la respuesta ya la conocemos.
Para los que no, básicamente aquí se presenta la vulnerabilidad conocida con el identificador: CVE-2023-32784, que se trata de la posibilidad de obtener la Master Key a partir del volcado de memoria del proceso asociado a KeePass. Para más detalles, también tuve la oportunidad de escribir un artículo al que llamé: «BruteForce-to-KeePass: Complementa la explotación del CVE-2023-32784 para llegar a la Master Key«.
El aprovechamiento en este caso lo haremos a través de una herramienta escrita en Python llamado KeePwn que fue desarrollado por la gente de Orange Cyberdefense.

Esta tool que cuenta con otras características y funcionalidades, que ya hablaremos en otro momento, nos proporciona a través de su apartado «parse_dump«, la posibilidad de indicarle nuestro volcado de memoria KeePass.DMP
y nuestro repositorio de KeePass Database.kdbx
para conseguir identificar la Master Key concreta del fichero y así llegar a su contenido. Observemos:
python3 KeePwn.py parse_dump -d ~/Documents/Learning/VulNyx/Belial/KeePass.DMP -b ~/Documents/Learning/VulNyx/Belial/Database.kdbx

En cuanto accedamos a la base de datos, observaremos las siguiente credenciales del usuario kohanic
:

Pero… ¿No teníamos ya estas credenciales? La respuesta es: «no del todo!»
Si nos vamos a la pestaña «Advanced» del KeePass, observamos que se adjunta lo que se intuye como una clave RSA:

Evidenciemos su contenido (muestra de un extracto):

Genial, si intentamos autenticarnos con estos elementos vía SSH sin más, obtendremos el siguiente resultado:

Es decir, será necesario configurar los permisos adecuados de la clave RSA.
chmod 600 id_rsa
Volveremos a intentarlo una vez más:

Estamos dentro y ya tenemos acceso al sistema mediante este usuario llamado kohanic
.
Por aquí será momento de sumergirnos en una primera enumeración en post-explotación y una de las cosas de será de obligado cumplimiento es identificar puertos y servicios locales:
ss -ltnp

El puerto altísimo 65533 debería llamar poderosamente nuestra atención. Por ahora la tendremos en mente y seguiremos con la enumeración. ¿Qué tal si revisamos procesos del sistema?
ps -aux

Observemos que el usuario gelal
(otro usuario del sistema) ejecuta un script en bash llamado start.sh
.
Complementariamente podremos apoyarnos en la herramienta pspy, que nos permitirá monitorizar los procesos que estén siendo ejecutados en el sistema en tiempo real. Lo descargaremos de sus repositorio de GitHub, le asignaremos permisos de ejecución y lo pondremos en marcha:

En pocos segundos seremos capaces de volver a observar ese script del usuario gelal
:

Si esperamos un poco más, con pspy tendremos la oportunidad de identificar trazas como la siguiente:

Esto ya son varias piezas en el puzzle, tendremos que ver como encajarlas.
Si continuamos con la enumeración básica en post-explotación llegaremos a ejecutar lo siguiente:
sudo -l

Contar con la posibilidad de ejecutar tcpdump mediante sudo y sin contraseña podría parecer la vía idónea para alcanzar root en esta VM, sobre todo si tenemos dependencia de GTFOBins, pero no, aún tendremos que armar nuestro «rompecabezas» (de esa no os quiero privar, XD).
Por tanto y tomando en cuenta en puerto local TCP 65533 identificado anteriormente, pondremos en marcha tcpdump y lo haremos en la interfaz de loopback. El resultado lo guardaremos para su posterior análisis con Wireshark:
sudo tcpdump -i lo -w out.pcap

En Wireshark filtraremos los paquetes del protocolo HTTP y observaremos el tipo de peticiones:

Veamos el contenido de estas interesantes peticiones POST:

El body de esta petición POST, parece querer indicarnos algo, antes de su análisis, vayamos a observar la respuesta del servidor:

Un simple mensaje de respuesta escueta.
Bien, con esto he querido representar/emular (espero que de forma no muy alejada) al tráfico que puede generar un C2 o C&C, que básicamente genera tráfico «ofuscado» usando protocolos que pueden pasar desapercibidos para los IDS/IPS.
En la petición POST también se observa la cabecera HTTP Authorization
que lleva consigo lo que es un «pseudo» token de acceso JWT (JSON Web Token), que si lo pasamos por herramienta online como jwt.one, nos revelará lo siguiente:

Quedémonos con la ultima parte que remarco, pero por ahora lo dejaré de lado.
Vuelvo al body de la petición POST para darle su tratamiento. El contenido integro lo guardo en un fichero de texto:

Inmediatamente después lo paso a formato legible a través del siguiente bucle for:
for a in $(cat request.post); do dec=$(printf '%x' $a); printf "\\x$dec"; done
Que me revelará el «secreto» y mostrará una nueva clave privada:

Veamos de emplearla nuevamente para conectar por SSH, esta vez mediante el usuario gelal
:

Dado que necesitamos conocer la passphrase de dicha clave privada, será momento de llamar a John The Ripper y su utilidad conocida como: ssh2john.py:
/usr/share/john/ssh2john.py gelal.key > gelal.hash

Realizamos el crackeo de dicho hash y obtenemos el siguiente resultado en pocos segundos:
john --wordlist=/usr/share/wordlists/rockyou.txt gelal.hash

Volvemos una vez más a intentar conectarnos por SSH al activo:

Genial, ya estamos con el usuario gelal
. Ahora en su directorio podremos leer la primera flag:

Por curiosidad observemos lo que hay detrás del script start.sh
y el otro fichero del directorio c2
:

Pienso sinceramente que llegados hasta aquí ya habremos hecho lo más difícil en esta VM, para llegar a ser superusuario debemos enumerar un poco más el directorio actual del usuario gelal
:
ls -laR
Revisando ficheros y directorios consecutivos, nos encontraremos con el siguiente fichero comprimido:

Ojo con la conformación de directorios que hemos generado (alerta spoiler!).
Al descargarlo y pretender obtener su contenido nos toparemos con el siguiente requerimiento:

Recordamos la contraseña identificada en el «famoso» token JWT (P$ssw0rd!321
), pues es momento de encajar dicha pieza:

El nombre del fichero comprimido también debería ser una pista.
Este fichero descomprimido con extensión msg, realmente intenta engañarnos (por si no tuvieras suficiente), pero rápidamente deberíamos conocer su composición real:

Siendo un fichero PDF lo abriremos con nuestro visor por defecto y nos encontraremos este mensaje de GBK (el Big Boss):

Con lo descrito, debería ser suficiente para identificar el vector que emplearemos en la escalada de privilegios. Una última búsqueda por Google nos llevará a este post que reza: «Vulnerabilidad en el Kernel de Linux propicia la escalada de privilegios (CVE-2023-0386) – Bit SUID + OverlayFS«:

Ahí comento estos automatismos que logré validar en su momento a partir de los exploits de estos investigadores de seguridad:


En este caso y por comodidad tiraremos del segundo automatismo, del de la gente de DataDog. Que básicamente una vez descargado el exploit en la VM lo compilaremos de la siguiente forma:
gcc poc.c -o exp -D_FILE_OFFSET_BITS=64 -static -lfuse -ldl

Ya con el automatismo compilado, lo pondremos en marcha y llegaremos al root
!

Por último podremos leer la ansiada flag final!

Ya sé lo que estáis pensando, que VM más larga (y que pereza, tal vez!), ya me tiró las orejas D4t4s3c, XD! Creo que me emocioné y no medí, metí todo lo que tenía en mente y pues resultó en todo esto. En todo caso, espero que pueda seros de entretenimiento y os aporte. Nos vemos pronto!
Referencias
- https://blog.projectdiscovery.io/php-http-server-source-disclosure/
- https://github.com/roys/cewler
- https://github.com/Orange-Cyberdefense/KeePwn
- https://github.com/DominicBreuker/pspy
- https://github.com/xkaneiki/CVE-2023-0386
- https://github.com/DataDog/security-labs-pocs/tree/main/proof-of-concept-exploits/overlayfs-cve-2023-0386