JScape

Explicación

Instrucciones: Para completar cada nivel es necesario ejecutar el código "alert(document.cookie)".

Filtro
        

Campo manipulable

Html


            

Log


          
Web Page

Bienvenido

El objetivo de este sistema es mostrar los vectores que se utilizan para generar un ataque tipo XSS. Al avanzar de nivel podrás utilizar el botón de ayuda para obtener información que te permita evadir los filtros. Si estás leyendo esto por curiosidad es buen momento para empezar con el primer reto. Si no tienes ni idea de que es lo que se debe hacer continúa leyendo esta guía, y si haz logrado superarlo nunca esta de mas repasar los conceptos básicos.

¿Los ataques XSS representan un peligro real?

Antes de empezar con una explicación del tema quisiera mencionar las implicaciones e impactos que pueden tener estos ataques con dos simples ejemplos. Mediante un ataque XSS se comprometio un servidor de la Fundación Apache. Utilizando XSS se logró obtener las credenciales administrativas del foro de Ubuntu, lo cual significo el robo de la información de 1.82 millones de usuarios. En conclusión: Si, los ataques XSS pueden ser muy peligrosos.

¿Qué es XSS?

El sicrónimo XSS significa Cross-Site Scripting (la X inicial se utiliza en lugar de la C para evitar confusión con las hojas de estilo CSS). Mediante este tipo de ataques se inyecta código en las páginas web vistas por los usuarios. Las posibles consecuencias van desde un simple Deface (modificación de la página) hasta el robo de credenciales administrativas.
Al principio puede parecer inofensivo el hecho de inyectar código que genere alerts, sin embargo mediante Javascript se puede cargar un recurso externo (imagenes, páginas, audios) desde una URL formada maliciosamente de la forma www.sitiomaligno.net/ruta-maliciosa/script.ext?info_leak=document.cookie o cuyo contenido sirva para explotar otras vulnerabilidades como una película en Flash o, antes de que se eliminara el soporte, un applet en Java. Otra forma de aprovechar estas vulnerabilidades es generar un popup en HTML que pida el usuario y la contraseña para continuar usando la página, ataque al que la mayoria de los usuarios son susceptibles ya que confian en la petición por originarse en la misma página.
La forma en la que se puede abusar de una aplicación una vez que se logra inyectar código está limitada únicamente por la creatividad y existen frameworks como BeEF que proveen una gran cantidad de funcionalidades.

Los ataques de tipo XSS se generan cuando el sistema no verifica la información que obtiene por parte de los usuarios y se clasifican de la siguiente forma:

Las primeras dos clasificaciones se refieran a la forma en la que el vector XSS llega a un usuario. En un XSS reflejado el usuario debe mandar el código para que este se ejecute. Para lograr explotar esta vulnerabilidad se necesita de un punto intermedio como un link apuntando a la URL modificada o un form en páginas que no utilizan prevención de CSRF. Debido a la interacción con el usuario este tipo de ataques se consideran de baja peligrosidad. Un XSS almacenado se da cuando la información se guarda con la finalidad de presentarla posteriormente. Este tipo de ataques se puede dar en foros o muros de publicación, donde se utilizan muchos campos introducidos por los usuarios como el nombre, el mensaje, la firma y otros elementos personalisables. Una vez que la información se guarda lo único que se necesita es que los usuarios observen la página donde se generó el ataque, por lo que el nivel de riesgo de este tipo es alto, a diferencia del reflejado, ya que no requiere ningun tipo de interacción. Por último se encuentran los ataques basados en DOM. Bajo esta clasificación se reunen los ataques en los que la vulnerabilidad se encuentra dentro del propio código en el cliente. En los ejemplos anteriores el código malicioso es enviado al servidor y al hacer la petición el servidor envia la página con la inyección. En un ataque al DOM la información no llega al servidor. Este tipo de ataques se generan cuando se rompe alguna función escrita en Javascript y se logra inyectar código dentro de la aplicación. A lo largo de estos ejercicios todos los ataques pueden ser clasificados como ataques al DOM, sin embargo las técnicas empleadas pueden implementarse en lenguajes como PHP, ASP.Net y otros, por lo que los vectores también pueden utilizarse para evitar filtros y generar un ataque de tipo reflejado o almacenado.

Inyección de Código

¿De que forma se logra inyectar código en una página? La forma más común es mediante Javascript. Este es un lenguaje interpretado en el navegador que permite implementar funcionalidades en el sitio para que sea dinámico e interactivo. Un vector muy famoso para verificar la existencia de problemas es: <script>alert('Mensaje XSS')</script>. Una vez que el código se ha inyectado se observa una ventana con el mensaje. Este vector se utiliza para fines de PoC, ya que no puede utilizarse para realizar ataques pero muestra la existencia de la vulnerabilidad. Otra opción menos llamativa es mediante el uso de la función console.log('Mensaje XSS') que registra el mensaje en la consola de Javascript (accesible en cualquier navegador moderno).

Saneando las variables

Una forma de prevenir estos ataques es usando filtros que sanean las variables, eliminando asi las partes peligrosas de la información y guardando las partes seguras, sin embargo estos filtros pueden evitarse. El objectivo de estos retos es mostrar las formas en las que los filtros fallan. Los niveles aumentan su dificultad de forma progresiva y aunque el saneado se implementa en Javascript algunas de estas técnicas se implemetan en otros lenguajes y sistemas IDS, por lo que el potencial de ataque de los vectores es muy grande.

En este primer nivel el filtro utilizado muestra el problema de los lenguajes interpretados como Javascript. Al utilizar las dobles comilla para delimitar el texto se corre un peligro: la concatenación de variables permite terminar la cadena de texto e inyectar código.
Utilizando una variable con dobles comillas como variable = '");otraFuncion("argumento' el interprete convierte la expresión texto = 'funcion("' + variable + ")' en texto = 'funcion("");otraFuncion("argumento")'. Dependiendo del contexto la ejecución del código puede fallar ya que cada sentencia, menos la última donde esto es opcional, debe terminar en ;. Añadir ; es una forma de evitar errores en tiempo de ejecución. Otra forma de garantizar la ejecución del codigo es insertando // o /* al final para que todo el código restante sea interpretado como un comentario y no se genere ningún error.
Esta información y un conocimiento básico de Javascript debe ser suficiente para completar este nivel.

Referencias

Entrada en Wikipedia
CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The Browser Exploitation Framework Project

Inyección HTML

La primer inyección abusa la forma en que se interpreta el código Javascript, sin embargo las inyecciones más básicas hacen uso de inyecciones HTML. Un sistema que imprime de forma directa cualquier cosa que se introduzca tiene un gran fallo de seguridad. Aunque actualmente es dificil encontrar un sistema que haga esto, fue de esta forma que comenzaron los ataques XSS y aún es una practica común enviar código HTML para observar la forma en la que se procesa. Observar la página una vez procesada nos permite deducir como se sanean las variables.

Tratar de imprimir en pantalla <b>"Negritas'<b> permite obtener una gran cantidad de información en el procesamiento del texto sin generar sospechas. La respuesta puede eliminar las comillas, codificar los carácteres especiales o, si existe un fallo grave, imprimir el texto en negritas. En el última caso estamos frente a una inyección de HTML lo que nos permite introducir cualquier script que deseemos e incluso cambiar completamente la página.

Escape con regex

El término "escape" se refiere a cambiar caracteres especiales por caracteres seguros. Esto se consigue al cambiar la codificación o haciendo que el compilador no los interprete. Una de las formas habituales de escapar carácteres es buscarlos mediante expresiones regulares y sustituirlos.

En JavaScript la función string.replace() acepta como argumentos una expresión regular y la sustitución. Las expresiones regulares son de la forma /RegExp/flags. El mayor riesgo que se corre es tener una expresión regular que no sea capaz de escapar las expresiones malformadas. Entre los parámetros mas importantes que se deben incluir en estas expresiones se encuentra la flag g que indica una busqueda global. Si esta bandera no se encuentra activada el remplazo termina en la primer coincidencia y nuestro filtro se vuelve inservible.

Mito Popular #1

Existe el mito popular de que eliminar los carácteres ",< y > evita ataques XSS. Aunque existen ataques más sofisticados que contradicen el mito con este ejemplo se demuestra lo sencillo que es introducir fallas de seguridad cuando no se tiene el cuidado necesario.

Inyección de HTML 2

Mientras que en el primer ejercicio cambiamos la ejecución del código al introducir dobles comillas (") y en el segundo incluimos código HTML de forma directa, este es un nivel que combina ambos conceptos. La expresión regular elimina las dobles comillas de forma segura, sin embargo podemos incluir < y >. ¿Qué riesgo representan estos carácteres? Para terminar la ejecución del JavaScript podemos hacer una acción muy simple: terminar la etiqueta HTML. Si queremos ejecutar código y emplear cadenas de texto podemos utilizar las comillas simples (') en lugar de las comillas dobles. De esta manera vencemos al filtro.