當前位置:
首頁 > 新聞 > 高級域滲透技術之再談Kerberoast攻擊

高級域滲透技術之再談Kerberoast攻擊

Rebeus是一個用C#編寫Kerberos 濫用工具包,最初是由@gentilkiwi 編寫的 Kekeo 工具包中的一個埠,這個工具包從那時起就在不斷發展。要了解更多關於 Rubeus 的信息,請查看"從 Kekeo 到 Rubeus"這篇文章後續的"Rubeus ——Now With More keo"或最近修訂的 Rubeus README.md。

我最近對 Rubeus 做了一些改進,其中包括重新審查了它的 kerberos 實現。 這導致了對 Rubeus 的 Kerberoast 方法的一些修改,也解釋了我們之前在這個領域看到的一些"奇怪"的行為。 由於 kerberos 是一種如此常用的技術,現在我們已經對它的細微差別有了更好的理解,因此我想深入研究細節。

如果你不熟悉 Kerberoast,現有的大量信息可供你查閱,其中一些我在這篇文章的開頭做過一些討論。 如果你對 Kerberos (或 Kerberos)的工作原理沒有一個基本的了解,那麼這篇文章的大部分內容對你來說就沒有什麼意義,所以如果你對這些概念感到不舒服的話,我強烈推薦你多讀一些相關的文章。 但是這裡有一個關於 kerberos 執行過程的簡短總結:

1. 攻擊者對一個域進行身份驗證,然後從域控制器伺服器獲得一個票證授予票證(TGT) ,該票證授予票證用於以後的票證請求

2. 攻擊者使用他們的 TGT發出服務票證請求(TGS-REQ) 獲取特定形式(sname/host)的 servicePrincipalName (SPN), 例如,MSSqlSvc/SQL.domain.com。此SPN在域中應該是唯一的,並且在用戶或計算機帳戶的servicePrincipalName欄位中註冊。 在服務票證請求(TGS-REQ)過程中,攻擊者可以指定它們支持的Kerberos加密類型(RC4_HMAC,AES256_CTS_HMAC_SHA1_96等等)。

3. 如果攻擊者的 TGT 是有效的,則 DC 將從 TGT 中提取信息並填充到服務票證中。 然後,域控制器查找哪個帳戶在 servicedprincipalname 欄位中註冊了所請求的 SPN。 服務票證使用註冊了所要求的 SPN 的帳戶的哈希進行加密, 並使用了攻擊者和服務帳戶都支持的最高級別的加密密鑰。 票證以服務票證回復(TGS-REP)的形式發送回攻擊者。

4. 攻擊者從 TGS-REP 中提取加密的服務票證。 由於服務票證是用鏈接到請求 SPN 的帳戶的哈希加密的,所以攻擊者可以離線破解這個加密塊,恢復帳戶的明文密碼。

本文中我們將要提到的三種主要加密密鑰類型分別是RC4_HMAC_MD5 (ARCFOUR-HMAC-MD5,其中帳戶的 NTLM 散列函數作為密鑰)、 AES128_CTS_HMAC_SHA1_96和 AES256_CTS_HMAC_SHA1_96。 為了簡單起見,我將它們稱為 RC4、 AES128和 AES256。

此外,這裡所有的例子都是在 Windows 10客戶端上運行的,而Server 2012域控制器是一個2012 R2的域功能級別。

Kerberoast 方法

Kerberos 通常採用兩種通用的方法:

·Kerberos 協議的一個獨立實現,通過連接到網路上的設備使用,或者通過 SOCKS 代理將精心設計的流量作為輸入。 例如 Meterpreter 或者Impacket。這需要一個域帳戶的憑據來執行roasting,因為需要請求一個 TGT 在以後的服務票證請求中使用。

·在域聯接的主機上使用內置的 Windows 功能(如.NET KerberosRequestorSecurityToken . Net kerberos / requestorsecuritytoken類)請求票證,然後使用Mimikatz 或Rubeus 從當前登錄會話中提取票。另外一種可供選擇的方法是幾年前@machosec 意識到GetRequest() 方法可以用來從 KerberosRequestorSecurityToken 中挖掘出服務票證位元組,這意味著我們可以放棄使用 Mimikatz 來提取票證。 這種方法的另一個優點是,現有用戶的 TGT 可用於請求服務票證,這意味著我們不需要明文憑證或用戶的散列來執行 kerberos 廣播。

要利用Kerberoast,我們就真的需要 RC4加密類型的服務票證響應,因為這比其他的 AES 加密類型更容易被破解。如果我們在攻擊者一方實現了協議,我們就可以選擇在服務票證請求過程中指定我們只支持 RC4,從而更容易破解散列格式。 在主機端,我過去認為 KerberosRequestorSecurityToken方法默認請求的是 RC4加密的票證,因為通常返回的就是這個,但實際上"正常"票證請求行為發生在所有支持的密碼都得到支持的情況下才會發生。 那麼為什麼這種方法通常會返回 RC4哈希呢?

是時候快速繞道了。

msDS-SupportedEncryptionTypes

我們過去討論過的一個防禦指標是"加密降級活動"。 由於現代域(功能級別在2008及以上)和計算機(vista / 2008 )默認支持在 Kerberos 交換中使用 AES 密鑰,因此在任何 Kerberos 票證授予票證(TGT)請求或服務票證請求中使用 RC4都應該是異常的。 肖恩 · 梅特卡夫有一篇名為"檢測 Kerberoast 攻擊活動"的優秀文章,其中涵蓋了如何處理 DC 事件來檢測這種類型的攻擊行為,儘管他指出"可能會出現誤報"。

為什麼這種方法會出現誤報的問題,這個問題的完整答案也解釋了我多年來看到的一些使用 Kerberoast的"奇怪"行為。

為了說明這一點,假設我們有一個在其 servicePrincipalName (SPN)屬性中註冊了 MSSQLSvc/SQL.testlab.local 的用戶帳戶sqlservice 。 我們可以使用

powershell -C 」Add-Type -AssemblyName System.IdentityModel; $Null=New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList 『MSSQLSvc/SQL.testlab.local」

為此 SPN 請求服務票證。 然而,應用於當前登錄會話的結果服務票證指定使用 RC4,儘管請求用戶的(harmj0y) TGT 使用的是 AES256。

如前所述,由於某種原因,長期以來我認為 KerberosRequestorSecurityToken方法特別需要 RC4。 然而,看一下 Wireshark 從客戶端捕獲的 TGS-REQ (Kerberos 服務票證請求) ,我們可以看到所有適當的加密類型(包括 AES)都被指定為支持:

正如我們所期望的那樣,返回的 TGS-REP (服務票證應答)中的enc-part部分使用發起請求的客戶端的 AES256密鑰進行了適當的加密。 然而,我們關心的用於 Kerberoast 的 enc-part 部分(包含在返回的服務票證中)是用sqlservice帳戶的 RC4密鑰(而不是 AES 密鑰)加密的:

到底發生了什麼?

事實證明,這與 KerberosRequestorSecurityToken方法無關。 這個方法請求了一個由提供的 SPN 指定的服務票證,這樣它就可以構建一個包含 SOAP 請求的服務票證的 AP-REQ,我們可以在上面看到它執行的"正常"請求並聲明它支持 AES 加密類型。

這種行為是由於 msDS-SupportedEncryptionTypes 域對象屬性引起的,Jim Shaver 和 Mitchell Hennigan 在他們的 DerbyCon——"Return From The Underworld: The Future Of Red Team Kerberos"演講中談到了這一點。 此屬性是在[ MS-KILE ]2.2.7中定義的一個32位無符號整數,表示具有以下可能值的位欄位:

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/6cfc7b50-11ed-4b4d-846d-6f08f0812919

根據微軟的[ MS-ADA2]說明 ,"密鑰分發中心(KDC)使用這些信息[ msDS-SupportedEncryptionTypes ]同時為這個帳戶生成服務票證。" 因此,即使域支持 AES 加密(即域功能在2008及以上) ,在請求的 SPN 註冊的帳戶上,msDS-SupportedEncryptionTypes 欄位的值決定了 Kerberoast 流程中返回的服務票證的加密級別。

根據 MS-KILE 3.1.1.5的說明,該欄位在 Windows 7 和 Server 2008R2 上默認值分別是0x1C (RC4_HMAC_MD5 | AES128_CTS_HMAC_SHA1_96 | AES256_CTS_HMAC_SHA1_96 = 28)。 這就是為什麼機器的服務票證幾乎總是使用 AES256的原因,因為最高的且相互支持的加密類型將用於 Kerberos 票證交換。 我們可以通過在Rubeus.exe klist 後執行dir \primary.testlab.localC$來確認這一結果:

但是,此屬性僅在默認情況下設置在計算機帳戶上,而不是在用戶帳戶上。 如果該屬性沒有定義,或者設置為0,[MS-KILE]3.3.5.7告訴我們默認使用的值是0x7,這意味著將使用 RC4對服務票證進行加密。 因此,在前面的例子中,註冊到用戶帳戶 sqlservice的MSSQLSvc/SQL.testlab.local SPN中,我們收到的是使用 RC4加密的票證。

如果我們在活動目錄的用戶賬戶和計算機賬戶中選擇"This account supports AES [128/256] bit encryption",那麼 msDS-SupportedEncryptionTypes 就會被設置為24,並且指定只支持 AES 128/256加密。

當我第一次研究這個問題時,我假設這意味著既然 msDS-SupportedEncryptionTypes 值是非空的,而且 RC4的標誌位並不存在,那麼如果在為一個帳戶請求服務票證時(通過 /tgtdeleg 標誌)只指定為 RC4,交換票證的時候就會出現錯誤。

但是你猜怎麼著? 我們仍然得到一個 RC4(類型是23)加密的票證,我們可以破解這個票證!

通過Wireshark 抓包確認 RC4是請求中唯一受支持的 etype值,而且票證的 enc-part 實際上是用 RC4加密的。

ˉ\_(ツ)_/ˉ

我假設這是出於故障安全向後兼容的原因,並且我在多個測試域中運行了這個場景,得到了相同的結果。 然而,當我要求其他人復現時卻無法做到這一點,所以我不確定我是否遺漏了什麼,或者這是否準確地反映了正常的域的行為。 如果任何人有更多關於這個的信息,或者不能復現,請告訴我!

為什麼上述問題很重要? 因為如果那是真的的話,這就意味著在用戶賬戶上禁用 RC4_HMAC 似乎不是一個簡單的方法。 這意味著,即使你使用 servicePrincipalName 欄位設置了對用戶帳戶啟用 AES 加密,這些帳戶仍然會使用對黑客友好的 RC4進行加密,從而可以繼續執行 Kerberoast攻擊!

經過一些測試,似乎如果你使用這篇文章里描述的方法在域或域控制器級別禁用 RC4 ,那麼為任何帳戶請求 RC4服務票證都將失敗。 然而,TGT 請求也不再適用於 RC4。 因為這可能會導致很多東西出現問題,所以在生產環境中做任何改變之前,一定要先在實驗室環境中先嘗試進行類似的測試。

旁註: 還可以為表示域信任的 trustedDomain 對象設置 msDS-SupportedEncryptionTypes 屬性,但它最初也是未定義的。 這就是為什麼內部域的信任票證最終默認使用的是 RC4:

然而,與用戶對象一樣,這種行為可以通過修改可信域對象的屬性來改變,指定外部域支持 AES:

這將可信域對象上的 msDS-SupportedEncryptionTypes 的值設置為24(AES128_CTS_HMAC_SHA1_96 | AES256_CTS_HMAC_SHA1_96) ,這意味著內部域將默認發出AES256加密的信任票證:

嘗試建立一個更好的 Kerberoast

由於我們傾向於執行約定的方式,因此,我們經常會傾向於濫用基於主機的功能,而不是在來自攻擊者伺服器上的我們自己的協議實現中的管道。 我們經常在高延遲的命令和控制伺服器(C2)上操作,所以對於像 Kerberos 這樣複雜的多方交換,我們的個人偏好傳統上總是在使用 KerberosRequestorSecurityToken 方法。 但是正如我在第一個章節中提到的,這個方法在請求服務票證時會請求最高支持的加密類型。 對於啟用了 AES 的用戶帳戶,此默認方法將返回加密類型為 AES256的票證(哈希中的類型是18) :

現在,Rubeus 的 Kerberoast攻擊的一個明顯的替代方法是允許指定一個現有的 TGT 塊或者文件,然後在票證請求中使用它。 如果我們有一個真正的 TGT,並且正在實現原始的 TGS-REQ或TGS-REP過程並手動提取出正確的加密部分,那麼我們可以在發出服務票證請求時指定需要的支持的任何加密類型。 因此,如果我們有啟用了AES 的帳戶,我們仍然可以得到一個基於 RC4的票證,然後進行離線破解! 實際上,這種方法現在是在 Rubeus 中使用kerberoast 命令的 /ticket:

那麼這種做法的缺點是什麼呢?首先,你需要一個票證授予票證來構建原始的 TGS-REQ 服務票證請求,所以你需要: a)在系統上特權升級後並提取出另一個用戶的 TGT; b)擁有一個用戶的散列,你可以使用 asktgt模塊來請求一個新的 TGT。 如果你好奇為什麼用戶不能在沒有特權提升的情況下提取出可用的 TGT 版本,請查看"Rubeus?—?Now With More Kekeo"這篇文章中的解釋。

解決方案是@gentilkiwi的 Kekeo tgtdeleg 技巧,它使用 Kerberos GSS-API 為啟用了無約束委派的目標 SPN 請求了一個"假"委派(例如 cifs/DC.domain.com)。 這是以前在 Rubeus 中使用 tgtdeleg 命令實現的。 這種方法允許我們為當前用戶提取可用的 TGT,包括會話密鑰。為什麼我們不在對"易受攻擊的"SPN 執行 TGS-REQ 時使用這個"假冒"的委派 TGT,並指定 RC4作為我們支持的唯一加密演算法呢?

新的 kerberost /tgtdeleg 選項就是這樣做的!

在這個欄位中,默認的 KerberosRequestorSecurityToken Kerberoast 方法也有失敗的時候——我們希望 /tgtdeleg選項可以在其中的一些情況下仍然可以正常工作。

如果我們想更進一步,避免可能的"加密降級"指示器,我們可以搜索不支持 AES 加密類型的帳戶,然後聲明我們支持服務票證請求中的所有加密類型。 由於結果支持的最高加密類型將是 RC4,我們仍然會得到可破解的票證。 kerberoast /rc4opsec 命令執行 tgtdeleg 技巧並過濾掉這些啟用了AES的帳戶:

如果我們想要相反的結果,並且只想要啟用了 AES 的帳戶,/aes 標誌將執行相反的 LDAP 過濾器。 雖然我們目前沒有工具來破解使用 AES 的票證(即使我們這樣做了,由於 AES 關鍵的推導演算法將使得破解速度會慢上千百倍) ,但是破解的方法正在研究中。

用於 Kerberoast廣播的 /tgtdeleg 方法的另一個優點是,由於我們正在手動構建和解析 TGS-REQ/TGS-REP流量,服務票證將不會在我們正在使用的系統上進行緩存。 默認的 KerberosRequestorSecurityToken方法導致在當前登錄會話中為我們正在處理的每個 SPN 緩存了一個服務票證。 /tgtdeleg方法導致一個附加的cifs/DC.domain.com 票證被添加到當前的登錄會話中,最小化了潛在的基於主機的指示器(即用戶登錄會話中的大量服務票證)。

作為參考,我在 README 中整理了一個比較了在Rubeus中的不同的kerberost方法的表格:

最後要說明的是,從這個commit開始,kerberost應該比域信任更有效。 在 README 的 kerberoast 章節中我添加了兩個外部可信域的示例。

總結

希望這篇文章的內容消除了一些人(比如我)可能對 kerberoast 的不同加密支持產生的一些困惑。 我也渴望人們嘗試使用新的 Rubeus Kerberoast參數,看看他們在該領域會如何工作。

像往常一樣,如果我在這篇文章中犯了一些錯誤,請讓我知道,我會儘快糾正它! 此外,如果有人對 「RC4票證依舊可用於僅支持AES的賬戶」這種情況有什麼看法,請給我發電子郵件(will [at] harmj0y. net)或者在 https://bloodhoundgang.herokuapp.com/ 上找我。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

Windows x86 Shellcode開發:尋找Kernel32.dll地址
扒一扒CARBANAK的源代碼,看它們是如何巧妙構思並運行的?(二)

TAG:嘶吼RoarTalk |