
Un informe sobre la versión de Sleirsgoevy de la implementación del exploit de CVE-2018-4386 por Fire30 llamado Bad_Hoist
[!Nota] Información general sobre la PS4:
La consola PlayStation 4 cuenta con una CPU AMD x86-64 personalizada (8 núcleos), su sistema operativo Orbis OS está basado en FreeBSD (v9.0) con partes también de NetBSD. También incluye una amplia variedad de software de código abierto adicional, como Mono VM y WebKit.
El navegador de Internet utilizado por la PS4 está construido con el proyecto WebKit de código abierto. Este es el motor de diseño de código abierto que renderiza páginas web en los navegadores de iOS, Wii U, 3DS, PS Vita y la PS4.
El navegador de Internet de la PS4 consta de dos procesos separados. El que secuestramos para la ejecución de código es el Proceso Principal de WebKit (que maneja, por ejemplo, el análisis de HTML y CSS, la decodificación de imágenes y la ejecución de JavaScript). El otro proceso maneja todo lo demás: mostrar gráficos, recibir entrada del controlador, gestionar el historial y los marcadores, etc.
El navegador WebKit de la PS4 emplea múltiples asignadores de montón, cada uno al servicio de diferentes componentes. Estos son los siguientes:
El núcleo de CVE-2018-4386 es un fallo lógico en el motor JavaScriptCore (JSC) de WebKit (v605.1.15), que es la versión utilizada en el firmware 6.XX de la PS4. El fallo reside en la función BytecodeGenerator::hoistSloppyModeFunctionIfNecessary e implica un manejo inadecuado del hoisting de variables en el modo sloppy de JavaScript, específicamente dentro de los bucles for-in.
Componente vulnerable (ForInContext):
Lo que atacamos principalmente es ForInContext. Esta es una estructura interna utilizada por JavaScriptCore para gestionar el estado de un bucle for-in, rastreando la variable de iteración actual y el conjunto de propiedades que se están enumerando.
Cuando una declaración de función es hoisted dentro de un bucle for-in, el motor debería invalidar el objeto ForInContext asociado si la variable de iteración es sobrescrita. Sin embargo, debido al error, esta invalidación no ocurre. Esto permite que la variable de iteración sea reemplazada por un objeto arbitrario. A pesar de esto, el motor continúa tratando la variable como un nombre de propiedad de tipo cadena.
Cuando el manejador de bytecode op_get_direct_pname se invoca posteriormente, utiliza la variable de iteración directamente como un objeto cadena, sin comprobación de tipo.
Al pasar un objeto manipulado en lugar de una cadena, se provoca una confusión de tipos, lo que nos permite explotar esto de manera que se logra una corrupción de memoria, e incluso primitivas de explotación útiles como addrof, fakeobj y Lectura/Escritura Arbitraria.
ID de Estructura: Todo objeto en JavaScriptCore, incluyendo representaciones internas como WTF::StringImpl, tiene un ID de estructura (o etiqueta de tipo) que le dice al motor qué tipo de objeto es y cómo interpretar sus campos.
Confusión de Tipos: Nuestro exploit abusa del error CVE-2018-4386 para que un objeto JavaScript sea interpretado como un StringImpl. Este es el propósito de la función create_impl(), que devuelve un objeto con confusión de tipos de WTF::StringImpl, que luego puede ser pasado a la función trigger() como el objeto arbitrario del que hablamos anteriormente en la parte del mecanismo de vulnerabilidad de este análisis.
Sin embargo, para que esto funcione, el diseño de la memoria y el ID de estructura deben estar "lo suficientemente cerca" de lo que el motor espera para un objeto cadena real.
JSString::toIdentifier()?Existe un método en el motor JavaScriptCore de WebKit del navegador de Internet de la PS4 llamado JSString::toIdentifier(). Este método convierte un objeto cadena de JavaScript (JSString) en una representación interna de Identifier.
Este Identifier se utiliza en todo el motor para comparar, almacenar y buscar de manera eficiente nombres de propiedades, nombres de variables y otras cadenas que deben ser referenciadas rápida y frecuentemente por el motor JavaScript.
Comprueba que el objeto sea una cadena válida y que su ID de estructura coincida con lo que el motor espera para un objeto cadena. Si la cadena es una rope (una concatenación de cadenas), puede aplanarla antes de convertirla. Luego, recupera un Identifier existente para la cadena o crea uno nuevo si no existe.
Este Identifier se utiliza internamente para búsquedas rápidas de propiedades y variables.
JSString::toIdentifier()Cuando el exploit entra en el bucle for que itera 1024 veces, cada iteración crea un nuevo objeto WTF::StringImpl con confusión de tipos con 32 nuevos IDs de Estructura devueltos por la función create_impl(). Cuando este objeto con confusión de tipos se utiliza y se pasa a trigger() como el objeto arbitrario, JSC llama a JSString::toIdentifier() sobre él.
JSString::toIdentifier() comprueba ciertos bits en el ID de estructura para confirmar que el objeto es una cadena válida o puede ser tratado como tal. Al generar muchos objetos con diferentes diseños e IDs de estructura, el exploit aumenta las posibilidades de que al menos uno tenga un ID de estructura que pase las comprobaciones internas en JSString::toIdentifier().