Historial de parches de Apple

imagen


Este año, a1exdandy y yo hablamos en las conferencias de VolgaCTF y KazHackStan con una charla sobre los programas Patch Diffing escritos en Objective-C, y cómo usarlo para buscar y encontrar vulnerabilidades de 0 días y 1 día en productos Apple. Puede ver el video de la presentación aquí , y para leer el artículo, bienvenido a cat.


La Difusión Binaria es el proceso de comparar dos archivos ejecutables para encontrar similitudes y diferencias entre ellos. Patch Diffing es un caso especial de Binary Diffing cuando un archivo con vulnerabilidad se compara con un archivo fijo (archivo con un parche). Para que pueda averiguar qué correcciones ha realizado el desarrollador y comprender cuál fue la vulnerabilidad.


Hace unos años (es decir, en 2013), se publicó un artículo sobre Patch Diffing para programas de Windows, al que también echamos una mano. Le recomendamos que se familiarice con él si está interesado en este tema en relación con el sistema operativo Windows. En el mismo artículo hablaremos sobre el análisis de programas para Apple OS.


¿Cómo pueden ser útiles la Difusión Binaria y la Difusión de Parche?


La tarea principal de Binary Diffing es rastrear qué cambios se han realizado en la aplicación. Para hacer esto, debe tomar la versión anterior y compararla con la nueva para ver qué cambios agregó el desarrollador y cómo se implementan.


Veamos situaciones en las que esto puede ser útil:


  • Análisis del desarrollo del programa : al comparar las versiones nuevas y antiguas, puede comprender cómo se está desarrollando la aplicación, qué nueva funcionalidad se agrega, qué se elimina y qué cambios ha sufrido el código existente.
  • Importar el conocimiento existente : en los programas que no usan información simbólica, los ingenieros inversos tienen que pasar mucho más tiempo estudiando la lógica y buscando vulnerabilidades. Pero sucede que en alguna versión del software, los desarrolladores dejan accidental o deliberadamente información simbólica. Esta información se puede transferir desde allí a la versión de software que necesita. Por ejemplo , los empleados de Google Project Zero que utilizaban la Difusión Binaria pudieron obtener caracteres para versiones nuevas de Windows de Adobe Reader de versiones anteriores para otros sistemas operativos, lo que les ayudó a encontrar vulnerabilidades;
  • Capacitación en software real : en nuestra opinión, Patch Diffing es una excelente manera de pasar sin problemas de estudiar pequeños problemas de CTF a investigar software real. Al explorar el parche, puede ver la vulnerabilidad real en un gran producto de software con todas sus características (mientras sabe con certeza que la vulnerabilidad está presente en el código). Al explorar los errores en un producto, puede pasar gradualmente a encontrar las mismas vulnerabilidades. Como beneficio adicional, puedes intentar escribir exploits para ellos;
  • Creación de exploits de 1 día : cuando un desarrollador ya ha lanzado un parche, puede analizarlo rápidamente, escribir un exploit para esta vulnerabilidad y obtener un exploit de 1 día. Al mismo tiempo, existe el denominado Patch Gapping, el tiempo entre el lanzamiento del parche y su instalación directa por parte de los clientes. Durante este tiempo, un exploit de 1 día puede funcionar con éxito y beneficiar a su autor (¡instale actualizaciones de manera oportuna!) Hasta que todos instalen el parche lanzado por los desarrolladores. Hay situaciones en las que se corrige una vulnerabilidad en una biblioteca, pero los programas aún usan una versión desactualizada de la biblioteca. Aquí hay algunos ejemplos interesantes de Patch Gapping para Chrome y WebKit ;
  • Busque vulnerabilidades de 0 días : no importa cuán extraño pueda sonar esto, al analizar parches, también puede encontrar vulnerabilidades previamente desconocidas (vulnerabilidades de 0 días). Los desarrolladores también se equivocan y, por lo tanto, en el proceso de creación de un parche, la vulnerabilidad puede no cerrarse correctamente. Entonces, al analizar un parche, puede encontrar una forma de evitarlo. Por ejemplo, los desarrolladores de Apache Struts corrigieron una vulnerabilidad cinco veces, ¡pero el parche solo funcionó en su sexta versión! Además, a menudo un desarrollador, que cumple claramente la tarea establecida para corregir una cierta vulnerabilidad, puede no darse cuenta de lo que sucede en las secciones vecinas del código. Podría haber exactamente la misma vulnerabilidad cerca, y en caso de detección será de 0 días. Es importante estudiar el patrón de un error de desarrollador detectado e intentar encontrar algo similar en el mismo programa. Si el desarrollador cometió un error en un lugar, entonces la probabilidad de repetir el mismo error en otro lugar es alta.

Existe el mito de que ocultar la información del parche de vulnerabilidad aumenta la seguridad. Sin embargo, los atacantes, como regla, ya han desarrollado infraestructura para analizar parches, por lo que encontrarán rápidamente los datos que les interesan. Ocultar las vulnerabilidades complica el trabajo de los responsables de proteger el sistema, porque sin acceso total a la información es imposible comprender la importancia de este parche para la empresa. Sobre este tema, le recomendamos que lea el artículo "Rashomon de divulgación" del investigador Halvar Flake, donde se ve la situación desde diferentes ángulos.


No siempre se descubren vulnerabilidades ocultas intencionalmente. Es posible que los desarrolladores no otorguen una importancia particular a algunas de las deficiencias de su producto y las solucionen sin publicidad, como un error común.


Estamos seguros de que estas no son todas las situaciones en las que puede utilizar la Difusión binaria y la Difusión de parches, y en los comentarios puede escribir sus propios scripts.


Kit de herramientas


De la teoría pasamos gradualmente a la práctica. Naturalmente, hacer Binary Diffing manualmente es una tarea loca. Se ha desarrollado un extenso kit de herramientas que consta de programas independientes y complementos para analizadores binarios populares: Diaphora, BinDiff, DarunGrim, YaDiff, rizzo, Realyze, Turbodiff, patchdiff2, revancha y otros.


imagen
Interfaz BinDiff.


imagen
Interfaz Diaphora


En la práctica, utilizamos principalmente solo los dos primeros (se presentan en las capturas de pantalla anteriores). Lamentablemente, la mayoría de las herramientas actuales no son alentadoras con la calidad del trabajo o están completamente abandonadas. Ahora hay nuevas herramientas que utilizan ML, pero su calidad deja mucho que desear, aunque tienen ideas interesantes para comparar archivos binarios de diferentes arquitecturas.


También me gustaría señalar por separado las herramientas recientemente aparecidas para comparar código de código abierto en archivos binarios: Pigaios y Karta. Esta es una dirección muy interesante y útil. Recopilan métricas del código fuente y luego las usan para comparar funciones en archivos binarios. Esto es muy útil en ausencia de caracteres y enlaces estáticos. La tarea de estas herramientas es asignar funciones en un archivo a funciones en otro.


Comparación de parches para sistemas operativos Apple


Como regla general, las aplicaciones para Apple OS escriben en Objective-C. Esta es una extensión orientada a objetos para C, basada en paradigmas de lenguaje Smalltalk con su propio tiempo de ejecución.


Si abrimos el programa en Objective-C en algún analizador binario (en nuestro caso, esto es un IDA), veremos algo como esto: las funciones en C / C ++ tendrán nombres abstractos, y las funciones en Objective-C se llamarán muy bien. (Diremos de inmediato que no consideramos situaciones con ofuscación de código; esta es una historia separada). Esto facilita la ingeniería inversa: es fácil ver qué objeto se llama, qué método se usa y qué argumentos tiene. Además, esta información simbólica simplifica enormemente el trabajo con herramientas para comparar archivos binarios. Le permite rápidamente y con un número mínimo de errores asignar funciones.


imagen


Cuando no hay símbolos, las herramientas tienen que usar algoritmos internos para análisis, heurística, etc. Naturalmente, no siempre funcionan correctamente.


Casos de uso donde la diferenciación de parches fue muy útil


Probablemente, esta presentación (en el formato de 45 minutos) y este artículo no hubieran nacido si recientemente Apple no hubiera sorprendido a la comunidad mundial de investigación varias veces. Veamos estos casos.


Caso 1: CVE-2019-8606


En mayo de 2019, se lanzó iOS 12.3 para iPhone, donde se corrigió la vulnerabilidad con la que era posible instalar jailbreak. En julio de ese año, Apple lanzó la versión 12.4, donde el jailbreak comenzó a funcionar nuevamente: los empleados quitaron accidentalmente el parche protector. La versión corregida se lanzó solo después de un mes: todo este tiempo, cualquier dispositivo en la última versión podría ser fácilmente sometido a operaciones de jailbreak. Todo esto fue descubierto gracias a la diferencia de parches.


imagen


Caso 2: CVE-2019-7278 y CVE-2019-7286


El investigador de seguridad Stefan Esser describió la experiencia personal con Patch que difirió en la conferencia Hack in the Box en su informe La recreación de un jailbreak iOS de 0 días a partir de los parches de seguridad de Apple . Habló sobre CVE-2019-7278 y CVE-2019-7286: son notables para aquellos que fueron descubiertos gracias al Google Threat Analysis Group durante su uso real por parte de los atacantes (ITW, en la naturaleza). Apple recibió información sobre ellos, pero ni ellos ni los chicos de Google revelaron detalles técnicos. Entonces Stefan se preguntó qué estaban usando los atacantes. Le recomendamos encarecidamente que lea su informe, ya que también habla sobre el proceso de comparación de los componentes del núcleo y el espacio del usuario.
Dato interesante: uno o dos días antes del discurso de Stefan, el Proyecto Cero Ian Beer publicó una serie de artículos "Una inmersión muy profunda en las cadenas de exploits iOS que se encuentran en la naturaleza" , que confundieron los mapas para el investigador;)


Caso 3: checkm8


Los dispositivos Apple usan dos cargadores de arranque: Bootrom e Iboot. El primero comienza a funcionar tan pronto como se enciende el dispositivo. Está en la memoria de solo lectura y no se puede actualizar. Iboot es un gestor de arranque de segundo nivel que mejora la autenticación que se ejecuta en la cadena de arranque.
La peculiaridad de los cargadores es que comparten el código. A principios del año pasado, los especialistas compararon las actualizaciones de Iboot y descubrieron que Apple solucionó una vulnerabilidad en la pila USB. Sabiendo que se usa el mismo código en la parte no actualizada de Bootrom, se dieron cuenta de que esta vulnerabilidad también existe allí. Luego comenzó el desarrollo del exploit checkm8. Ahora todos los dispositivos basados ​​en chips de A5 a A11 (desde iPhone 4s a iPhone X) son completamente vulnerables, y es posible ejecutar su propio código en ellos. Al mismo tiempo, en los dispositivos de las versiones XR y 11, esta vulnerabilidad ya está cerrada, y no hubo informes de esto por parte de Apple.
Entonces, sabiendo dónde se parchó y cómo se divide el código, ¡puedes encontrar algunas cosas realmente geniales!


Nuestra historia: CVE-2019-8574


imagen
En mayo, Apple lanzó una nueva actualización para sus dispositivos. Observamos la lista de vulnerabilidades reparadas y encontramos la utilidad sysdiagnose. Este programa recopila información de diagnóstico de varias fuentes y la transfiere al usuario en forma de archivo para su posterior análisis, soporte o centro de servicio. Parecía que era imposible influir en la forma en que recopila información. La descripción del parche indicó que la vulnerabilidad podría usarse para elevar los privilegios y es un error de corrupción de memoria, lo que nos intrigó aún más. Y el autor del hallazgo mismo no publicó ninguna descripción de sí mismo ...


imagen


Puede llamar a sysdiagnose en macOS presionando Ctrl + Opción + Shift +., O usando el comando sudo sysdiagnose. En dispositivos iOS, debe mantener presionada la tecla de encendido y las teclas de volumen hacia arriba y hacia abajo.


Patch Diffing Apple en la práctica


Si desea parchear dispositivos Apple de diferenciación, necesita obtener dos versiones de la actualización (antigua y nueva). En macOS, puede analizar archivos en el Catálogo de actualizaciones de software. Este método no siempre ayuda, ya que Apple elimina algunas actualizaciones. Las actualizaciones también se pueden encontrar en el directorio / Library / Updates. Puede encontrar firmware para dispositivos iOS en el sitio web ipsw.me.
Para macOS, debe extraer archivos ejecutables, archivos de biblioteca, marcos y el núcleo utilizando la utilidad Paquete sospechoso.
Para dispositivos iOS, las cosas son un poco más complicadas. La actualización en sí es un archivo ZIP. En este archivo debe encontrar el archivo kernelcache: dentro está el kernel y su extensión. Sin embargo, antes del análisis necesita convertir el archivo al formato Mach-O. Esto se puede hacer usando las utilidades img4tool, joker, jtool2 y otras.
El firmware del componente de tierra del usuario se puede encontrar en la imagen DMG más grande: contiene el sistema raíz y los archivos ejecutables. Sin embargo, si observa bibliotecas y marcos compartidos, no estarán allí. El hecho es que para optimizar el espacio se colocan en dyld_shared_cache. Este archivo contiene todas las bibliotecas del iPhone y ocupa más de 1 gigabyte, lo que complica su análisis. Si necesita descargar una parte separada del archivo ipsw, use la utilidad ipsw ( https://github.com/blacktop/ipsw ).


Patchdifting CVE-2019-8574


Para estudiar el parche CVE-2019-8574, obtenemos un archivo de Library / Updates y extraemos dos archivos ejecutables sysdiagnose (antiguo y nuevo) usando el Paquete sospechoso, y luego buscamos actualizaciones a través de utilidades para comparar códigos binarios, por ejemplo, Diaphora o BinDiff (son mucho mejor que el editor hexadecimal).


Como funciona el parche


Para la arquitectura x86_64, encontramos solo una función modificada. Hay más cambios en ARM, pero son insignificantes.


imagen


El problema fue con el método [SDTask start]: agregó una nueva verificación. En la figura, puede ver cómo se llama a una función isAppleInternal de alguna llamada y se verifica la presencia de la subcadena / usr / local en alguna ruta.


imagen


Como se indicó anteriormente, sysdiagnose recopila información de varias fuentes. Las fuentes pueden ser archivos (por ejemplo, un registro de eventos) o la salida de algunos comandos de información (por ejemplo, enumerar procesos o subprocesos que usan ps); estas tareas se almacenan en sysdiagnose como objetos SDTask. El método [SDTask start] inicia la ejecución de tareas. En la figura a continuación puede ver el código en el que se forman todas las tareas. Todas las rutas de los archivos ejecutables y sus argumentos están escritos directamente en el programa, y ​​hay tareas de varios directorios, incluido / usr / local.


imagen! [] (./ assets / 8.png)


Por lo tanto, antes de instalar el parche, cualquier tarea podría realizarse independientemente de dónde se encuentre el archivo ejecutable. Después de instalar el parche, se llama a la función isAppleInternal, que verifica si el dispositivo es un dispositivo de prueba interno de Apple. Si se trata de un dispositivo interno, la tarea se realiza de forma estándar y, si es del lado del cliente, se verifica la presencia de la subcadena / usr / local / en la ruta del archivo ejecutable de la tarea. Si se encuentra una subcadena, la tarea no se completará.


Recuerde que en la descripción de la vulnerabilidad se dijo que se trata de un error de corrupción de memoria, pero en el parche no notamos nada parecido ... En nuestra opinión, esta es una vulnerabilidad lógica bien explotada y estable.


Cómo explotarlo


Para aprovechar la vulnerabilidad, debe realizar los siguientes pasos:
Cree cualquier archivo ejecutable (binario o script de shell) que sysdiagnose se inicie desde / usr / local / bin, y coloque nuestra carga allí. La lista de archivos válidos se da a continuación. Es importante que el administrador de paquetes de café esté instalado en el sistema: permite al usuario crear archivos en / usr / local / sin elevar los privilegios.


Es necesario llamar a sysdiagnose. Al mismo tiempo, nuestra carga útil se ejecutará con derechos de usuario root, y su salida se colocará en el archivo que forma sysdiagnose. Por lo tanto, tenemos escalada de privilegios. Sin embargo, ejecutar sysdiagnose requiere privilegios elevados. Pero, como se mencionó anteriormente, sysdiagnose también se puede iniciar utilizando el método abreviado de teclado, y esto funciona incluso desde la pantalla de bloqueo de macOS.
Esta vulnerabilidad se puede usar para crear varios programas maliciosos.


/usr/local/bin/airplayutil /usr/local/bin/amstool /usr/local/bin/apsclient /usr/local/bin/audioDeviceDump /usr/local/bin/cdcontexttool /usr/local/bin/cddebug /usr/local/bin/cdknowledgetool /usr/local/bin/dastool /usr/local/bin/idstool /usr/local/bin/imtool /usr/local/bin/keystorectl /usr/local/bin/pmtool /usr/local/bin/xcpm /usr/local/efi/bin/efi-perf 

Curiosamente, otras vulnerabilidades podrían estar asociadas con el administrador de paquetes de café, o más bien con la capacidad de escribir a / usr / local / sin privilegios.


Conclusión


Con este estudio, nos gustaría mostrar la importancia y la importancia de que los parches difieran no solo para los atacantes, sino también para aumentar la seguridad de los productos de software. Desafortunadamente, el parche no solo puede cerrar la vulnerabilidad, sino también jugar en manos del atacante.


Sin embargo, este enfoque permite no solo estudiar vulnerabilidades conocidas, sino también buscar nuevas como ellas. Por lo tanto, creemos que la diferenciación de parches es imprescindible para todos los investigadores.

Source: https://habr.com/ru/post/479972/


All Articles