Múltiples vulnerabilidades del kernel que afectan a todos los dispositivos de Qualcomm

Múltiples vulnerabilidades del kernel que afectan a todos los dispositivos de Qualcomm

Hace ocho meses, el equipo de investigación de Zimperium (zLabs) reveló a Qualcomm dos vulnerabilidades del kernel que afectaban a todos Dispositivos Android con conjuntos de chips Qualcomm.

Estas vulnerabilidades, combinadas con otras vulnerabilidades descubiertas previamente por zLabs (CVE-2017-13253, CVE-2018-9411 y CVE-2018-9539) podría permitir que una aplicación maliciosa a la que no se le otorgó ningún permiso para lograr capacidades raíz completas. Los posibles efectos negativos para las empresas son muchos. Es decir, la aplicación podría realizar acciones como:

  • Leer todos los datos privados almacenados en el dispositivo, como fotos, videos, mensajes de texto (incluidas las aplicaciones de mensajería encriptada de extremo a extremo como WhatsApp o Telegram), archivos adjuntos de correo electrónico o prácticamente cualquier otra cosa que se te ocurra que esté en el dispositivo.
  • Obtener todas las credenciales para cualquier aplicación en la que el usuario haya iniciado sesión. Con el nombre de usuario y la contraseña, el atacante tiene acceso directo a valiosos datos personales o de la empresa.
  • Grabación de video/audio a través de la cámara y el micrófono sin el conocimiento del usuario.

Después de informar estas vulnerabilidades, Qualcomm designó CVE-2019-14040 y CVE-2019-14041 para ellas y publicó correcciones como parte de su boletín de seguridad de febrero.

En esta publicación de blog, repasaré los detalles técnicos de las dos vulnerabilidades. Los enlaces a la prueba de concepto para ambas vulnerabilidades están disponibles al final de la publicación del blog.

El controlador donde se encuentran las vulnerabilidades es QSEECOM, que significa QTI Secure Execution Environment Communicator. Este controlador permite que los procesos del espacio de usuario de Normal World se comuniquen con Secure World, también conocido como TrustZone. La API expuesta por el controlador consta de llamadas ioctl al /dev/qseecom dispositivo.

Si bien solo un conjunto de servicios privilegiados de Android tiene acceso a /dev/qseecomhe descrito múltiples vulnerabilidades que afectan a este tipo de servicios en anterior Blog publicaciones. Por lo tanto, esta publicación de blog es una continuación de estas publicaciones de blog anteriores y describe el siguiente paso para lograr privilegios completos del kernel.

Las vulnerabilidades en sí son:

  • CVE-2019-14041: una condición de carrera que puede causar todo tipo de daños en la memoria, según el lugar exacto en el que se produzca la carrera.
  • CVE-2019-14040: un uso posterior a la asignación de memoria del kernel.

Como la condición de carrera es menos confiable y puede causar resultados diferentes, creo que el uso después de libre es más interesante. Por lo tanto, voy a extenderme un poco más sobre el uso después de la vulnerabilidad libre.

El problema de la condición de carrera se deriva de una función: __qseecom_update_cmd_buf (y también su equivalente de 64 bits __qseecom_update_cmd_buf_64 que por el bien de la condición de carrera opera de la misma manera). En resumen, el propósito de esta función es actualizar un búfer destinado a ser enviado a TrustZone con punteros que TrustZone pueda entender.

Para evitar código duplicado la función está diseñada para manejar dos casos diferentes en los que se necesita modificar dichos búferes (desafortunadamente, no existe tal diseño para manejar casos de 64 bits; la función de 64 bits tiene mucha duplicación de código). Por lo tanto, se puede llegar a esta función desde dos ioctls completamente diferentes. La cuestión es que, en algunas partes, la función aún tiene que comportarse de manera diferente según el ioctl desde el que se llamó originalmente. Para ello, la función comprueba datos->tipo:

1684345669 641 Multiples vulnerabilidades del kernel que afectan a todos los dispositivos
fuente

Como puede verse, en un caso datos->tipo sería QSEECOM_CLIENT_APP. En el otro caso sería QSEECOM_LISTENER_SERVICE. Verificaciones como esta existen en toda la función.

el problema es que datos es en realidad un puntero a un qseecom_dev_handle estructura, que se adjunta a la abierta /dev/qseecom archivo en el que se está realizando ioctl. ¿Qué pasa si es posible modificar datos->tipo mientras __qseecom_update_cmd_buf ¿Esta corriendo?

1684345669 810 Multiples vulnerabilidades del kernel que afectan a todos los dispositivos
fuente

Resulta que ejecutar el ioctl QSEECOM_IOCTL_APP_LOADED_QUERY_REQ modifica instantáneamente datos->tipo! Aunque existen algunos mecanismos para limitar la ejecución simultánea de ioctls, solo entran en vigor después datos->tipo fue cambiado. Ejecutando este ioctl al mismo tiempo __qseecom_update_cmd_buf se está ejecutando provocaría una condición de carrera.

La función comenzará con un comportamiento que coincida con un datos->tipo de QSEECOM_LISTENER_SERVICE pero continuará con un comportamiento que coincide con un datos->tipo de QSEECOM_CLIENT_APP.

Esto puede causar diferentes tipos de corrupción de la memoria, dependiendo de dónde golpea exactamente la carrera. Si bien la mayoría de estos son relativamente inofensivos como una desreferencia NULL, algunas condiciones pueden causar un desbordamiento de búfer, lo que en realidad es peligroso y posiblemente se pueda explotar. Esa es la vulnerabilidad.

Información de contexto

Para permitir que los procesos del espacio de usuario de Normal World se comuniquen con TrustZone, el mecanismo de iones (la razón de esto, lamentablemente, está fuera del alcance de esta publicación de blog). En resumen, el mecanismo ION permite que los procesos del espacio de usuario asignen memoria de montones especiales que se comportan de manera diferente a otra memoria normal. Los procesos del espacio de usuario pueden mapearlo en su propio espacio de memoria y leer/escribir en él como deseen.

La forma en que ION trabaja con QSEECOM es que un abierto /dev/qseecom El archivo se puede hacer para hacer referencia a un búfer ION asignado. Entonces, el kernel sabe usar ese búfer para futuras comunicaciones con TrustZone. Si bien está destinado principalmente a que el proceso del espacio del usuario lea/escriba desde ese búfer ION, el núcleo mismo a veces también puede modificarlo (hecho por __qseecom_update_cmd_buf que se describió en el apartado anterior).

1684345670 380 Multiples vulnerabilidades del kernel que afectan a todos los dispositivos
fuente

El código anterior maneja una solicitud del espacio de usuario para hacer referencia a un búfer ION asignado. Como se puede ver, se guardan múltiples parámetros relacionados con el búfer ION, como un identificador y una asignación del mismo en el espacio del núcleo (datos es lo mismo que en la sección anterior, un puntero a una estructura que se adjunta a la abierta /dev/qseecom archivo).

1684345670 163 Multiples vulnerabilidades del kernel que afectan a todos los dispositivos
Cómo se ve el uso del búfer ION en QSEECOM

Una cosa a tener en cuenta es que cuando se libera el búfer ION, el identificador del kernel se establece en NULL:

1684345670 227 Multiples vulnerabilidades del kernel que afectan a todos los dispositivos
fuente
1684345670 571 Multiples vulnerabilidades del kernel que afectan a todos los dispositivos
Datos QSEECOM después de liberar el búfer ION

Este posible NULL se usa luego cuando se intenta usar el búfer ION del kernel. Se verifica que el identificador no sea NULL:

1684345671 283 Multiples vulnerabilidades del kernel que afectan a todos los dispositivos
fuente

Detalles de vulnerabilidad

Echemos un vistazo más de cerca al código que hace referencia a un búfer ION desde un /dev/qseecom archivo:

1684345672 896 Multiples vulnerabilidades del kernel que afectan a todos los dispositivos
fuente

Obviamente, este código no solo permite cualquier solicitud del espacio del usuario sin verificarlo primero. Hay varias comprobaciones a lo largo de esta función para verificar completamente la solicitud procedente del espacio del usuario. El cheque que se muestra en el código anterior es un ejemplo; si la longitud de la solicitud es mayor que la longitud del búfer ION (el Len variable), entonces la solicitud no es válida.

¡Sin embargo, el problema está exactamente en este cheque! ¿Qué pasaría con los parámetros en datos si la longitud de la solicitud es demasiado grande? Más importante aún, ¿qué pasaría si eso se abriera? /dev/qseecom ¿El archivo ya hacía referencia a un búfer ION antes pero se liberó?

1684345672 789 Multiples vulnerabilidades del kernel que afectan a todos los dispositivos
Datos QSEECOM después de que se libera el búfer ION y luego se recibe una solicitud con una longitud incorrecta

En este escenario, el identificador ya no sería NULL, pero el resto de los parámetros no se modificarán, por lo que apuntarán al búfer ION al que se hizo referencia anteriormente. Por ejemplo, sb_virt apuntaría a una asignación de memoria que ya estaba liberada. Todo esto es mientras los intentos de usar el búfer ION al que se hace referencia desde el kernel deberían funcionar, ya que, nuevamente, el identificador ya no es NULL. Este es el uso después de gratis! Al intentar usar el búfer ION, el núcleo modificará una asignación de memoria que ya estaba liberada.

Estas vulnerabilidades podrían permitir que un atacante alcance todos los privilegios de root/kernel. Especialmente el uso después de libre, ya que es mucho más confiable que la condición de carrera. Como se mencionó en la introducción, esta publicación de blog es esencialmente una continuación de un conjunto anterior de publicaciones de blog que describen vulnerabilidades en servicios privilegiados de Android. En teoría, podría ser posible que un atacante sin privilegios creara una cadena a partir de estas vulnerabilidades para lograr privilegios de root completos.

El código fuente completo para PoC para ambas vulnerabilidades está disponible en GitHub:

  • 31 de julio de 2019: vulnerabilidades descubiertas
  • 4 de agosto de 2019: detalles de vulnerabilidades + PoC enviados a Qualcomm
  • 4 de noviembre de 2019: Qualcomm dice que envió parches a los proveedores
  • 3 de febrero de 2020: Qualcomm publicó un boletín de seguridad
  • 3 de marzo de 2020: Samsung distribuyó correcciones como parte de su actualización de seguridad de marzo
  • 6 de abril de 2020: Google distribuyó correcciones como parte de su actualización de seguridad de abril

Si tiene alguna pregunta, puede enviarme un mensaje privado en Twitter (@tamir_zb). Para obtener más información sobre cómo Zimperium brinda protección contra dispositivos, redes, phishing y ataques de aplicaciones maliciosas, por favor Contáctenos.

Deja un comentario