Skip to content

Commit 958513b

Browse files
committed
Fix rapid7#9522, Add output file support to the vulns command
This adds a new feature for the vulns command for msfconsole. It allows the user to be able to save the vulnerability as a CSV file. Fix rapid7#9522
1 parent cb1b595 commit 958513b

File tree

1 file changed

+37
-3
lines changed
  • lib/msf/ui/console/command_dispatcher

1 file changed

+37
-3
lines changed

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

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@ def cmd_vulns_help
777777
print_line "Usage: vulns [addr range]"
778778
print_line
779779
print_line " -h,--help Show this help information"
780+
print_line " -o <file> Send output to a file in csv format"
780781
print_line " -p,--port <portspec> List vulns matching this port spec"
781782
print_line " -s <svc names> List vulns matching these service names"
782783
print_line " -R,--rhosts Set RHOSTS from the results of the search"
@@ -801,6 +802,7 @@ def cmd_vulns(*args)
801802
search_term = nil
802803
show_info = false
803804
set_rhosts = false
805+
output_file = nil
804806

805807
# Short-circuit help
806808
if args.delete "-h"
@@ -817,6 +819,14 @@ def cmd_vulns(*args)
817819
when "-h","--help"
818820
cmd_vulns_help
819821
return
822+
when "-o", "--output"
823+
output_file = args.shift
824+
if output_file
825+
output_file = File.expand_path(output_file)
826+
else
827+
print_error("Invalid output filename")
828+
return
829+
end
820830
when "-p","--port"
821831
unless (arg_port_range(args.shift, port_ranges, true))
822832
return
@@ -846,6 +856,10 @@ def cmd_vulns(*args)
846856
host_ranges.push(nil) if host_ranges.empty?
847857
ports = port_ranges.flatten.uniq
848858
svcs.flatten!
859+
tbl = Rex::Text::Table.new(
860+
'Header' => 'Vulnerabilities',
861+
'Columns' => ['Timestamp', 'Host', 'Name', 'References', 'Information']
862+
)
849863

850864
each_host_range_chunk(host_ranges) do |host_search|
851865
framework.db.hosts(framework.db.workspace, false, host_search).each do |host|
@@ -857,19 +871,34 @@ def cmd_vulns(*args)
857871
)
858872
end
859873
reflist = vuln.refs.map { |r| r.name }
874+
860875
if(vuln.service)
861876
# Skip this one if the user specified a port and it
862877
# doesn't match.
863878
next unless ports.empty? or ports.include? vuln.service.port
864879
# Same for service names
865880
next unless svcs.empty? or svcs.include?(vuln.service.name)
866-
print_status("Time: #{vuln.created_at} Vuln: host=#{host.address} name=#{vuln.name} refs=#{reflist.join(',')} #{(show_info && vuln.info) ? "info=#{vuln.info}" : ""}")
867-
868881
else
869882
# This vuln has no service, so it can't match
870883
next unless ports.empty? and svcs.empty?
871-
print_status("Time: #{vuln.created_at} Vuln: host=#{host.address} name=#{vuln.name} refs=#{reflist.join(',')} #{(show_info && vuln.info) ? "info=#{vuln.info}" : ""}")
872884
end
885+
886+
print_status("Time: #{vuln.created_at} Vuln: host=#{host.address} name=#{vuln.name} refs=#{reflist.join(',')} #{(show_info && vuln.info) ? "info=#{vuln.info}" : ""}")
887+
888+
if output_file
889+
row = []
890+
row << vuln.created_at
891+
row << host.address
892+
row << vuln.name
893+
row << reflist * ","
894+
if show_info && vuln.info
895+
row << "info=#{vuln.info}"
896+
else
897+
row << ''
898+
end
899+
tbl << row
900+
end
901+
873902
if set_rhosts
874903
addr = (host.scope ? host.address + '%' + host.scope : host.address)
875904
rhosts << addr
@@ -878,6 +907,11 @@ def cmd_vulns(*args)
878907
end
879908
end
880909

910+
unless tbl.rows.empty?
911+
File.write(output_file, tbl.to_csv)
912+
print_status("Wrote vulnerability information to #{output_file}")
913+
end
914+
881915
# Finally, handle the case where the user wants the resulting list
882916
# of hosts to go into RHOSTS.
883917
set_rhosts_from_addrs(rhosts.uniq) if set_rhosts

0 commit comments

Comments
 (0)