03 octubre 2011

Pimp my android


Introducción

Hace unos días tuve la oportunidad de asistir a la NCN para dar una charla sobre Android, donde se trataron temas sobre cómo hacer un reversing de las aplicaciones, análisis forenses, o saltarse las protecciones del market entre otros temas.

Una de las sorpresas que preparamos entre mi colega @Ehooo y yo, fue una demostración en directo de una vulnerabilidad que permitía realizar TapJacking en el teléfono.

Para los que no pudisteis asistir, os dejo sobre estas líneas los detalles del mismo y su funcionamiento. Y por si buscas el material de la misma:
Un poco de historia

El 21/05/10 el grupo de investigadores de la conocida firma Lookout, alertaba sobre una vulnerabilidad que parecía afectar a todos los dispositivos Android en el mercado. Cualquier versión anterior a la 2.3 (Que estaba a punto de ver la luz) era vulnerable a todos los efectos.
Tras presentar una PoC se decidió reportar la vulnerabilidad a Google y estos respondieron con una actualización para Gingerbread (v2.3) en la que decían haber corregido el problema (esto fue el 06/12/10, casi 7 meses después de avisar de la misma).
Nosotros movidos por la curiosidad decidimos diseñar un nuevo PoC para comprobar si efectivamente estaba corregido y nos llevamos una sorpresa (aunque conociendo el historial de Google, tampoco fue tan grande).

¿Qué se hizo?

El resultado fue montar una pequeña aplicación que mostraba al usuario una imagen en determinadas coordenadas, con el objetivo de incitarle a pulsar en la pantalla y realizar acciones sin su consentimiento que de otra manera hubieran sido imposibles.
En nuestro caso la PoC contenía acciones para realizar llamadas de teléfono, enviar SMS, instalar aplicaciones del Market, formatear el dispositivo. Pero se podrían haber desarrollado otras para obligar a pulsar en bloques de publicidad, realizar transferencias bancarias, o hacer un robo de credenciales.

¿Cómo funciona la vulnerabilidad?

Gracias al modelo de confianza implementado en Android, es posible que una aplicación abra un diálogo (p.e. para cambiar determinadas opciones de configuración, instalar widgets, cambiar el fondo de pantalla, etc.) para que el usuario realice una acción que por sí misma no puede ser realizada directamente por la aplicación por falta de permisos. De esta forma se intenta evitar peligros como la escalada de privilegios.


Pero esto puede ser aprovechado por una aplicación maliciosa para abrir diálogos (p.e. formatear el dispositivo) y superponer una capa opaca que se encargue de recibir las pulsaciones realizadas por el usuario y pase estos eventos a la capa situada por debajo. De forma que el usuario crea que está interactuando con la capa superior cuando no es así.

Si bien los diálogos normales de Android, llamados “Activities” no permiten hacer esto, Android pone a disposición de los desarrolladores una clase especial de diálogos llamada “Toasts” que permiten superponer la actividad actual mientras pasan los eventos a capas inferiores. Siendo usados para comunicar pequeños mensajes al usuario, pueden ser modificados para que ocupen la totalidad de la pantalla utilizando una interfaz específica definida por el desarrollador, de esta forma se facilita la tarea de engañar al usuario.

El único problema en todo esto es el tiempo de vida que tiene un “Toast” que tras 3 segundos, desaparece y la actividad en la capa inferior vuelve a pasar a un primer plano, por lo que es necesario estar constantemente refrescando la pantalla para evitar que esto suceda.

La clave está en conseguir que el tiempo de refresco sea lo mínimo posible para que el usuario no sea consciente en ningún momento del engaño.

En la versión 2.3 del SDK habilitaron una subclase de la clase vista que heredaba el método setFIlterTouchesWhenObscuredMethod , de forma que al colocarlo en tu objeto vista pudieras prevenir cualquier tipo de interacción cuando se intente colocar una capa por encima. Aunque se debe tener presente que si se activa esta “medida de seguridad” evitaremos que los eventos de una vista reciban las interacciones de los eventos que se produzcan cuando se muestre un “Toast” por pantalla, así que debes de tener cuidado y usarlo conscientemente.

Para que veáis cómo quedaría, sería tal que así;
El problema de esto es que Google no lo ha activado por defecto. Por tanto (y en esto recalco que me baso en las declaraciones de Google) los usuarios con versiones anteriores a la 2.3 están desprotegidos, lo que viene siendo observando la cuota de mercado proporcionada por Google (Fragmentación de versiones) un 51.2% de los usuarios.

Dando ahora mi versión, es que un 98.6% de todos los teléfonos Android en el mercado (hasta la versión 2.3.4) que es hasta donde se probó el PoC son vulnerables (basándonos en un estudio realizado el 2 de Septiembre del 2011)
¿Cómo está estructurado el PoC?
La funcionalidad está dividida en los siguientes ficheros:
  • Main.java – Se encarga de crear y lanzar el servicio principal, y por cada payload tiene su correspondiente función para lanzarlo.
  • MalwarePayload.java – Abstracción interna realizada con el fin de facilitar la implementación de los payloads, de cara al usuario.
  • MalwareService.java – Crea el toast y se encarga de recoger las peticiones de ejecución para los payloads y lanzarlos, además de iniciar el proceso de tapjacking.
  • Main.xml – Definimos el layout principal de la aplicación, con un evento onClick asociado a cada payload para ejecutarlo.
Y los payloads definidos son los siguientes:
  • CallPayload.java – Realiza llamadas de teléfono al número indicado.
  • MarketPayload.java – Descarga una aplicación del market evitando mostrar al usuario la pantalla de permisos necesarios.
  • ResetPayload.java – Devuelve el teléfono al estado de fábrica.
  • SMSPayload.java – Envía un mensaje de texto al número indicado.
Otra de las cosas que se quisieron tener en cuenta a la hora de desarrollar el PoC, fue que al instalarlo no levantara sospechas de ningún tipo y por tanto evitar que usara permisos.

Si un usuario instala una aplicación para cambiar el fondo de pantalla y esta le solicita permisos para realizar una llamada, es probable que destape nuestra tapadera y se nos acabe el juego.

Así mismo la posibilidad de implementar cualquier payload diferente a los que se han usado de ejemplo es relativamente sencillo. Llamadas a números de tarificación especial, envío de SMS a números Premium, hacer un dump de la base de datos de las aplicaciones de Google para su posterior envío, son sólo algunos ejemplos.

Conclusión

Tras lo expuesto aquí, creo que una vez más queda destapada la importancia que Google le da a los problemas relacionados con Android.
Se me pasan por la cabeza las siguientes preguntas:
  • ¿Cómo es posible que siga funcionando una vulnerabilidad que ya corrigieron?
  • ¿Qué clase de medida de prevención son esas que decidieron? (¿A alguien más le parece una chapuza?).
  • ¿Cuánto tiempo es necesario que transcurra entre que se reporta una vulnerabilidad y se corrige?
  • ¿Son conscientes de todo esto?
Y uno de los principales problemas que va a seguir afectando a todo esto y que permitirá que el malware, las vulnerabilidades, los exploits, etc… sigan comiendo terreno es la multitudinaria fragmentación de versiones que existe.

Es imposible controlar en condiciones un fallo y liberar una actualización que lo solucione, porque hasta que llegue al usuario final, y esta sea adaptada por cada uno de los ISP que ofrecen servicios de telefonía para smartphones como Android, va un largo periodo de tiempo.

A la vista está la medida a la desesperada que se tomó cuando se sucedió el problema de que el tráfico viajaba en texto claro, con el consiguiente peligro que conllevaba realizar un ataque MiTM. Recordaréis que la solución fue totalmente imposible de implementar a nivel de usuario, debida a la fragmentación de versiones que existía en el mercado, y que la solución terminó siendo parchear a nivel de servidor, para que fuese este el que cifrase las conexiones que realizaba el dispositivo.

Son muy malas las gestiones que está realizando Google ante las incidencias que acaecen sobre Android, y esto sólo se traduce en un mal servicio y una falsa sensación de seguridad que se ofrece a los usuarios.

----------------

Contribución por Sebastián Guerrero

5 comments :

ehooo dijo...

Bajo mi punto de vista para que esto pueda ser marcado como parcheado, Google tendría que implentar en las aplicaciones que vienen con el sistema la llamada a la función 'setFIlterTouchesWhenObscuredMethod' o que el valor por defecto de esta sea "true"

Sebastián Guerrero Selma dijo...

Sí claro, en mi opinión la solución ofrecida por Google no sirve para proteger al usuario de primeras, una medida de protección que requiera del conocimiento previo por parte del usuario sobre cómo realizarla, no es una buena solución.

Debería de estar puesta a "true" por defecto. Y aun así me sigue pareciendo insuficiente, porque eso no evita que yo como usuario desarrolle una aplicación maliciosa y la cuelgue en el market, realizando infecciones a diestro y siniestro, robando tarjetas de crédito y demás. ¿Ofrece protección contra eso la solución propuesta por Google?

No. ¿Pero a quién le importa? ya estamos acostumbrados a este buen trato xDD.

Juan Aguilera dijo...

El gran problema que le veo yo es cómo hicísteis para hacer que no usara permisos. Como dices si me pide permisos para hacer llamadas en una aplicación que no lo requiere me mosqueo. Lo de la capa transparente no lo veo tan problemático. He sido programador de windows y ahí también se usa y me imagino que iOS y WP7 también lo permitirán.

Yo no trabajo en seguridad, pero el problema me parece el de los permisos. ¿Se me pasa algo?

Gracias!

errepunto dijo...

Entiendo que si pusieran esa opción a True, podrían romper una gran cantidad de aplicaciones que implementasen esa funcionalidad, ¿no es así?

Es un asunto peliagudo, y me temo que Google no tiene bien resuelto el asunto de las actualizaciones de seguridad, al parecer relegan parte de esa responsabilidad en el programador.

De todas formas, complicada solución le veo...

ehooo dijo...

Según entiendo yo la protección, actua evitando manda eventos a las capas inferiores, que se encuentren tapadas por una capa superior.

Con esto solucionas parcialmente el problema, dado que cuando se pone una capa encima los eventos no llegan a la inferior, ni son recibidos por la superior.

De este modo podría hacerse denegaciones de servicio si se pone una capa superpuesta, transparete, que el usuario no ve, pero evita que se envien las pulsaciones a las aplicaciones de abajo.

Yo entiendo que si proteges tu app con 'setFIlterTouchesWhenObscuredMethod' solo le llegarán las pulsaciones que se realizen sobre esa capa cuando está sobre todo, y cuando aparezca un Toast si pulsas sobre el no recibiras ningún evento.