En junio de 2019, investigadores de ESET identificaron un exploit de una vulnerabilidad zero-day que estaba siendo utilizado en ataques altamente dirigidos en Europa del Este.

El exploit abusa de una vulnerabilidad de escalada de privilegios local en Microsoft Windows, más específicamente una desreferencia de puntero NULL (nulo) en el componente win32k.sys. Una vez que se descubrió y analizó el exploit, se procedió a reportar el hallazgo al Centro de Respuesta de Seguridad de Microsoft, quien rápidamente reparó la vulnerabilidad y lanzó un parche.

La vulnerabilidad afecta las siguientes versiones de Windows:

  • Windows 7 for 32-bit Systems Service Pack 1
  • Windows 7 for x64-based Systems Service Pack 1
  • Windows Server 2008 for 32-bit Systems Service Pack 2
  • Windows Server 2008 for Itanium-Based Systems Service Pack 2
  • Windows Server 2008 for x64-based Systems Service Pack 2
  • Windows Server 2008 R2 for Itanium-Based Systems Service Pack 1
  • Windows Server 2008 R2 for x64-based Systems Service Pack 1

Este artículo se centra en los detalles técnicos de la vulnerabilidad y su explotación. En otro artículo que publicaremos más adelante, profundizaremos en el malware y sus implicancias.

Explotación

Al igual que con otras vulnerabilidades en Microsoft Windows win32k.sys reveladas en años recientes, este exploit utiliza objetos del tipo menú emergente. Por ejemplo, los exploit de escalada de privilegios local del grupo Sednit que analizamos en 2017 utilizaron objetos del tipo menú y técnicas muy similares a las de este exploit

Este exploit crea dos ventanas: una para la primera etapa y otra para la segunda etapa de la explotación. Para la primera ventana, crea objetos de menú emergentes y agrega elementos de menú utilizando las funciones CreatePopupMenu y AppendMenu. Adicionalmente, el exploit configura los hooks WH_CALLWNDPROC y EVENT_SYSTEM_MENUPOPUPSTART.

Luego, el exploit despliega un menú utilizando la función TrackPopupMenu. A este punto el código hookeado a EVENT_SYSTEM_MENUPOPUPSTART es ejecutado. Este código intenta abrirse como el primer ítem disponible en el menú mediante el envío de la secuencia de mensajes MN_SELECTITEM, MN_SELECTFIRSTVALIDITEM y MN_OPENHIERARCHY al menú.

El siguiente paso es muy importante para desencadenar esta vulnerabilidad. El exploit deberá capturar el momento en que el menú inicial es creado y que el sub menú está a punto de ser creado. Para eso, el exploit cuenta con código que manipula el mensaje WM_NCCREATE en el hook WH_CALLWNDPROC. Cuando el código del exploit detecta que el sistema está en este estado, envía el mensaje MN_CANCELMENUS (0x1E6) al primer menú, el cual cancela ese menú. Sin embargo, su submenú aún está por crearse.

Ahora, si revisamos el objeto submenú en el modo kernel veremos que tagPOPUPMENU‑>ppopupmenuRoot es igual a 0. Este estado permite al atacante utilizar ese elemento en esta estructura kernel como una desreferencia de puntero NULL. El exploit asigna una nueva página en la dirección 0x0 y esta dirección será tratada como un objeto tagPOPUPMENU (ver Figura 1) por el kernel.

Figura 1. La estructura kernel tagPOPUPMENU

En este punto, los atacantes utilizan la segunda ventana. El objetivo principal del exploit es dar vuelta el bit bServerSideWindowProc en la estructura tagWND de la segunda ventana. Esto causa la ejecución de un procedimiento WndProc en modo kernel.

Para llevar adelante esta acción, los atacantes filtran la dirección de memoria del kernel de la estructura tagWND de la segunda ventana al llamar a la función HMValidateHandle no exportada en la librería user32.dll. Luego, el exploit crea un falso objeto tagPOPUPMENU en la página nula y envía un mensaje MN_BUTTONDOWN a un submenú.

Luego de eso, el kernel eventualmente ejecutará la función win32k!xxxMNOpenHierarchy.

Figura 2. Código desensamblado de la función win32k!xxxMNOpenHierarchy

Esta función pasa un objeto creado a la página nula a win32k!HMAssignmentLock. El bServerSideWindowProc bit está configurado en el interior de la función win32k!HMDestroyUnlockedObject, la cual está ubicada a unas pocas llamadas más profundas en el interior de win32k!HMAssignmentLock.

Figura 3. Código desensamblado de la función win32k!HMDestroyUnlockedObject

¡Todo está hecho! Ahora el exploit puede enviar un mensaje específico a la segunda ventana con el fin de ejecutar WndProc en modo kernel.

Como etapa final, el exploit reemplaza el token del proceso actual con el token del sistema.

El parche publicado, entre otros, añade la revisión de un puntero NULL en la función win32k!xxxMNOpenHierarchy.

Figura 4. Diferencias de código entre dos versiones de win32k.sys– original (izquierda) y parcheada (derecha)

Conclusión

El exploit solo funciona en antiguas versiones de Windows, ya que desde la salida de Windows 8 un proceso de usuario no tiene permitido mapear la página nula. Microsoft implementó esta mitigación en Windows 7 para sistemas basados en x64.

Aquellos que sigan utilizando Windows 7 Service Pack 1 en sistemas de 32 bit deberían considerar actualizarse a un sistema operativo más nuevo, dado que la extensión del soporte para Service Pack 1 de Windows 7 finalizará el 14 de enero de 2020. Esto quiere decir que los usuarios de Windows 7 no recibirán actualizaciones de seguridad críticas, por lo que vulnerabilidades como estas permanecerán sin parchear para siempre.

Indicadores de Compromiso (IoCs)

SHA-1 hash ESET detection name
CBC93A9DD769DEE98FFE1F43A4F5CADAF568E321 Win32/Exploit.CVE-2019-1132.A