From 131585235b846d996fcd7c371d090c89e109e82e Mon Sep 17 00:00:00 2001 From: adfoster-r7 Date: Wed, 28 Feb 2024 16:24:16 +0000 Subject: [PATCH] Update SMB Login to support additional configuration --- lib/metasploit/framework/login_scanner/smb.rb | 19 ++++++++++++++++++- lib/msf/core/exploit/remote/smb/client.rb | 2 +- lib/rex/proto/smb/simple_client.rb | 4 +++- modules/auxiliary/scanner/smb/smb_login.rb | 2 ++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/metasploit/framework/login_scanner/smb.rb b/lib/metasploit/framework/login_scanner/smb.rb index 2ff11491721d..955bba993b56 100644 --- a/lib/metasploit/framework/login_scanner/smb.rb +++ b/lib/metasploit/framework/login_scanner/smb.rb @@ -48,6 +48,12 @@ module StatusCodes ].freeze end + # @returns [Array[Integer]] The SMB versions to negotiate + attr_accessor :versions + + # @returns [Boolean] By default the client uses encryption even if it is not required by the server. Disable this by setting always_encrypt to false + attr_accessor :always_encrypt + # @!attribute dispatcher # @return [RubySMB::Dispatcher::Socket] attr_accessor :dispatcher @@ -104,7 +110,16 @@ def attempt_login(credential) realm = (credential.realm || '').dup.force_encoding('UTF-8') username = (credential.public || '').dup.force_encoding('UTF-8') password = (credential.private || '').dup.force_encoding('UTF-8') - client = RubySMB::Client.new(dispatcher, username: username, password: password, domain: realm) + client = RubySMB::Client.new( + dispatcher, + username: username, + password: password, + domain: realm, + smb1: versions.include?(1), + smb2: versions.include?(2), + smb3: versions.include?(3), + always_encrypt: always_encrypt + ) if kerberos_authenticator_factory client.extend(Msf::Exploit::Remote::SMB::Client::KerberosAuthentication) @@ -187,6 +202,8 @@ def set_sane_defaults self.connection_timeout = 10 if connection_timeout.nil? self.max_send_size = 0 if max_send_size.nil? self.send_delay = 0 if send_delay.nil? + self.always_encrypt = true if always_encrypt.nil? + self.versions = ::Rex::Proto::SMB::SimpleClient::DEFAULT_VERSIONS if versions.nil? end end diff --git a/lib/msf/core/exploit/remote/smb/client.rb b/lib/msf/core/exploit/remote/smb/client.rb index 7b46b82fc3ff..786154205ebb 100644 --- a/lib/msf/core/exploit/remote/smb/client.rb +++ b/lib/msf/core/exploit/remote/smb/client.rb @@ -96,7 +96,7 @@ def initialize(info = {}) # @return (see Exploit::Remote::Tcp#connect) def connect(global=true, versions: [], backend: nil) if versions.nil? || versions.empty? - versions = datastore['SMB::ProtocolVersion'].split(',').map(&:to_i) + versions = datastore['SMB::ProtocolVersion'].split(',').map(&:strip).reject(&:blank?).map(&:to_i) # if the user explicitly set the protocol version to 1, still use ruby_smb backend ||= :ruby_smb if versions == [1] end diff --git a/lib/rex/proto/smb/simple_client.rb b/lib/rex/proto/smb/simple_client.rb index 5ec1d574db40..1b192064de6b 100644 --- a/lib/rex/proto/smb/simple_client.rb +++ b/lib/rex/proto/smb/simple_client.rb @@ -16,6 +16,8 @@ class SimpleClient XCEPT = Rex::Proto::SMB::Exceptions EVADE = Rex::Proto::SMB::Evasions + DEFAULT_VERSIONS = [1, 2, 3].freeze + # Public accessors attr_accessor :last_error, :server_max_buffer_size, :address, :port @@ -23,7 +25,7 @@ class SimpleClient attr_accessor :socket, :client, :direct, :shares, :last_share, :versions # Pass the socket object and a boolean indicating whether the socket is netbios or cifs - def initialize(socket, direct = false, versions = [1, 2, 3], always_encrypt: true, backend: nil, client: nil) + def initialize(socket, direct = false, versions = DEFAULT_VERSIONS, always_encrypt: true, backend: nil, client: nil) self.socket = socket self.direct = direct self.versions = versions diff --git a/modules/auxiliary/scanner/smb/smb_login.rb b/modules/auxiliary/scanner/smb/smb_login.rb index 47f2ab6bca1b..4a56974ef330 100644 --- a/modules/auxiliary/scanner/smb/smb_login.rb +++ b/modules/auxiliary/scanner/smb/smb_login.rb @@ -128,6 +128,8 @@ def run_host(ip) send_delay: datastore['TCP::send_delay'], framework: framework, framework_module: self, + always_encrypt: datastore['SMB::AlwaysEncrypt'], + versions: datastore['SMB::ProtocolVersion'].split(',').map(&:strip).reject(&:blank?).map(&:to_i), kerberos_authenticator_factory: kerberos_authenticator_factory, use_client_as_proof: create_session? )