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ásHacker 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. Enumeración de artefactos internos vía la API de listado de una media library
MediaVDP50 min

Enumeración de artefactos internos vía la API de listado de una media library

Por @gorka

La API de listado de assets ecoa el filtro que le envías y el store de ficheros no autentica: enumera artefactos internos y extrae el secreto embebido en un bundle.

472 visitas5 completadosActualizado sept 2026
Iniciar sesión para empezar

Aprende a encontrar este bug

Un hackeo real de HackerOne, 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.

650

hunters entrenando

50

labs de hackeos reales

380

completaciones

$12.000

pagados por estos bugs

40 flags capturadas esta semana
Crear cuenta
Ya tengo cuenta

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

Hackers que lo han resuelto· 5

w4tchw0lf1
@w4tchw0lfHace 5 días
kaneki2
@kanekiHace 10 días
alejandrorubiocam3
@alejandrorubiocamHace 10 días
benjaminnocervigni
@benjaminnocervigniHace 14 días
CR
@crashHace 14 días

Objetivos

1
Descubrir la API de listado de medios leyendo el XHR que dispara la galería pública.
2
Detectar que la respuesta ecoa el filtro que le mandas y qué parámetros acepta.
3
Enumerar artefactos internos cambiando u omitiendo el parámetro de visibilidad.
4
Contrastar el 401 de las rutas de escritura frente al 200 del listado y la descarga.
5
Descargar sin autenticación el bundle interno vigente desde su source_url.
6
Extraer el fichero de licencia embebido dentro del ZIP y localizar el secreto.
7
Descartar los 4 decoys del lab por razonamiento acotado, no por fuerza bruta.

Información

Plataforma
HackerOne
Dificultad
Media
Duración
50 min
Bounty
VDP
Completados
5
Creador
gorka@gorka
Actualizado
sept 2026

Descarga el entorno

Reprodúcelo y encuentra el bug tú mismo

Crear cuenta

Herramientas

curlunzipNavegadorDevTools

Prerequisitos

  • HTTP y APIs REST
  • Uso básico de curl
  • Nociones de ficheros ZIP

Tags

BACInformation DisclosureIDOR

Logro que recibirás

Cuando resuelvas este lab desbloqueas este logro compartible

BBLABS.ESLab Resuelto
MediaVDP
// achievement_unlocked

Enumeración de artefactos internos vía la API de listado de una media library

BACInformation DisclosureIDOR
sept 2026
gorka
solved_by@gorkaMiembro desde mar 2026
bblabs.es// real hacking practice

Writeups de la comunidad

Contenido del lab

Escenario

Assetria es una plataforma de gestión de activos digitales (DAM) para estudios de diseño web: sus clientes suben logos, imágenes de marca y bundles de build a una biblioteca central, y publican una galería pública para que sus propios equipos y sus partners consuman los assets aprobados. Por debajo de la galería vive una API de catálogo de medios (/api/v1/media) que la misma interfaz consume y que, según la documentación interna, también usan integraciones de terceros — de ahí que sea machine-readable y acepte parámetros de filtro explícitos en vez de estar cableada a una única vista.

Eres pentester contra el sitio público de Assetria. Tu misión: demostrar que la API de catálogo expone más superficie de la que la galería deja ver, y usar esa superficie para llegar hasta un artefacto interno del estudio (un bundle de build) que nunca debería ser público — y de ahí, extraer el service_license_key embebido dentro, un secreto de licencia de la organización.

Qué tienes

  • Cuenta demo: attacker@assetria.local / password123 — un colaborador de marca (contributor) de baja privilegia. Te sirve para entrar y ver tu perfil, pero no te da acceso al panel de administración (/admin/media, restringido a admin) y no es el punto de entrada de la vulnerabilidad.
  • La galería pública de Assetria, con buscador, paginación y vista de detalle por asset.
  • El bundle JavaScript público del front-end (galería + panel) — servido igual que cualquier SPA, sin ofuscar ni requerir sesión para descargarlo.

Guía paso a paso

  1. Recon del surface: encuentra el XHR que alimenta la galería. Navega la galería pública y abre la pestaña de red. Verás que dispara GET /api/v1/media?type=image&visibility=public&page=1&per_page=20. La respuesta es JSON: items[] (cada uno con id, type, visibility, title, filename, source_url, size, created_at), un bloque pagination, y un bloque filter que ecoa exactamente lo que mandaste: "filter":{"type":"image","visibility":"public","q":null}. Auto-descubrimiento puro: no adivinas ni la ruta ni los nombres de los parámetros, los lees directamente del tráfico que la propia galería genera.

  2. Prueba a cambiar o quitar el filtro de visibilidad. El bloque filter que acabas de ver ecoando tu petición es una invitación a experimentar: repite la llamada con visibility=internal, o quítala del todo. El filter de la respuesta cambia exactamente con lo que mandaste — confirmación de que el servidor aplica tu valor tal cual, sin comprobar si tienes permiso para pedirlo. Aparecen de inmediato items nuevos que la galería nunca mostró: "visibility":"internal", "type":"application", con title del estilo "Studio Brand Kit — internal build 2025" y filename con el patrón studio-brandkit-build-<año>-<sufijo>.zip. El total de pagination sube respecto a la vista pública, y cada item trae su propia source_url ya resuelta.

  3. Contrasta con las rutas de escritura del mismo catálogo. Antes de asumir que "toda la API es así de abierta", prueba a crear o borrar un asset sin sesión (POST/DELETE sobre la ruta de administración del catálogo): responde 401 sin cookie. El listado y la lectura, en cambio, no te pidieron nada. La asimetría es la pista: la restricción existe de verdad en esta API — solo que no cubre lectura ni descarga, únicamente escritura.

  4. Descarga sin autenticarte el artefacto interno más reciente. Con la source_url del paso 2, pide el fichero directamente (sin cookie, sin header Authorization): 200, content-type: application/zip. El store de ficheros que sirve estos assets no comprueba nada antes de entregar los bytes por su clave.

  5. Descomprime y localiza el secreto — confirma que es el build vigente. Dentro del ZIP hay un fichero LICENSE.key con nombre inequívoco. Contiene varios campos de acompañamiento y uno decisivo: service_license_key. En el build 2025 (el más reciente por created_at y por el nombre del title) ese campo trae la flag en claro. Si grepeas un build más viejo primero, el campo sale vacío o marcado EXPIRED — señal de que hay que quedarse con el vigente.

Canales de feedback (no vuelas a ciegas)

  • El XHR de la galería responde 200 con JSON legible/grep-able; el bloque filter ecoa exactamente lo que mandaste, invitando a experimentar con otros valores.
  • Cambiar o quitar el filtro de visibilidad hace aparecer de inmediato items nuevos y sube el total de la paginación — no hace falta adivinar si "hay algo más", la respuesta te lo muestra.
  • El contraste 401 (crear/borrar sin sesión) frente a 200 (listar/leer/descargar sin sesión) es observable en cada request, sin ambigüedad.
  • La descarga del artefacto responde 200 application/zip sin cookie; el fichero de licencia dentro del ZIP tiene un nombre que no deja lugar a dudas sobre qué grepear.
  • Los builds antiguos traen el campo del secreto vacío o EXPIRED — un confirmador explícito de "este no es, prueba el vigente", no un callejón silencioso.

Decoys (descártalos por razonamiento acotado)

  • Bundles públicos de marketing. Ya visibles en la galería (type:"application", visibility:"public"), descargan 200 igual que el resto. Pero dentro solo hay un README.txt de prensa y un par de imágenes — sin LICENSE.key. Refutable en una prueba: unzip + grep no encuentra el campo.
  • Una imagen de campaña sin publicar. Aparece con la misma etiqueta de visibilidad "escondida" que los artefactos de verdad, y el mismo fallo la deja descargar sin auth — exposición real, pero es un .png: no hay ZIP que abrir ni secreto que extraer. Refuerza el fallo sin ser el objetivo.
  • El login con la cuenta demo. Entrar con attacker@assetria.local no abre ningún camino nuevo: es una cuenta contributor, no tiene acceso al panel de administración, y la descarga del artefacto interno funciona exactamente igual con o sin sesión. Refutable en una prueba: pedir el artefacto sin cookie ya da 200.
  • Builds antiguos del brand kit. Descargan 200 igual que el vigente, pero su LICENSE.key trae el campo del secreto vacío o marcado EXPIRED (clave rotada). Fuerza a no conformarte con el primer ZIP que encuentres, sino a comparar fechas y quedarte con el build 2025.

La falla del laboratorio

Clase: CWE-200 (Exposure of Sensitive Information to an Unauthorized Actor), con CWE-862 (Missing Authorization), CWE-306 (Missing Authentication for Critical Function) y CWE-602 (Client-Side Enforcement of Server-Side Security) como CWEs relacionadas. OWASP A01:2021 (Broken Access Control) + A05:2021 (Security Misconfiguration).

El catálogo de medios de Assetria trata visibility y type como filtros que el cliente puede suministrar libremente, y los aplica al pie de la letra (WHERE visibility = <valor recibido>, o sin cláusula alguna si se omite) sin derivar, del rol o de la sesión de quien pregunta, qué visibilidad tiene derecho a pedir. La restricción "un usuario anónimo solo debería ver public" no vive en el servidor: vive en la galería, que sencillamente elige mandar visibility=public en su propia llamada. Cualquier otro consumidor de la misma API — o el mismo atacante con curl — puede pedir lo contrario. No es un if invertido ni una comprobación rota: es la ausencia de una regla de autorización sobre un parámetro que el código de listado, por lo demás, procesa correctamente.

Esa ausencia se combina con una segunda: el store de ficheros que sirve los blobs por su clave de almacenamiento no exige ninguna credencial antes de devolver el contenido. Aunque el listado hubiera estado bien protegido, cualquiera que conociera (o enumerara) una clave de almacenamiento podría descargar el fichero igualmente. Juntas, ambas ausencias convierten un catálogo pensado para distinguir "público" de "interno" en una fuga total: el atacante enumera lo que no debería ver y lo descarga sin credencial alguna.

La escalada final añade una tercera capa, más de diseño que de código: el equipo de build embebe un secreto de licencia real (service_license_key) dentro de un artefacto binario pensado para uso interno, confiando en que ese artefacto nunca sea alcanzable desde fuera. Cuando la exposición de arriba lo hace alcanzable, el secreto sale con él — sin que el atacante necesite ninguna credencial en ningún punto de la cadena.

Lo que habría prevenido el bug es enunciable en una frase: derivar la visibilidad permitida del rol del solicitante en vez de aceptar la del cliente (anon ⇒ solo public, sin excepción), y exigir autenticación/autorización en el store de ficheros igual que se exige en las rutas de escritura del mismo catálogo. Adicionalmente, ningún artefacto con secretos reales debería residir en un store alcanzable sin control de acceso, con independencia de si su URL es "adivinable" o no.

Lección: que una API "solo" acepte parámetros de filtro razonables (tipo, visibilidad, paginación) no implica que esté autorizando correctamente quién puede pedir cada valor — filtrar y autorizar son preguntas distintas, y basta con responder bien a la primera para dar una falsa sensación de control sobre la segunda. Cuando la UI restringe algo "por defecto" mandando un valor concreto, comprueba siempre si esa restricción también vive en el servidor o si solo vive en la elección del cliente.

Laboratorio basado en la reproducción anonimizada (empresa ficticia Assetria) de una técnica real de bug bounty sobre una media library cuya API de listado indexaba artefactos internos que la interfaz nunca enlazaba, servidos por un store de ficheros sin autenticación.

Contacto

Practica, aprende y hackea

Plataforma de práctica de bug bounty con labs basados en hackeos 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 hackeos pagados en HackerOne, YesWeHack y Bugcrowd. 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 hackeos 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 hackersLabs 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érminosPrivacidadCookiesComparativaEN

© 2026 BBLABS v2 — Todos los derechos reservados