因此,這個想法很簡單,你可以登錄到你的混合 Azure AD 加入的 Windows 10 設備并自動訪問云和本地資源。FIDO2 安全密鑰成為進入云和本地資源的途徑。
Microsoft 之前僅針對加入 Azure AD 的設備發布了相同的功能,但現在范圍已擴展到混合環境。
一個新的證書收集攻擊向量涉及只讀域控制器服務器,讓我們看看從研究新功能到實現對Impacket的新攻擊的所有方法。
Azure 中的無密碼體驗
如上所述,Microsoft 通過 Azure Active Directory 將無密碼體驗擴展到本地資源。既然我們談論的是本地資源的 SSO 功能,那就要先了解一下 Kerberos。
Kerberos 是主要的身份驗證協議,用于驗證 Windows 域中的安全對象(用戶或主機)的身份。它基于對稱密碼學(共享秘鑰)并使用票據的概念來驗證這些身份。粗略地說,Kerberos 發出兩種票據,一種是驗證對象身份的票據授予票據 (TGT),另一種是對象用于對域中的其他服務進行身份驗證的服務票據。
假設我想訪問在服務器 A 中運行的服務 1。身份驗證流程如下:
Kerberos 身份驗證
很清楚、很簡單。現在讓我們把事情弄得更復雜一點。讓我們將這種情況轉移到混合環境。使用安全密鑰的身份驗證流程如下:
無密碼身份驗證
可以看到部分 TGT 交換完整的TGT,以及在云中復制的 Kerberos 服務器密鑰。這是怎么回事?讓我們開始深入研究這個問題。到目前為止,只有位于域控制器上的密鑰發布中心 (KDC) 服務有權發布 TGT。但是,這種新的無密碼體驗的引入使事情發生了一些變化:正如我們在之前的流程中看到的那樣,Azure AD 現在可以為一個或多個域發出 Kerberos TGT!這讓我想到了另一個問題,krbtgt 帳戶呢?
KDC 在任何域中使用的安全對象是 krbtgt 帳戶。這是一個無法刪除,也無法更改名稱的特殊帳戶,其密碼用于派生密鑰,用于加密 KDC 發布的 TGT。出于顯而易見的原因,此帳戶不會離開 AD 服務器。那么,Azure AD 如何在沒有這個特殊帳戶的情況下發布 TGT?以下是 Azure AD Kerberos 服務器對象圖出現的位置。
Kerberos 服務器對象屬性
Azure AD Kerberos 服務器是在本地 AD 中創建的對象,它在Azure AD中復制,不與任何物理服務器相關聯(它是虛擬的)。它由遵循命名格式“krbtgt_######”的禁用用戶帳戶對象和關聯的計算機帳戶“AzureADKerberos”組成。
Azure AD 使用此對象為域生成部分 TGT。這樣,用戶帳戶擁有 Azure AD Kerberos 服務器 TGT 加密密鑰。這是在身份驗證流程的第二步中用于加密部分票據的 Kerberos 服務器密鑰。
但問題只解決了一半,我們域名的 krbtgt 密鑰不需要發布到云端,而是使用這個新的 krbtgt_###### 帳戶的密鑰。因此,Azure 現在可以發行票據,但是服務票據和授權呢?
服務票據和授權繼續由本地 AD 域控制器控制。Azure AD 沒有將特權屬性證書 (PAC) 包含到票據中所需的所有信息,這就是為什么它只簽發部分票據的原因。
流量如何繼續?一旦我們獲得了部分票據,就必須將它(針對本地 AD)換成包含所有所需授權信息的完整票據,最后,使用它來請求不同的服務票據以訪問本地資源。至此,我們獲得了 Kerberos SSO 功能,并完成了無密碼體驗。
至此,只剩下一個問題,這個 Kerberos Server 對象到底是什么?為什么我們的本地 AD 信任它的密鑰?只需查看與對象相關的設備帳戶的屬性,就很容易獲得答案:
計算機屬性
我們談論的是只讀域控制器 (RODC)。Microsoft 重用 RODC 的概念來實現 Kerberos 的“云”版本,允許 Azure AD 提供 SSO 功能。
還記得只讀域控制器嗎?
在繼續之前,需要回顧一些關于 RODC 的基本概念。如果想了解更多信息,請點此了解。
簡而言之,RODC 是一種域控制器,它承載 Active Directory 數據庫的只讀分區。除帳戶密碼外,它保存可寫域控制器保存的所有 AD 對象和屬性。但是,無法對存儲在 RODC 上的數據庫進行更改。它主要被設計用于部署在遠程或分支機構環境中,這些環境通常具有相對較少的用戶、較差的物理安全性或到中心站點的網絡帶寬較差。
我想回顧的主要概念是憑據緩存,它將非常有用。正如我之前提到的,默認情況下,帳戶密碼不會保存到RODC中(出于安全目的),因此分支站點中的身份驗證過程略有不同:
1.用戶向其站點的 RODC 發送 一個TGT 請求;
2.RODC 服務器檢查用戶憑據是否已緩存:
2.1如果沒有,RODC 將請求轉發到可寫 DC;
2.3如果憑據已緩存,則身份驗證由 RODC 解析;
3.可寫 DC 對用戶進行身份驗證,簽署 TGT,并將響應發送回 RODC;
4.RODC 將檢查用戶是否允許緩存其憑據:
4.1如果用戶包含在 Allowed RODC Password Replication中,則他們的憑據存儲在服務器中,并且 RODC 的 msDS-RevealedList 屬性填充有用戶名。后續的身份驗證請求將由 RODC 管理;
4.2如果用戶包含在Denied RODC Password Replication中,則不會存儲他們的憑據,后續的身份驗證請求將轉發到可寫 DC。
5.RODC 將 TGT 轉發給用戶,用戶可以使用它來請求服務票據。
因此,當可寫DC不可訪問且RODC無法將請求轉發給它時,緩存對于確保用戶和計算機可以向RODC進行身份驗證非常有用。然而,這可能是一把雙刃劍。沒有緩存憑據的原因是為了防止當RODC服務器被破壞時整個域處于危險之中。正如上所述,這些分支站點的安全性級別較低。因此,憑據緩存背后的主要思想只是保持在站點上操作所需的最少密碼數量。
回到無密碼場景,我們看到了 Microsoft 如何使用 Kerberos 在混合環境中支持 SSO 到本地資源。但是,對使用 NTLM 等舊協議的資源的訪問發生了什么?
分析這種情況的簡單方法是檢查 Wireshark 捕獲的無密碼身份驗證。我們最感興趣分析的身份驗證部分是圖 2 的第 4 步和第 5 步,即部分票據和完整票據之間的交換。
完整的TGT是通過向KDC (krbtgt服務)發送一個TGS-REQ(packet n°577)獲得的:
TGS-REQ 包括兩個預認證數據 (PA-DATA)。帶有部分 TGT 和未知 PA-DATA 類型編號 161 的 PA-TGS-REQ。
未知類型是一個明顯的跡象,表明那里正在發生某些事情。如果 Wireshark 沒有定義該數據類型,那是因為該數據相對較新。因此,首先要做的是查看 [MS-KILE]:Kerberos 協議擴展,并檢查此 PA-DATA 類型。第一個結果是一種新型的 TGS-REQ:
3.3.5.7.8 密鑰列表請求
當密鑰發布中心 (KDC) 收到包含 aKERB-KEY-LIST-REQ[161] padata 類型的 krbtgt 服務名稱 (sname) 的 TGS-REQ 消息時,KDC應該包括長期秘鑰的客戶端請求的加密類型?KERB-KEY-LIST-REP?[162]響應消息,并將其插入到 EncKDCRepPart 結構的加密數據中,如 [RFC6806] 中所定義:
2.2.11 KERB-KEY-LIST-REQ
KERB-KEY-LIST-REQ 結構用于請求 KDC 可以提供給客戶端的密鑰類型列表,以支持舊協議中的單點登錄功能。它的結構是使用 ASN.1 符號定義的。語法如下:
KERB-KEY-LIST-REQ ::= SEQUENCE OF Int32 — encryption type —
KERB-KEY-LIST-REQ 的結構用于支持舊協議的 SSO 功能。只需檢查請求的加密類型以及響應。捕獲的內容如下:
PA-DATA 的內容是編碼值 3003020117,代表加密類型 23 或 RC4-HMAC。這代表我們正在請求用戶的 NT 哈希!
確認后,我開始查看響應(packet n°583):
在 TGS-REP 的加密部分(用會話密鑰解密)中,我們可以找到 PA-DATA 類型 162,即 KERB-KEY-LIST-REP:
回到MS-KILE,我檢查了結構的編碼以解碼數據并獲取密鑰:
2.2.12 KERB-KEY-LIST-REP
KERB-KEY-LIST-REP 結構包含 KDC 提供給客戶端的密鑰類型列表,以支持舊協議中的單點登錄功能。它的結構是使用 ASN.1 符號定義的。語法如下:
?KERB-KEY-LIST-REP ::= SEQUENCE OF EncryptionKey
編碼后的 PA-DATA 被解碼為:
用戶現在可以使用其 NT-Hash 與 NTLM 進行身份驗證。
密鑰列表攻擊
現在,我們發現了 Windows 使用舊協議實現 SSO 的方式。在檢查之后,反應是立竿見影的,我們還發現了一種新的潛在方法來轉儲要求較低的憑據!
這種新技術背后的想法很簡單。如果我們能夠用新的 PA-DATA 重現之前的 TGS-REQ,我們將擁有用戶所有長期秘鑰的列表。
因此,第一次嘗試是將 TGS-REQ 復制到 krbtgt 服務,并使用普通用戶添加 KERB-KEY-LIST-REQ 結構。這意味著包含的 TGT 是由 KDC 頒發給該普通用戶的,無需知道 krbtgt 憑據即可輕松獲取。響應是正常的 TGS-REP,沒有新數據(不包括 KERB-KEY-LIST-REP)。第二次嘗試是管理員用戶的新 TGS-REQ。同樣的過程,同樣的結果,答案中沒有關鍵字。這個想法并不是那么簡單。
如果該過程適用于 RODC,讓我們嘗試將由此服務器簽名的部分 TGT 包含到 TGS-REQ 中。復制由 RODC 簽名并頒發給特定用戶的部分 TGT,將其包含到 TGS-REQ 中,解密響應并獲取密鑰,可以對我們想要的任何用戶重復。
經過幾次嘗試,漏洞開始顯現:KDC_ERR_TGT_REVOKED(TGT 已被撤銷)。為什么?這些用戶包含在拒絕 RODC 密碼復制組中,因此,此新 Kerberos 功能受到限制。默認情況下,拒絕管理員等用戶復制其密碼。
不過,我們可以攻擊物理 RODC 服務器和虛擬服務器(Azure AD Kerberos 服務器對象包含在我們的攻擊面中!)。同樣重要的是,目標用戶不需要緩存在 RODC 中!這是以前針對這類域控制器的攻擊所需要的。
總而言之:
我們必須知道RODC (-rodcKey)的krbtgt憑據,因為我們需要創建帶有一些特殊條件的部分票據和TGS-REQ。我們有幾種獲取憑據的方法,例如,如果我們獲得RODC的本地管理員權限,就可以用Mimikatz轉儲SAM數據庫。如果我們討論的是虛擬RODC,可以針對Azure AD連接服務器;
我們必須有RODC的krbtgt帳戶的ID (-rodcNo);
我們必須針對在拒絕組中未明確詳細說明的用戶;
有了這些要求,我打開了一個PR,其中包含一個新的示例腳本(keylistattack.py)和secretsdump.py中的一個新選項(-use-keylist),以演示這種攻擊。
基本上,攻擊有兩個主要部分:用戶列表和票據請求:
首先,我們需要知道我們的目標是什么,可以通過參數(LIST 選項)定義目標用戶名(-t 標志)或定義具有目標用戶名列表(-tf 標志)的文件,或者我們可以進行枚舉(例如,SAMR 用戶枚舉) )。對于最后一個選項,我們需要一個低憑據用戶,我們有兩個選項。默認選項,過濾包含在拒絕組中的域用戶,以及完整的一個(-full 標志)。
一旦我們知道要攻擊誰,我們就會請求票據、處理響應并獲取密鑰!
keylistattack.py 使用沒有過濾的 SAMR 用戶枚舉(-full 標志)
keylistattack.py 使用 SAMR 用戶枚舉和過濾(默認攻擊)
keylistattack.py 定義目標用戶名(-t 標志)
使用 Kerberos 密鑰列表攻擊選項 (-use-keylist) 的 secretsdump.py
如何檢測?
提出了新的攻擊,我們如何檢測它?由于攻擊實施了有效的密鑰列表請求,該請求可能出現在啟用了無密碼的環境的正常操作中,因此選項并不多:
1.審計枚舉操作:
SAMR 枚舉:事件 4661——請求對象句柄(對象類型:SAM_DOMAIN、SAM_ALIAS、SAM_GROUP);
LDAP 枚舉;
2.審核 Kerberos 服務票據操作:
成功請求:事件 4769——請求了 Kerberos 服務票據(票據選項:0x10000 ——可代理);
TGT 撤銷:事件 4769——請求了 Kerberos 服務票據(失敗代碼:0x14 – KDC_ERR_TGT_REVOKED)
如何緩解這種攻擊?
物理 RODC:
1.不要將“經過身份驗證的用戶”或“域用戶”添加到“允許的 RODC 密碼復制組”中。如果需要,應以與可寫 DC(第 0 層)類似的級別保護這些 RODC;
2.將所有特權帳戶和組添加到“拒絕 RODC 密碼復制組”;
3.不要將常規用戶帳戶設置為 RODC 管理員,這些類型的帳戶通常不如知名帳戶安全,并且它們的泄露可能導致本地帳戶(包括 RODC 的 krbtgt 帳戶)的憑據轉儲。
虛擬 RODC(Azure AD Kerberos 服務器/無密碼方案):
1.請確保只將具有無密碼能力的用戶添加到“允許的RODC密碼復制組”;
2.Azure AD Connect服務器包含關鍵的身份數據,應該被視為第 0 層;
總結
1.物理和虛擬 RODC 都可能受到攻擊;
2.由于需要復制權限,虛擬 RODC 中的攻擊面更加廣泛;
3.要攻擊的帳戶不需要緩存在 RODC 上;
4.不需要管理員憑據,如果你有用戶列表,甚至不需要憑據;
5.該攻擊要求至少有一臺DC服務器使用Windows 2016/2019的更新版本(分別為kb4534307和kb4534321補丁);