通過對網絡訪問帳戶進行解密來探索 SCCM
Microsoft系統中心配置管理器(SCCM)。SCCM是一款微軟產品體系架構下的桌面端,服務器,移動端管理產品。主要是負責桌面標準化,網絡批量安裝部署軟件和操作系統,殺毒策略,資產收集,移動端管理等等。是一款作為IT管理員,企業基礎架構管理的必備工具。在這篇文章中,我們將介紹 SCCM 如何使用其 HTTP API 來初始化客戶端。我們還將了解如何從 SCCM 檢索網絡訪問帳戶,以及我們如何解密這些憑據而無需使用 DPAPI 或管理員帳戶。
實驗室設置
對于我們的實驗室設置,我們將使用默認的 SCCM 部署。我發現最簡單的方法是通過自動化實驗室,它支持通過 ConfigurationManager 角色進行安裝:

我們將在這篇文章中使用的版本是 Configuration Manager 2103,我們將把我們的主站點命名為 P01。本實驗的服務器將稱為 SCCM01,我們將配置為使用 HTTP 進行通信。
一旦SCCM服務器的設置完成,我們將把一切都保留為標準,并添加一個Network Access Account供以后使用:

完成后,我們就可以繼續探索了!
客戶端注冊
讓我們首先看看客戶機嘗試向SCCM注冊時生成的請求。為了做到這一點,我們使用@_Mayyhem awesome SharpSCCM工具:

當 SharpSCCM 調用實際的 .NET 客戶端庫時,我們會收到一個清晰的請求,我們可以使用 WireShark 來識別它。客戶端向 SCCM 服務器注冊的初始步驟如下:

這個 HTTP 請求被發送到 SCCM 服務器,由兩部分組成,一個是 XML 編碼的標頭,另一個是在多部分/混合 HTTP 請求中發送的 XML 編碼的正文。有趣的是,該協議還使用了 CCM_POST 的 HTTP 方法。
標頭采用 UTF-16 編碼,如下所示:

請求正文是zlib壓縮和Unicode編碼:

為了簡單起見,我刪除了一些較長的十六進制字符串,但我們在這里看到的是三個十六進制blob被發送到服務器,以及一些關于我們的客戶端的初始信息。
讓我們轉儲 Signing blob:

如果我們看這個,我們實際上會看到這是一個 DER 編碼的證書:

生成此證書時,添加了兩個擴展密鑰使用 OID:

這些將證書標記為短信簽名證書(自簽名)。
因此,我們看到客戶端證書被傳遞給SCCM服務器以供稍后使用,但是SignatureValue字段呢?讓我們啟動dnSpy并深入研究System.ConfigurationManagement.Messaging.dll程序集,該程序集位于安裝了客戶端的主機上的 C:\Windows\CCM 中。
經過一番搜尋,我們在Interop.Crypt32.HashAndSignData中找到了答案:

這表明,使用帶有PKCSv15填充的RSA- sha256正在使用與證書關聯的 RSA 私鑰對 XML 請求正文進行簽名。
這里需要注意的一件奇怪的事情是,一旦生成簽名,字節在ASCII十六進制編碼并添加到請求ˉ\_(ツ)_/ˉ之前會被反轉。
當服務器響應這個客戶端注冊請求時,我們再次看到有一個 XML 標頭和正文,其中正文數據被 zlib 壓縮。可以看到我們被分配給了 ClientID,它是在我們的客戶端與服務器通信期間使用的 UUID:

在這個階段值得注意的是,這個請求可以發送到未經身份驗證的SCCM URL http://SCCM01/ccm_system/request。這足以向SCCM添加一個客戶端條目,但是我們將處于“未批準”狀態。這種狀態在以后會變得很重要:

政策要求
客戶端注冊后,客戶端執行的下一個階段是檢索策略列表。此調用還使用

不幸的是,這是事情變得有點復雜的地方。我們首先需要關注的是 PublicKey blob。這實際上只是客戶端之前為證書生成的 RSA 公鑰,但是這次它被編碼為 PUBLICKEYBLOB。
接下來是 ClientIDSignature。這是我們之前看到的用于簽署 ClientID 的 RSA-SHA256 簽名,前面帶有 GUID:,然后轉換為 Unicode。例如:

最后是PayloadSignature,它是隨后壓縮的主體的簽名。
這個請求的主體是 zlib 壓縮和 Unicode 編碼的,帶有我們客戶端的信息:

對該請求的響應是XML主體中可用的策略列表:


雖然這里有很多有趣的東西,但我們現在要關注的領域將是網絡訪問帳戶的共享方式。
秘密政策
如果你遍歷我們檢索到的策略列表,你一定會遇到標記為“秘密”的策略。其中一個策略是NAAConfig,它包含了網絡訪問帳戶:

你可能已經看到 @gentilkiwi 在 2021 年發布的 Mimikatz 更新中引用了這些帳戶,這表明通常這些憑據是在 SCCM 客戶端上使用 DPAPI 加密的:

但是,如果我們嘗試使用 RequestAssignments 請求返回的 URL 直接下載此策略,我們會看到出現一個錯誤。

這樣做的原因是需要對秘密策略的請求進行身份驗證。但是由于這是SCCM,所以還需要進行另一種類型的身份驗證。
經過一番搜尋之后,我發現了對 SCCM 服務器上名為 ccmgencert.dll 的 DLL 中使用的身份驗證類型的引用:

既然我們知道了一些使用的簽名方法,這些標頭實際上可以很容易被創建。看看被添加到SCCM平臺的客戶端,我們看到它們是這樣的:

ClientToken只是我們的cliententid和當前DateTime的一個連接。ClientTokenSignature是使用上面相同的RSA-SHA256算法的簽名。
讓將這些標頭添加到我們的請求中,看看會得到什么:

這一次,我們得到了不同的回應。我的意思是我們出現錯誤,但我們也沒有得到任何不好的數據。
事實證明,對于我們的客戶端實際請求秘密策略,他們需要在服務器上處于 Approved 狀態。
默認情況下,SCCM 安裝有以下內容:

那么,計算機是如何自動自我認可的呢?還有另一個URL被/ccm_system_windowsauth/request的客戶端使用。如果之前的XML ClientRegistrationRequest被發送到這個路徑,并完成NTLMSSP驗證計算機帳戶,則客戶端設置為 Approved 狀態:

現在,當對此 URL 進行身份驗證時,我們似乎可以使用任何隨機域用戶帳戶。然而,問題是它似乎不足以迫使客戶進入批準狀態。相反,我們需要使用計算機帳戶(盡管它不需要與我們嘗試注冊的客戶端相對應),所以 addcomputer.py 在這里非常有用。

通過將此身份驗證步驟添加到我們的注冊請求并強制我們的客戶端進入 Approved 狀態,下次我們請求 NAAConfig 策略時,我們會得到如下所示的內容:

好吧,回到 dnSpy,我們去嘗試弄清楚。答案在 Interop.DecryptMessageFromCertificateFile 方法中找到,該方法顯示了 CryptDecryptMessage API 調用的使用。

參數顯示此加密策略是使用 3DES CBC 的 PKCS7 編碼 blob,其密鑰源自我們之前在證書中提供的 RSA 公鑰。
解密后,我們終于看到了一些實際的憑證,如下所示:

網絡訪問帳戶混淆
起初,獲取這些賬戶似乎需要更多的加密貨幣。但是 MimiKatz 已經向我們展示了這些憑據最終可以在客戶端上訪問,因此我們知道我們的客戶端必須能夠在使用 DPAPI 保護它們之前以某種方式解密這些憑據……那么密鑰是什么?在尋找這個加密是如何完成的之后,我在客戶端上找到了一個名為 PolicyAgent.dll 的 DLL。
最重要的是調試字符串:

UnobfuscateString 聽起來很有希望,當然聽起來比 DecryptString 更好。我沒有深入研究這個反匯編的所有部分,而是創建了一個快速調試工具來調用這個函數。

當運行在與SCCM實驗室網絡無關的主機上時,并且連接到調試器以逐步解決通過以這種方式調用方法而發生的不可避免的訪問沖突時,就會解密用戶名和密碼:


這意味著所使用的加密與描述的完全一樣,它是被混淆的!我們擁有在密文中解密這些憑證所需的所有信息,而且我們可以完全離線完成!
通過重新創建unobfuscation方法的步驟,我們可以創建如下所示的解密代碼。

有了計算機帳戶,我們就可以在SCCM 中添加虛假客戶端,下載加密的網絡訪問帳戶憑據,并對其進行解密,而無需處理提升權限或任何 DPAPI 解密。
參考及來源:https://blog.xpnsec.com/unobfuscating-network-access-accounts/