Skip to content

Commit 6d897ea

Browse files
authored
Merge pull request #20327 from cgranleese-r7/update-vulns-command
Update `vulns` command
2 parents c0dfbf4 + 65ed80f commit 6d897ea

File tree

2 files changed

+118
-4
lines changed
  • lib/msf/ui/console/command_dispatcher
  • spec/lib/msf/ui/console/command_dispatcher

2 files changed

+118
-4
lines changed

lib/msf/ui/console/command_dispatcher/db.rb

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,8 @@ def cmd_vulns_help
10591059
[ '-R', '--rhosts' ] => [ false, 'Set RHOSTS from the results of the search.' ],
10601060
[ '-S', '--search' ] => [ true, 'Search string to filter by.', '<filter>' ],
10611061
[ '-i', '--info' ] => [ false, 'Display vuln information.' ],
1062-
[ '-d', '--delete' ] => [ false, 'Delete vulnerabilities. Not officially supported.' ]
1062+
[ '-d', '--delete' ] => [ false, 'Delete vulnerabilities. Not officially supported.' ],
1063+
[ '-v', '--verbose' ] => [ false, 'Display additional information.' ]
10631064
)
10641065

10651066
def cmd_vulns(*args)
@@ -1073,6 +1074,7 @@ def cmd_vulns(*args)
10731074

10741075
search_term = nil
10751076
show_info = false
1077+
show_vuln_attempts = false
10761078
set_rhosts = false
10771079
output_file = nil
10781080
delete_count = 0
@@ -1111,6 +1113,8 @@ def cmd_vulns(*args)
11111113
search_term = val
11121114
when '-i', '--info'
11131115
show_info = true
1116+
when '-v', '--verbose'
1117+
show_vuln_attempts = true
11141118
else
11151119
# Anything that wasn't an option is a host to search for
11161120
unless (arg_host_range(val, host_ranges))
@@ -1182,11 +1186,20 @@ def cmd_vulns(*args)
11821186
end
11831187

11841188
if output_file
1185-
File.write(output_file, tbl.to_csv)
1186-
print_status("Wrote vulnerability information to #{output_file}")
1189+
if show_vuln_attempts
1190+
print_warning("Cannot output to a file when verbose mode is enabled. Please remove verbose flag and try again.")
1191+
else
1192+
File.write(output_file, tbl.to_csv)
1193+
print_status("Wrote vulnerability information to #{output_file}")
1194+
end
11871195
else
11881196
print_line
1189-
print_line(tbl.to_s)
1197+
if show_vuln_attempts
1198+
vulns_and_attempts = _format_vulns_and_vuln_attempts(vulns)
1199+
_print_vulns_and_attempts(vulns_and_attempts)
1200+
else
1201+
print_line(tbl.to_s)
1202+
end
11901203
end
11911204

11921205
# Finally, handle the case where the user wants the resulting list
@@ -2347,6 +2360,50 @@ def print_msgs(status_msg, error_msg)
23472360
end
23482361
end
23492362

2363+
def _format_vulns_and_vuln_attempts(vulns)
2364+
vulns.map.with_index do |vuln, index|
2365+
vuln_formatted = <<~EOF.strip.indent(2)
2366+
#{index}. Vuln ID: #{vuln.id}
2367+
Timestamp: #{vuln.created_at}
2368+
Host: #{vuln.host.address}
2369+
Name: #{vuln.name}
2370+
References: #{vuln.refs.map {|r| r.name}.join(',')}
2371+
Information: #{_format_vuln_value(vuln.info)}
2372+
EOF
2373+
2374+
vuln_attempts_formatted = vuln.vuln_attempts.map.with_index do |vuln_attempt, i|
2375+
<<~EOF.strip.indent(5)
2376+
#{i}. ID: #{vuln_attempt.id}
2377+
Vuln ID: #{vuln_attempt.vuln_id}
2378+
Timestamp: #{vuln_attempt.attempted_at}
2379+
Exploit: #{vuln_attempt.exploited}
2380+
Fail reason: #{_format_vuln_value(vuln_attempt.fail_reason)}
2381+
Username: #{vuln_attempt.username}
2382+
Module: #{vuln_attempt.module}
2383+
Session ID: #{_format_vuln_value(vuln_attempt.session_id)}
2384+
Loot ID: #{_format_vuln_value(vuln_attempt.loot_id)}
2385+
Fail Detail: #{_format_vuln_value(vuln_attempt.fail_detail)}
2386+
EOF
2387+
end
2388+
2389+
{ :vuln => vuln_formatted, :vuln_attempts => vuln_attempts_formatted }
2390+
end
2391+
end
2392+
2393+
def _print_vulns_and_attempts(vulns_and_attempts)
2394+
print_line("Vulnerabilities\n===============")
2395+
vulns_and_attempts.each do |vuln_and_attempt|
2396+
print_line(vuln_and_attempt[:vuln])
2397+
print_line("Vuln attempts:".indent(5))
2398+
vuln_and_attempt[:vuln_attempts].each do |attempt|
2399+
print_line(attempt)
2400+
end
2401+
end
2402+
end
2403+
2404+
def _format_vuln_value(s)
2405+
s.blank? ? s.inspect : s.to_s
2406+
end
23502407
end
23512408

23522409
end end end end

spec/lib/msf/ui/console/command_dispatcher/db_spec.rb

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,13 +305,70 @@
305305
" -R, --rhosts Set RHOSTS from the results of the search.",
306306
" -S, --search <filter> Search string to filter by.",
307307
" -s, --service <name> List vulns matching these service names.",
308+
" -v, --verbose Display additional information.",
308309
"Examples:",
309310
" vulns -p 1-65536 # only vulns with associated services",
310311
" vulns -p 1-65536 -s http # identified as http on any port"
311312
]
312313
end
313314
end
314315

316+
describe "-v" do
317+
before(:example) do
318+
vuln_opts = {
319+
updated_at: Time.utc(2025, 6, 17, 9, 17, 37),
320+
host: '192.168.0.1',
321+
name: 'ThinkPHP Multiple PHP Injection RCEs',
322+
info: 'Exploited by exploit/unix/webapp/thinkphp_rce to create Session 1',
323+
refs: ["CVE-2018-20062"]
324+
}
325+
326+
vuln_attempt_opts = {
327+
id: 3,
328+
vuln_id: 1,
329+
attempted_at: Time.utc(2025, 6, 17, 9, 17, 37),
330+
exploited: true,
331+
fail_reason: nil,
332+
username: "foo",
333+
module: "exploit/unix/webapp/thinkphp_rce",
334+
session_id: 1,
335+
loot_id: nil,
336+
fail_detail: nil
337+
}
338+
339+
@vuln = framework.db.report_vuln(vuln_opts)
340+
@vuln_attempt = framework.db.report_vuln_attempt(@vuln, vuln_attempt_opts)
341+
end
342+
343+
after(:example) do
344+
framework.db.delete_vuln({ids: [@vuln.id]})
345+
end
346+
347+
it "should list vulns and vuln attempts" do
348+
db.cmd_vulns "-v"
349+
expect(@output).to match_array [
350+
"Vulnerabilities",
351+
"===============",
352+
" 0. Vuln ID: #{@vuln.id}",
353+
" Timestamp: #{@vuln.created_at}",
354+
" Host: 192.168.0.1",
355+
" Name: ThinkPHP Multiple PHP Injection RCEs",
356+
" References: CVE-2018-20062",
357+
" Information: Exploited by exploit/unix/webapp/thinkphp_rce to create Session 1",
358+
" Vuln attempts:",
359+
" 0. ID: #{@vuln_attempt.id}",
360+
" Vuln ID: #{@vuln.id}",
361+
" Timestamp: #{@vuln_attempt.attempted_at}",
362+
" Exploit: true",
363+
" Fail reason: nil",
364+
" Username: foo",
365+
" Module: exploit/unix/webapp/thinkphp_rce",
366+
" Session ID: 1",
367+
" Loot ID: nil",
368+
" Fail Detail: nil",
369+
]
370+
end
371+
end
315372
end
316373

317374
describe "#cmd_workspace" do

0 commit comments

Comments
 (0)