Skip to content

Commit 540139c

Browse files
authored
Merge pull request rapid7#21341 from g0tmi1k/smb
Fix various smb/samba issues
2 parents cb1cfbb + 76cae04 commit 540139c

8 files changed

Lines changed: 63 additions & 31 deletions

File tree

lib/msf/core/exploit/remote/ms_samr.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def connect_samr(tree)
6060
rescue RubySMB::Dcerpc::Error::DcerpcError => e
6161
elog(e.message, error: e)
6262
raise MsSamrUnexpectedReplyError, e.message
63-
rescue RubySMB::Error::RubySMBError
63+
rescue RubySMB::Error::RubySMBError => e
6464
elog(e.message, error: e)
6565
raise MsSamrUnknownError, e.message
6666
end

modules/auxiliary/scanner/smb/psexec_loggedin_users.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ def get_hku(ip, smbshare, cmd, text, bat)
8080
command = "#{cmd} /C echo reg.exe QUERY HKU ^> %SYSTEMDRIVE%#{text} > #{bat} & #{cmd} /C start cmd.exe /C #{bat}"
8181
out = psexec(command)
8282
output = get_output(ip, smbshare, text)
83+
return nil unless output
8384
cleanout = Array.new
8485
output.each_line { |line| cleanout << line.chomp if line.include?("HKEY") && line.split("-").size == 8 && !line.split("-")[7].include?("_") }
8586
return cleanout

modules/auxiliary/scanner/smb/smb_enumshares.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,9 @@ def run_host(ip)
311311
connect(versions: [1, 2, 3])
312312
end
313313
smb_login
314-
break unless enum_shares(ip).empty?
314+
shares = enum_shares(ip)
315+
next if shares.nil? || shares.empty?
316+
break
315317
rescue ::Interrupt
316318
raise $ERROR_INFO
317319
rescue Errno::ECONNRESET => e

modules/auxiliary/scanner/smb/smb_enumusers.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,12 @@ def run_service(port, direct)
108108
def run_service_domain(tree, smb_domain: nil)
109109
@smb_domain = smb_domain
110110

111-
samr_con = connect_samr(tree)
111+
begin
112+
samr_con = connect_samr(tree)
113+
rescue ::Exception => e
114+
print_error("SAMR connection failed: #{e.class} #{e}")
115+
return nil
116+
end
112117

113118
lockout_info = samr_con.samr.samr_query_information_domain(
114119
domain_handle: samr_con.domain_handle,
@@ -132,8 +137,10 @@ def run_service_domain(tree, smb_domain: nil)
132137
end
133138
end
134139
ensure
135-
samr_con.samr.close_handle(samr_con.domain_handle) if samr_con.domain_handle
136-
samr_con.samr.close_handle(samr_con.server_handle) if samr_con.server_handle
140+
if samr_con
141+
samr_con.samr.close_handle(samr_con.domain_handle) if samr_con.domain_handle
142+
samr_con.samr.close_handle(samr_con.server_handle) if samr_con.server_handle
143+
end
137144
end
138145

139146
def report_username(domain, username)

modules/auxiliary/scanner/smb/smb_login.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,10 +270,6 @@ def report_creds(ip, port, result)
270270
# Private can be nil if we authenticated with Kerberos and a cached ticket was used. No need to report this.
271271
return unless result.credential.private
272272

273-
if !datastore['RECORD_GUEST'] && (result.access_level == Metasploit::Framework::LoginScanner::SMB::AccessLevels::GUEST)
274-
return
275-
end
276-
277273
service_data = {
278274
address: ip,
279275
port: port,
@@ -282,6 +278,14 @@ def report_creds(ip, port, result)
282278
workspace_id: myworkspace_id
283279
}
284280

281+
report_service(
282+
host: service_data[:address],
283+
port: service_data[:port],
284+
proto: service_data[:protocol],
285+
name: service_data[:service_name]
286+
)
287+
return if !datastore['RECORD_GUEST'] && result.access_level == Metasploit::Framework::LoginScanner::SMB::AccessLevels::GUEST
288+
285289
credential_data = {
286290
module_fullname: fullname,
287291
origin_type: :service,

modules/auxiliary/scanner/smb/smb_lookupsid.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ def format_results(results)
177177

178178
# Each result contains 0 or more arrays containing: SID Type, Name, RID
179179
results.compact.each do |result_set|
180+
next unless result_set.respond_to?(:each)
180181
result_set.each { |result| sids_table << result }
181182
end
182183

@@ -195,7 +196,9 @@ def run_host(_ip)
195196
results_table = format_results(results)
196197
results_table.rows = results_table.rows.uniq # Remove potentially duplicate entries from port 139 & 445
197198

198-
print_line
199-
print_line results_table.to_s
199+
unless results_table.rows.empty?
200+
print_line
201+
print_line results_table.to_s
202+
end
200203
end
201204
end

modules/auxiliary/scanner/smb/smb_uninit_cred.rb

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ def is_vulnerable?(ip)
127127
::Rex::Proto::SMB::Exceptions::InvalidWordCount,
128128
::Rex::Proto::SMB::Exceptions::NoReply => e
129129
elog(e)
130+
rescue ::Rex::Proto::DCERPC::Exceptions::Fault => e
131+
elog(e)
132+
return false
130133
rescue ::Exception => e
131134
if e.to_s =~ /execution expired/i
132135
# So what happens here is that when you trigger the buggy code path, you hit this:
@@ -204,33 +207,34 @@ def maybe_vulnerable?(samba_version)
204207

205208
# Check command
206209
def check_host(ip)
207-
samba_info = ''
210+
@samba_info = ''
208211
smb_ports = [445, 139]
209212
smb_ports.each do |port|
213+
# Update line prefix, as port changes
214+
remove_instance_variable(:@print_prefix) if instance_variable_defined?(:@print_prefix)
210215
@smb_port = port
211-
samba_info = get_samba_info
212-
vprint_status("Samba version: #{samba_info}")
216+
@samba_info = get_samba_info
217+
vprint_status("Samba version: #{@samba_info}")
213218

214-
if samba_info !~ /^samba/i
219+
if @samba_info !~ /^samba/i
215220
vprint_status("Target isn't Samba, no check will run.")
216221
return Exploit::CheckCode::Safe('Target is not running Samba')
217222
end
218223

219224
if datastore['PASSIVE']
220-
if maybe_vulnerable?(samba_info)
221-
flag_vuln_host(ip, samba_info)
225+
if maybe_vulnerable?(@samba_info)
226+
flag_vuln_host(ip, @samba_info)
222227
return Exploit::CheckCode::Appears('Samba version appears to be vulnerable based on version check')
223228
end
224229
else
225230
# Explicit: Actually triggers the bug
226231
if is_vulnerable?(ip)
227-
flag_vuln_host(ip, samba_info)
228-
return Exploit::CheckCode::Vulnerable('Samba uninitialized credential vulnerability confirmed')
232+
flag_vuln_host(ip, @samba_info)
229233
end
230234
end
231235
end
232236

233-
return Exploit::CheckCode::Detected('Samba detected but vulnerability could not be confirmed') if samba_info =~ /^samba/i
237+
return Exploit::CheckCode::Detected('Samba detected but vulnerability could not be confirmed') if @samba_info =~ /^samba/i
234238

235239
Exploit::CheckCode::Safe('Target does not appear to be running Samba')
236240
end
@@ -249,7 +253,8 @@ def flag_vuln_host(ip, samba_version)
249253

250254
def run_host(ip)
251255
peer = "#{ip}:#{rport}"
252-
case check_host(ip)
256+
result = check_host(ip)
257+
case result
253258
when Exploit::CheckCode::Vulnerable
254259
print_good("The target is vulnerable to CVE-2015-0240.")
255260
when Exploit::CheckCode::Appears
@@ -259,5 +264,14 @@ def run_host(ip)
259264
else
260265
print_status("The target appears to be safe")
261266
end
267+
268+
report_service(
269+
:host => ip,
270+
:port => rport,
271+
:proto => 'tcp',
272+
:name => 'smb',
273+
:info => @samba_info.to_s
274+
) if [Exploit::CheckCode::Vulnerable, Exploit::CheckCode::Appears, Exploit::CheckCode::Detected].include?(result)
262275
end
263276
end
277+

modules/auxiliary/scanner/smb/smb_version.rb

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ def run_host(ip)
318318
})
319319
end
320320

321-
# Report the service with a friendly banner
321+
# Report the service with a detailed friendly banner
322322
report_service(
323323
host: ip,
324324
port: rport,
@@ -338,20 +338,21 @@ def run_host(ip)
338338
)
339339
elsif smb1_fingerprint['native_os'] || smb1_fingerprint['native_lm']
340340
desc = "#{smb1_fingerprint['native_os']} (#{smb1_fingerprint['native_lm']})"
341-
report_service(host: ip, port: rport, name: 'smb', info: desc)
341+
342+
# Report the service with a friendly banner
343+
report_service(
344+
host: ip,
345+
port: rport,
346+
proto: 'tcp',
347+
name: 'smb',
348+
info: desc
349+
)
350+
342351
lines << { type: :status, message: " Host could not be identified: #{desc}" }
343352
else
344353
lines << { type: :status, message: ' Host could not be identified', verbose: true }
345354
end
346355

347-
report_service(
348-
host: ip,
349-
port: rport,
350-
proto: 'tcp',
351-
name: 'smb',
352-
info: "#{smb_desc}. #{os_desc}"
353-
)
354-
355356
# Report a smb.fingerprint hash of attributes for OS fingerprinting
356357
report_note(
357358
host: ip,

0 commit comments

Comments
 (0)