Kerberos 委派攻擊原理之 S4U2 利用詳解
Kerberos 委派攻擊原理之 S4U2 利用詳解
為了更好地防止約束委派的濫用,請查看"從 Kekeo 到 Rubeus"文章中的"s4u"部分。
幾周前,我和同事李 · 克里斯滕森(在他的幫助下我完成了這篇文章和相關材料)花了一些時間深入研究了活動目錄的 S4U2Self 和 S4U2Proxy 協議擴展。就在最近,本傑明 · 德爾皮 和 Ben Campbell在推特上就同一話題進行了一次有趣的公開對話。對話的結果是本傑明發布了一個修改過的 Kekeo,使得濫用 S4U 錯誤配置更為容易。在我寫這篇文章的時候,Ben 還發表了一篇關於這個話題的優秀文章,每個人在繼續閱讀本文之前都應該讀一讀他的文章。說真的,讀者們真的應該先去看看 Ben 的文章。
李和我想寫出我們對這項技術的理解,以及在交戰中如何濫用任何錯誤配置。其中一部分內容將與 Ben 的文章重疊,但是我們已經合併了一些不同的方面,我們認為至少可以增加一些價值。Ben 還介紹了 Linux 方面的漏洞利用,我們在本文中不會涉及到這一點。
這個問題的核心是特權委派——允許一個用戶在活動目錄中假冒成另一個用戶。這種委派(當前)有兩種形式: 無約束和有約束的委派。如果你不關心技術細節,請直接跳到濫用 S4U 部分。
無約束委派
假設你有一個伺服器(或服務帳戶) ,由於某種原因需要假冒為另一個用戶。一個常見的場景是,當用戶使用 Kerberos 或其他協議向 Web 伺服器進行身份驗證時,伺服器希望與 SQL 後端進行良好的集成。活動目錄提供了兩種實現此目的的通用方法: 約束委派和無約束委派。
在 Windows 2000中,無約束委派曾經是唯一可用的選項,並且後來保留了這個功能(可能是出於向後兼容的原因)。我們只簡單介紹一下這種委派類型,因為 Sean Metcalf 有一篇很棒的文章深入介紹了這種委派類型。在那篇文章中 Sean 說,"當 Kerberos 無約束委派在伺服器上啟用,伺服器託管了在 TGS-REQ (步驟3)中引用的服務主體名稱中指定的服務時,DC 域控制器將用戶 TGT 的一個副本放到服務票證中。當向伺服器提供用戶的服務票證(TGS)以進行服務訪問時,伺服器打開 TGS 並將用戶的 TGT 放入 LSASS 中供後續使用。此時,應用程序伺服器就可以無限制地假冒該用戶!」 .
下面是來自微軟官方對於該協議的圖形概述:
https://msdn.microsoft.com/en-us/library/cc246080.aspx
Tl;dr: TGT 將被塞入內存,攻擊者可以在以下情況下提取和重用 TGT :
1.你可以攻擊具有無約束委派設置的伺服器。
2.你可以欺騙未啟用"帳戶是敏感的,不能委派"設置的域用戶(見下面的「保護措施」章節) ,以連接到計算機上的任何服務。包括單擊 \\SERVER\Share。
這允許攻擊者假冒該用戶到域上的任何服務或計算機!很明顯這種情況比較糟糕。相比之下,如果不啟用無約束委派,則只會提交一個沒有填充 TGT 的普通服務票證,這樣攻擊者就不會獲得額外的橫向擴展的優勢。
如何判斷哪些機器具有無約束委派設置?這實際上非常簡單: 搜索任何具有 userAccountControl 屬性的機器,該屬性包含 ADS_UF_TRUSTED_FOR_DELEGATION。你可以使用 LDAP 過濾器『(userAccountControl:1.2.840.113556.1.4.803:=524288)』,這是 PowerView 的 Get-DomainComputer 函數在傳遞 -Unconstrained 標誌時所做的:
約束委派
顯然,無約束委派在粗心的管理員手中是相當危險的。微軟很早就意識到了這一點,並在 Windows 2003上發布了"約束"委派。其中包括一組 Kerberos 協議擴展,稱為 S4U2Self 和 S4U2Proxy。這些擴展還支持所謂的協議轉換,我們會在稍後詳細介紹。
從本質上講,約束委派是一種可以在假冒其他用戶時準確地限制特定機器或帳戶可以訪問到某些服務的方法。以下是配置了約束委派的服務帳戶在活動目錄 GUI 中的樣子:
指定的"服務"是允許帳戶在假冒其他用戶時訪問的服務主體名稱。在上面的例子中是 HOST/PRIMARY.testlab.local。在我們詳細討論它是如何工作的之前,下面是目標對象在 PowerView 中的樣子:
我們感興趣的欄位是 msds-allowedtodelegateto,但是也對帳戶的 userAccountControl 屬性進行了修改。實際上,如果計算機或用戶對象的 userAccountControl 值包含 TRUSTED_TO_AUTH_FOR_DELEGATION ,那麼任何拿到該帳戶許可權的用戶都可以模擬 msds-allowedtodelegateto中設置的 SPN。Ben 提到要修改這些參數 SeEnableDelegationPrivilege 是必需的,後續我將更深入地討論這個問題。
但是首先,我們來了解一下活動目錄是如何實現整個過程的。如果你不感興趣,可以直接跳到本文的濫用 S4U 部分。
S4U2Self,S4U2Proxy 和協議轉換
假設你擁有一個 web 服務帳戶,該帳戶需要將用戶假冒為一個特定的後端服務賬戶,但是你不想開啟無約束委派。微軟的解決方案是通過 Kerberos 擴展設置的用戶服務(S4U)實現。這裡有關於這個主題已有大量的文檔; 李和我偏愛微軟的"Kerberos 協議擴展: 面向用戶和約束委派協議的服務"([ MS-SFU ])。以下是我們目前的理解。如果我們有什麼謬誤,請讓我們知道!
實現約束委派的第一個擴展是 S4U2self 擴展,它允許服務代表特定用戶向自己請求一個特殊的可轉發服務票證。這是為了在用戶以不使用 Kerberos 的方式對服務進行身份驗證的情況下使用,例如在我們之前提到的 web 服務案例。在 KRB_TGS_REQ 第一次發送到 KDC 的過程中,它設置了可轉發的標誌,該標誌要求 TGS 返回的標記為可轉發的,從而能夠與 S4U2proxy 擴展一起使用。在無約束委派中,使用 TGT 標識用戶,但在這種情況下,S4U 擴展使用 PA-FOR-USER 結構作為"padata"預身份驗證數據欄位中的新類型。
注意,S4U2self 進程可以被任何用戶執行,並且不需要目標用戶的密碼。此外,只有請求用戶在其 userAccountControl 中設置了 TRUSTED_TO_AUTH_FOR_DELEGATION 欄位時,才允許 S4U2self 進程。
現在,李和我首先想到的是,這可能是一種對任何我們想要的用戶執行 Kerberoast 攻擊的方式,但不幸的是,對於我們攻擊者來說,情況並非如此。PAC 是為源用戶(而不是目標用戶)簽名的,在這種情況下是請求服務帳戶,因此通用的 Kerberoast 攻擊方法不在考慮範圍之內。但是我們現在有一個特殊的服務票證,在這種情況下可以轉發到配置為約束委派的目標服務上。
第二個擴展是 S4U2proxy,它允許調用者(在我們的例子中是服務帳戶)使用這個轉發票證向 msds-allowedtodelegateto 中指定的任何 SPN 請求服務票證,假冒 S4U2self 步驟中指定的用戶。KDC 檢查請求的服務是否在被請求服務的 msds-allowedtodelegateto 欄位中,並在該檢查通過時發出票證。通過這種方式,委派"約束"到特定的目標服務。
下面是微軟官方關於 S4U2self 和 S4U2proxy 工作過程的示意圖:
https://msdn.microsoft.com/en-us/library/cc246080.aspx
這個擴展設置就是微軟所謂的協議轉換,即從 S4u2Self 組件期間的第一個 Kerberos 交換開始。這意味著服務可以通過非 Kerberos 協議對用戶進行身份驗證,並將身份驗證"轉換"到 Kerberos,從而可以輕鬆地與現有環境進行互操作。
濫用 S4U
從頭讀到此處,如果你問自己「那又怎樣」,或者跳過前面的內容直接來到本章節,那麼我們可以想出一些方法,讓 S4U 擴展在滲透測試中發揮作用。
第一種方法是使用非空的 msds-allowedtodelegateto欄位設置枚舉所有計算機和用戶。使用 PowerView 的 Get-DomainUser/Get-DomainComputer函數並帶有 -TrustedToAuth 標誌可以很容易地實現這一點:
現在,請記住,將 SPN 設置為 msds-allowedtodelegateto 的機器或用戶帳戶可以假冒成任何他們希望成為的目標服務 SPN 。因此,如果你能夠拿到其中一個帳戶的許可權,就可以欺騙對目標 SPN 的特權訪問。對於 HOST SPN,則可以實現完全的遠程接管。對於 MSSQLSvc SPN,則可以拿到 DBA 許可權。對於 CIFS SPN 則可以實現完全的遠程文件訪問。對於 HTTP SPN 則可能實現接管遠程網路服務,而對於 LDAP 則可以執行 DCSync;) ,對於 HTTP 或 SQL 服務帳戶,即使它們沒有提升目標伺服器上的管理員許可權,也可能使用 Rotten Potato 進一步濫用,提權至 SYSTEM 的許可權(儘管我還沒有親自測試過)。
幸運的是,本傑明最近發布了一個修改過的 Kekeo ,支持在我們知道特定賬戶的明文密碼的前提下,輕易的執行這類橫向傳播攻擊。李和我設想了四種不同的情況,包括你可能想要濫用的 S4U。我們已經在實驗室中可靠地測試了其中的兩個場景,但是沒能成功測試另外兩個場景(注釋如下)。@gentilkiwi 聯繫並告訴李和我 asktgt.exe 接受一個 /key: NTLM 參數和一個密碼。這使得我們可以使用帳戶哈希而不是純文本密碼來執行下面的場景3和4!
場景1: 用戶帳戶的配置為約束委派並且已知明文密碼
這是本傑明在他的推特中展示的場景。如果你能夠破解啟用了約束委派的用戶帳戶的明文密碼,那麼你可以使用 Kekeo 請求 TGT,執行 S4U TGS 請求,然後就可以訪問目標服務。
同樣,如果你希望從 Linux 系統執行這種攻擊,請閱讀 Ben 的這篇文章。
場景2: 計算機上的代理配置為約束委派
如果你能夠拿到一個配置為約束委派(而不是用戶帳戶)的計算機帳戶的許可權,那麼攻擊方法就有點不同了。由於任何作為 SYSTEM 運行的進程都具有本地計算機帳戶所具有的許可權,因此我們可以跳過 Kekeo asktgt.exe 步驟。你可以使用另一種方法來執行 S4U2Proxy 進程,這是微軟提供的幫助。李和我將這個過程從 C# 翻譯成了 PowerShell 代碼,如下:
# translated from the C# example at
https://msdn.microsoft.com/en-us/library/ff649317.aspx
# load the necessary assembly
$Null = [Reflection.Assembly]::LoadWithPartialName("System.IdentityModel")
# execute S4U2Self w/ WindowsIdentity to request a forwardable TGS for the specified user
$Ident = New-Object System.Security.Principal.WindowsIdentity @("Administrator@TESTLAB.LOCAL")
# actually impersonate the next context
$Context = $Ident.Impersonate()
# implicitly invoke S4U2Proxy with the specified action
ls \\PRIMARY.TESTLAB.LOCAL\C$
# undo the impersonation context
$Context.Undo()
正如微軟官方所詳細說明的,在使用 WindowsIdentity 時,在大多數情況中,默認情況下返回的是"標識級"的標記。這允許你查看哪些組與用戶標記是相關聯的,但不允許重用訪問。為了假冒上下文以訪問其他網路資源,需要一個模擬級別的令牌,只有在請求帳戶擁有"Act as part of the operating system"用戶許可權(SeTcbPrivilege)時才返回該令牌。這種許可權只在默認情況下授予 SYSTEM 賬戶,但是因為我們已經在網路上使用計算機帳戶的許可權拿到了 SYSTEM 許可權,所以我們不需要擔心這一點。
另外,我之前提到過,由於 PowerShell.exe 的一些特性,如果你正在使用 PowerShell Version 2,那麼你需要在單線程的 apartment 模式(帶有"-sta"標誌)中啟動 PowerShell.exe,以便令牌假冒正常工作:
場景3: 用戶帳戶配置為約束委派並且已知 NTLM 哈希
我們的下一個目標是僅給定目標用戶的 NTLM 哈希就從 windows 系統執行這種轉換攻擊,遺憾的是,我們無法使用與場景2相同的方法正常工作。我們的直覺是,我們忽略了一些愚蠢的細節,但我們想詳細說明我們嘗試了什麼,哪裡出了問題,以防有人給出一個能正常工作的建議。Ben 指出 /key:NTLM 也適用於 asktgt.exe,下面將介紹這一點。
我們嘗試使用 Mimikatz 的 PTH 命令將用戶的哈希注入內存(假設你是跳板機上的本地管理員) ,而不是使用 Kekro 的 asktgt.exe。這裡的一個問題(如場景2中所示)就是 SeTcbPrivilege,但是儘管明確地授予了我們的重要用戶這種許可權,我們依舊遇到了問題。看起來 S4U2Self 操作步驟可以工作正常:
儘管我們已經拿到了必要的特權或許可權,但似乎 S4U2Proxy 進程退回到了 NTLM,而不是 Kerberos,用一些值為 NULL 的身份驗證信息代替了正確的進程:
你可以使用 asktgt.exe /s4u.exe 執行此方案,其執行方式幾乎與場景1完全相同。只需將 / assword:PLAINTEXT 替換為 /key: NTLM,如下圖所示:
場景4: 計算機帳戶配置為約束委派配置並且已知 NTLM 哈希
如果你通過某種方式拿到了計算機帳戶的哈希,並希望從另一個域的計算機執行攻擊,我們設想你將執行一個幾乎與場景3相同的攻擊流程。不幸的是,我們也遇到了同樣的問題。再次強調,如果有人能告訴我們哪裡做錯了,請告訴我們,我們會非常感激:) 這可以用 /user:MACHINE$ 和 /key:NTLM執行,與場景3相同:
保護措施
微軟已經在活動目錄中內置了很好的保護措施,可以幫助減少委派濫用。如果一個帳戶啟用了"(敏感賬戶不能委派)Account is sensitive and can not be delegated",那麼"即使將服務帳戶設置為 Kerberos 委派的受信任帳戶,也不會將用戶的安全上下文委派給服務"。通過再次檢查 userAccountControl 屬性,檢查 NOT_DELEGATED 值,就可以輕鬆地檢查帳戶是否設置了這個屬性。Powerview 允許你輕鬆搜索已設置或未設置該值的帳戶(Get-DomainUser -AllowDelegation/-DisallowDelegation) ,並且可以使用 ConvertFrom-UACValue 函數檢查特定帳戶中該屬性的值,如前面的示例所示。


TAG:嘶吼RoarTalk |