獨角獸暑期訓練營系列 | Windows Hash傳遞攻擊的本質、緩解及繞過
Author: 獨角獸暑期訓練營第二季-程賽,指導老師-王永濤 2018/09/04
獨角獸暑期訓練營
360無線電安全研究院每年暑假都會面向在校學生舉辦一次暑期訓練營, 申請者投遞簡歷並提交自己想做的課題介紹後 ,若入選,會在360技術專家的指導下完成課題。
本系列文章會發布今年5位學員在訓練營中的成果。文章相關程式碼後續會在訓練營 github程式碼倉庫 釋出 。
LM Hash、NTLM Hash、Net-NTLM Hash的區別與聯絡
LM Hash
LM Hash是一種較古老的Hash,在LAN Manager協議中使用,非常容易通過暴力破解獲取明文憑據。Vista以前的Windows OS使用它,Vista之後的版本預設禁用了LM協議,但某些情況下還是可以使用。
NTLM Hash
Vista以上現代作業系統使用的Hash。通常意義上的NTLM Hash指儲存在SAM資料庫及NTDS資料庫中對密碼進行摘要計算後的結果,這類Hash可以直接用於PtH,並且通常存在於 lsass 程序中,便於 SSP 使用
Net-NTLM Hash
Net-NTLM Hash用於網路身份認證(例如ntlm認證中),目前分為兩個版本:
- Net-NTLMv1
- Net-NTLMv2
通常我們使用Responder等工具獲取到的就是NetNTLM,這類hash並不能直接用來PtH,但可以通過暴力破解來獲取明文密碼
Net-NTLM出現在NTLM認證過程中,其計算過程依賴NTLM Hash
參考資料: https://medium.com/@petergombos/lm-ntlm-net-ntlmv2-oh-my-a9b235c58ed4
NTLM認證
本文提到的NTLM認證特指Microsoft NTLM Protocol。
工作組環境
NTLM認證 是一種在網路上進行認證的安全協議,其主要過程粗略地分為三步:
- 客戶端發起認證請求
- 服務端收到認證請求,向客戶端傳送隨機數(chanlleng/挑戰)
- 客戶端使用NTLM Hash打亂該隨機數,生成Net-NTLM Hash,傳送回服務端
上面的過程發生在工作組環境中,在域環境中使用NTLM Pass-Through認證,核心過程與工作組沒有太大區別:
主要區別在於Server會將認證資訊使用netlogon協議傳送給域控制器,由域控制器完成檢驗並返回認證結果
參考資料: http://davenport.sourceforge.net/ntlm.html
網路登入與非網路登入
網路登陸
在網路登入過程中不使用憑證輸入對話方塊來收集資料,而會使用到預先生成的憑據。
非網路登陸
分為網路明文登陸和互動式登陸等。這些登入型別在認證期間將使用者明文密碼傳送到伺服器。 伺服器可以在LSASS中快取這個密碼或其處理後的值,並使用它來驗證其他資源。
網路登入與NTLM認證
NTLM認證出現在網路登入中,而遠端伺服器不快取使用者憑據,這也與ntlm認證的特性相吻合。 Double-Hop的問題也與網路/非網路登入的性質有關。
PtH攻擊原理
注意:本文所指均為狹義上的Pass-the-Hash,即一種在NTLM認證中使用NTLM Hash進行認證的手段
在上面的三步過程中,我們發現並沒有使用到使用者提供的明文密碼,而是使用NTLM Hash來計算NetNTLM Hash。Hash傳遞攻擊就發生在NTLM認證的第三步,我們能使用獲取到的NTLM Hash來完成一次完整的認證。
PtH操作演示
靶機ip:
攻擊機ip:
以mimikatz為例,在攻擊機上以管理員身份執行mimikatz:
在攻擊之前我們需要知道目標賬戶名以及hash值,這裡我們假設獲取到了ntlm hash:
我們使用mimikatz來pth:
這裡需要domain,user,ntlm以及開啟的程式四個引數。預設情況下開啟cmd。 我們知道,pth只是一種無明文認證的手段,我們還需要針對具體的服務進行攻擊,這裡以smb服務為例。通常我們訪問一個unc路徑時,不考慮double-hop的情況下,如果沒有指定windows會自動用當前使用者的憑據進行ntlm認證,例如命令dir \\Target\aaa。由於windows某些ssp會在lsass中快取hash值,並使用它們來ntlm認證,那麼理論上我們如果在lsass中新增包含目標賬戶的hash的合法資料結構,就可以在使用類似dir這些命令時用目標賬戶進行認證,這也是mimikatz中pth功能的原理。 上一步裡面我們已經用mimikatz修改了記憶體中的hash值,那麼我們就能利用彈出的cmd來測試一下是否能網路登入目標系統,訪問c$共享。 這裡使用的exist使用者是非內建管理員使用者,儘管c$共享允許管理員組成員訪問,但由於uac對網路登入的限制,導致直接訪問會被Access Died:
出於演示的需要,我們把靶機上的UAC級別設定為從不通知並重啟,再次pth:
能成功訪問c$共享。
緩解手段及其侷限性或可能的繞過方式
試圖緩解PtH的危害可以從兩個方面入手(當然不僅僅是這兩方面):
- 禁止NTLM認證
- 防止NTLM Hash被獲取到
第一種方式當然是一勞永逸地阻止了PtH,但是NTLM認證已經被微軟使用了很長時間,完全禁止可能會破壞已部署的一些環境,在實際應用中阻力較大。 由於NTLM認證的天然缺陷,微軟似乎很難改變其行為,因此更多地把防禦放在了阻止Hash被獲取到這種思路。下面我們來介紹微軟釋出的一些補丁以及它們可能的繞過方式。
kb2871997
kb2871997在緩解PtH上做出了不少努力,其為windows增加的特性值得深入研究。它在win server 2012 R2及以上版本已預設整合。 根據 微軟公告 ,安裝kb2871997後會有這麼些行為:
刪除lsass的明文憑證
我們前面提到過,lsass程序會快取使用者憑據,有明文有Hash,這取決於使用的ssp型別以及補丁情況。
上圖中msv、tspkg、wdigest、kerberos這幾個ssp都獲取到了憑據,它們分別用於Terminal Server認證(RDSH),ntlm認證,摘要認證以及kerberos認證。我們能看到只有msv沒有明文密碼。從前文中對ntlm認證過程的描述,我們可以發現除了第一步客戶端要求使用者輸入明文密碼,之後的認證過程再也沒有出現過明文密碼。這也就是說,ssp只需要計算ntlm hash並放在記憶體中就行了。 我們看到摘要認證wdigest在windows 2008 中快取了明文密碼。摘要認證類似於ntlm認證,也使用了挑戰-響應機制,但它與ntlm認證較大的區別在於客戶端計算響應時,需要使用到明文密碼,為了實現SSO,需要將明文密碼放在記憶體中方便進行計算,因此客戶端一方的ssp理論上必須在記憶體中快取明文密碼,這也是為什麼我們能抓到明文密碼的原因;與之相比,NTLM SSP使用的單向函式如NTOWFv2只需要計算一次並放置在記憶體中,之後計算響應只需要這個hash值即可。
kb2871997會刪除除了wdigest ssp以外其他ssp的明文憑據,但對於wdigest ssp只能選擇禁用。使用者可以選擇將HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest\UseLogonCredential更改為0來禁用。
安裝kb2871997之後我們使用mimikatz抓取記憶體中的密碼:
wdigest ssp預設仍然在記憶體中儲存明文密碼,更改登錄檔後登出,重新登入,再次抓取:
wdigest已經抓不到明文密碼以及密碼hash。
這僅僅是增大了從記憶體中獲取ntlm hash的難度,但並不能阻止從登錄檔等其他地方獲取。
能夠禁止使用者網路登入
下圖中,工作組環境可以在本地安全策略->使用者許可權分配->拒絕從網路訪問這臺計算機配置是否允許使用者或使用者組網路登入:
理論上UAC無法限制RID為500的使用者網路登入,但打補丁並配置好禁止administrator(RID==500)網路登入,測試結果如下:
處理方式太過粗暴,可能會影響使用者正常需求。
新增“受限管理員模式”
受限管理員模式能阻止主機快取記憶體中遠端驗證使用者的憑據。 我們來做兩個測試
- 測試一: RDP客戶端使用微軟自家的mstsc,服務端未打kb2871997,不加任何引數啟動:
- 啟動連線,客戶端要求我們輸入使用者名稱和密碼:
- 登入成功後,使用mimikatz獲取記憶體中的密碼:
- 我們能夠獲取到明文密碼,ntlmssp的NTLM Hash也能獲取到,這裡就不再截圖了。
測試二:客戶端使用mstsc /restrictedadmin,也即受限管理員模式啟動,服務端支援受限管理員模式:
我們發現mstsc提示將使用我們到windows登入憑據進行連線。 如果客戶端和服務端有相同使用者名稱和密碼的賬戶,可以直接連線成功,沒有彈出要求輸入憑據的對話方塊。連線成功後,使用mimikatz獲取記憶體中的密碼:
我們發現遠端桌面會話沒有快取使用者憑據,這其實就是受限管理員模式的特性。 下面我們來聊聊為什麼會出現這種情況:
- 遠端桌面預設無約束委派使用者憑據,以達到完全在遠端伺服器上代表使用者的目的。當我們連線到遠端桌面伺服器上,可以使用dir命令連線其他的smb伺服器並使用我們的憑據認證,這是因為客戶端進行遠端桌面連線的時候會發送使用者的明文密碼,這個密碼可以用於計算NTLM Hash並快取在遠端桌面伺服器上。
- 受限管理員模式下,遠端桌面客戶端會首先使用客戶端機器上已快取的NTLM Hash進行認證,不需要使用者輸入使用者名稱和密碼,也就不會把明文密碼委派到目標;即便快取的hash認證失敗,使用者必須輸入明文密碼,mstsc也不會直接傳送明文密碼,而是計算出所需的值後再發送。這種模式下,登入到遠端桌面伺服器上並使用dir命令向其他smb伺服器認證時,將使用空使用者(使用者名稱\ )登入,幾乎都會登陸失敗。
從上面兩種模式對比可以看出,客戶端直接傳送明文密碼到服務端,可能會被mimikatz從記憶體中獲取到;而受限管理員模式則能避免傳送明文,服務端記憶體中也不會快取使用者憑據。
“受限管理員模式”的初衷是為了保護遠端桌面服務端,即當服務端被攻陷時,使用受限管理員模式可以在一定程度上保護客戶端使用者的憑據不被mimikatz等工具獲取到。因此,這個保護措施並不是直接針對PtH,效果也是有限的。 實際上受限管理員模式本身就會增加新的攻擊路徑,即可以以PtH的方式向遠端桌面伺服器發起認證。也就是說,在實際應用中,我們可以利用mimikatz的sekurlsa::pth來啟動mstsc,使用受限管理員模式來無明文密碼登入,當然也有些其他的RDP客戶端可以實現利用密碼Hash來認證,例如FreeRDP。
Protected Users
受保護使用者是一個新的域全域性安全組,對於該組的成員,Windows 8.1裝置或Windows Server 2012 R2主機不會快取受保護使用者不支援的憑據。如果這些組的成員登入到執行早於Windows 8.1的Windows版本的裝置,則該組的成員沒有其他保護。
登入到Windows 8.1裝置和Windows Server 2012 R2主機的受保護使用者組的成員不能再使用:
- 預設憑據委派(CredSSP) – 即使啟用了“ 允許委派預設憑據”策略,也不會快取純文字憑據
- Windows摘要 – 即使啟用明文憑據也不會進行快取
- NTLM – NTOWF未快取
- Kerberos長期金鑰 – Kerberos票證授予票證(TGT)在登入時獲取,無法自動重新獲取
- 離線登入 – 未建立快取的登入驗證程式
如果域功能級別是Windows Server 2012 R2,則該組的成員不能再:
- 使用NTLM身份驗證進行身份驗證
- 在Kerberos預身份驗證中使用資料加密標準(DES)或RC4密碼套件
- 通過使用無約束或約束委派來委派
- 更新使用者票證(TGT)超過最初的4小時生命週期
在域賬戶未加入Protected Users組時,我們使用mimikatz獲取記憶體中的憑據:
我們可以看到ntlmssp快取了emanon賬戶的密碼hash。我們將此使用者加入Protected Users:
登出,重新登入,再次使用mimikatz抓取密碼:
emanon使用者的ntlm hash已經無法獲取到,但機器賬戶DM1$以及本地使用者的hash仍然能獲取到,這也說明Protected Users保護範圍是有限的。 網上有些文章提到了Pass-the-Key(Overpass-the-hash),Protected Users對這種攻擊方式也有一定緩解功能。PtK是在域中攻擊kerberos認證的一種方式,據稱可以在NTLM認證被禁止的情況下用來實現類似PtH的功能(畢竟是針對kerberos認證,其實與NTLM認證沒什麼關係)。關於這種攻擊方式可以檢視本節的參考,這裡不再贅述。我們比較關心使用mimikatz來Pass-the-Key所需要的資訊,其中必須有的是請求tgt所需的使用者hash,這可以使用mimikatz中的sekurlsa::ekeys來獲取:
經測試,域功能級別為windows server 2012 R2(未測試低等級),將域使用者加入Protected Users使用者組後無法通過ekeys命令獲取Hash。當然,機器賬戶還是能夠獲取到。
Protected Users是一個域安全組,僅能在域中保護使用者,並且阻止抓取使用者Hash並沒有直面PtH這種攻擊方式,域使用者憑據仍可能通過登錄檔Cache、釣魚攻擊等方式獲取到。
參考資料: https://www.blackhat.com/docs/us-14/materials/us-14-Duckwall-Abusing-Microsoft-Kerberos-Sorry-You-Guys-Don’t-Get-It-wp.pdf
Additional LSA Protection
LSA(包括本地安全機構伺服器服務(LSASS)程序)驗證使用者是否進行本地和遠端登入,並實施本地安全策略。Windows 8.1作業系統為LSA提供額外保護,以防止未受保護的程序讀取記憶體和程式碼注入。啟用此功能後無法把debugger attach到程序上。在win8.1及2012 r2以上有效,啟用的方法是reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa /v RunAsPPL /t REG_DWORD /d 1 之後重啟。 重啟之後,使用mimikatz抓取記憶體中的密碼:
使用lsadump::lsa /inject:
同樣無法獲取到密碼hash
繞過方式
mimikatz能夠通過載入其驅動程式來繞過LSA Protection。在實際使用中需要注意mimikatz同目錄下需要有驅動程式mimidrv.sys 命令:
privilege::Debug
!+
!processprotect /process:lsass.exe /remove
測試:
參考資料: https://adsecurity.org/?page_id=1821
Microsoft本地管理員密碼解決方案(LAPS)
LAPS是用於管理計算機本地使用者密碼的一個客戶端擴充套件(CSE),在域中依賴比較少,核心在於組策略支援。 LAPS一個重要功能是隨機化所有域成員本地管理員密碼,密碼按照較強的密碼策略生成,定期修改。這使得用相同憑據橫向滲透變得很困難。
本地管理員密碼明文儲存在AD中,僅有管理員及獲得管理員委派的賬戶能訪問到。
LAPS和僅僅增大了橫向滲透的難度,並且配置上出錯也可能導致前功盡棄。LAPS配置上可能出現的一個問題是向非授權使用者授予“All Extended Rights”許可權,這導致如果我們獲取該賬戶,就能訪問AD中的密碼。
參考資料: https://github.com/leoloobeek/LAPSToolkit
Credentials Guard
Credentials Guard是win10中引入的新功能,據稱能保護NTLM密碼雜湊值,Kerberos票證授予票證和應用程式儲存的憑據。該程序是唯一能使用明文憑據的程序,它的原理大概是這樣: 當NTLM認證過程中需要用到例如ntlm hash這類憑證的時候(第三步),將Credentials Guard視為黑箱,由lsass等程序輸入生成NetNTLM所需的資訊(第二步收到的challenge等等),由CG處理並輸出結果,而CG本身記憶體禁止讀取,使得mimikatz這一類工具無從下手:
繞過方式
對付Credentials Guard有一些曲線救國的方法:
SSP的二進位制形式是DLL,提供用來處理身份認證的介面(SSPI)。如果我們無法從記憶體中直接獲取憑據,那麼通過註冊一個ssp來處理使用者登入時輸入的憑據也是一種辦法。mimikatz直接在記憶體中載入自定義的ssp dll,能夠在使用者登入時獲取到明文憑據。 演示: mimikatz 記憶體注入ssp
鎖屏等待使用者再次登入後,檢視system32下的檔案
NetNTLM Downgrade Attack
NetNTLM有兩個版本——v1和v2。v1相比v2更加脆弱,因此如果我們能將NetNTLMv2降級為v1,破解的效率會更高;如果能降級到NetLM,那麼爆破成功率就變得極高。
在 Monologue" rel="nofollow,noindex" target="_blank">這篇文章 中提到了一種迂迴獲取憑據的方式,核心思想是修改登錄檔使Windows允許在網路認證中傳送演算法較弱的NetHash例如NetNTLMv1,而實際上我們可以直接與NTLM SSP互動而不必產生網路流量,並能獲取到NetNTLMv1用於降低破解的難度。
Credentials Guard執行時,我們雖然不能直接從記憶體獲取到NTLM Hash,但利用上面提到的思路獲取NetNTLM Hash是有可能的。
Internal-Monologue.ps1使用演示:
參考資料: https://blog.nviso.be/2018/01/09/windows-credential-guard-mimikatz/ https://github.com/eladshamir/Internal-Monologue https://technet.microsoft.com/en-us/library/2006.08.securitywatch.aspx
總結
由於NTLM認證本身具有缺陷性,導致攻擊者可以在不知道明文密碼,只知道密碼Hash的情況下完成認證。這個缺陷就目前來看無法修復,微軟也只能建議使用更安全的kerberos協議來代替ntlm協議,而其釋出的補丁也並沒有觸及PtH這種攻擊思想的本質,僅僅是增大了攻擊的難度或者粗暴地禁止NTLM認證,因此依然存在繞過的可能。
Thanks
我在學習及研究過程中受到 @360無線電安全研究院&天馬安全團隊 及@SycloverSecurity的大力支援與幫助,在此表示衷心的感謝。