Nivel AvanzadoGratis

Reflected XSS en página 429 vía Google Analytics — el snippet de tracking como vector

El snippet de Google Analytics tomaba parte de la URL como input sin sanitizar. Un breakout de string literal dentro del propio script: la inyección estaba ya en contexto JavaScript.

Gorka El Bochi9 de mayo de 20269 min

Deja de leer sobre bugs y empieza a cazarlos

Sin tarjeta · Academy gratis · cancela cuando quieras

Crear cuenta gratis

Respuesta rápida

La página de error 429 (Too Many Requests) de un subdominio de una red social Q&A reflejaba parte de la URL dentro del bloque <script> de Google Analytics, sin sanitizar. Como el input ya estaba en contexto JavaScript, no hacía falta romper HTML: bastaba romper el string literal con '-alert(document.domain)-'. Reflected XSS clásico, pero el vector — el snippet de GA — es interesante.


1. Contexto — la página de error 429

Cuando un usuario realiza demasiadas peticiones a un subdominio de la plataforma, el servidor devuelve una página de error 429. Esta página incluye un snippet de Google Analytics que toma parte de la URL como input para construir sus llamadas de tracking.

El problema es que ese valor de la URL se inserta directamente dentro del bloque <script> de Google Analytics sin ningún tipo de sanitización, convirtiéndose en un punto de inyección de JavaScript.


2. El payload y la URL vulnerable

bash
https://subdomain.target.tld/'-alert(document.domain)-'

La parte de la URL después de la barra ('-alert(document.domain)-') se refleja directamente dentro del script de Google Analytics en la respuesta HTTP.


3. El código vulnerable en la respuesta

html
<script type="text/javascript">
  ...
  ga('set', 'dimension1', 'board-'-alert(document.domain)-'');
  ga('set', 'dimension2', 'False');
  ga('set', 'dimension3', 'False');
  });
});
</script>

El valor de la URL se concatena dentro de un string literal JavaScript entre comillas simples. El payload cierra la comilla de apertura con ', inyecta la llamada a alert(document.domain) con concatenación de strings (-alert(document.domain)-), y reabre la comilla para que el resto del código sea sintácticamente válido.

Desglose del payload

lua
dimension1', 'board-   ← string original hasta donde llega el input
'-alert(document.domain)-'  ← input del atacante

La secuencia resultante en el script es:

javascript
ga('set', 'dimension1', 'board-' - alert(document.domain) - '');

JavaScript evalúa -alert(document.domain)- como una operación aritmética, lo que fuerza la evaluación de alert(document.domain) como parte de la expresión. El resultado aritmético no importa — lo que importa es que alert(document.domain) se ejecuta.


4. Condición para triggear el XSS

La página de error 429 solo se muestra cuando el servidor detecta demasiadas peticiones desde el mismo cliente. Para que la víctima cargue la página vulnerable, primero tiene que estar en rate limit. En la práctica esto se consigue de varias formas:

  • El atacante envía muchas peticiones previas desde la IP de la víctima (no trivial).
  • La víctima ya está en rate limit de forma natural por su propio uso.
  • Se envía directamente el link cuando ya está en estado 429.

5. Clasificación técnica

CampoValor
Tipo de vulnerabilidadReflected XSS — Input reflejado en bloque <script>
CWECWE-79 — Improper Neutralization of Input
VectorSegmento de URL reflejado en snippet de Google Analytics
PersistenciaReflected — se activa solo al cargar la URL maliciosa
Condición previaEstado 429 (rate limit) activo en el cliente

6. Notas técnicas

  • El XSS está dentro de un bloque <script> existente, no en un atributo HTML. Esto lo hace especialmente directo: no hace falta salir de un contexto HTML, el input ya está dentro de un contexto JavaScript donde cualquier código es ejecutable directamente.
  • El vector es el snippet de Google Analytics, un bloque de código de terceros que la plataforma incluía en sus páginas de error. La superficie de ataque está en cómo la app construía los parámetros pasados a ga() usando datos de la URL sin escapar.
  • La condición del 429 limita ligeramente la explotabilidad respecto a un Reflected XSS sin condiciones previas, pero no la elimina — la URL maliciosa sigue siendo crafteada por el atacante y compartible.

Lección general

Cuando un valor del cliente acaba dentro de un bloque <script>, el vector ya está medio cocinado: solo necesitas romper el contexto del string literal que lo contiene. No mires solo HTML cuando audites páginas de error o snippets de tracking — el contexto JavaScript es donde menos sanitización suele haber.


Labs relacionados

Practica reflected XSS en script blocks y bypasses con concatenación aritmética: labs de XSS.

Gratis · sin cuenta

La checklist que repaso en cada objetivo nuevo

47 comprobaciones ordenadas por coste: primero lo que te puede meter en un lío, luego lo barato, y al final lo caro — que es donde están los bounties grandes. Te la mando al correo ahora mismo.

Te das de baja en un clic, desde cualquier correo.

Practica esto en un lab

Xss

Resolver

Sigue aprendiendo · cuenta gratis

Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.

Crear cuenta

Artículos relacionados

2.786

hunters entrenando

63

labs de hackeos reales

1.767

completaciones

$14.790

pagados por estos bugs

37 flags capturadas esta semana·Hackeos reales de HackerOne · YesWeHack · Bugcrowd·Sin permanencia·Academy gratis

La comunidad

Esto no es una plataforma con usuarios.Es gente rompiendo lo mismo que tú.

Dentro se pregunta, se enseña lo que se ha encontrado y se resuelve en grupo lo que atascaría a cualquiera solo. Se entra gratis: sin cuenta, sin plan y sin dejar el correo.

Entrar a la comunidad de BBLABS en Discord
Entrar al Discord

Es gratis y abierto. No hace falta tener cuenta en BBLABS para entrar.