Insights
HackTheBox: Hercules

A long Windows Active Directory chain from LDAP injection and NTLM coercion through delegated ACL abuse, AD CS ESC3, protected-object inheritance repair, and S4U2Self U2U with RBCD.

HackTheBox: Hercules

Overview

Hercules was a long Windows Active Directory chain that rewarded careful mapping of delegated permissions rather than a single dominant vulnerability.

The route to domain compromise was:

  1. exploit LDAP injection in an IIS application;
  2. forge its ASP.NET Forms Authentication state;
  3. coerce an NTLM response through vulnerable document functionality;
  4. move through several users using delegated Active Directory ACLs;
  5. abuse AD CS ESC3 to obtain a certificate for a more privileged user;
  6. trigger a SYSTEM cleanup task that repaired inheritance on a protected account;
  7. use that account to control an RBCD-trusted service account;
  8. combine S4U2Self U2U and S4U2Proxy to impersonate Administrator.

Initial access

The exposed IIS application built LDAP filters without safely escaping user-controlled input. The injection disclosed enough application material to reproduce the ASP.NET Forms Authentication state and create a valid privileged session.

With the forged session, I reached document-generation functionality that could be used for a BadODT-style file and credential-coercion attack. The resulting NTLM response belonged to Natalie and was crackable offline.

The recovered domain identity was:

HERCULES\natalie.a : <redacted>

This first stage crossed three boundaries in sequence: LDAP injection exposed application secrets, those secrets enabled session forgery, and the authenticated document workflow provided an NTLM coercion primitive.

Natalie to Bob through shadow credentials

BloodHound and direct ACL inspection showed that Natalie had GenericWrite over Bob. Rather than making a permanent password or group change, I used Certipy's reversible shadow-credentials workflow:

certipy shadow auto -k -no-pass \
  -account bob.w \
  -target dc.hercules.htb \
  -dc-ip <redacted-dc-ip>

The operation temporarily added attacker-controlled key credential material, authenticated as Bob, and restored the original msDS-KeyCredentialLink state automatically. This produced a usable Kerberos context for Bob without leaving the injected key credential behind.

bob.w : <redacted-nt-hash>

Bob to Auditor

Bob was a Recruitment Manager and controlled the Security Department path containing Auditor. That delegated control was enough to take over Auditor, enable the account, reset its password, and obtain a TGT.

Auditor belonged to Forest Management, which controlled the Forest Migration OU. I changed the OU owner to Auditor and granted it full control, creating a stable point from which to manage delegated ACEs beneath that OU.

This section of the chain was a reminder that Active Directory privilege is often encoded in object ownership and inheritance rather than obvious group membership. None of these accounts was a domain administrator, but each controlled the next security boundary.

Fernando and AD CS ESC3

Fernando was reachable through the Forest Migration ACL. His Smartcard Operators-related enrollment rights allowed access to the EnrollmentAgent certificate template:

certipy req -k -no-pass \
  -dc-ip <redacted-dc-ip> \
  -dc-host dc.hercules.htb \
  -target dc.hercules.htb \
  -target-ip <redacted-dc-ip> \
  -ca CA-HERCULES \
  -template EnrollmentAgent \
  -out fernando-agent.pfx \
  -dcom -dynamic-endpoint

The CA restricted enrollment-agent use to members of Domain Employees. A direct request for Administrator was therefore denied, but Ashley satisfied the policy. I used Fernando's enrollment-agent certificate to request a Smartcard Logon certificate on Ashley's behalf:

certipy req -k -no-pass \
  -dc-ip <redacted-dc-ip> \
  -dc-host dc.hercules.htb \
  -target dc.hercules.htb \
  -target-ip <redacted-dc-ip> \
  -ca CA-HERCULES \
  -template SmartcardLogon \
  -on-behalf-of 'HERCULES\ashley.b' \
  -pfx fernando-agent.pfx \
  -out ashley.pfx \
  -dcom -dynamic-endpoint

Authenticating with that certificate returned Ashley's TGT and account hash:

ashley.b : <redacted-nt-hash>

The important ESC3 condition was not simply the presence of an enrollment-agent template. The path required control of an eligible enrollment principal, permission to use the agent template, a target user accepted by the CA's restrictions, and a second template that allowed enrollment on behalf of that user.

The hidden cleanup task

Ashley belonged to IT Support and Remote Management Users. The IT share contained cleanup.lnk, which referenced:

C:\Users\ashley.b\Desktop\aCleanup.ps1

The script appeared absent over the Users SMB share because access-based enumeration hid it. From Ashley's Kerberos-authenticated WinRM session, however, the file was visible and contained only:

Start-ScheduledTask -TaskName "Password Cleanup"

The scheduled task ran as SYSTEM and wrote its log beneath Ashley's profile. Mail in the profile explained its purpose: formerly privileged users retained protected DACLs, preventing departmental password-reset delegation from applying. The cleanup task repaired inheritance, but only in OUs containing a delegated password-reset ACE.

IIS_Administrator lived inside Forest Migration with adminCount=1 and a protected DACL. I added an inherited Reset Password delegation for IT Support to the controlled OU:

dacledit.py -k -no-pass \
  -dc-ip <redacted-dc-ip> \
  -dc-host dc.hercules.htb \
  -action write \
  -rights ResetPassword \
  -inheritance \
  -principal 'IT Support' \
  -target-dn 'OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb' \
  'hercules.htb/auditor'

After starting Password Cleanup again, its log included IIS_Administrator. The task removed the account's adminCount, disabled DACL protection, and restored inherited permissions.

I could then add inherited control for Auditor, clear ACCOUNTDISABLE, and reset the account password through Kerberos-authenticated SAMR as Ashley:

changepasswd.py -k -no-pass -reset \
  -altuser 'hercules.htb/ashley.b' \
  -newpass '<redacted>' \
  -protocol smb-samr \
  -dc-ip <redacted-dc-ip> \
  'hercules.htb/iis_administrator@dc.hercules.htb'

The escalation depended on understanding the cleanup task's selection logic. Triggering it alone was insufficient; the controlled OU first needed the delegated password-reset ACE that made the protected account eligible for repair.

Service Operators to RBCD

IIS_Administrator belonged to Service Operators. That group had Force Change Password over the iis_webserver$ service account.

The domain controller's resource-based constrained delegation descriptor trusted the service account SID. The service account did not have an SPN, so the ordinary S4U2Self path was unavailable. I used the user-to-user Kerberos variant instead:

  1. set iis_webserver$ to controlled key material;
  2. request an RC4 TGT for the account;
  3. extract the TGT session key;
  4. change the account key to match that session key while the TGT remained valid;
  5. perform S4U2Self using U2U;
  6. pass the resulting evidence ticket into S4U2Proxy for a service hosted by the domain controller.

The core request was:

KRB5CCNAME='iis_webserver$.ccache' getST.py \
  -k -no-pass \
  -dc-ip <redacted-dc-ip> \
  -u2u \
  -impersonate Administrator \
  -spn cifs/dc.hercules.htb \
  'hercules.htb/iis_webserver$'

This produced an Administrator service ticket for CIFS without requiring the controlled account to advertise its own SPN. I repeated the request for HTTP/dc.hercules.htb and used the resulting ticket for an Administrator WinRM session.

hercules\administrator

Why the chain worked

Hercules combined several independent trust failures:

  • LDAP input reached a raw directory filter. The application disclosed material that should never have been queryable through user input.
  • Application secrets enabled session forgery. Authentication integrity depended on secrets exposed by the injection.
  • Authenticated document handling enabled NTLM coercion. A web feature became a domain-credential capture primitive.
  • Delegated ACLs formed a privilege graph. GenericWrite, ownership, and inherited ACE control connected otherwise unprivileged identities.
  • AD CS allowed constrained enrollment-agent abuse. Template permissions and issuance restrictions still permitted escalation to an eligible user.
  • A SYSTEM maintenance task modified protected-object security descriptors. Attacker-controlled OU delegation influenced which accounts the task repaired.
  • A privileged group could reset an RBCD-trusted account. Password-reset control became control of the delegation principal.
  • U2U bypassed the missing-SPN limitation. S4U2Self could still create evidence for the later S4U2Proxy request.

Defensive takeaways

  • escape LDAP filter input with a library designed for the directory API in use;
  • protect ASP.NET authentication keys and rotate them after any suspected disclosure;
  • remove or isolate document features that can coerce outbound authentication;
  • continuously review object ownership, GenericWrite, password-reset, and inherited-control paths in Active Directory;
  • audit AD CS enrollment-agent templates, issuance requirements, and eligible target groups as one combined policy;
  • do not let scheduled maintenance tasks derive privileged security-descriptor changes from user-controlled OU ACLs;
  • alert on unexpected adminCount removal and DACL-protection changes;
  • treat password-reset rights over computer and service accounts as potential delegation compromise;
  • monitor unusual U2U S4U activity and service-ticket requests involving RBCD-trusted principals.

Hercules was less about one exotic exploit than about maintaining a correct model of identity, ownership, inheritance, certificate issuance, and Kerberos delegation across a long chain. Each stage became possible because the previous principal controlled exactly one more trust decision than it should have.