Cross-Site Scripting: Inyección XSS

Tras los posts sobre SQL Injection y NoSQL Injection, hoy te traigo la XSS Injection. Este ataque consiste en inyectar código malicioso en páginas web benignas. El atacante inyecta código desde el lado del cliente, de forma que por una mala configuración de la página web, este código se muestre a otros usuarios

Este tipo de ataques suelen ocurrir cuando el navegador utiliza un campo de entrada de usuario para generar un campo de salida sin validarlo previamente.

Para tratar de obtener una inyección de Cross-Site Scripting, hay que tratar de encontrar zonas de una página web donde un valor que introduzcamos aparezca reflejado. Un ejemplo sería encontrar una página web donde tengas que introducir un nombre de usuario en el registro, por ejemplo “Lethani”, y que al hacer login aparezca un mensaje de bienvenida diciendo “Hello, Lethani”.

Si mirásemos el código fuente de esa supuesta página, veríamos un código html como este:

Pero si en vez de “Lethani” escribiéramos en el registro un nombre de usuario que contuviera un código javascript malicioso, éste se ejecutaría al renderizarse la página html. Por ejemplo:

Este código provocaría que se ejecute la función alert() de javascript que hace que el navegador muestre un pop-up.

Para mostrarte la prueba de concepto, he utilizado la página xss-game.appspot.com, la cual te recomiendo para que puedas probar tú mismo esta vulnerabilidad:

Para probar este tipo de vulnerabilidades usualmente se usa la función alert() de javascript. Si introduciendo en algún lugar de la web la función te salta un pop-up, entonces la página es vulnerable a XSS.

No obstante, que una página refleje una entrada de usuario no significa que sea vulnerable a XSS. Para evitar esta vulnerabilidad, basta con que el desarrollador haya validado todas las entradas, utilizando funciones creadas para ello, de forma que independientemente de lo que introduzcas ese valor sea tratado como una variable, y nunca como código que pueda variar el código fuente.

Existen dos versiones de este tipo de inyección: XSS Reflected y XSS Persistent. Cuando la inyección es reflejada, el código malicioso no se guarda en la base de datos, tan solo se refleja en el cliente. Por ello para que a un usuario se le muestre, tiene que haberlo introducido él mismo. Sin embargo, cuando se trata de una inyección XSS persistente, el payload introducido se guarda en la base de datos, y se muestra a cualquier usuario que acceda al valor inyectado. Por ello una vulnerabilidad XSS Persistent es mucho más grave que una Reflected.

 

Alcance de ataques XSS

Cabría preguntarse de qué podría servirnos este ataque. Más allá de que un usuario se sorprenda con un pop-up, hay muchas cosas interesantes que podemos hacer si hemos conseguido una inyección XSS.

– Cookie Stealing XSS: es posible robar la cookie de sesión de un usuario. Esto lo podemos conseguir si ejecutamos la función de javascript document.cookie. Supongamos que podemos realizar una inyección XSS en una url de amazon. Mediante phising podría hacer que un usuario abra el enlace en el que he inyectado el siguiente payload:

De esta forma, mandaría a mi página web su cookie de sesión. Yo la obtendría, y podría realizar compras en su nombre.

– Force to Download a File: es posible hacer que un usuario se descargue un archivo malicioso al visitar un enlace vulnerable a XSS Injection. Por ejemplo, podríamos hacerlo con el siguiente payload:

– Redirecting User: también lo podemos usar para enviar al usuario a otra página web. Se podría redirigir al usuario a una página controlada por el atacante que sea idéntica, de forma que introduzca sus credenciales creyendo que está en la página original:

Además de estos, puedes encontrar muchos otros scripts para activar keyloggers, sacar fotos y vídeos a través de la cámara web, etc. en este enlace.

 

XSS Ofuscados / Políglotas

En muchas ocasiones me he encontrado páginas web donde sospechaba que eran vulnerables a XSS pero que tenían filtrado el texto “<script>” de forma que nada pasaba al inyectar el payload. A continuación muestro algunas formas de ejecutar código de javascript sin utilizar las etiquetas de script.

Además de estas puedes encontrar otras formas de ofuscar inyecciones XSS para evitar los filtros en la página de OWASP.

En esta otra página web puedes encontrar muchas demos de “XSS Políglota”, en los que se encodean los caracteres para evadir los filtros.

Por último, podemos encontrar un codificador llamado JSFuck que convierte el código javascript que queramos en código javascript esotérico:

En próximos posts mostraré algunos casos de XSS avanzados como el Blind XSS o el Dom Based XSS.

Lethani.

 

Lethani

Hola! Soy el admin ;)

Esta entrada tiene 5 comentarios

  1. P03t4

    hola no me dices como evitar ataques 🙂

    1. Lethani

      Buenas! Es cierto. Para evitar ataques de inyección XSS, se recomienda escanear todas las entradas de datos del sitio web adecuadamente en busca de scripts con contenido potencialmente maliciosos. Las medidas de protección general contra XSS incluyen validar todas las entradas de usuario para secuencias de caracteres que puedan ser potencialmente ataques XSS. El método más destacado es tener una lista blanca con todos los caracteres permitidos en cada uno de los campos de entrada. Esta acción debe restringir el rango de caracteres que puede introducir el usuario a sólo aquellos que sean necesarios para cada campo. Al hacer esto, la lista prohibiría los caracteres especiales que se utilizan para realizar scripting (por ejemplo < > ( ) / % # @ etc). Mientras que el enfoque de la lista blanca es la defensa más efectiva para evitar el cross-site scripting, no es práctico para ciertas aplicaciones o campos en los que esos caracteres pueden ser necesarios.
      Un método menos efectivo es implementar una lista negra de caracteres “malignos” que conozcamos, de esa forma ciertos caracteres que sabemos que se utilizan en alguna parte del lenguaje de scripting son eliminados de la cadena de entrada del usuario. Como mínimo, caracteres como < > y / deben ser eliminados de cualquier entrada de usuario y reemplazados por su equivalente código HTML. Los lenguajes más comunes incluyen funciones para facilitar la codificación de cadenas. El enfoque de la lista negra es menos efectivo porque este filtro puede ser evadido utilizando combinaciones de caracteres extraños de distintos esquemas de codificación, y nuevas técnicas y ataques contra las listas negras aparecen diariamente.
      Además se recomienda evitar volver a mostrar en los mensajes de error la entrada del usuario y la codificación de la salida cuando se renderiza el contenido del parámetro en las respuestas del servidor.

      Espero que te haya servido 🙂

  2. Jonathan

    Me gustaría aportar y ayudar a crear contenido para tu WEB, puedo?

Deja una respuesta