Skip to content

Commit 84df403

Browse files
committed
Land rapid7#4852, vuln note import/export addition
2 parents cb9922a + 095431c commit 84df403

File tree

4 files changed

+50
-38
lines changed

4 files changed

+50
-38
lines changed

lib/msf/core/db_export.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,18 @@ def extract_host_info(report_file)
374374
report_file.write(" #{el}\n")
375375
end
376376

377+
# Notes attached to vulns instead of the host
378+
report_file.write(" <notes>\n")
379+
@notes.where(vuln_id: e.id).each do |note|
380+
report_file.write(" <note>\n")
381+
note.attributes.each_pair do |k,v|
382+
el = create_xml_element(k,v)
383+
report_file.write(" #{el}\n")
384+
end
385+
report_file.write(" </note>\n")
386+
end
387+
report_file.write(" </notes>\n")
388+
377389
# References
378390
report_file.write(" <refs>\n")
379391
e.refs.each do |ref|

lib/msf/core/db_manager/import/metasploit_framework/xml.rb

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,30 @@ def import_msf_file(args={})
6464
import_msf_xml(args.merge(:data => data))
6565
end
6666

67+
# Imports `Mdm::Note` objects from the XML element.
68+
#
69+
# @param note [REXML::Element] The Note element
70+
# @param allow_yaml [Boolean] whether to allow yaml
71+
# @param note_data [Hash] hash containing note attributes to be passed along
72+
# @return [void]
73+
def import_msf_note_element(note, allow_yaml, note_data={})
74+
note_data[:type] = nils_for_nulls(note.elements["ntype"].text.to_s.strip)
75+
note_data[:data] = nils_for_nulls(unserialize_object(note.elements["data"], allow_yaml))
76+
77+
if note.elements["critical"].text
78+
note_data[:critical] = true unless note.elements["critical"].text.to_s.strip == "NULL"
79+
end
80+
if note.elements["seen"].text
81+
note_data[:seen] = true unless note.elements["critical"].text.to_s.strip == "NULL"
82+
end
83+
%W{created-at updated-at}.each { |datum|
84+
if note.elements[datum].text
85+
note_data[datum.gsub("-","_")] = nils_for_nulls(note.elements[datum].text.to_s.strip)
86+
end
87+
}
88+
report_note(note_data)
89+
end
90+
6791
# Imports web_form element using {Msf::DBManager#report_web_form}.
6892
#
6993
# @param element [REXML::Element] web_form element.
@@ -280,21 +304,7 @@ def import_msf_xml(args={}, &block)
280304
note_data = {}
281305
note_data[:workspace] = wspace
282306
note_data[:host] = hobj
283-
note_data[:type] = nils_for_nulls(note.elements["ntype"].text.to_s.strip)
284-
note_data[:data] = nils_for_nulls(unserialize_object(note.elements["data"], allow_yaml))
285-
286-
if note.elements["critical"].text
287-
note_data[:critical] = true unless note.elements["critical"].text.to_s.strip == "NULL"
288-
end
289-
if note.elements["seen"].text
290-
note_data[:seen] = true unless note.elements["critical"].text.to_s.strip == "NULL"
291-
end
292-
%W{created-at updated-at}.each { |datum|
293-
if note.elements[datum].text
294-
note_data[datum.gsub("-","_")] = nils_for_nulls(note.elements[datum].text.to_s.strip)
295-
end
296-
}
297-
report_note(note_data)
307+
import_msf_note_element(note,allow_yaml,note_data)
298308
end
299309

300310
host.elements.each('tags/tag') do |tag|
@@ -335,6 +345,13 @@ def import_msf_xml(args={}, &block)
335345

336346
vobj = report_vuln(vuln_data)
337347

348+
vuln.elements.each("notes/note") do |note|
349+
note_data = {}
350+
note_data[:workspace] = wspace
351+
note_data[:vuln_id] = vobj.id
352+
import_msf_note_element(note,allow_yaml,note_data)
353+
end
354+
338355
vuln.elements.each("vuln_details/vuln_detail") do |vdet|
339356
vdet_data = {}
340357
vdet.elements.each do |det|

lib/msf/core/db_manager/note.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ def report_note(opts)
124124
conditions = { :ntype => ntype }
125125
conditions[:host_id] = host[:id] if host
126126
conditions[:service_id] = service[:id] if service
127+
conditions[:vuln_id] = opts[:vuln_id]
127128

128129
case mode
129130
when :unique
@@ -162,6 +163,9 @@ def report_note(opts)
162163
note.ntype = ntype
163164
note.data = data
164165
end
166+
if opts[:vuln_id]
167+
note.vuln_id = opts[:vuln_id]
168+
end
165169
msf_import_timestamps(opts,note)
166170
note.save!
167171
ret[:note] = note

lib/msf/core/db_manager/vuln.rb

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,29 +45,8 @@ def find_vuln_by_details(details_map, host, service=nil)
4545
end
4646

4747
def find_vuln_by_refs(refs, host, service=nil)
48-
49-
vuln = nil
50-
51-
# Try to find an existing vulnerability with the same service & references
52-
# If there are multiple matches, choose the one with the most matches
53-
if service
54-
refs_ids = refs.map{|x| x.id }
55-
vuln = service.vulns.where({ 'refs.id' => refs_ids }).includes(:refs).sort { |a,b|
56-
( refs_ids - a.refs.map{|x| x.id } ).length <=> ( refs_ids - b.refs.map{|x| x.id } ).length
57-
}.first
58-
end
59-
60-
# Return if we matched based on service
61-
return vuln if vuln
62-
63-
# Try to find an existing vulnerability with the same host & references
64-
# If there are multiple matches, choose the one with the most matches
65-
refs_ids = refs.map{|x| x.id }
66-
vuln = host.vulns.where({ 'service_id' => nil, 'refs.id' => refs_ids }).includes(:refs).sort { |a,b|
67-
( refs_ids - a.refs.map{|x| x.id } ).length <=> ( refs_ids - b.refs.map{|x| x.id } ).length
68-
}.first
69-
70-
return vuln
48+
ref_ids = refs.find_all { |ref| ref.name.starts_with? 'CVE-'}
49+
host.vulns.joins(:refs).where(service_id: service.try(:id), refs: { id: ref_ids}).first
7150
end
7251

7352
def get_vuln(wspace, host, service, name, data='')

0 commit comments

Comments
 (0)