From 6911c3559a6673834f493a7dc8a4c749ee3dbb90 Mon Sep 17 00:00:00 2001 From: sjanusz-r7 Date: Mon, 13 May 2024 18:13:07 +0100 Subject: [PATCH] Add support for configurable RPORT, session & default rports to lookupsid --- lib/msf/core/exploit/remote/ms_icpr.rb | 2 +- lib/msf/core/exploit/remote/ms_lsarpc.rb | 14 +-- lib/msf/core/exploit/remote/ms_samr.rb | 2 +- .../auxiliary/scanner/smb/smb_lookupsid.rb | 117 ++++++++++++++---- spec/acceptance/smb_spec.rb | 2 +- 5 files changed, 99 insertions(+), 38 deletions(-) diff --git a/lib/msf/core/exploit/remote/ms_icpr.rb b/lib/msf/core/exploit/remote/ms_icpr.rb index 339e8d6e1a300..e85877feff73a 100644 --- a/lib/msf/core/exploit/remote/ms_icpr.rb +++ b/lib/msf/core/exploit/remote/ms_icpr.rb @@ -11,7 +11,7 @@ module Msf module Exploit::Remote::MsIcpr - include Msf::Exploit::Remote::MsIpc + include Msf::Exploit::Remote::SMB::Client::Ipc include Msf::Exploit::Remote::DCERPC # [2.2.2.7.7.4 szOID_NTDS_CA_SECURITY_EXT](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/e563cff8-1af6-4e6f-a655-7571ca482e71) diff --git a/lib/msf/core/exploit/remote/ms_lsarpc.rb b/lib/msf/core/exploit/remote/ms_lsarpc.rb index d791e9d515b79..42c70d3cc8278 100644 --- a/lib/msf/core/exploit/remote/ms_lsarpc.rb +++ b/lib/msf/core/exploit/remote/ms_lsarpc.rb @@ -88,7 +88,7 @@ def close_policy(policy_handle) def disconnect_lsarpc begin self.lsarpc_pipe.close if self.lsarpc_pipe&.is_connected? - rescue RubySMB::Error::UnexpectedStatusCode => e + rescue RubySMB::Error::UnexpectedStatusCode, RubySMB::Error::CommunicationError => e wlog e end end @@ -97,16 +97,14 @@ def disconnect_lsarpc def connect_lsarpc(tree) begin - vprint_status('Connecting to LSARPC') - self.lsarpc_pipe = tree.open_file(filename: 'LSARPC', write: true, read: true) + vprint_status('Connecting to Local Security Authority Remote Protocol') + self.lsarpc_pipe = tree.open_file(filename: 'lsarpc', write: true, read: true) - raise MsLsarpcConnectionError.new('Could not open LSARPC pipe on remote SMB server.') unless lsarpc_pipe + raise MsLsarpcConnectionError.new('Could not open lsarpc pipe on remote SMB server.') unless lsarpc_pipe - self.lsarpc_pipe.extend(LSARPC_ENDPOINT) unless lsarpc_pipe.is_a?(LSARPC_ENDPOINT) - - vprint_status('Binding to \\LSARPC...') + vprint_status('Binding to \\lsarpc...') self.lsarpc_pipe.bind(endpoint: LSARPC_ENDPOINT) - vprint_good('Bound to \\LSARPC') + vprint_good('Bound to \\lsarpc') self.lsarpc_pipe rescue RubySMB::Dcerpc::Error::FaultError => e diff --git a/lib/msf/core/exploit/remote/ms_samr.rb b/lib/msf/core/exploit/remote/ms_samr.rb index 966f8fa77131b..13923ff556bdd 100644 --- a/lib/msf/core/exploit/remote/ms_samr.rb +++ b/lib/msf/core/exploit/remote/ms_samr.rb @@ -8,7 +8,7 @@ module Msf module Exploit::Remote::MsSamr - include Msf::Exploit::Remote::MsIpc + include Msf::Exploit::Remote::SMB::Client::Ipc class MsSamrError < StandardError; end class MsSamrConnectionError < MsSamrError; end diff --git a/modules/auxiliary/scanner/smb/smb_lookupsid.rb b/modules/auxiliary/scanner/smb/smb_lookupsid.rb index e3eefaad7fd7d..c10e2aee2ba45 100644 --- a/modules/auxiliary/scanner/smb/smb_lookupsid.rb +++ b/modules/auxiliary/scanner/smb/smb_lookupsid.rb @@ -46,19 +46,41 @@ def initialize ) end - # Fingerprint a single host - def run_host(ip) - sids_table = Rex::Text::Table.new( - 'Indent' => 4, - 'Header' => "SMB Lookup SIDs Output", - 'Columns' => - [ - 'Type', - 'Name', - 'RID' - ], - 'SortIndex' => 2, # Sort by RID - ) + def rport + @rport + end + + def smb_direct + @smb_direct + end + + def connect(*args, **kwargs) + super(*args, **kwargs, direct: @smb_direct) + end + + def run_session + smb_services = [{ port: self.simple.peerport, direct: self.simple.direct }] + smb_services.map { |smb_service| run_service(smb_service[:port], smb_service[:direct]) } + end + + def run_rhost + if datastore['RPORT'].blank? || datastore['RPORT'] == 0 + smb_services = [ + { port: 445, direct: true }, + { port: 139, direct: false } + ] + else + smb_services = [ + { port: datastore['RPORT'], direct: datastore['SMBDirect'] } + ] + end + + smb_services.map { |smb_service| run_service(smb_service[:port], smb_service[:direct]) } + end + + def run_service(port, direct) + @rport = port + @smb_direct = direct ipc_tree = connect_ipc lsarpc_pipe = connect_lsarpc(ipc_tree) @@ -95,21 +117,23 @@ def run_host(ip) print_status(all_info) target_sid = case action.name.upcase - when 'LOCAL' - info[:local][:sid] == 'null' ? info[:domain][:sid] : info[:local][:sid] - when 'DOMAIN' - # Fallthrough to the host SID if no domain SID was returned - if info[:domain][:sid] == 'null' - print_error 'No domain SID identified, falling back to the local SID...' - info[:local][:sid] - else - info[:domain][:sid] - end - end + when 'LOCAL' + info[:local][:sid] == 'null' ? info[:domain][:sid] : info[:local][:sid] + when 'DOMAIN' + # Fallthrough to the host SID if no domain SID was returned + if info[:domain][:sid] == 'null' + print_error 'No domain SID identified, falling back to the local SID...' + info[:local][:sid] + else + info[:domain][:sid] + end + end min_rid = datastore['MinRID'] max_rid = datastore['MaxRID'] + output = [] + # Brute force through a common RID range min_rid.upto(max_rid) do |rid| print "%bld%blu[*]%clr Trying RID #{rid} / #{max_rid}\r" @@ -117,7 +141,7 @@ def run_host(ip) sid = "#{target_sid}-#{rid}" sids = lookup_sids(policy_handle, sid, endpoint::LSAP_LOOKUP_WKSTA) sids.each do |sid| - sids_table << [ map_security_principal_to_string(sid[:type]), sid[:name], rid ] + output << [ map_security_principal_to_string(sid[:type]), sid[:name], rid ] end rescue RubySMB::Dcerpc::Error::LsarpcError => e # Ignore unmapped RIDs @@ -127,9 +151,11 @@ def run_host(ip) end end - print_line - print_status sids_table.to_s + output + rescue Msf::Exploit::Remote::SMB::Client::Ipc::SmbIpcAuthenticationError => e + print_warning e.message + nil rescue ::Timeout::Error rescue ::Exception => e print_error("Error: #{e.class} #{e}") @@ -138,4 +164,41 @@ def run_host(ip) disconnect_lsarpc disconnect_ipc(ipc_tree) end + + def format_results(results) + sids_table = Rex::Text::Table.new( + 'Indent' => 4, + 'Header' => "SMB Lookup SIDs Output", + 'Columns' => + [ + 'Type', + 'Name', + 'RID' + ], + 'SortIndex' => 2, # Sort by RID + ) + + # Each result contains 0 or more arrays containing: SID Type, Name, RID + results.compact.each do |result_set| + result_set.each { |result| sids_table << result } + end + + sids_table + end + + # Fingerprint a single host + def run_host(_ip) + if session + self.simple = session.simple_client + results = run_session + else + results = run_rhost + end + + results_table = format_results(results) + results_table.rows = results_table.rows.uniq # Remove potentially duplicate entries from port 139 & 445 + + print_line + print_line results_table.to_s + end end diff --git a/spec/acceptance/smb_spec.rb b/spec/acceptance/smb_spec.rb index 2d5ab53d79f2a..6c5078f40a138 100644 --- a/spec/acceptance/smb_spec.rb +++ b/spec/acceptance/smb_spec.rb @@ -36,7 +36,7 @@ lines: { all: { required: [ - "PIPE(LSARPC) LOCAL", + "PIPE(lsarpc) LOCAL", /User( *)(Administrator|nobody)/, /Group( *)(None|Domain (Admins|Users|Guests|Computers))/, ],