Cross-Site Scripting (XSS): Vectores de ataque y defensas

Security2026-09-13TryQuickToolBox

Por qué XSS sigue acechando las aplicaciones web

El cross-site scripting (XSS) sigue siendo una de las vulnerabilidades web más prevalentes. A pesar de la concienciación generalizada, aparece consistentemente en el OWASP Top 10. El problema central: las aplicaciones confían en la entrada del usuario y la representan sin un manejo adecuado. Los atacantes inyectan scripts maliciosos que se ejecutan en los navegadores de las víctimas, lo que lleva al secuestro de sesiones, robo de datos y desfiguración.

Este artículo desglosa los vectores de ataque XSS y proporciona defensas prácticas que puede implementar hoy mismo.

¿Qué es XSS y cómo funciona?

XSS ocurre cuando una aplicación incluye datos no confiables en una página web sin validación ni codificación. El navegador luego ejecuta el script inyectado como si fuera parte del sitio legítimo. Debido a que el script se ejecuta en el contexto del sitio vulnerable, puede acceder a cookies, almacenamiento local y realizar solicitudes en nombre del usuario.

Considere una página de búsqueda simple que refleja la consulta:

<?php echo 'You searched for: ' . $_GET['q']; ?>

Si un atacante crea una URL como search.php?q=<script>alert('XSS')</script>, el script se ejecuta cuando la víctima visita el enlace.

Tres tipos principales de XSS

1. XSS reflejado

El script malicioso es parte de la solicitud (por ejemplo, parámetro URL) y se refleja inmediatamente en la respuesta. Las víctimas deben ser engañadas para hacer clic en un enlace o enviar un formulario. Esto se usa a menudo en campañas de phishing.

2. XSS almacenado

El script se almacena permanentemente en el servidor (por ejemplo, en una base de datos, campo de comentarios o perfil de usuario). Cada visitante de la página afectada ejecuta el script. El XSS almacenado es más peligroso porque no requiere interacción más allá de ver la página.

3. XSS basado en DOM

La vulnerabilidad existe en JavaScript del lado del cliente que lee datos de una fuente no confiable (como location.hash) y los escribe en el DOM sin un manejo seguro. Es posible que el servidor nunca vea la carga maliciosa.

document.getElementById('output').innerHTML = location.hash.substring(1);

Si el hash contiene <img src=x>, el script se ejecuta.

Vectores de ataque comunes

  • Entrada de usuario sin escape en HTML: Inyección directa en contenido HTML, atributos o JavaScript.
  • Uso incorrecto de sumideros peligrosos: Funciones como innerHTML, document.write, eval y setTimeout con argumentos de cadena.
  • Inyecciones basadas en URL: Manipulación de atributos href, src o style con URIs javascript:.
  • Componentes de terceros: Bibliotecas o widgets vulnerables que representan datos no confiables.

Defensas contra XSS

1. Codificación de salida (escape contextual)

Codifique todos los datos no confiables antes de representarlos en HTML, atributos, JavaScript, CSS o URL. Utilice una codificación adecuada al contexto:

  • Codificación de entidades HTML: Convierta &, <, >, ", ' a entidades.
  • Codificación JavaScript: Escape los caracteres no alfanuméricos a Unicode.
  • Codificación URL: Utilice encodeURIComponent() para parámetros de consulta.

La mayoría de los frameworks modernos (React, Angular, Vue) escapan automáticamente de forma predeterminada, pero tenga cuidado al usar dangerouslySetInnerHTML o escotillas de escape similares.

2. Validación y saneamiento de entrada

Valide la entrada en el lado del servidor utilizando listas de permitidos. Para texto enriquecido, use una biblioteca como DOMPurify para sanear el HTML, eliminando etiquetas y atributos peligrosos.

const clean = DOMPurify.sanitize(userInput);

Nunca confíe únicamente en la validación del lado del cliente.

3. Política de seguridad de contenido (CSP)

CSP es un poderoso mecanismo de defensa en profundidad. Restringe las fuentes de scripts ejecutables, scripts en línea y otros recursos. Una CSP estricta puede bloquear XSS incluso si ocurre una inyección.

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; object-src 'none';

Evite unsafe-inline y unsafe-eval. Utilice nonces o hashes para scripts en línea legítimos.

4. Atributos de cookies seguras

Establezca cookies con HttpOnly (evita el acceso de JavaScript) y Secure (solo HTTPS). Esto mitiga el secuestro de sesiones mediante XSS.

5. Utilice frameworks modernos y evite API peligrosas

Frameworks como React, Angular y Vue escapan automáticamente los datos. Evite la manipulación directa del DOM con innerHTML. Si debe insertar HTML, sanee primero.

6. Pruebas de seguridad regulares

Incorpore SAST, DAST y pruebas de penetración manuales. Herramientas como OWASP ZAP pueden ayudar a identificar vulnerabilidades XSS.

Comparación de tipos de XSS y defensas principales

Tipo de XSSDescripciónDefensa principal
ReflejadoCarga útil en la solicitud, reflejada en la respuestaCodificación de salida, validación de entrada
AlmacenadoCarga útil almacenada en el servidor, servida a todos los usuariosSaneamiento, codificación de salida, CSP
Basado en DOMInyección del lado del cliente mediante API DOM insegurasAPI DOM seguras, CSP, evitar eval

Paso a paso: Implementación de defensas XSS

  1. Identifique todos los puntos de entrada: Formularios, parámetros URL, encabezados, cookies.
  2. Aplique codificación de salida contextual: Utilice funciones integradas o bibliotecas como OWASP Java Encoder.
  3. Sanee texto enriquecido: Utilice DOMPurify o similar.
  4. Implemente CSP: Comience con el modo de solo informe, luego aplique.
  5. Establezca cookies HttpOnly y Secure.
  6. Eduque a los desarrolladores: Capacítelos en prácticas de codificación seguras.
  7. Pruebe regularmente: Integre pruebas de seguridad en CI/CD.

Preguntas frecuentes

¿Cuál es la diferencia entre XSS y CSRF?

XSS ejecuta scripts maliciosos en el navegador de la víctima, mientras que CSRF engaña al navegador para que envíe solicitudes no autorizadas a un sitio donde el usuario está autenticado. XSS se puede utilizar para eludir las protecciones CSRF.

¿Puede la Política de seguridad de contenido prevenir completamente XSS?

No, CSP es una medida de defensa en profundidad. Reduce significativamente el riesgo, pero no puede reemplazar la codificación de salida adecuada y la validación de entrada. Una CSP mal configurada aún puede permitir algunos ataques.

¿Es suficiente la validación del lado del cliente para prevenir XSS?

No. La validación del lado del cliente se puede eludir fácilmente. Siempre valide y codifique en el lado del servidor, y trate todos los datos del cliente como no confiables.

Conclusión

XSS es una amenaza persistente, pero con una estrategia de defensa en capas—codificación de salida, validación de entrada, CSP y cookies seguras—puede mitigarla eficazmente. Manténgase vigilante, mantenga los frameworks actualizados y pruebe continuamente.

Para herramientas de seguridad adicionales, consulte nuestro Analizador de registros de Nginx para detectar patrones sospechosos en los registros de su servidor.