Cerrar panel

Cerrar panel

Cerrar panel

Cerrar panel

Ciberseguridad 11 may 2018

Detectando comportamientos maliciosos en el navegador

En este artículo explicamos cómo incluir seguridad en el navegador y poder monitorizar en tiempo real ataques dirigidos al cliente y que son muy complicados de controlar en el servidor.

ordenador-movil-navegador-bbva

Introducción

En el ámbito de la seguridad informática aplicada a entornos web es ampliamente aceptado que el lado del cliente es un entorno hostil. Los equipos de ingeniería y arquitectura de sistemas centramos nuestros esfuerzos en robustecer de puertas para dentro protegiendo "lo nuestro": delimitamos las redes, aplicamos reglas de control de acceso, monitorizamos su uso y le asignamos alertas asociadas a acciones de respuesta automáticas o manuales según criterios de criticidad, pero… ¿y de cara al lado del cliente?

¿Qué sucede en el lado del cliente?

Exactamente lo mismo: es un entorno vivo. Un navegador web o aplicación móvil es comúnmente la puerta de entrada por la cual disfruta el cliente de nuestros servicios. Las piezas de terceros que componen tanto navegador como sistema operativo en el cliente están en contínua evolución.

Nuevas vulnerabilidades, así como tipos de ataques, aparecen cada día y pueden dejar expuestos a nuestros clientes y conseguir acceder a información de su PC o incluso operar en su nombre, generalmente, sin que sean conscientes de que ha sucedido.

Cabe destacar que, añadido a la cantidad de piezas de software modificadas e instaladas diariamente, los sistemas de cliente suelen estar menos protegidos que los entornos de servidores corporativos. Esta circunstancia hace que tengamos que permanecer en estado de alerta y seguir con una estrategia de monitorización activa para asegurar la buena salud de nuestro sistema, así como cuidar de los usuarios usen nuestro sistemas.

Ataques tan habituales como un Cross Site Scripting (XSS) o un Clickjacking (que tratamos más abajo) en los que el usuario está expuesto a que su navegador ejecute un programa o código malicioso sin que éste sea consciente de ello, no siempre pueden ser mitigados solamente de parte del servidor. Sería útil poder "cuidar" a los usuarios más allá de nuestras fronteras.

Como veremos a continuación, para cada ataque hay una estrategia de defensa y cada defensa es susceptible de ser puesta a prueba. Los "malos" son buenos buscando resquicios por donde echar nuestra estrategia abajo. Nuestra misión será por tanto mantener el sistema robusto e intentar saber cuándo están intentando romperlo, tratando de lidiar con este juego del “ratón y el gato”.

Felisa

Muchos de los ataques más comunes pueden ser mitigados aplicando defensas centradas en la parte servidor, securizando los accesos o mejorando los sistemas de filtrado.

Desde BBVA Labs quisimos ir un poco más allá realizando un estudio sobre las posibles defensas en el lado del cliente de forma que pudieran ayudarnos a robustecer el conjunto de la solución completa: servidor + cliente.

Siguiendo con nuestra filosofía de empezar pequeño e iterar en base a los resultados obtenidos, decidimos comenzar por el navegador web y ver cómo podríamos proteger o, al menos, ser capaces de alertar de un uso indebido o sospechoso en el navegador del cliente. A este experimento lo llamamos Felisa: Frontend Layer Inspector for Security Alerts y que, internamente, representamos con el dibujo de esta simpática señora:

Jugando al gato y al ratón

Como decíamos al comienzo del artículo, el lado del cliente es un entorno hostil para la seguridad informática. Un sistema donde nuestro software corre con unos permisos limitados y donde va a convivir con infinidad de configuraciones y piezas de software de terceros que pueden alterar el funcionamiento del mismo. Si nosotros integramos una pieza defensora nada impide a otra pieza atacante encontrarnos y bloquear nuestra funcionalidad. Una vez que sepamos que nos están bloqueando buscaríamos otro método de escondernos entre el código y hacernos más indetectables y el atacante contra atacaría con una nueva versión y así hasta hacerlo tan tedioso que deje de ser rentable para el atacante invertir su tiempo para saltarse los controles.

Por esta razón creamos Felisa con las siguientes premisas:

  1. Desde el primer momento no buscamos el crear un sistema infalible que protegiera al cliente de un uso indebido (somos conscientes que eso es imposible) sino únicamente proporcionar una herramienta configurable y extensible mediante plugins que ayude a monitorizar y alertar lo que sucede en las aplicaciones que lo integren.
  2. Teníamos también claro que no queríamos hacer una herramienta distribuible que tuviera que instalarse cada usuario a modo de extensión de navegador sino que tendría que quedar integrada en el software que desplegamos que quiera disponer de esta funcionalidad.
  3. Establecimos, además, dos requisitos extras: tenía que ser liviana tanto en descarga como en consumo de CPU u otros recursos. No podíamos transformarnos en una pesada librería que ralentizara nuestras aplicaciones o que empeorase la experiencia de usuario, ya que sería peor la solución que el problema.

OWASP Top 10 y los peligros en el navegador

Para los que estéis menos familiarizados con la seguridad informática, OWASP se corresponde con las siglas de Open Web Application Security Project, que es un proyecto de carácter abierto y colaborativo dedicado a identificar, combatir y mitigar las causas que hacen que el software sea inseguro. La Fundación OWASP es un organismo sin ánimo de lucro que apoya y gestiona los proyectos e infraestructura de OWASP.

Nuestra primera tarea fue, por tanto, acudir al muro de la "fama" que publican cada año con el TOP 10 de los ataques más frecuentes y de, esta forma, identificar cuál o cuáles podrían ser interesante trabajar para nuestro MVP.

Algunos de los peligros en el navegador

Si tuviéramos una aplicación web vulnerable a ataques en el cliente, un atacante podría elegir entre un ámplio catálogo de ataques que llevar a cabo:

Desde...

La simple ejecución en tu navegador un inocente cuadro de alerta con un mensaje más o menos molesto,

Hasta...

La inyección de una completa suite de control remoto (command-and-control), usando la aplicación vulnerable como puente para llegar hasta el navegador y ponerlo en un estado que se conoce como "man in the browser", con la que el atacante podría hacer uso de tu sesión activa pudiendo llegar a:

  • Suplantarte y operar en la aplicación en tu nombre
  • Robar información sensible
  • Extraer contraseñas de tu password manager instalado en el navegador
  • Usar tu PC y tu navegador para atacar otros webs

Desde una aplicación web vulnerable un atacante podrá instalar un completo panel de control con el que operar sobre todo nuestro sistema

Seguridad en extensiones del navegador

En la actualidad, todos los navegadores web proveen de sistemas de extensiones para que terceros puedan desarrollar piezas de software que amplíen la experiencia. Para ello cuentan con una serie de APIs entre las que destaca WebExtensions API por ser compatible con Google Chrome, Firefox y Edge.

Las extensiones desarrolladas bajo este estándar incluyen un fichero de texto plano con la configuración de la aplicación bajo el nombre de manifest.json.

En las versiones iniciales era posible acceder a estos datos con una consulta XHR simple al sistema local de archivos vía chrome-extension://{ID}/manifest.json así como cargando sus recursos asociados en etiquetas o evaluando el CSS que estas cargaban. Hoy en día, y por motivos de privacidad y seguridad, los navegadores han agregado una capa de protección extra haciendo inaccesibles estos recursos salvo que la propia extensión indique que están expuestos mediante el atributo "web_accesible_resource" contenido en el fichero manifest.json.

En la actualidad no es posible desde una aplicación web detectar si está instalada o no una extensión en el navegador cliente. Una posible estrategia sería recurrir a las mutaciones de DOM que genere dicha extensión y responder a ellas mediante las técnicas que explicamos anteriormente.

Objetivo de la investigación

Tras invertir tiempo en el estudio investigaciones existentes, papers relacionados y analizar estadísticas sobre diferentes ataques con troyanos bancarios, pusimos el foco en 3 de los tipos de ataques de uso frecuente: Clickjacking, Cross-Site Scripting (XSS) y Cross-Site Request Forgery (CSRF)

Clickjacking

Es una técnica habitual de los troyanos en la que se busca secuestrar los clics del usuario y ejecutar acciones en el navegador diferentes a las que él pretendía y a menudo sin que sea consciente de ello.

Lo más habitual es poner una imagen (o capa HTML) encima del contenido real donde queremos que el usuario haga click, entonces tratamos que el usuario, a través de algún tipo de engaño, a que haga click en la imagen que pusimos. En la siguiente imagen podéis haceros un poco mejor una idea del ataque:

Esta técnica suele usarse para campos en los formularios de una aplicación para extraer información que no estaba solicitada originalmente.

Cross-Site Scripting (XSS)

Es posiblemente el rey de los ataques en el navegador y pese a su peligrosidad, es una técnica conocida, ampliamente documentada y perfectamente mitigable.

Los ataques XSS se categorizan en 2 tipos: reflejados y almacenados

Reflejados (o Indirectos)

cuando se alteran cabeceras, mensajes o variables directamente en una URL o petición y estos hacen eco directamente en el navegador del usuario. Son ataques efímeros, pero no por ellos menos peligrosos.

Almacenados (o persistentes)

cuando se logra insertar código HTML o Javascript en un sistema de almacenamiento (un base de datos, por ejemplo). Cada vez que la información de la base de datos sea recuperado y mostrada el usuario, también se devolverá el ataque en sí.

Como ejemplo de este ataque, imaginemos el siguiente escenario: si logramos introducir un código Javascript como parte de nombre del usuario y esta información es almacenada en la base de datos del perfil del usuario, cada vez que muestre en el navegador el nombre de éste, también será ejecutado el código de Javascript.

El proceso en ambos casos precisa de una mala configuración de políticas de seguridad o un incorrecto filtrado de los valores de entrada a la aplicación: tanto en el cliente como en el servidor, pero una vez traspasada la puerta… se abre un mundo de posibilidades para el atacante.

Cross-Site Request Forgery (CSRF)

A menudo veremos esta técnica va de la mano de un phishing o de algún tipo de artimaña para engañar a la víctima y que "pique" en el anzuelo, accediendo al contenido que el atacante le envía.

El objetivo de este ataque es ejecutar una operación en el servidor aprovechando que el usuario tiene una sesión activa en el mismo. El atacante, también podría alterar los datos enviados en la petición al servidor: agregarle cabeceras HTTP o forzar a que la cookie sea válida, si fuera necesario.

Para explicar mejor cómo funciona esta técnica, podemos ver la siguiente figura:

Modos detección: entrada en juego de Felisa

Existen diferentes estrategias que se pueden adoptar para evitar los ataques CSRF:

  • mediante el sincronizado de tokens cifrados,
  • activando políticas de acceso a recursos en el servidor
  • y otra serie de técnicas que vienen recopiladas al detalle en la propia web de OWASP

En este experimento, como ya os adelantamos, buscamos únicamente explorar el comportamiento inusual y el poder reportarlo. Lo que se conoce habitualmente con el término de WUA por el inglés Web Under Analysis.

Método 1: Monitorización del objeto XMLHTTPRequest

A pesar de su nombre, el objeto XMLHTTPRequest (abreviado como XHR), puede ser utilizado para recibir cualquier tipo de formato de respuesta, como son: texto plano, binario, JSON o por supuesto XML.

En JavaScript se nos da la opción de alterar el comportamiento base de un objeto sobrescribiendo la funcionalidad de su prototype con nuevo código y en este caso lo vamos a aplicar al método send.

En el siguiente ejemplo le pasaremos una función que responderá a los diferentes estados del objeto XHR:

0 - Sin inicializar, todavía no se ha llamado a open()
1 - Cargando, todavía no se ha llamado a send()
2 - Cargado, se ha invocado send y las cabeceras y estado están disponibles
3 - Interactivo, responseText tiene información parcial
4 - Completado, la operación ha terminado

En el código mostrado esperamos a la llamada del DOMContentLoaded para inyectarle un interceptador a las peticiones de nuestra aplicación web y las mostramos por consola local.

Aprovechando este sencillo sistema podemos reportar todo el tráfico de nuestra web a un servidor externo que aplique una lógica sobre ello o, incluso, aplicar una lógica de protección en cliente que interrumpiera la salida de las peticiones que no estén en nuestra lista de URLs de confianza.

Como hemos dicho con anterioridad, si el atacante percibe que estamos bloqueando la salida de sus peticiones hacia su servidor malicioso, nada le impide investigar nuestro modo de interceptación y eludir nuestro sistema usando el mismo método.

Aplicación en la prevención del Clickjacking

En una primera aproximación se nos podría ocurrir que la forma adecuada de evitar el clickjacking es evaluando si lo que está viendo el cliente es lo mismo que acordamos mandarle haciendo una comprobación de CSS con soluciones como PhantomCSS o directamente contrastando la imagen generada frente a una imagen almacenada con anterioridad y comprando los píxeles de ambas imágenes tratando de encontrar diferencias con un rango de tolerancia que podemos establecer:

Como rápidamente deduciréis, esta aproximación implicaría no sólo el consumo de recursos y CPU necesario para procesar las imágenes en busca de diferencias, si no también la descarga de la imagen esperada. Eso sin contar la generación de las diferentes imágenes de contrato.

Descartada esta opción llegamos a la solución más sencilla: notificar si estamos contenidos en un iframe.

La técnica de clickjacking se basa precisamente en cargar una web vía iframe con opacidad cero encima de nuestra web original para que cuando vayamos a hacer clic en nuestra aplicación, pasemos antes por la suya. Si evaluamos que nuestro documento raíz sea window sabremos si estamos embebidos en un iframe.

En la actualidad contamos con la directiva X-Frame-Options para habilitar políticas de control de acceso y evitar así que puedan cargar nuestro site incrustado en un iframe desde otros dominios pero no está de más tener activada esta notificación que nos alertaría si un cambio en el servidor ha dejado sin efecto dicha política.

Aplicación en la prevención del explotado de vulnerabilidades del navegador

Hemos visto unos controles básicos para detectar manipulaciones sencillas pero teníamos la amenaza de que un atacante explotara una vulnerabilidad de nuestro navegador y consiguiera así enviar código javascript al cliente.

De nuevo la W3C nos dota de mecanismos para hacer frente a estas manipulaciones de Scripts y DOM mediante dos características:Mutation Observer y SubResource Integrity (SRI).

En la imagen superior hacemos uso del objeto MutationObserver para monitorizar y aplicar acciones sobre los cambios efectuados en nuestro DOM. En el ejemplo monitorizaremos cambios en sus atributos, elementos hijos, elementos de texto y recursivo en cascada.

Con la característica SubResource Integrtiy nos aseguramos además que nuestro script está sellado con un hash de integridad y no ha sido alterado. Si el navegador detecta cualquier inconsistencia lo bloqueará y no iniciará su ejecución.

Para crear el hash de integridad bastará con ejecutar un simple comando en nuestra consola:

Esta funcionalidad del navegador está presente en las últimas versiones de la mayoría de los navegadores actuales y en el caso de que no cuente con esta feature, ignorará los atributos integrity y crossorigin y no romperá la ejecución del mismo.

En la siguiente figura podemos los navegadores soportados:

Conclusiones y próximos pasos

Como conclusiones sacadas de nuestra investigación destacar que pese a las comentadas limitaciones de ejecución para implementar defensas efectivas, si tenemos suficiente ámbito de actuación como para poder notificar información relevante.

Con los datos extraídos podemos enriquecer los del servidor y alimentar un sistema de alertas por reglas tan complejo como queramos implementar o incluso implementar un sistema de machine learning sobre esa fuente de datos para que nos reporte patrones irregulares y anomalías en el comportamiento del usuario o del sistema.

Se implementar multitud de técnicas para hacer cada vez menos rentable para el atacante saltarse nuestras medidas de seguridad mediante:

  • Operaciones de ofuscación del código,
  • Cifrado en cliente,
  • Implementando sistemas RASP (Runtime Application Self-Protection) para evitar que puedan alteren nuestro código en vivo
  • O jugando con nuevas características del navegador cómo usar partes del código compilado mediante WebAssembly.

Un nuevo mundo de posibilidades al servicio de la detección temprana y una interesante línea de trabajo.