原文連結:https://itm4n.github.io/lsass-runasppl/
關於在Windows上防止憑據被盜的保護,啟用LSA Protection(RunAsPPL)LSASS可能被認為是第一個實施的建議。但是您真的知道PPL是什麼嗎?在這篇文章中,我想介紹一些有關「受保護進程」的核心概念,並為後續幾天要發布的文章做準備。
介紹當你想想看,RunAsPPL對於LSASS一個真正的利器。配置非常容易,因為您要做的唯一一件事就是在註冊表中添加一個簡單的值,然後重新啟動。像其他任何保護一樣,僅靠它是不夠的,但是它仍然特別有效。攻擊者若想解決該問題,就必須使用一些相對高級的技巧,最終增加了被檢測到的機率。
因此,作為安全顧問,這是我通常向客戶提出的最重要的建議之一。但是,從客戶的角度來看,我注意到這種保護傾向於與 Credential Guard[1] 混淆,後者是完全不同的。我認為這種混淆是由於儘管Credential Guard和LSA Protection實際上是互補的,但後者似乎提供了更強大的機制。
但是作為顧問,如果您想說服客戶他們同時實行這兩項防禦措施,就必須解釋這些概念。不久前,我說我認為的LSA Protection意思就是:「只有經過數字籤名的二進位文件才能訪問受保護的進程」。您可能已經注意到,這句話沒有什麼深意,讓我意識到我並不真正了解LSA Protection的工作方式。因此,我做了一些研究,發現了一些非常有趣的東西,這也是我為什麼要寫這篇文章。
免責聲明:我在這篇文章中討論的大多數概念已經被微軟官方文檔和 Windows Internals 7th Edition[2] 所涵蓋,這是我的兩個主要信息來源。這篇博客文章的目的不是解釋它們,而是收集我認為從安全顧問的角度來看最有價值的信息。
如何啟用LSA保護(RunAsPPL)如前所述,RunAsPPL啟用非常容易。該過程在官方文檔中有詳細說明,並且之前在許多博客文章中也介紹了該過程。
如果要在公司環境中啟用它,則應遵循Microsoft提供的文檔創建一個組策略:配置其他LSA保護[3]。但是,如果您只想在一臺計算機上手動啟用它,則只需:
1.以管理員身份打開註冊表編輯器(regedit.exe);2.找到 HKLM\SYSTEM\CurrentControlSet\Control\Lsa3.添加DWORD值RunAsPPL並將其設置為1;4.重啟。
image.png就是這樣!大功告成!
在整個公司環境中應用此設置之前,需要考慮兩個特殊情況。它們都在官方文檔中進行了描述。如果對以下兩個問題中至少一個的回答為「是」,則需要採取一些預防措施。
1.您是否使用任何第三方身份驗證模塊?2.您是否使用UEFI和/或安全啟動?
第三方身份驗證模塊–如果需要第三方身份驗證模塊(例如在智慧卡讀卡器中),則應確保它們滿足此處列出的要求:受保護進程的插件或驅動要求[4]。最基本的,該模塊必須使用Microsoft籤名進行數字籤名,並且必須符合Microsoft安全開發生命周期(SDL)。該文檔還包含一些有關如何在推出階段之前設置審核策略的說明,以確定如果RunAsPPL啟用該模塊是否將被阻止。
安全啟動–如果啟用了安全啟動,例如現代筆記本電腦通常會啟用安全啟動,則需要注意一件事。當RunAsPPL啟用時,將設置存儲在固件,在UEFI變量。這意味著,一旦設置了註冊表項並且計算機已重新啟動,刪除新添加的註冊表值將無效並RunAsPPL保持啟用狀態。如果要禁用保護,則必須遵循Microsoft在此處提供的步驟:禁用LSA保護[5]。
你現在抓不到密碼了!到現在為止,我想大家都知道,RunAsPPL對一些抓密碼的工具防護很有效,如Mimikatz(在接下來的部分更多的事情)或ProcDump。因此,如下所示的輸出應該看起來很熟悉。
image.png此屏幕快照顯示了幾件重要的事情:
1.當前用戶是默認Administrators組的成員;2.當前用戶擁有SeDebugPrivilege(儘管當前已被禁用);3.該命令privilege::debug在Mimikatz成功啟用SeDebugPrivilege;4.該命令sekurlsa::logonpasswords失敗,並顯示錯誤代碼0x00000005。
因此,儘管當前用戶擁有所有特權,該命令仍然失敗。要理解為什麼,我們應該看看kuhl_m_sekurlsa_acquireLSA()在mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.c的代碼。這是代碼的簡化版本,僅顯示我們感興趣的部分。
HANDLE hData = NULL;DWORD pid;DWORD processRights = PROCESS_VM_READ | PROCESS_QUERY_INFORMATION;
kull_m_process_getProcessIdForName(L"lsass.exe", &pid);hData = OpenProcess(processRights, FALSE, pid);
if (hData && hData != INVALID_HANDLE_VALUE) { } else { PRINT_ERROR_AUTO(L"Handle on memory");}在此代碼段中,PRINT_ERROR_AUTO是一個宏,該宏基本上列印出失敗的函數的名稱以及錯誤代碼。錯誤代碼本身是通過調用檢索的GetLastError()。對於那些不熟悉Windows API工作方式的人,您只需要知道這一點,SetLastError()並且這GetLastError()是兩個Win32函數,可用來設置和獲取最後的標準錯誤代碼。此處列出了前500個代碼:系統錯誤代碼(0-499)[6]。
除此之外,其餘代碼非常簡單。它首先獲取被調用進程的PID,lsass.exe然後嘗試通過標誌並通過調用Win32函數將其打開(即獲取進程句柄)。我們在上一個屏幕截圖中看到的是,此功能失敗,並顯示錯誤代碼,僅表示「訪問被拒絕」。這確認了一旦啟用,即使具有的管理員也無法使用所需的訪問標誌打開。 PROCESS_VM_READ PROCESS_QUERY_INFORMATION OpenProcess 0x00000005 RunAsPPL SeDebugPrivilegeLSASS
到目前為止,我已經解釋的所有內容都可以視為常識,因為之前在許多其他博客文章或滲透測試備忘單中已經討論過這些內容。但是我必須做一下總結,以確保我們都在同一頁上,並且還介紹了以下部分。
使用當前已知的技術繞過RunAsPPL在撰寫此博客文章時,有三種主要的已知技術可以繞過RunAsPPL和訪問lsass.exe(或一般而言任何其他PPL)的內存。這已經在其他博客文章中討論過了,因此我將儘量保持簡短。
利用mimikatz的mimidrv.sys在前面的部分中,我說過RunAsPPL有效地阻止了Mimikatz訪問的內存lsass.exe,但是該工具實際上也是繞過它的最普遍的技術。
為此,Mimikatz使用數字籤名的驅動程序來刪除內核中Process對象的保護標誌。該文件mimidrv.sys必須位於當前文件夾中,以便使用命令作為內核驅動程序服務加載!+。然後,您可以使用命令!processprotect刪除保護並最終訪問lsass.exe。
mimikatz mimikatz mimikatz mimikatz image.png完成後,您甚至可以使用相同的命令「恢復」保護,而無需使用/remove參數,最後使用卸載驅動程序!-。
image.png如果您這樣做,則需要注意一件事!您必須知道Mimikatz 不能將保護級別恢復到原始級別。下面的兩個屏幕截圖顯示了lsass.exe發出命令前後該過程的保護級別!processprotect /process:lsass.exe。正如你所看到的,當RunAsPPL被啟用,保護等級為PsProtectedSignerLsa-Light,而它PsProtectedSignerWinTcb的保護是後恢復 通過Mimikatz。在某種程度上,這使系統比在下一部分中看到的更加安全,但是它也可能具有一些不良的副作用。
image.pngimage.png方法二:用自己的驅動先前方法的主要缺點是可以很容易地被防病毒軟體檢測到。例如,即使您能夠在內存中執行Mimikatz,您仍然必須將其複製mimidrv.sys到目標上。此時,您可以考慮編譯驅動程序的自定義版本,以逃避基於籤名的檢測,但這也會破壞文件的數字籤名。因此,除非您願意支付幾百美元來籤署新的驅動程序,否則不會這樣做。
如果您不想執行正式的籤名過程,則可以使用一個巧妙的技巧。這個技巧包括加載一個官方的,易受攻擊的驅動程序,可以利用該驅動程序在內核中運行任意代碼。一旦加載了驅動程序,就可以從User-land利用它來加載未籤名的驅動程序。例如,這項技術是在gdrv-loader[7]和PPLKiller[8]中實現的。
方法三:pypykatz後兩種技術都依賴於使用驅動程序來在內核中執行任意代碼並禁用進程保護。這樣的技術仍然非常危險,犯了一個錯誤,就會觸發BSOD。
不過,最近,@SkelSec提出了另一種訪問方法lsass.exe。在題為Duping AV with handles[9]的文章中,他介紹了一種繞過AV檢測/阻止對LSASS進程的訪問的方法。
如果要訪問LSASS的內存,則要做的第一件事是調用OpenProcess以獲取對Process對象具有適當權限的句柄。因此,某些反病毒軟體可能會阻止此類嘗試,從而在早期階段有效地終止攻擊。SkelSec描述的技術背後的想法很簡單:根本不要調用 OpenProcess。但是,那您如何獲得初始處理呢?答案來自以下觀察。有時,其他進程,例如防病毒軟體,已經在其內存空間中的LSASS進程上打開了句柄。因此,作為具有調試特權的管理員,您可以將此句柄複製到您自己的進程中,然後使用它來訪問LSASS。
事實證明,該技術還有另一個目的。它也可以用來繞過,RunAsPPL因為某些不受保護的進程可能已經通過另一種方式(例如使用驅動程序)獲得了LSASS進程的句柄。在這種情況下,可以通過以下命令使用pypykatz。
pypykatz live lsa --method handledup什麼是PPL流程?有趣的部分到了。在前面的段落中,我故意掩蓋了一些關鍵概念。我選擇展示所有眾所周知的事物,以便在這裡對其進行更詳細的說明。
首先,PPL表示「受保護的流程」,但在此之前,只有「受保護的流程」。Windows Vista / Server 2008引入了受保護進程的概念,其目的不是保護您的數據或憑據。其最初目標是保護媒體內容並符合DRM(數字版權管理)要求。Microsoft開發了此機制,以便您的媒體播放器可以讀取例如藍光,同時防止您複製其內容。當時的要求是映像文件(即可執行文件)必須使用特殊的Windows Media證書進行數字籤名(如Windows Internals的「受保護的過程」部分所述)。
在實踐中,一個受保護的過程可通過未保護的過程僅具有非常有限的權限訪問:PROCESS_QUERY_LIMITED_INFORMATION,PROCESS_SET_LIMITED_INFORMATION,PROCESS_TERMINATE和PROCESS_SUSPEND_RESUME。對於某些高度敏感的過程,甚至可以減少此設置。
幾年後,從Windows 8.1 / Server 2012 R2開始,Microsoft引入了Protected Process Light的概念。PPL實際上是對先前「受保護過程」模型的擴展,並添加了「保護級別」的概念,這基本上意味著某些PP(L)進程可以比其他進程受到更多保護。
保護等級進程的保護級別已添加到EPROCESS內核結構中,並且更具體地存儲在其Protection成員中。該Protection成員是一個PS_PROTECTION結構,在此處進行了說明。
typedef struct _PS_PROTECTION { union { UCHAR Level; struct { UCHAR Type : 3; UCHAR Audit : 1; UCHAR Signer : 4; }; };} PS_PROTECTION, *PPS_PROTECTION;儘管將其表示為結構,但所有信息都存儲在單個字節的兩個半字節中(Level是a UCHAR,即an unsigned char)。前3位代表保護Type(見PS_PROTECTED_TYPE下文)。它定義過程是PP還是PPL。後4位代表Signer類型(請參見PS_PROTECTED_SIGNER下文),即實際的保護級別。
typedef enum _PS_PROTECTED_TYPE { PsProtectedTypeNone = 0, PsProtectedTypeProtectedLight = 1, PsProtectedTypeProtected = 2} PS_PROTECTED_TYPE, *PPS_PROTECTED_TYPE;
typedef enum _PS_PROTECTED_SIGNER { PsProtectedSignerNone = 0, PsProtectedSignerAuthenticode, PsProtectedSignerCodeGen, PsProtectedSignerAntimalware, PsProtectedSignerLsa, PsProtectedSignerWindows, PsProtectedSignerWinTcb, PsProtectedSignerWinSystem, PsProtectedSignerApp, PsProtectedSignerMax } PS_PROTECTED_SIGNER, *PPS_PROTECTED_SIGNER;您可能已經猜到了,進程的保護級別由這兩個值的組合定義。下表列出了最常見的組合。
image.pngSigner Types在「受保護進程」的早期,保護級別是二進位的,即某個進程是否受保護。我們看到在Windows NT 6.3中引入PPL時,情況發生了變化。PP和PPL現在都具有一個保護級別,該保護級別由籤名者級別確定,如上所述。因此,要知道的另一件有趣的事情是如何確定籤名者類型和保護級別。
這個問題的答案很簡單。儘管有一些例外,但籤名者級別最常見的是由文件的數字證書中的特殊欄位確定的:增強密鑰用法(Enhanced Key Usage 簡稱EKU)。
image.png在此屏幕截圖中,您可以wininit.exe在左側和SgrmBroker.exe右側看到兩個示例。在這兩種情況下,我們都可以看到EKU欄位包含代表Windows TCB Component籤名者類型的OID 。第二個突出顯示的OID代表保護級別,Protected Process Light在wininit.exe和Protected Process的情況下都是如此SgrmBroker.exe。結果,我們知道後者可以作為PP執行,而前者只能作為PPL執行。但是,它們都將具有WinTcb級別。
保護優先級需要討論的最後一個關鍵方面是保護優先級。在Windows Internals 7th Edition第1部分的「 Protected Process Light(PPL)」部分中,您可以閱讀以下內容:
在解釋進程時,請記住,首先,受保護的進程始終勝過PPL,其次,較高價值的籤名者流程可以訪問較低的籤名者流程,反之亦然。
換句話說:
•PP可以打開具有完全訪問權限的PP或PPL,只要其籤名者級別大於或等於此級別即可;•一個PPL可以打開另一個具有完全訪問權限的PPL,只要其籤名者級別大於或等於該PPL;•PPL不能打開具有完全訪問權限的PP,無論其籤名者級別如何。
注意:毫無疑問,ACL檢查仍然適用。成為受保護的流程並不能賦予您超能力。如果您以低特權用戶身份運行受保護的進程,則將無法神奇地訪問其他用戶的進程。這是附加保護。
為了說明這一點,我選擇了3個易於識別的進程/圖像文件:
•wininit.exe –會話0初始化•lsass.exe – LSASS流程•MsMpEng.exe – Windows Defender服務
image.pngimage.png這3個PPL的運行方式NT AUTHORITY\SYSTEM與之相同,SeDebugPrivilege因此在此示例中無需考慮用戶權限。這全部歸結為保護級別。正如wininit.exe籤名者類型WinTcb(對於PPL而言,這是最大可能的值)一樣,它可以訪問其他兩個進程。然後,lsass.exe可以MsMpEng.exe在籤名者級別Lsa高於時訪問Antimalware。最後,MsMpEng.exe由於它具有最低級別,因此不能訪問其他兩個進程。
結論最後,受保護過程(輕量級)的概念仍然是對Userland的保護。它旨在防止普通應用程式(即使具有管理員權限)訪問受保護的進程。這就解釋了為什麼大多數常見的繞過這種保護的技術都需要使用驅動程序。如果您能夠在內核中執行任意代碼,則可以(幾乎)執行所需的任何操作,並且完全可以禁用對任何Protected Process的保護。當然,多年來,由於您現在需要加載數字籤名的驅動程序,這變得有些複雜,但是如我們所見,此限制可以解決。
在本文中,我們還看到該概念已從基本的未受保護的模型演變為分層模型,在分層模型中,某些進程可能比其他進程受到更多保護。特別是,我們看到「 LSASS」具有其自己的保護級別– PsProtectedSignerLsa-Light。這意味著具有較高保護級別的進程(例如:「 WININIT」)仍然可以完全訪問權限打開該進程。
我沒有提到PP / PPL的一個方面。這裡的「 PPL」中的「 L」是有原因的。確實,通過使用「受保護的過程燈」的概念,整體安全模型被部分地放寬了,這為Userland的利用打開了方便之門。在接下來的幾天中,我將發布本文的第二部分,以討論其中一種技術。這也將伴隨著新工具PPLdump的發布。顧名思義,此工具為本地管理員提供了僅使用Userland技巧即可轉儲任何PPL進程的內存的功能。
最後,我想提一下,這項研究和開發工作部分是根據我在SCRT的工作而完成的。因此,下一部分將發布在他們的Blog上,但我會讓您發布在Twitter上。最好的還沒有到來,敬請期待!
連結與資源Microsoft-如何配置憑據的其他LSA保護 https://docs.microsoft.com/zh-cn/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection
Windows Internals 7th Edition(Part 1) https://docs.microsoft.com/zh-cn/sysinternals/resources/windows-internals
References[1] Credential Guard: https://docs.microsoft.com/en-us/windows/security/identity-protection/credential-guard/credential-guard
[2] Windows Internals 7th Edition: https://docs.microsoft.com/en-us/sysinternals/resources/windows-internals
[3] 配置其他LSA保護: https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection#to-enable-lsa-protection-using-group-policy
[4] 受保護進程的插件或驅動要求: https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection#protected-process-requirements-for-plug-ins-or-drivers
[5] 禁用LSA保護: https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection#to-disable-lsa-protection
[6] 系統錯誤代碼(0-499): https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
[7] gdrv-loader: https://github.com/alxbrn/gdrv-loader
[8] PPLKiller: https://github.com/RedCursorSecurityConsulting/PPLKiller
[9] Duping AV with handles: https://skelsec.medium.com/duping-av-with-handles-537ef985eb03分享、點讚、在看就是對我們的一種支持!