你並不懂 Mimikatz Part 1-Wdigest SSP
n1nty@360 A-TEAM
有不少文章說過 Mimikatz 能導出明文密碼的原因是因為 Wdigest SSP 在內存中以加密的形式保存了用戶的明文。但也僅此而已,從沒看到有文章說為什麼 Wdigest SSP 會這麼做。
緩存在 LSASS 中的明文憑據(或可逆的密文)
根據微軟官方博客的說法,在 KB2871997 出現之前,除了 Wdigest SSP 外,還有其他幾個 SSP 也會在用戶進行了互動式登陸後緩存用戶的明文憑據。在 KB2871997 後,就只有 Wdigest SSP 依然有可能緩存用戶明文憑據(取決於註冊表中 UseLogonCredential 的值)。
Digest
與 NTLM 類似也一種挑戰認證的協議,MSDN 的文檔說這個協議目前主要只用於 IIS 與 LDAP。
挑戰認證的基本流程就是:
客戶端訪問服務端發起認證
服務端返回一個隨機值
客戶端利用自己知道的密碼或一些其他信息來對這個隨機值做一些計算,得運算結果 response,將 response 發送至服務端
服務端利用同樣的方法也計算出一個 response,並將自己計算出的這個與客戶端發送過來的 response 進行對比,如果一致,則證明客戶端確實是知道密碼,認證成功。
關於 Digest 認證,有兩份 RFC 文檔:
RFC 2069
RFC 2617
微軟的 Digest SSP(wdigest.dll)是對這兩份 RFC 的實現。Digest 本身並不是一個非常安全的認證協議,它出現的主要目的是為了替代 HTTP BASIC 認證。BASIC 認證會直接將認證的賬號密碼以近乎明文(BASE64)的方式發送,Digest 是為了解決這個問題。並且 Digest SSP 只能用於進行域賬號認證,不能像 NTLM 一樣進行本地賬號認證。
RFC 2069 中 Response 的計算方式
Hash1=MD5(username:realm:password)
Hash2=MD5(method:digestURI)
response=MD5(Hash1:nonce:Hash2)
各個欄位解釋
RFC 2617 中 Response 的計算方式
Hash1=MD5(username:realm:password)
Hash2=MD5(method:digestURI)
response=MD5(Hash1:nonce:nonceCount:cnonce:qop:Hash2)
相比 2069 中的計算方式,2617 的計算方式包含了幾個新的欄位。我沒去深究這些欄位到底是做什麼的,因為跟主題無關。
Digest 驗證與明文憑據
可以看到前面無論是 RFC 2069 還是 RFC 2617,在計算 Hash 1 的時候,都需要用到明文密碼。
所以,在用戶進行了互動式登陸後,為了實現 Digest 認證機制的 SSO,Digest SSP 只能將密碼加密後保存在內存裡面,在有任何客戶端軟體需要與遠程伺服器進行 Digest 認證的時候解密還原成明文用於計算 Digest response。
Digest 客戶端 與 Digest 服務端
使用 Digest SSP 與遠程伺服器進行身份認證的一端叫做 Digest 客戶端,而接收並驗證 Digest 客戶端發起的驗證請求的是 Digest 服務端。
Digest 服務端(MSDN 文檔說 Digest 認證一般情況下只用於 IIS 和 LDAP,那麼可以將 Digest 服務端狹義地理解為 IIS 或 LDAP,當然肯定其他的程序也可以用)為了驗證 Digest 客戶端發送過來的 Response 是否正確,所以他自身也要計算 Response,來與客戶端 response 進行對比。所以,Digest 服務端也會需要用到賬號的明文密碼(為了不超出本文主題,這裡省略了一點東西),所以要求被驗證的賬號的密碼需要被明文保存在域里,所以這裡就涉及到 Windows 域的 Reversible Encryption 功能(MSDN 說 Digest SSP 只能用於在域環境下進行域賬號的身份驗證)。
Reversible Encryption
默認情況下,域里的所有賬號都是關閉這個功能的(在沒有 Advanced digest 的時候,關閉了這個功能的域賬號將不能使用 digest 進行認證)。所以,域資料庫裡面默認只保存了密碼的 Hash 而沒有保存密碼本身。
開啟 Reversible Encryption 的三種方法:
在域控的組策略裡面對所有域成員開啟,此時除了 HASH 外,所有域成員的明文密碼都會以一種可逆加密的形式保存在域資料庫中。以可逆加密形式存儲的明文密碼,跟直接存儲明文沒有什麼區別
在域用戶管理裡面,單獨為某些用戶啟用 Reversible Encryption 功能。啟動了此功能的用戶會在它們的 UserAccessControl 屬性裡面留下標誌
利用 fine grained password policy 啟用
Exploit Reversible Encryption
harmj0y 與 adsecurity.org 上提到過通過開啟 Reversible Encryption 來留後門的文章:
Dump Clear-Text Passwords for All Admins in the Domain Using Mimikatz DCSync
https://adsecurity.org/?p=2053
Targeted Plaintext Downgrades with PowerView
http://www.harmj0y.net/blog/redteaming/targeted-plaintext-downgrades-with-powerview/
簡而言之
Digest 客戶端如果使用名為 user01 的域賬號與 Digest 服務端進行 Digest 身份認證,那麼就需要 user01 的密碼是以可逆加密的形式保存在域資料庫中的,否則 Digest 服務端無法計算 response,也就無法判斷 Digest 客戶端提交的認證信息是否正確。在 Windows 2003 以前,確實是這樣的,不過從 Windows 2003 開始,引入了Advanced Digest(就是 Digest 的升級版)。
Digest vs Advanced Digest
從 Windows 2003 開始, wdigest.dll 實現的就是 Advanced digest,而不再是老的 digest 認證協議了。其中一項改變就是,它允許不再存儲賬號的明文密碼。
重新來看一下 Digest Response 的計算方法:
Hash1=MD5(username:realm:password)
Hash2=MD5(method:digestURI)
response=MD5(Hash1:nonce:nonceCount:cnonce:qop:Hash2)
明文密碼是需要的因為我們要利用它來計算出 Hash 1(也被稱為 HA1)。而 Advanced digest 解決這個問題的方法就是,他會預先計算好 Hash 1。
比如域的 FQDN 為 EAST.COM,域賬號為 user01,密碼為 123456。那麼域控並不會保存 user01 賬號的明文密碼 123456,而是將 MD5(user01:EAST.COM:123456) 後的 HASH保存在域資料庫中,這樣就繞過了需要明文密碼的問題。
實際上並沒有這麼簡單,根據 [MS-SAMR] 文檔,域控一共保存了 29 種 Hash 1,計算方法分別如下:
MD5(sAMAccountName, NETBIOSDomainName, password)
MD5(LOWER(sAMAccountName), LOWER(NETBIOSDomainName), password)
MD5(UPPER(sAMAccountName), UPPER(NETBIOSDomainName), password)
MD5(sAMAccountName, UPPER(NETBIOSDomainName), password)
MD5(sAMAccountName, LOWER(NETBIOSDomainName), password)
MD5(UPPER(sAMAccountName), LOWER(NETBIOSDomainName), password)
MD5(LOWER(sAMAccountName), UPPER(NETBIOSDomainName), password)
MD5(sAMAccountName, DNSDomainName, password)
MD5(LOWER(sAMAccountName), LOWER(DNSDomainName), password)
MD5(UPPER(sAMAccountName), UPPER(DNSDomainName), password)
MD5(sAMAccountName, UPPER(DNSDomainName), password)
MD5(sAMAccountName, LOWER(DNSDomainName), password)
MD5(UPPER(sAMAccountName), LOWER(DNSDomainName), password)
MD5(LOWER(sAMAccountName), UPPER(DNSDomainName), password)
MD5(userPrincipalName, password)
MD5(LOWER(userPrincipalName), password)
MD5(UPPER(userPrincipalName), password)
MD5(NETBIOSDomainNamesAMAccountName, password)
MD5(LOWER(NETBIOSDomainNamesAMAccountName), password)
MD5(UPPER(NETBIOSDomainNamesAMAccountName), password)
MD5(sAMAccountName, "Digest", password)
MD5(LOWER(sAMAccountName), "Digest", password)
MD5(UPPER(sAMAccountName), "Digest", password)
MD5(userPrincipalName, "Digest", password)
MD5(LOWER(userPrincipalName), "Digest", password)
MD5(UPPER(userPrincipalName), "Digest", password)
MD5(NETBIOSDomainNamesAMAccountName, "Digest", password)
MD5(LOWER(NETBIOSDomainNamesAMAccountName), "Digest", password)
MD5(UPPER(NETBIOSDomainNamesAMAccountName), "Digest", password)
你使用 mimikatz 的 dcsync 或其他功能看到的一大堆 Wdigest 的 Hash,就是這 29 種 Hash。而你如果給賬號開了 Reversible Encryption ,則 dcscync 會將明文密碼讀出來,如下圖:
Advanced Digest 只能杜絕在服務端存儲明文的問題,無法解決在客戶端存儲明文的問題。因為對於域來說,它的 realm (domain name 是固定的),所以可以預先計算 Hash 1 並保存。但是對於客戶端來說,客戶端有可能利用 Digest SSP 與任何域進行認證,所以無法預先計算 Hash 1。
參考資料
https://technet.microsoft.com/pt-pt/library/cc778868(v=ws.10).aspx
https://www.wikiwand.com/en/Digest_access_authentication
https://articles.forensicfocus.com/2014/04/28/windows-logon-password-get-windows-logon-password-using-wdigest-in-memory-dump/
https://blogs.technet.microsoft.com/srd/2014/06/05/an-overview-of-kb2871997/
https://blogs.technet.microsoft.com/askpfeplat/2016/04/18/the-importance-of-kb2871997-and-kb2928120-for-credential-protection/
https://stackoverflow.com/questions/9534602/what-is-the-difference-between-digest-and-basic-authentication
https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/store-passwords-using-reversible-encryption
360 A-TEAM 是隸屬於 360 企業安全集團旗下的純技術研究團隊。團隊主要致力於 Web 滲透,APT 攻防、對抗,前瞻性攻防工具預研。從底層原理、協議層面進行嚴肅、有深度的技術研究,深入還原攻與防的技術本質。
歡迎有意者加入!
TAG:n1nty |