El siguiente post es una traducción del texto realizado por Aleksandr Matrosov, Eugene Rodionov, Juraj Malcho y David Harley, especialistas de seguridad de ESET, y publicado en el blog de ESET en inglés sobre las vulnerabilidades explotadas por Stuxnet.

Si bien la vulnerabilidad parcheada por LNK MS10-046 dominó los titulares cuando el carnaval Stuxnet comenzó a rodar de nuevo a principios del verano de 2010, una de las sorpresas luego de un análisis más profundo de los archivos binarios y componentes de Stuxnet, es que explotan al menos tres vulnerabilidades más que fueron en general desconocidos en ese momento. El ataque de cola de impresión (MS10-61) es, como la vulnerabilidad LNK, descrito en nuestro extenso análisis "Stuxnet bajo el microscopio".

Sin embargo, también se indica en ese documento que hay dos vulnerabilidades de Elevación de Privilegios (EOP) las cuales elegimos no describir hasta que los parches se encontraran disponibles. Uno de estas ya ha sido parcheada (MS10-073, CVE-2010-2743), por lo que estamos ahora en condiciones de publicar parte de la información que tenemos de ella (cuando la otra vulnerabilidad haya sido parcheada, tenemos la intención de actualizar el documento de Stuxnet con información sobre ambas).

Cuando el gusano Win32/Stuxnet no tiene privilegios suficientes para instalarse en el sistema, explota una vulnerabilidad 0-day parcheada recientemente en el módulo del sistema win32k.sys para así escalar privilegios hasta lograr acceso a nivel  SISTEMA, lo que le permite realizar cualquier acción que guste en el equipo local. Los sistemas vulnerables son los siguientes:

  • Microsoft Windows 2000
  • Windows XP – todos los service packs

Para realizar este truco, carga un archivo de distribución del teclado especialmente diseñado , lo que le permite ejecutar código arbitrario con privilegios de SYSTEM. Esta elevación de privilegio se produce mientras se envían los datos ingresados desde el teclado en el módulo Win32k.sys. Mientras se procesa lo ingresado desde el teclado usando el servicio del sistema NtUserSendInput, el código ejecuta lo siguiente:

Un fragmento del código ejecutado mientras se procesa la entrada del teclado

El propósito de este código es determinar cómo distribuir el código de la tecla virtual de la tecla pulsada. El registro ecx especificado en la tabla de procedimiento _aNLSVKProc indica el tipo de controlador utilizado, de acuerdo con la distribución de teclado que se posea. Esta tabla se compone de tres controladores:

Tabla de procesos _aNLSVKProc

Como podemos ver en la figura anterior, el _aNLSVKProc es seguido por tres DWORD, el último de los cuales (en rojo) se puede interpretar como un indicador que apunta a 0×60636261 en el espacio de direcciones en modo de usuario. Por lo tanto, si ponemos el registro ecx en el código en la figura 1 con el valor apropiado, en este caso 5, entonces podremos ejecutar código en el 0×6036261 con privilegios de SYSTEM.

Podríamos manipular el registro ecx en este código al cargar un archivo de teclado especialmente diseñado que especifique la carga de ciertos códigos de tecla virtual indexados como 5. El archivo de distribución de teclado es una librería de enlace dinámico que esté especialmente estructurada en la sección .datos del mismo.  A continuación se presenta una estructura que las claves de los mapas virtuales de los procedimientos correspondientes de dicha tabla.

Mapeo virtual de teclas

El gusano carga un archivo de distribución de teclado especialmente armado, llamado por NtUserLoadKeyboardLayoutEx y le pasa la constante hexadecimal 0x01AE0160 como parámetro offTable. Las palabra en minúscula de este parámetro especifican el RVA (Relative Virtual Address) de la estructura KBDTABLES desde el principio del archivo, mientras que la palabras en mayúscula especifican el RVA de KBDNLSTABLES, que es de particular interés. La estructura de este último determina la dirección y el tamaño de la matriz de estructuras VK_F contenida en el archivo.

Estructura VK_F

En la siguiente figura se presenta el contenido de la sección .datos ,donde podemos ver que la estructura de KBDNLSTABLES ubicada en RVA 0x1AE especifica una estructura VK_F situada en el RVA 0x01C2.

Sección .data del archivo de distribución de teclado armado

Como podemos ver, el archivo de distribución de teclado contiene exactamente una estructura VK_F a la cual se le asigna una tecla virtual con un código igual a el procedimiento de _aNLSVKProc con indexado 5.

Una cosa que tenemos que hacer para aprovechar esta vulnerabilidad es asignar un buffer para el código que se ejecutará en la dirección 0×60636261 como en el caso de Stuxnet, que asigna 32 KB de la memoria en 0×60630000 y escribe el código shell a 0×60636261:

Stuxnet almacena 32kb de memoria en 0×60630000 para código shell

Aleksandr Matrosov
Eugene Rodionov
Juraj Malcho
David Harley