Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions lib/metasploit/framework/login_scanner/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ module Base
# @!attribute bruteforce_speed
# @return [Integer] The desired speed, with 5 being 'fast' and 0 being 'slow.'
attr_accessor :bruteforce_speed
# @!attribute sslkeylogfile
# @return [String] The SSL key log file path
attr_accessor :sslkeylogfile

validates :connection_timeout,
presence: true,
Expand Down
4 changes: 3 additions & 1 deletion lib/metasploit/framework/login_scanner/http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ def create_client(opts)
rport = opts['rport'] || port
cli_ssl = opts['ssl'] || ssl
cli_ssl_version = opts['ssl_version'] || ssl_version
cli_sslkeylogfile = opts['SSLKeyLogFile'] || sslkeylogfile
cli_proxies = opts['proxies'] || proxies
username = opts['credential'] ? opts['credential'].public : http_username
password = opts['credential'] ? opts['credential'].private : http_password
Expand All @@ -357,7 +358,8 @@ def create_client(opts)
username,
password,
kerberos_authenticator: kerberos_authenticator,
subscriber: http_logger_subscriber
subscriber: http_logger_subscriber,
sslkeylogfile: cli_sslkeylogfile
)
configure_http_client(cli)

Expand Down
2 changes: 1 addition & 1 deletion lib/metasploit/framework/login_scanner/mssql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def attempt_login(credential)
}

begin
client = Rex::Proto::MSSQL::Client.new(framework_module, framework, host, port, proxies)
client = Rex::Proto::MSSQL::Client.new(framework_module, framework, host, port, proxies, sslkeylogfile)
if client.mssql_login(credential.public, credential.private, '', credential.realm)
result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL
if use_client_as_proof
Expand Down
3 changes: 3 additions & 0 deletions lib/metasploit/framework/login_scanner/rex_socket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ module RexSocket
# @!attribute ssl_verify_mode
# @return [String] the SSL certification verification mechanism
attr_accessor :ssl_verify_mode
# @!attribute sslkeylogfile
# @return [String, nil] The SSL key log file path
attr_accessor :sslkeylogfile
# @!attribute ssl_cipher
# @return [String] The SSL cipher to use for the context
attr_accessor :ssl_cipher
Expand Down
20 changes: 19 additions & 1 deletion lib/metasploit/framework/mssql/tdssslproxy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ class TDSSSLProxy
TYPE_PRE_LOGIN_MESSAGE = 18
STATUS_END_OF_MESSAGE = 0x01

def initialize(sock)
def initialize(sock, sslkeylogfile = nil)
@tdssock = sock
@sslkeylogfile = sslkeylogfile
@s1, @s2 = Rex::Socket.tcp_socket_pair
end

Expand All @@ -48,10 +49,27 @@ def cleanup
@t1.join
end

def write_to_keylog_file(ctx, sslkeylogfile)
# writing to the sslkeylogfile is required, it adds support for network capture decryption which is useful to
# decrypt TLS traffic in wireshark
if sslkeylogfile
unless ctx.respond_to?(:keylog_cb)
raise 'Unable to create sslkeylogfile - Ruby 3.2 or above required for this functionality'
end

ctx.keylog_cb = proc do |_sock, line|
File.open(sslkeylogfile, 'ab') do |file|
file.write("#{line}\n")
end
end
end
end

def setup_ssl
@running = true
@t1 = Thread.start { ssl_setup_thread }
ctx = OpenSSL::SSL::SSLContext.new(:SSLv23)
write_to_keylog_file(ctx, @sslkeylogfile)
ctx.ciphers = "ALL:!ADH:!EXPORT:!SSLv2:!SSLv3:+HIGH:+MEDIUM"
@ssl_socket = OpenSSL::SSL::SSLSocket.new(@s1, ctx)
@ssl_socket.connect
Expand Down
1 change: 1 addition & 0 deletions lib/metasploit/framework/tcp/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def connect(global = true, opts={})
'SSL' => dossl,
'SSLVersion' => opts['SSLVersion'] || ssl_version,
'SSLVerifyMode' => opts['SSLVerifyMode'] || ssl_verify_mode,
'SSLKeyLogFile' => opts['SSLKeyLogFile'] || sslkeylogfile,
'SSLCipher' => opts['SSLCipher'] || ssl_cipher,
'Proxies' => proxies,
'Timeout' => (opts['ConnectTimeout'] || connection_timeout || 10).to_i,
Expand Down
1 change: 1 addition & 0 deletions lib/msf/core/auxiliary/auth_brute.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def initialize(info = {})
OptInt.new('TRANSITION_DELAY', [false, "Amount of time (in minutes) to delay before transitioning to the next user in the array (or password when PASSWORD_SPRAY=true)", 0]),
OptInt.new('MaxGuessesPerService', [ false, "Maximum number of credentials to try per service instance. If set to zero or a non-number, this option will not be used.", 0]), # Tracked in @@guesses_per_service
OptInt.new('MaxMinutesPerService', [ false, "Maximum time in minutes to bruteforce the service instance. If set to zero or a non-number, this option will not be used.", 0]), # Tracked in @@brute_start_time
OptString.new('SSLKeyLogFile', [ false, 'The SSL key log file', ENV['SSLKeyLogFile']]),
OptInt.new('MaxGuessesPerUser', [ false, %q{
Maximum guesses for a particular username for the service instance.
Note that users are considered unique among different services, so a
Expand Down
1 change: 1 addition & 0 deletions lib/msf/core/auxiliary/login_scanner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def configure_login_scanner(conf)
proxies: datastore['Proxies'],
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
sslkeylogfile: datastore['SSLKeyLogFile'],
framework: framework,
framework_module: self,
local_port: datastore['CPORT'],
Expand Down
2 changes: 1 addition & 1 deletion lib/rex/proto/http/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def connect(t = -1)
'Context' => context,
'SSL' => ssl,
'SSLVersion' => ssl_version,
'SSLKeyLogFile' => sslkeylogfile,
'SSLKeyLogFile' => config['SSLKeyLogFile'] || sslkeylogfile,
'Proxies' => proxies,
'Timeout' => timeout,
'Comm' => comm
Expand Down
10 changes: 7 additions & 3 deletions lib/rex/proto/mssql/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ class Client
attr_accessor :ssl_version
attr_accessor :ssl_verify_mode
attr_accessor :ssl_cipher
# @!attribute sslkeylogfile
# @return [String] The SSL key log file path
attr_accessor :sslkeylogfile
attr_accessor :proxies
attr_accessor :connection_timeout
attr_accessor :send_lm
Expand All @@ -50,7 +53,7 @@ class Client
# @return [String] The database name this client is currently connected to.
attr_accessor :current_database

def initialize(framework_module, framework, rhost, rport = 1433, proxies = nil)
def initialize(framework_module, framework, rhost, rport = 1433, proxies = nil, sslkeylogfile = nil)
@framework_module = framework_module
@framework = framework
@connection_timeout = framework_module.datastore['ConnectTimeout'] || 30
Expand All @@ -68,6 +71,7 @@ def initialize(framework_module, framework, rhost, rport = 1433, proxies = nil)
@rhost = rhost
@rport = rport
@proxies = proxies
@sslkeylogfile = sslkeylogfile
@current_database = ''
end

Expand Down Expand Up @@ -336,7 +340,7 @@ def mssql_login(user='sa', pass='', db='', domain_name='')
# upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header
# is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentification
if tdsencryption == true
proxy = TDSSSLProxy.new(sock)
proxy = TDSSSLProxy.new(sock, sslkeylogfile)
proxy.setup_ssl
resp = proxy.send_recv(pkt)
else
Expand Down Expand Up @@ -454,7 +458,7 @@ def mssql_login(user='sa', pass='', db='', domain_name='')
pkt = "\x10\x01" + [pkt.length + 8].pack('n') + [0].pack('n') + [1].pack('C') + "\x00" + pkt

if self.tdsencryption == true
proxy = TDSSSLProxy.new(sock)
proxy = TDSSSLProxy.new(sock, sslkeylogfile)
proxy.setup_ssl
resp = mssql_ssl_send_recv(pkt, proxy)
proxy.cleanup
Expand Down