Skip to content

Commit 371196f

Browse files
authored
Merge pull request #20115 from cgranleese-r7/adds-additional-support-for-network-capture-decryption
Adds additional support for network capture decryption
2 parents dace39f + c967e94 commit 371196f

File tree

8 files changed

+36
-5
lines changed

8 files changed

+36
-5
lines changed

.github/workflows/ldap_acceptance.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ on:
3333
- 'metsploit-framework.gemspec'
3434
- 'Gemfile.lock'
3535
- '**/**ldap**'
36+
- 'lib/metasploit/framework/tcp/**'
37+
- 'lib/metasploit/framework/login_scanner/**'
3638
- 'spec/acceptance/**'
3739
- 'spec/support/acceptance/**'
3840
- 'spec/acceptance_spec_helper.rb'

.github/workflows/postgres_acceptance.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ on:
3333
- 'metsploit-framework.gemspec'
3434
- 'Gemfile.lock'
3535
- '**/**postgres**'
36+
- 'lib/metasploit/framework/tcp/**'
37+
- 'lib/metasploit/framework/login_scanner/**'
3638
- 'spec/acceptance/**'
3739
- 'spec/support/acceptance/**'
3840
- 'spec/acceptance_spec_helper.rb'

lib/metasploit/framework/login_scanner/base.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ module Base
4545
# @!attribute bruteforce_speed
4646
# @return [Integer] The desired speed, with 5 being 'fast' and 0 being 'slow.'
4747
attr_accessor :bruteforce_speed
48+
# @!attribute sslkeylogfile
49+
# @return [String] The SSL key log file path
50+
attr_accessor :sslkeylogfile
4851

4952
validates :connection_timeout,
5053
presence: true,

lib/metasploit/framework/login_scanner/mssql.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def attempt_login(credential)
7777
}
7878

7979
begin
80-
client = Rex::Proto::MSSQL::Client.new(framework_module, framework, host, port, proxies)
80+
client = Rex::Proto::MSSQL::Client.new(framework_module, framework, host, port, proxies, sslkeylogfile: sslkeylogfile)
8181
if client.mssql_login(credential.public, credential.private, '', credential.realm)
8282
result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL
8383
if use_client_as_proof

lib/metasploit/framework/mssql/tdssslproxy.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ class TDSSSLProxy
3838
TYPE_PRE_LOGIN_MESSAGE = 18
3939
STATUS_END_OF_MESSAGE = 0x01
4040

41-
def initialize(sock)
41+
def initialize(sock, sslkeylogfile: nil)
4242
@tdssock = sock
43+
@sslkeylogfile = sslkeylogfile
4344
@s1, @s2 = Rex::Socket.tcp_socket_pair
4445
end
4546

@@ -48,10 +49,27 @@ def cleanup
4849
@t1.join
4950
end
5051

52+
def write_to_keylog_file(ctx, sslkeylogfile)
53+
# writing to the sslkeylogfile is required, it adds support for network capture decryption which is useful to
54+
# decrypt TLS traffic in wireshark
55+
if sslkeylogfile
56+
unless ctx.respond_to?(:keylog_cb)
57+
raise 'Unable to create sslkeylogfile - Ruby 3.2 or above required for this functionality'
58+
end
59+
60+
ctx.keylog_cb = proc do |_sock, line|
61+
File.open(sslkeylogfile, 'ab') do |file|
62+
file.write("#{line}\n")
63+
end
64+
end
65+
end
66+
end
67+
5168
def setup_ssl
5269
@running = true
5370
@t1 = Thread.start { ssl_setup_thread }
5471
ctx = OpenSSL::SSL::SSLContext.new(:SSLv23)
72+
write_to_keylog_file(ctx, @sslkeylogfile)
5573
ctx.ciphers = "ALL:!ADH:!EXPORT:!SSLv2:!SSLv3:+HIGH:+MEDIUM"
5674
@ssl_socket = OpenSSL::SSL::SSLSocket.new(@s1, ctx)
5775
@ssl_socket.connect

lib/metasploit/framework/tcp/client.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ def connect(global = true, opts={})
8989
'SSL' => dossl,
9090
'SSLVersion' => opts['SSLVersion'] || ssl_version,
9191
'SSLVerifyMode' => opts['SSLVerifyMode'] || ssl_verify_mode,
92+
'SSLKeyLogFile' => opts['SSLKeyLogFile'] || sslkeylogfile,
9293
'SSLCipher' => opts['SSLCipher'] || ssl_cipher,
9394
'Proxies' => proxies,
9495
'Timeout' => (opts['ConnectTimeout'] || connection_timeout || 10).to_i,

lib/msf/core/auxiliary/auth_brute.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def initialize(info = {})
3838
OptBool.new('REMOVE_USERPASS_FILE', [ true, "Automatically delete the USERPASS_FILE on module completion", false]),
3939
OptBool.new('PASSWORD_SPRAY', [true, "Reverse the credential pairing order. For each password, attempt every possible user.", false]),
4040
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]),
41+
OptString.new('SSLKeyLogFile', [ false, 'The SSL key log file', ENV['SSLKeyLogFile']]),
4142
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
4243
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
4344
OptInt.new('MaxGuessesPerUser', [ false, %q{

lib/rex/proto/mssql/client.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ class Client
2525
attr_accessor :ssl_version
2626
attr_accessor :ssl_verify_mode
2727
attr_accessor :ssl_cipher
28+
# @!attribute sslkeylogfile
29+
# @return [String] The SSL key log file path
30+
attr_accessor :sslkeylogfile
2831
attr_accessor :proxies
2932
attr_accessor :connection_timeout
3033
attr_accessor :send_lm
@@ -50,7 +53,7 @@ class Client
5053
# @return [String] The database name this client is currently connected to.
5154
attr_accessor :current_database
5255

53-
def initialize(framework_module, framework, rhost, rport = 1433, proxies = nil)
56+
def initialize(framework_module, framework, rhost, rport = 1433, proxies = nil, sslkeylogfile: nil)
5457
@framework_module = framework_module
5558
@framework = framework
5659
@connection_timeout = framework_module.datastore['ConnectTimeout'] || 30
@@ -68,6 +71,7 @@ def initialize(framework_module, framework, rhost, rport = 1433, proxies = nil)
6871
@rhost = rhost
6972
@rport = rport
7073
@proxies = proxies
74+
@sslkeylogfile = sslkeylogfile
7175
@current_database = ''
7276
end
7377

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

456460
if self.tdsencryption == true
457-
proxy = TDSSSLProxy.new(sock)
461+
proxy = TDSSSLProxy.new(sock, sslkeylogfile: sslkeylogfile)
458462
proxy.setup_ssl
459463
resp = mssql_ssl_send_recv(pkt, proxy)
460464
proxy.cleanup

0 commit comments

Comments
 (0)