La lucha de Windows contra la ejecución de código: Éxitos y fracasos (III)

lunes, 6 de agosto de 2018

Es complicado entender todo el entramado de seguridad que está montando Microsoft alrededor de Windows 10, con medidas de seguridad cada vez más integradas y complejas. Es muy positivo, sino fuera porque algunas medidas están adquiriendo una complejidad tal que para el usuario medio (poco instruido en seguridad) le resultan poco menos que esotéricas, incompresibles y por tanto, inútiles si no están activadas por defecto (que muchas no lo están). Hablamos en la anterior entrega de Windows Defender Exploit Guard englobada dentro de lo que Microsoft llama Windows Defender. Veamos concretamente en estas entradas, qué técnicas a bajo nivel utiliza.

La tecnología específica de Windows Defender para evitar los exploits es "Exploit Guard". Desde la entrada anterior, nos centramos en Exploit Protection. Vamos a cubrir ahora algunas técnicas de protección contra exploits, heredadas de lo que se comenzó con EMET y hoy en día integradas en Windows 10. En concreto, veremos en esta entrada cómo evitar que se cargue código en memoria (que suele ocurrir un poco después de la explotación exitosa de alguna vulnerabilidad).

CIG Code Initegrity Guard
El atacante ha conseguido que su exploit funcione, superando las técnicas propias "anti-exploit". Ahora necesita cargar instrucciones en memoria, y tiene dos fórmulas para conseguirlo:
  • Cargar un fichero que ya esté en disco
  • Construir o generar el código en memoria
Esto último es mucho más habitual, pues el atacante no sabrá normalmente qué hay en disco, o lo que haya no le interesará especialmente para el fin de completar la ejecución. Aunque la primera circunstancia también puede darse, si ha conseguido ya descargar algo (y quiere inyectarlo en memoria como segunda fase), o necesita de una DLL legítima para completar su ataque… en definitiva, son dos estrategias que pueden darse en un ataque, aunque con diferente frecuencia. Inyectar DLLs no deseadas es especialmente habitual para atacar navegadores pues mucho adware se incrusta así en el sistema modificando el comportamiento del navegador (algo que ha sido muy popular durante los últimos años para "secuestrar" el navegador o entre los troyanos bancarios).

En el contexto de Microsoft Edge, CIG restringe la inyección o carga de DLLs en memoria a las que estén firmadas. En resumen, Edge solo dejará inyectarse en memoria, DLLs firmadas por la propia Microsoft y por tanto con un mínimo de garantías de legitimidad. Cualquier programador ajeno a Microsft, tiene que pedir que la firmen para poder inyectarse en Edge. Como podéis imaginar, no es más que una evolución de la política de drivers firmados que comenzó hace muchos años.

CIG comienza a aplicarse en Windows 10 (update 1511) y se enmarca dentro de la política de UMCI (User Mode Code Integrity) que ofrece al kernel la posibilidad de marcar los procesos (en las últimas versiones, en tiempo de creación) con las habilidades de crear procesos hijo (o no), o cargar DLLs más "integras" firmadas, por ejemplo como es el caso de CIG.

Como siempre nos preguntamos... ¿Es eludible CIG?. Sí, CIGslip es cómo llamaron a una técnica, bastante reciente. Crearon una prueba de concepto, que se basa en apoyarse en procesos que no tengan el CIG habilitado. Hookean el método "createsection" antes de que pase por el kernel y obtienen un manejador sin restricción al proceso… Aun así, el ataque sigue y no mereció el bounty en opinión de Microsoft.

Documentación oficial, cómo crear un proceso con los parámetros necesarios para  aplicar las diferencias políticas de mitigación, entre ellas CIG imagen
Documentación oficial, cómo crear un proceso con los parámetros necesarios para
aplicar las diferencias políticas de mitigación, entre ellas CIG
 
¿Viene habilitado por defecto? Sí, excepto si usas extensiones IME en Edge (paquetes de idiomas para caracteres no occidentales como Japonés o Chino que permiten escribir en ese idioma sin un teclado especial…) porque si es así, no están activos por defecto. Suponemos que dispararían mucho falso positivo. ACG también viene deshabilitado por defecto cuando hay paquetes IME. Hablemos de ACG.

Arbitrary Code Guard ACG
Este es el complemento de CIG pero en dinámico, en memoria, porque, si bien gracias a CIG un proceso no puede cargar binarios no firmados… ¿qué pasa si el código cambia una vez mapeado el fichero en memoria? ¿Qué pasa si se construye el código al vuelo? (que es lo habitual) ACG Cubre la integridad de las páginas de memoria para que un proceso no pueda realocarlas o remapearlas… o sea, la integridad de los procesos, no de los binarios. Bastante interesante técnica teniendo en cuenta que impide hacer un VirtualAlloc y VirtualProtect, parte fundamental de la inmensa mayoría de los procesos de explotación que acaban en ejecución de código arbitrario, porque ahí crean "dinámicamente" la página y cuelgan en ella el código.

Se consigue como el resto de mitigaciones, llamando a la api SetProcessMitigationPolicy con la constante PROCESS_MITIGATION_DYNAMIC_CODE_POLICY para el proceso. En la práctica, las páginas de memoria son ahora inmutables y no se puede hacer el típico PAGE_EXECUTE_READWRITE con VirtualAlloc para crear una nueva, o VirtualProtect para modificar las existentes.


Interesante e innovador, de esta forma no se puede cargar código sin firmar ni dinámico ni estático pero... ¿Qué pasa con el código compilado JIT? La copilación "just in time" por ejemplo se encarga de procesar JavaScript, dentro del navegador, y constantemente crea "código" en el proceso del navegador que no estará firmado, pero que aun sin ser un ataque, sería impedido por la política de ACG. Ante esta problemática, lo que han hecho en Microsoft es crear en Chakra (el motor de JavaScript) como un proceso aparte sin ACG y con su propia sandbox para procesar el código JIT.

programa que no puede lanzarse porque no se permite ACG imagen
Un programa cualquiera que no puede lanzarse porque no se permite ACG
Esta tecnología es tan "innovadora" que están en constante "tanteo" para aplicarla. Puede ser incompatible con muchos programas. Así que por ahora, ACG solo está activa por defecto en Edge en sistemas de 64 bits con WDDM 2.2 (la arquitectura gráfica de Window). Para saber tu WDDM, ejecuta dxdiag...

sistema con WDDM 2.1 imagen
Un sistema con WDDM 2.1
También, aunque parezca extraño, se puede forzar a que Edge utilice ACG marcando esta opción en el navegador.

Marcando esta opción se activa "Dynamic code prohibited" (o sea, ACG) en Edge imagen
Marcando esta opción se activa "Dynamic code prohibited" (o sea, ACG) en Edge
Por tanto, muy pocos tendrán esta tecnología activada o funcionará sobre muy pocos programas… Para colmo, hasta hace no mucho con ACG se activaba también el AllowThreadsToOptOut en "ON", que permitía que se salieran de esta políticas las hebras de los procesos y por tanto facilitaba desactivar la técnica. En mayo de 2018 desde Project Zero de Google se analizaron detenidamente algunos de los problemas (y decimos "problemas" y no "vulnerabilidades" directamente) de ACG. Se reportaron pero como no se arreglaron en 90 días, se hicieron públicos. En realidad, la conclusión es que no está mal, tiene algunos problemas de diseño porque todavía se aplica una política muy laxa, pero lo princiipal es que, (en realidad como casi todo) no será efectiva si no se utiliza conjuntamente con CFG y CIG, porque por ejemplo, para intentar eludir ACG, es necesario ya haberse saltado CFG, cosa que no es difícil.

La estrategia es introducirla muy lentamente porque no quieren romper nada. A todo esto, aun con estas técnicas, los exploits a través de técnicas ROP (tomar de aquí y de allí instrucciones de tipo RETURN para crear código ejecutable que pasa "desapercibido") siguen pudiéndose hacer, eso sí, algo más complicado porque no solo se debe crear con gadgets la fase de creación de la memoria ejecutable, sino que todo el payload tendría que hacerse con ROP… así que veremos algo más de esto en las próximas entradas.

Sergio de los Santos
ssantos@11paths.com

No hay comentarios:

Publicar un comentario