> For the complete documentation index, see [llms.txt](https://4lec4st.gitbook.io/4lec4st/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://4lec4st.gitbook.io/4lec4st/writes-ups/hack-the-box/easy/twomillion.md).

# TwoMillion

## Información de la máquina

<figure><img src="/files/KVXUrZrMBg0KlOd5C2xp" alt=""><figcaption></figcaption></figure>

TwoMillion es una máquina Linux de dificultad fácil que se lanzó para celebrar los 2 millones de usuarios que HackTheBox ha alcanzado. Esta máquina utiliza una versión antigua de la plataforma HackTheBox que incluye el antiguo código de invitación pirateable. Tras piratear el código de invitación, se puede crear una cuenta en la plataforma. Esta cuenta permite `enumerar varios endpoints de API`, uno de los cuales permite elevar al usuario a administrador. Con acceso administrativo, el usuario puede ejecutar una inyección de comandos en el `endpoint de generación de VPN` de administrador, obteniendo así un shell del sistema. Se descubrió que un archivo .env contenía credenciales de base de datos y, gracias a la reutilización de contraseñas, los atacantes pudieron iniciar sesión como administrador en la máquina. El kernel del sistema está desactualizado y se puede usar `CVE-2023-0386` para obtener un shell de root.

***

## Reconocimiento

La fase de **reconocimiento** es el primer paso a la hora de resolver una máquina. Su objetivo es recopilar la mayor cantidad de información posible sobre el sistema objetivo, permitiendo entender su estructura, tecnología y posibles vectores de ataque.&#x20;

Empezaremos haciendo un ping a la máquina víctima para ver si está encendida y ante que nos enfrentamos.

<figure><img src="/files/IhkbSw1tEQVw1I7ieyan" alt=""><figcaption></figcaption></figure>

Si recibimos respuesta, significa que la máquina está en línea. Además, observamos que el **TTL** (Time To Live) es **63**, lo que indica que es un sistema **Linux** (normalmente, los sistemas Windows tienen un TTL de 127).&#x20;

{% hint style="success" %}
Esto sucede porque Hack The Box virtualiza las máquinas, lo que a menudo reduce el TTL en un punto respecto al valor estándar.

En entornos reales tendrían los siguientes valores:

TTL Linux **→** 64

TTL Windows **→** 128
{% endhint %}

Empezaremos haciendo un primer reconocimiento para ver los puertos abiertos en el sistema.

<figure><img src="/files/T0aMbToWSmKeCuV6IJJq" alt=""><figcaption></figcaption></figure>

**1. `-p-` → Escaneo de todos los puertos (1-65535)**

Por defecto, `nmap` solo escanea los **1000 puertos más comunes**.\
Con `-p-`, forzamos a que escanee **los 65535 puertos** de la máquina objetivo, lo que puede ser útil para encontrar servicios que corren en puertos poco convencionales.

**2. `--open` → Filtrar solo los puertos abiertos**

Cuando escaneamos un sistema, muchos puertos pueden estar cerrados o filtrados por un firewall.\
Este parámetro hace que `nmap` **solo muestre los puertos abiertos**, reduciendo el ruido y facilitando el análisis.

**3. `-sS` → Stealth Scan (Escaneo Sigiloso con SYN)**

Es conocido como **"TCP SYN Scan"**, y funciona de la siguiente manera:

* `nmap` envía un paquete **SYN** (solicitud de conexión).
* &#x20;Si el puerto está abierto, el servidor responde con **SYN-ACK**.
* En lugar de completar la conexión con un **ACK**, `nmap` responde con un **RST (Reset)**, interrumpiendo la comunicación.

**4. `--min-rate 5000` → Velocidad mínima de paquetes (5000 por segundo)**

Por defecto, `nmap` ajusta dinámicamente la velocidad de los paquetes según la respuesta de la red.\
Con `--min-rate 5000`, obligamos a `nmap` a **no enviar menos de 5000 paquetes por segundo**, acelerando el escaneo.

**5. `-n` → Deshabilitar resolución DNS**

Normalmente, `nmap` intenta resolver el nombre de dominio de las IPs escaneadas (DNS lookup).\
Con `-n`, evitamos esta resolución de nombres, lo que **acelera el escaneo** y evita que los servidores DNS registren nuestra actividad.

**6. `-Pn` → Omitir detección de host (Host Discovery Off)**

Por defecto, `nmap` envía paquetes ICMP (ping) para ver si un host está activo antes de escanearlo.\
Si un firewall bloquea los pings, `nmap` puede marcarlo como "host down" y no escanearlo.

**7. `-oG`** **→ Exportar el contenido en formato grepeable**

Todo el resultado del escaneo lo exportaremos en un archivo llamado **`puertos` .**

El escaneo revela 2 puertos abiertos, puerto 22(SSH) y puerto 80(HTTP). Ahora realizamos un escaneo más avanzado sobre estos 2 puertos

<figure><img src="/files/fp1Xw3IV6Uyz4TGJz0sY" alt=""><figcaption></figcaption></figure>

**1. `-p22,80` → Escaneo de puertos específicos**

Con `-p22,80`, le indicamos que **solo** escanee los puertos **22 (SSH)** y **80 (HTTP)**

**2. `-sCV` → Escaneo de versiones y scripts básicos**

Este parámetro en realidad es **dos combinaciones en una**:

* **`-sC`** → Activa los **NSE scripts por defecto** en `nmap` (similar a usar `--script=default`).\
  Ejecuta scripts básicos para enumerar información del servicio detectado, como banners, versiones, etc.
* **`-sV`** → Realiza **fingerprinting de versiones**, intentando identificar la versión exacta del software en cada puerto abierto.

**3. `-oN` → Guardar el resultado en formato Normal**

Por defecto, `nmap` muestra los resultados en pantalla, pero con **`-oN targeted`**, guardamos el resultado en un archivo en **formato legible para humanos**.

Cambiaremos el /etc/host ya que se aplica una redirección al dominio `2million.htb` .

<figure><img src="/files/uRKexTXIKoJiQ5oHA8Y4" alt=""><figcaption></figcaption></figure>

## Enumeración web

Antes de visitar la web, useremos la herramienta `whatweb`, para saber que datos con que tecnologías y que usa esta página.

<figure><img src="/files/VLYwnizVlWreN2uCqQhV" alt=""><figcaption></figcaption></figure>

No vemos nada interesante como alguna versión importante... Solo vemos que se usa nginx que nos lo reportó nmap anteriormente. Ahora visitaremos la página web.

<figure><img src="/files/YZExtyxoET4m5nh6WFqf" alt=""><figcaption></figcaption></figure>

Esto es lo que se muestra.

Viendo la página, vemos que necesitamos un código de invitación. Si listamos las funciones disponibles con this desde la consola del navegador vemos una función makeInviteCode.

<figure><img src="/files/xAwr4cvYBKvN4hXodahz" alt=""><figcaption></figcaption></figure>

Si hacemos uso de la función:

<figure><img src="/files/DfJyOwRPE4jPSi6jA2Gx" alt=""><figcaption></figcaption></figure>

Nos devuelve un código encriptado con ROT13, de tal forma que ese mensaje tendremos que desencriptarlo.

<figure><img src="/files/uzppX2CPa1ujIX9lildO" alt=""><figcaption></figcaption></figure>

Usando la página cryptii podemos hacer esto, aunque tambien se puede hacer por consola. Nos dice que para generar una invitación, tenemos que realizar una solicitud por POST a esa API.

***

## Vulnerable API and access web

Hacemos una solicitud a la API para que nos genere un código de invitación. La respuesta que obtenemos de la API viene en formato `base64`, lo cual significa que el código está codificado y no es legible directamente.

<figure><img src="/files/eEv8iDSASeJNUvXBcYNt" alt=""><figcaption></figcaption></figure>

Dado que la API nos devuelve el código en base64, debemos decodificarlo para obtener su valor real. Para ello, utilizamos el siguiente comando en la terminal:

<figure><img src="/files/SVDpkeqNpWfd4MM50Lru" alt=""><figcaption></figcaption></figure>

Una vez decodificado el código de invitación, podemos usarlo para registrarnos en la plataforma. Este código puede ser necesario para validar nuestro acceso y crear una cuenta en el sistema.

<figure><img src="/files/lMge6gaRvioYcBGkiaAE" alt=""><figcaption></figcaption></figure>

Después de completar el registro, utilizamos las credenciales que creamos (usuario y contraseña) para iniciar sesión en la plataforma. Si el login es exitoso, ya tenemos acceso a la aplicación.

<figure><img src="/files/4LWmotAA7yGucReJeTHv" alt=""><figcaption></figcaption></figure>

Dentro de la plataforma, en el menú encontramos una sección llamada "access". Al inspeccionarla con herramientas como las herramientas de desarrollo del navegador (`F12` > "Network"), observamos que esta sección realiza solicitudes a una API

<figure><img src="/files/gIBtMyTLiGbSASjnTzKs" alt=""><figcaption></figcaption></figure>

## Initial access via RCE api/v1

Al interactuar con los botones dentro de la sección "access", notamos que cada uno realiza peticiones a la API. Para entender mejor cómo funciona la API, queremos descubrir todos los endpoints disponibles. Podemos hacerlo interceptando las peticiones con `Burp Suite` o revisando las respuestas en la consola del navegador.

<figure><img src="/files/WxbPigiZeRDBDWOLlYpR" alt=""><figcaption></figcaption></figure>

Al analizar los endpoints disponibles, encontramos algunos relacionados con la administración del sistema. Esto nos da la idea de intentar modificar nuestra cuenta de usuario y otorgarle permisos de administrador. Para ello, probaremos realizar una solicitud `PUT` hacia el endpoint correspondiente, enviando los datos modificados.

<figure><img src="/files/85v8nwPfo5p8d6w3CT9z" alt=""><figcaption></figcaption></figure>

Cuando intentamos hacer la petición `PUT` para modificar nuestro usuario, la API nos solicita que indiquemos el tipo de contenido (`Content-Type`). En este caso, la API trabaja con datos en formato JSON, por lo que debemos incluir la cabecera correcta:

<figure><img src="/files/jLOo4H7uUHDw8bdjmEor" alt=""><figcaption></figcaption></figure>

La API responde con un mensaje indicando que es necesario proporcionar un correo electrónico para modificar el usuario. Esto sugiere que en la solicitud `PUT` debemos incluir el campo `email` junto con otros datos.

<figure><img src="/files/AEmmCxfgAGb8R3DYGcq7" alt=""><figcaption></figcaption></figure>

Al seguir probando, la API devuelve otro mensaje informando que el parámetro `is_admin` es relevante. Observamos que este parámetro es un valor booleano (`true/false` o `1/0`). Si logramos establecerlo en `1` o `true`, podríamos conseguir permisos de administrador.

<figure><img src="/files/cHv9LEyEh20Ir1jFO91F" alt=""><figcaption></figcaption></figure>

Tras modificar el parámetro `is_admin`, verificamos con otro endpoint si el cambio ha sido exitoso. La API confirma que nuestro usuario ahora tiene permisos de administrador, lo que nos otorga acceso a funciones restringidas dentro del sistema.

<figure><img src="/files/vtsfWz6sIBI9gk8l4NK4" alt=""><figcaption></figcaption></figure>

Al ser administradores, obtenemos acceso a un nuevo endpoint que permite generar una VPN. Como este endpoint solo estaba disponible para usuarios con privilegios elevados, antes no podíamos acceder a él.

<figure><img src="/files/HpG1Sxgd9jtzK0xVmaJY" alt=""><figcaption></figcaption></figure>

Para generar la VPN, el endpoint solicita que proporcionemos un nombre de usuario. Probablemente, esto se deba a que el sistema necesita vincular la configuración de la VPN a una cuenta específica.

<figure><img src="/files/q743Jlt7kFuuJnMUgEZM" alt=""><figcaption></figcaption></figure>

La API responde con éxito cuando ingresamos un usuario válido, devolviendo la configuración de la VPN. Sin embargo, no sabemos cómo se está validando este usuario en el backend. Para comprobar si la aplicación es vulnerable, intentamos inyectar comandos en el campo `username`, buscando una posible ejecución remota de comandos (RCE).

<figure><img src="/files/eEycmntMKCqSblCsfpRz" alt=""><figcaption></figcaption></figure>

Si logramos ejecutar comandos a través del parámetro `username`, significa que la API es vulnerable a una inyección de comandos. Esto nos permite interactuar con el sistema de manera remota, por lo que el siguiente paso es usar esta vulnerabilidad para obtener acceso a la máquina.

<figure><img src="/files/b77oDOUnm5tCyadln4BU" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
Al construir nuestro payload para obtener una shell reversa, debemos asegurarnos de que la sintaxis sea correcta. Algunas API pueden rechazar comandos que contengan dobles comillas (`"`), por lo que es necesario escaparlas (`\"`) o usar otro método para evitar errores en la ejecución del exploit.
{% endhint %}

## Access admin&#x20;

Al explorar la máquina, encontramos un archivo llamado `Database.php`. Este tipo de archivos suele contener configuraciones relacionadas con bases de datos, como conexiones, nombres de tablas o incluso credenciales. Sin embargo, al revisar su contenido, no encontramos ninguna credencial visible que nos permita acceder directamente a la base de datos.

<figure><img src="/files/fgFQPsYLH5Q9DQnDkEzm" alt=""><figcaption></figcaption></figure>

Si bien el archivo `Database.php` no muestra credenciales explícitamente, es común que estas se almacenen en otro lugar para mayor seguridad. En entornos de desarrollo y producción, las credenciales suelen guardarse en un archivo `.env` (archivo de variables de entorno). Este archivo contiene información sensible.

<figure><img src="/files/C0mwMAI9nscxDoziKGyD" alt=""><figcaption></figcaption></figure>

Ahora procedemos a inspeccionar el contenido del archivo `.env` para comprobar si efectivamente almacena credenciales de acceso.&#x20;

<figure><img src="/files/9I0uzOpYXTuPosQf9EYM" alt=""><figcaption></figcaption></figure>

Al abrir el archivo `.env`, encontramos credenciales de acceso. El usuario `admin` y la contraseña `SuperDuperPass123` podrían servir para autenticarnos con SSH.

<figure><img src="/files/yTfwYYqU9GmhrNpuVpJ0" alt=""><figcaption></figcaption></figure>

Tras autenticarnos correctamente mediante SSH, ahora operamos dentro de la máquina con los privilegios del usuario `admin`. Esto nos permite acceder a más archivos y recursos dentro del sistema. En este punto, encontramos la primera flag.

<figure><img src="/files/EaqGGqF3HNfCit1CQGOk" alt=""><figcaption></figcaption></figure>

## Root access via exploit kernel

Continuamos explorando la máquina en busca de información relevante. Para ello, realizamos una enumeración detallada del sistema, lo que implica buscar archivos accesibles por el usuario `admin`. En este proceso, encontramos un archivo que podría ser clave para avanzar en la explotación de la máquina.

<figure><img src="/files/nfmoelJ9hOLlLgrNwXAa" alt=""><figcaption></figcaption></figure>

Procedemos a examinar el contenido del archivo encontrado.

<figure><img src="/files/xwJGJ0bFU7YPcKXQaEDB" alt=""><figcaption></figcaption></figure>

El contenido del archivo sugiere información sobre el kernel del sistema operativo. Esto es importante porque si el kernel está desactualizado o tiene vulnerabilidades conocidas, podríamos aprovecharlas para escalar privilegios y obtener acceso root en la máquina. Ahora verificamos la versión del kernel con:

<figure><img src="/files/vrascurhHH0a9sQhgZ2G" alt=""><figcaption></figcaption></figure>

La versión del kernel que encontramos no está actualizada, lo que aumenta la probabilidad de que existan exploits públicos disponibles para ella. Procedemos a buscar vulnerabilidades conocidas utilizando bases de datos de exploits, como Exploit Database, Google o herramientas automáticas como `searchsploit`:

<figure><img src="/files/MG8ohM3YN1j69UlXX9Jm" alt=""><figcaption></figcaption></figure>

Tras buscar en bases de datos de exploits, identificamos uno específico que nos permitiría escalar privilegios en esta máquina. El exploit viene con instrucciones o código fuente que nos explica cómo ejecutarlo para obtener acceso root.

<figure><img src="/files/Tm8BqUzJRHKgSrPNtk2M" alt=""><figcaption></figcaption></figure>

Para poder usar el exploit, primero debemos obtener su código en nuestra máquina atacante. Si el exploit se encuentra en un repositorio de GitHub, lo clonamos con:

<figure><img src="/files/0x8paPVHEE4tLFXTYevr" alt=""><figcaption></figcaption></figure>

Para facilitar la transferencia de archivos hacia la máquina víctima, comprimimos todo el contenido en un solo archivo `.zip`. Esto evita la necesidad de enviar cada archivo individualmente. En Linux, usamos:

<figure><img src="/files/oiMUaEPjDbq8JRq9aHQO" alt=""><figcaption></figcaption></figure>

Confirmamos que el archivo `.zip` se ha creado correctamente y está listo para ser transferido a la máquina objetivo.

<figure><img src="/files/gXpSPnb7oGHs8IXjxI1c" alt=""><figcaption></figcaption></figure>

Para enviar el archivo a la máquina víctima, iniciamos un servidor HTTP en nuestra máquina atacante con Python:

<figure><img src="/files/jT8oxTYSybEEZ9xLcKLl" alt=""><figcaption></figcaption></figure>

Aquí podemos ver que tenemos el .zip, por lo que lo descomprimimos con unzip y ya tendriamos el exploit. Como hemos visto antes, nos dice que tenemos que hacer make all primero:

<figure><img src="/files/sGj8wEeeFrgCP8EX9VwR" alt=""><figcaption></figcaption></figure>

El exploit requiere ejecutar dos comandos en paralelo en diferentes terminales. Para ello, abrimos dos sesiones SSH o usamos `tmux`/`screen` para manejar múltiples terminales en la misma conexión.

<figure><img src="/files/I02DarxfRiMSuLRrlq9s" alt=""><figcaption></figcaption></figure>

Tras ejecutar correctamente el exploit, conseguimos una shell con privilegios de superusuario (`root`). Esto nos otorga control total sobre la máquina y nos permite acceder a todos los archivos del sistema, incluida la flag final, que suele encontrarse en `/root/root.txt`. Para verla, usamos:

<figure><img src="/files/Zv4QbfV17VPwcCGJrFxe" alt=""><figcaption></figcaption></figure>

***

## Conclusión

La máquina **TwoMillion** ejemplifica cómo la explotación de vulnerabilidades en aplicaciones web y configuraciones inseguras puede llevar a un **compromiso total del sistema**.

El ataque comienza aprovechando una versión antigua de la plataforma **HackTheBox**, que contenía un código de invitación pirateable. Esto permite registrarse en la plataforma y acceder a varios **endpoints de API**, donde se encuentra una vulnerabilidad para **elevar privilegios a administrador**.

Con acceso administrativo, es posible explotar una **inyección de comandos** en el sistema de generación de VPN, logrando así una **shell inicial**.

Además, la presencia de un archivo **.env** con credenciales de base de datos y la **reutilización de contraseñas** facilitan el acceso completo a la máquina como administrador.

Finalmente, un **kernel desactualizado** permite la explotación de la vulnerabilidad **CVE-2023-0386**, lo que concede acceso como **root** y otorga control total del sistema.TwoMillion
