Timeline de Sesiones
Cronologia completa de las 13 sesiones de pentest — desde el descubrimiento inicial hasta HTTP Request Smuggling
Timeline de Sesiones
Evolucion del Pentest
Detalle de Sesiones Clave
Sesiones 1-2: Descubrimiento y Primer Contacto
Empezamos con recon basico: nmap full port scan, HTTP banner grabbing, Xtream API fingerprinting. Construimos la primera version de la herramienta CLI (iptv-recon) con commander, structured logging, y Result pattern.
Descubrimientos clave:
- Stalker Portal v5.3.1 confirmado (
/c/version.js) - Routing dual framework identificado (Silex 405 vs Laravel 404)
- 51 rutas admin Silex encontradas — todas devolviendo 405
- STB API auth bypass:
get_profiledevuelve 75+ campos sin autenticacion - Ruta
_fragmentRCE existe pero bloqueada por la paradoja de routing - 30+ tecnicas de bypass intentadas contra el front controller — todas fallaron
- Testing SSRF en 12 endpoints — todos negativos (timing analysis confirma sin fetch)
- SQLi en
series_idresulta ser PHP type crash, no SQL injection
Sesion 3: Mapeo de Infraestructura
Full port scan revelo infraestructura multi-puerto: :53 DNS, :4499 RTMP, :5060 SIP, :31210 internal API, :65432 SSH. Descubierto Nodo 141 con nginx 1.21.2 mas viejo. Token delivery probado en 8 canales — todos rechazados.
Construimos scripts de exploit: stalker-exploit.ts (Check Point 2019 chain), confirm-ssrf.ts, fragment-exploit.ts.
Sesion 4: Brute Force y DNS
SSH brute con 2700 combinaciones — cancelado al 32% sin exito. DNS zone transfer (AXFR) denegado en los 4 dominios a traves de 2 servidores. Reverse DNS revelo ns31681901.ip-141-94-3.eu. Puerto 4499 identificado como RTMP.
Sesion 5: Nace "La Cupula de Cristal"
Agotamos los vectores HTTP y le pusimos nombre al patron. Tambien encontramos:
- Laravel Ignition instalado pero POST -> 405
- RTMP solo tiene app
/livecon auth callback
Conclusion estrategica: Solo protocolos no-HTTP o ataques a nivel de protocolo pueden funcionar.
Sesion 6: Tercer Servidor Descubierto
Un descubrimiento importante: HEAD vs GET devuelve resultados diferentes:
HEAD /live/...-> 200 Content-Length:0 (sin redirect)GET /live/...-> 302 redirect al nodo 135
Esto revelo el tercer servidor (XXX.XXX.XXX.XXX) especializado en live streaming.
DNS recursive resolver descubierto en el servidor principal. Probamos h2c upgrade, WebSocket, CONNECT tunneling — todos cerrados.
Sesion 7: Fingerprint Completo Nodo 135
Port scan y dome-fingerprint del Nodo 135. Confirmada cupula identica en los 3 nodos. Player API leak muestra los mismos 22K+ canales. Comparativa de tres nodos completada. Todos los nodos comparten la misma base de datos, versiones de SSH, y patron de deploy.
Sesion 8: Deep Dive de Protocolos
RTMP PUBLISH en :4499 — notify callback llega a Stalker API pero no hace outbound HTTP fetch (timing analysis confirma sin SSRF). Path traversal en stream names: I/O error o "operation not permitted", nunca SSRF.
SIP :5060 — sin respuesta en TCP (3 nodos), sin respuesta en UDP (svmap). Puerto tcpwrapped — probablemente solo interno.
_method bypass revelo la mecanica exacta del routing dual: decision de routing hecha desde el metodo HTTP raw antes de procesar _method. Usar _method=GET en body POST escapa a Laravel — pero Laravel no tiene rutas admin.
Sesion 9: STB API Deep Dive y Descubrimiento de MAC
Encontramos MAC real (F5:57:59:66:90:AB) de una cuenta registrada de Apple TV. User profile revela blocked=1, passwords 0000, timezone Europe/Brussels. Rate limiting cross-node confirmado (DB compartida). CORS completamente abierto: Access-Control-Allow-Origin: *.
Descubiertos dos sistemas de auth independientes:
- STB API (
load.php): MAC cookie + token (usuario bloqueado) - Xtream API (
player_api.php): username/password (funciona, 22K canales)
Sesion 10: Ultimas Aristas
SSH user enumeration cerrada (CVE-2018-15473 parchado). set_settings confirmado read-only (8 nombres de action, 3 formatos de body). 4 acciones STB candidatas a SSRF — todas {"js":[]}. SQLi basada en MAC cerrada (prepared statements). Type juggling, PHP CVEs (6 evaluadas), XXE — todo cerrado. APP_DEBUG=false confirmado.
Sesion 11: RoadRunner y Cadena VOD
Testeo de stream real MP4/MKV desde Nodo 141 -> 302 redirect a main con tokens cifrados de un solo uso. Accept-Ranges con formato no estandar confirma RoadRunner (servidor de aplicaciones PHP basado en Go) en el stack — no es nginx mp4_module. CVEs de MP4 definitivamente cerradas.
Stack actualizado: nginx -> RoadRunner -> PHP (Silex+Laravel) -> MySQL
Rate limit bypass: ban solo de POST — GET handshake funciona durante cooldown.
Sesion 12: Check Point Chain y Portal.php
Check Point 2019: auth bypass a type=vclub funciona (no requiere auth), pero las tablas vclub estan vacias. SQLi via sortby no ejecuta en tablas vacias. type=vod/itv/series tiene datos (22K+) pero requiere is_authenticated=true. Vulnerabilidad existe en codigo pero es inexplotable en esta instancia.
portal.php: punto de entrada alternativo en root — mismo backend, misma cupula. Path manipulation exhaustivo (double slashes, encoded slashes, null bytes, CRLF, dot segments) — todo normalizado por nginx. 16+ puntos de entrada PHP alternativos — ninguno existe. 12 tipos STB no documentados — todos ignorados.
Sesion 13 (Actual): HTTP Request Smuggling
Target: CVE-2025-22871 (CVSS 9.1): Go net/http acepta bare LF (\n) en lineas chunk-size de chunked encoding. Como RoadRunner esta basado en Go y se situa detras de nginx, un diferencial de parsing podria permitir request smuggling para bypasear protecciones de nginx y alcanzar rutas internas (/_fragment, /adm/login).
Resultado: nginx y RoadRunner ambos aceptan bare LF — sin diferencial de parsing, sin smuggling. Bare CR en chunk-ext genera 400 en nginx 1.26.2, TIMEOUT en nginx 1.21.2 (ambiguo pero no explotable).
Cupula intacta.