Saltar al contenido
SDETRole
SDETRole

Glosario · Seguridad

Cross-site scripting (XSS)

En inglés: Cross-site scripting

También llamado: XSS, cross site scripting, secuencias de comandos en sitios cruzados, XSS almacenado

Definición

XSS es una vulnerabilidad en la que una entrada no confiable se renderiza como script ejecutable en el navegador de otro usuario, lo que permite al atacante actuar como él.

El cross-site scripting (XSS) ocurre cuando una aplicación toma la entrada de un usuario y la inserta en una página sin la codificación adecuada, de modo que el navegador la trata como HTML o JavaScript en lugar de como texto. El script se ejecuta entonces con la sesión de la víctima en el sitio vulnerable: puede leer datos de la página, hacer peticiones como el usuario o cambiar lo que ve. En el OWASP Top 10 2021 se agrupa dentro de A03 Injection.

Los tres tipos

  • Almacenado (stored). El payload se guarda (un comentario, un nombre de perfil, un ticket de soporte) y se sirve a todos los que lo ven. Suele ser el más grave.
  • Reflejado (reflected). El payload va en la petición, a menudo en un parámetro de la URL como un término de búsqueda, y se devuelve tal cual en la respuesta.
  • Basado en DOM. JavaScript del lado del cliente lee datos controlados por el atacante (por ejemplo location.hash) y los escribe en la página mediante un sink inseguro como innerHTML.

Qué comprueba un tester

Introduce un marcador inofensivo en cada campo que luego se muestre (a ti, a otros usuarios, a administradores en un back office) y observa si vuelve como texto o como markup activo. Una verificación automatizada en Playwright, solo para pruebas autorizadas:

import { test, expect } from '@playwright/test';

test('comment body is rendered as text, not HTML', async ({ page }) => {
  const probe = '<img src=x onerror="window.__xssProbe=1">';

  await page.goto('/posts/1');
  await page.getByLabel('Comment').fill(probe);
  await page.getByRole('button', { name: 'Post comment' }).click();

  // Escaped output shows the literal characters on screen
  await expect(page.getByText(probe)).toBeVisible();
  // and the handler never ran
  expect(await page.evaluate(() => (window as any).__xssProbe)).toBeUndefined();
});

Comprueba también contextos de salida distintos del HTML plano: valores dentro de atributos, dentro de scripts en línea, en URLs (enlaces javascript:) y en editores de texto enriquecido, porque cada uno necesita una codificación distinta.

Defensas que hay que verificar

  • Codificación de salida por defecto. Los frameworks modernos (React, Angular, Vue) escapan el texto automáticamente; busca las vías de escape como dangerouslySetInnerHTML, v-html o innerHTML.
  • Sanitización de HTML en las funcionalidades que de verdad aceptan markup.
  • Una cabecera Content Security Policy que bloquee los scripts en línea, como segunda capa.
  • Cookies de sesión HttpOnly, para que un XSS exitoso no pueda simplemente leer la cookie de sesión.

Nunca hagas pruebas en sistemas que no te pertenecen o para los que no tienes permiso por escrito.

Escribe para buscar en todo SDETRole.

Búsqueda de texto completo con Pagefind · se ejecuta en tu navegador Abrir la página de búsqueda →