Intercambio de datos entre páginas: SOP, CORS y WebMessage (y II)

miércoles, 29 de enero de 2014

Los navegadores son las aplicaciones más usadas por los usuarios a causa del desplazamiento del escritorio "a la nube" y por la grandes posibilidades que abarcan. La creciente complejidad del navegador ha permitido potenciar sus funcionalidades y (en consecuencia) aumentar los problemas de seguridad y su criticidad. Pero además, ha exigido nuevos métodos de intercambio de información y protocolos. Veamos algunos.


En el desarrollo web actual se pueden llegar a realizar múltiples peticiones AJAX a distintos componentes de la aplicación, como pueden ser gráficas que reciben JSON o un componente de login externoPuesto que SOP puede llegar a ser una política demasiado restrictiva para satisfacer esta demanda en algunos casos, la tecnología CORS nace como solución para compartir recursos con otros dominios sin llegar a poner en peligro la integridad de la información que manejan... siempre y cuando se implementen correctamente.


Usando CORS, se pueden realizar peticiones a otros dominios, como b.com. Fuente: http://linuxism.tistory.com/732
Cross Origin Sharing Resource (CORS) permite al navegador realizar una petición web a otro dominio que no cumpla con la política SOP siempre y cuando el dominio destino agregue la cabecera Access-Control-Allow-Origin, especificando a qué orígenes permite la petición. Por ejemplo:


Access-Control-Allow-Origin: http://www.dominio-tercero.com

Con apenas unas líneas, el navegador será capaz de realizar una petición XMLHttpRequest. Se observa cómo el flag Access-Control entra en juego:

Código JavaScript para realizar una petición XMLHttpRequest
En caso de que el servidor no responda con la cabecera Access-Control-Allow-Origin esperada, el navegador impedirá realizar la petición lanzando una excepción:

Chrome rechaza la petición XMLHttpRequest por no incluir el dominio destino la cabecera Access-Control-Allow-Origin
Por el contrario, si contiene la cabecera Access-Control-Allow-Origin, el código JavaScript obtendrá la respuesta en HTML o XML dependiendo del formato y continuará su ejecución. Como medida de seguridad, también es destacable que la cookie de sesión no se incluirá en la petición si el servidor no añade explícitamente la cabecera Access-Control-Allow-Credentials. De este modo, a menos que el servidor indique expresamente que quiere compartir sus recursos, el navegador no lo permitirá. Por otro lado los dominios que implementen esta funcionalidad añadiendo la cabecera Access-Control-Allow-Origin, permitirán al atacante leer el contenido de la página (lo que implica que además podrá evadir los Anti-Forgery Token que pueda contener la web).

Un posible ataque

Un escenario de ataque en el que el atacante obtuviese el contenido de una web interna y lo reportase, sería el siguiente:

Diagrama funcional de un posible ataque. Fuente: http://application-aegis.blogspot.com.es/2012/06/html5-feature-cross-origin-resource.html

El escenario consta de un servidor web interno que tiene habilitada la cabecera Access-Control-Allow-Origin a cualquier dominio representado con el asterisco (*), y una web atacante a la que el usuario accederá.

Una vez el usuario accede al sitio web del atacante, este incluirá una porción de código JavaScript que se ejecutará y provocará una petición XMLHttpRequest al servidor interno:


Código malicioso del atacante
Tras obtener el contenido de la petición, el JavaScript realizará una petición POST al sitio del atacante incluyendo el contenido de la web interna para almacenarlo en el servidor.

Por otro lado, Access-Control-Allow-Origin también permitiría evadir los Anti-Forgery Token. Este impedirá que un atacante pudiese forzar una acción en la web, sin que el usuario se diese cuenta.

Gracias a que CORS comparte el contenido de la página, se podría montar la otra web en un contenedor o un IFRAME y obtener el token haciendo una consulta al árbol DOM o filtrando por expresiones regulares:

Código para obtener el token de verificación
En este caso imprimimos el token, aunque podría usarse para formar una petición con parámetros y con ello ejecutar una acción:
Muestra del token de verificación
CORS es una forma de intercambiar información entre dominios, y esta funcionalidad abre otro vector para permitir que CORS pueda ser utilizado como puerta trasera para enviar información fuera de un dominio. Por ejemplo, en el caso de la existencia de un XSS, podría enviar la cookie de sesión para realizar un hijacking. Sería un comportamiento similar a lo que se ha dado en llamar shell of the future.

En cualquier caso CORS no es la única manera de intercambiar información entre dominios, pues con HTML 5 aparecen más formas que facilitan esta tarea y así nuevos vectores de ataque.

WebMessage

Otra forma de comunicarse entre dominios es WebMessage  que permite mandar y recibir mensajes mediante JavaScript sin necesidad de incluir una cabecera. Para usar esta funcionalidad basta con indicarlo en el JavaScript del "servidor" que recibirá el mensaje con un manejador de eventos y en la parte cliente que enviará el mensaje:

Código JavaScript del servidor para recibir para e imprimir el mensaje
Código JavaScript para enviar el mensaje


Es importante tener en cuenta de que en caso de que el "servidor" no maneje los mensajes, estos nunca llegarán.

Al necesitar un manejador explícito para usar WebMessage no se implementa SOP directamente, por lo que es importante comprobar el origen del cliente, porque si el servidor no comprueba el origen en su lógica, podría ser usado (y abusado) por otros dominios.

Además también es importante comprobar el contenido enviado por el usuario porque podría ser un vector de ataque para realizar un XSS a través de WebMessage:

Ejemplo de XSS preparado con WebMessage


Intercambio de datos entre páginas: SOP, CORS y WebMessage (I)
Oscar Sánchez
oscar.sanchez@11paths.com

No hay comentarios:

Publicar un comentario en la entrada