Win7, 8, 10, 2008, 2012 32/64bits exploit programador de tareas vía ALPC (CVE-2018–8440)

Hace ya un par de meses, el 27 de agosto de 2018, la investigadora de seguridad “SandboxEscaper” liberó un exploit de escalda de privilegios a SYSTEM para entornos Windows 10 64bits y que fue catalogada como CVE-2018-8440, con su consecuente parche en septiembre. Desde entonces sentía curiosidad por darle un vistazo al exploit y probarlo en otras versiones de Windows. Inicialmente, como es normal, no funcionó. Busqué por la red si existía alguna PoC modificada que lo hiciera, pero salvo algunos tweets con alguna pista, no encontré nada realmente funcional, así que me decidí a ver que se podía hacer. Después de echarle algunas horas y de varias broncas con la parienta, a continuación os muestro mi aproximación para portar el exploit a Win7, 8, 10, 2012 32/64bits, haciéndolo más generalista y estable que la versión original.

En primer lugar, vamos a ver en que consiste la vulnerabilidad y posteriormente el exploit. No voy a profundizar en ello ya que numerosos blogs ya han comentado el problema. Por último detallaremos la investigación realizada hasta llegar a hacer el exploit portable.

La vulnerabilidad permite a un usuario con mínimos privilegios (grupo USERS, no GUEST o al menos en win7 no lo he conseguido) invocar a la función _SchRpcSetSecurity publicada por el programador de tareas, a través de ALPC (protocolo utilizado para la intercomunicación entre procesos). Esta función lo que permite es establecer un DACL a un fichero de forma arbitraria, es decir cambiar los permisos. La única limitación es que el usuario SYSTEM debe ser capaz de escribir en él. Esto último es la clave para el exploit, ya que en las últimas versiones de Windows todo archivo (o casi todo) que viene de fábrica con el SO es tan solo el usuario TRUSTED INSTALLER el que tiene estas capacidades. Por lo tanto, tenemos que cambiar los permisos de algunos ficheros del sistema de forma arbitraria (un usuario plano puede), por ejemplo librerías .dll de “c:\windows\system32”.

Con esta “funcionalidad”, para producir el exploit y obtener una Shell de SYSTEM, lo único que hay que encontrar es una casuística donde se den todas estas situaciones al mismo tiempo:

  • Encontrar una librería (dll) o un ejecutable (exe) candidato a poder ser sobrescrito donde SYSTEM tenga full Access (F).
  • Esa librería no debe estar cargada en ninguno de los procesos actuales del sistema, o si lo está el usuario plano ha de ser capaz de matar el proceso. Esto es debido a que si tratamos de sobrescribir la dll y esta está siendo utilizada el SO, no nos dejará sobrescribirla, por muchos permisos que tengamos.
  • Un proceso que arranque en el sistema con privilegios de SYSTEM ha de cargar dicha DLL para poder ejecutar el código que nosotros hayamos desarrollado en nuestra propia dll.
  • Ese proceso de SYSTEM anterior ha de poder ser lanzado por el usuario plano, es decir hay que encontrar un “trigger” que haga cargar la dll.

El pseudocódigo del exploit a grandes rasgos será por tanto el siguiente:

  1. Localiza la dll a sobrescribir
  2. Llama a la función _SchRpcSetSecurity para que cambie los permisos de la dll victima
  3. Reemplaza la dll con una arbitraria que nos permita obtener una Shell.
  4. Ejecuta el disparador es decir arranca el proceso que cargará la nueva dll como SYSTEM.

Con esto claro, vamos a ver rápidamente el exploit de “SandboxEscaper” para ver como realizó todos estos pasos y porque solo funciona en Windows 10 64bits.

Nos vamos a centrar básicamente en el fichero fuente “ALPC-TaskSched-LPE.cpp” que es donde está “la harina” y más concretamente en la función main().

Paso 1. De lo comentado anteriormente, localizamos la librería a sobrescribir, en este caso PrintConfig.dll en el directorio DriverStore de System32

Aquí encontramos la primera clave por la cual el exploit solo va en Windows 10: “SandboxEscaper” encontró como proceso disparador (Paso 4 del pseudocódigo), el subsistema de colas de impresión (spoolsv.exe) el cual carga la dll PrintConfig.dll cuando se ejecuta la impresión de un trabajo/documento. Esta dll no se encuentra en operativos como Windows 7 u 8 por lo que buscarla en estos no nos funcionaría. Además, como veremos, si encontramos por ejemplo su hermana en Windows 7, esta no la carga el proceso SYSTEM sino el proceso de usuario plano. Hay que encontrar una alternativa…

A continuación crea un hard link en el directorio “C:\windows\Tasks” con el nombre de una tarea cualquiera (en este caso UpdateTask.job) y que apuntará a la dll a sobreescribir.

Paso 2. Ahora llama a la función vulnerable que nos permite modificar los permisos de esa dll.

En este momento el programador de tareas “seteará” el DACL que se ve en amarillo al fichero UpdateTask.job en “C:\windows\Tasks” y que por lo tanto apunta a la dll víctima.

Paso 3. En este punto tenemos que sobrescribir la dll. Para ello, lo que hace en el exploit original es dropear una dll que viene como recurso dentro del propio binario del exploit. Segundo kit de porque solo va en 64bits: si cambiamos la dll a una de 32bits, probablemente funcionaria para esta arquitectura.

De lo anterior, tan solo destacar que como hemos dicho, la dll objetivo puede estar cargada ya en algún proceso y por eso usa un bucle while para comprobar cuando se libera. Buena opción, pero podemos estar años esperando si la dll es utilizada por un proceso que no termine.

Paso 4. Por último se necesita llamar al proceso disparador. En este caso crea un trabajo de impresión (“Print Job 1”) usando una impresora que normalmente está instalada en el sistema como es “Microsoft XPS Document Writer”.

En este punto, si no recuerdo mal ya que no da el código de la dll que “dropea”, ejecuta un calc.exe como SYSTEM, con el cual no se puede interactuar con él. Veremos como lidiar con esto más adelante. Desde el punto de vista del pentester, lanzar un calc.exe no nos aporta mucho en una intrusión.

Hasta aquí el estado del arte, ahora veremos cómo portar el exploit a Windows 7, 8, 2012,10 en arquitecturas 32bits y 64bits.

Necesitamos poder disparar un proceso de SYSTEM desde un usuario plano. Dado esto, el primer impulso obviamente fue buscar tanto en las tareas programadas del sistema, como en los servicios que vengan por defecto en la instalación de Windows. En este caso no nos valen servicios/tareas de terceros tipo Lenovo/Intel/Nvidia, ya que es menos universal y requiere de ese software específico instalado. Comentar que sin este criterio hubiéramos acabado pronto ya que en los Lenovo rápidamente se encontró candidato.

En poco tiempo se identificó una nueva posible alternativa para Windows 7, tal y como encontró algún otro investigador como @wdormann en este tweet. El Servicio disparador en cuestión es “Windows CardSpace” el cual lanza como usuario SYSTEM el proceso .NET

“C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\Infocard.exe”

Este carga la dll siguiente y que como apreciamos en la imagen, es posible sobrescribir por permisos:

64bits

C:\Windows\assembly\NativeImages_v2.0.50727_64\mscorlib\0478aed7fc25ae268474c704fd2a3e0f\mscorlib.ni.dll

32 bits

C:\Windows\assembly\NativeImages_v2.0.50727_32\mscorlib\f8be9e33457f57805b4068f90099e428\mscorlib.ni.dll

El problema de este vector es que: necesita de la plataforma .NET V3.0 instalada, situación que a veces no nos hemos encontrado (Win 8); que el mencionado servicio esté presente (Cardspace), y por último que la dll no esté cargada por ningún otro proceso. Esta casuística hace que el vector no sea totalmente estable, por lo tanto se requiere algo más genérico y nativo.

La aproximación seguida para identificar nuevas dlls o exe candidatos fue utilizar las herramientas de sysinternals: accesschk y procmon. Con la primera establecimos un filtro para obtener todos los archivos con permiso de escritura para el usuario SYSTEM dentro de System32.

AccessChk>accesschk64.exe -w -s system c:\windows\System32 | findstr “.dll”

Tras algunas horas probando e identificando posibles candidatos, se identificó la siguiente dll.

C:\Windows\System32\DriverStore\FileRepository\wpdmtp.inf_x86_neutral_28f06ca2e38e8979\WpdMtp.dll

Como se aprecia en la captura, el usuario SYSTEM tiene permisos de acceso total “F”, por lo que ahora tenemos que ver si somos capaces de hacer que este elemento se cargue como SYSTEM desde usuario plano.

Para ello, primero hay que saber qué objetivo tiene la dll. Como se ve en la imagen, esta librería es la encargada de gestionar la transferencia de ficheros de dispositivos MTP (Multimedia Transfer Protocol) compatibles, cuando se conectan por USB. Es decir, cuando conectamos por ejemplo un terminal móvil al equipo, el proceso encargado de instalar los drivers (Drvinst.exe) carga esta dll y habilita el intercambio de datos multimedia. Este proceso se realiza por parte del usuario SYSTEM. Este vector tiene el hándicap de que se requiere acceso físico a la máquina para conectar el Smartphone. Pero este aspecto se podría evitar emulando vía software el dispositivo USB. Hay un framework de Microsoft que lo permite, no obstante no he llegado a profundizar en ello.

Por lo tanto en este punto tenemos tres formas o vectores diferentes para poder escalar privilegios:

  • El servicio cardspace, valido para Windows 7, 8, 2008 (Enterprise R2) que tengan .NET v3 instalado. En Windows 2008 Standard SP1 no lo he conseguido explotar.
  • El driver MTP, valido para 7, 8.
  • El driver XPS printer original de Sandboxscaper para 8, 2012 y 10 (posiblemente 2016 también pero no lo he probado).

Por lo tanto combinando los tres cubrimos el espectro de soluciones más modernas de Microsoft en 32 y 64 bits, haciendo mucho más portable y estable el exploit. Vamos a comentar ahora un poco por encima los elementos que lo componen y como usarlo.

En el directorio raíz encontramos lo siguiente:

Dos dlls (32 y 64 bits ) que son los payloads que queremos cargar, es decir esta es la dll que sustituirá a la original, el exploit detecta la arquitectura y elige una de las dos. Todas las POCs vistas en este punto ejecutan una bonita calculadora que básicamente no sirve para nada en un pentesting, así que os dejo estas que crean un usuario administrador local con las siguientes credenciales:

  • Usuario: mummy
  • Pass: Mys3cretPass.

Ojo porque el payload está para la versión inglesa de Windows por lo que el grupo de administradores es “administrators”. En la carpeta cmddll podéis modificaros vosotros mismos la lógica y cambiarlo al español, solo tenéis que renombrarla a cmdll32.dll o cmdll64.dll respectivamente y dejarlas en el mismo path que el tsalpc.exe.

Un único exploit ejecutable de 32 bits (funcional en 64 bits también) encargado de ejecutar en orden los 3 vectores candidatos, en el momento que uno de ellos tiene éxito no procede con el resto.

La captura anterior es por ejemplo de un Windows 8 64 bits donde no presenta instalado el .net v3.0 y por lo tanto el servicio cardspace no está, por lo que el segundo vector (MTP) hace explotable la vulnerabilidad.

Podemos seleccionar un vector concreto pasándole como opción el nombre del candidato tsalpc.exe [cardman/mtp/printer], por ejemplo si solo queremos probar “cardman” sería de la siguiente manera.

> tsalpc.exe cardman

Si queremos que automáticamente realice un autopwn, tan solo llamamos al binario sin parámetros.

> tsalpc.exe

En el caso de que ninguna de las tres opciones fuera explotable, el exploit permite pasarle por parámetro el path del fichero que queremos sobrescribir, abriendo la puerta al lector a que descubra sus propias dlls candidatas o por ejemplo modificar los permisos sobre un fichero a su elección:

Un consejo, cuando ejecutéis el exploit, tratad de tener los menores aplicaciones y ventanas abiertas, esto minimiza la probabilidad de que las dlls candidatas hayan sido cargadas por algún proceso previamente.

Por lo que respecta a la detección antivirus, en los motores que se ha probado son:

  • Windows Defender: detectado
  • Symantec: no detectado
  • Bitdefender: no detectado
  • Trend Micro: no detectado

Os dejo adjunto en este post tanto los binarios como el fuente, Happy hacking. – Descargar exploit – (Contraseña: 12345)