dradis-nessus 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/CONTRIBUTING.md +3 -0
- data/Gemfile +23 -0
- data/LICENSE +339 -0
- data/README.md +26 -0
- data/Rakefile +2 -0
- data/dradis-nessus.gemspec +35 -0
- data/lib/dradis-nessus.rb +9 -0
- data/lib/dradis/plugins/nessus.rb +11 -0
- data/lib/dradis/plugins/nessus/engine.rb +24 -0
- data/lib/dradis/plugins/nessus/field_processor.rb +53 -0
- data/lib/dradis/plugins/nessus/gem_version.rb +19 -0
- data/lib/dradis/plugins/nessus/importer.rb +178 -0
- data/lib/dradis/plugins/nessus/version.rb +13 -0
- data/lib/nessus/host.rb +82 -0
- data/lib/nessus/report_item.rb +118 -0
- data/lib/tasks/thorfile.rb +40 -0
- data/spec/dradis/plugins/nessus/field_processor_spec.rb +27 -0
- data/spec/dradis/plugins/nessus/importer_spec.rb +51 -0
- data/spec/fixtures/files/example_v2.nessus +2076 -0
- data/spec/fixtures/files/host-01.xml +20 -0
- data/spec/fixtures/files/report_item-with-list.xml +45 -0
- data/spec/nessus/host_spec.rb +23 -0
- data/spec/spec_helper.rb +10 -0
- data/templates/evidence.fields +16 -0
- data/templates/evidence.sample +53 -0
- data/templates/evidence.template +8 -0
- data/templates/report_host.fields +8 -0
- data/templates/report_host.sample +12 -0
- data/templates/report_host.template +14 -0
- data/templates/report_item.fields +31 -0
- data/templates/report_item.sample +41 -0
- data/templates/report_item.template +29 -0
- metadata +170 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Dradis
|
|
2
|
+
module Plugins
|
|
3
|
+
module Nessus
|
|
4
|
+
class Engine < ::Rails::Engine
|
|
5
|
+
isolate_namespace Dradis::Plugins::Nessus
|
|
6
|
+
|
|
7
|
+
include ::Dradis::Plugins::Base
|
|
8
|
+
description 'Processes Nessus XML v2 format (.nessus)'
|
|
9
|
+
provides :upload
|
|
10
|
+
|
|
11
|
+
# generators do
|
|
12
|
+
# require "path/to/my_railtie_generator"
|
|
13
|
+
# end
|
|
14
|
+
|
|
15
|
+
# Configuring the gem
|
|
16
|
+
# class Configuration < Core::Configurator
|
|
17
|
+
# configure :namespace => 'burp'
|
|
18
|
+
# setting :category, :default => 'Burp Scanner output'
|
|
19
|
+
# setting :author, :default => 'Burp Scanner plugin'
|
|
20
|
+
# end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Dradis
|
|
2
|
+
module Plugins
|
|
3
|
+
module Nessus
|
|
4
|
+
|
|
5
|
+
class FieldProcessor < Dradis::Plugins::Upload::FieldProcessor
|
|
6
|
+
|
|
7
|
+
def post_initialize(args={})
|
|
8
|
+
@nessus_object = (data.name == 'ReportHost') ? ::Nessus::Host.new(data) : ::Nessus::ReportItem.new(data)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def value(args={})
|
|
12
|
+
field = args[:field]
|
|
13
|
+
|
|
14
|
+
# fields in the template are of the form <foo>.<field>, where <foo>
|
|
15
|
+
# is common across all fields for a given template (and meaningless).
|
|
16
|
+
_, name = field.split('.')
|
|
17
|
+
|
|
18
|
+
if name.end_with?('entries')
|
|
19
|
+
# report_item.bid_entries
|
|
20
|
+
# report_item.cve_entries
|
|
21
|
+
# report_item.xref_entries
|
|
22
|
+
entries = @nessus_object.try(name)
|
|
23
|
+
if entries.any?
|
|
24
|
+
entries.to_a.join("\n")
|
|
25
|
+
else
|
|
26
|
+
'n/a'
|
|
27
|
+
end
|
|
28
|
+
else
|
|
29
|
+
output = @nessus_object.try(name) || 'n/a'
|
|
30
|
+
|
|
31
|
+
if field == 'report_item.description' && output =~ /^ -/
|
|
32
|
+
format_bullet_point_lists(output)
|
|
33
|
+
else
|
|
34
|
+
output
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
def format_bullet_point_lists(input)
|
|
41
|
+
input.split("\n\n").map do |paragraph|
|
|
42
|
+
if paragraph =~ /^ - (.*)$/m
|
|
43
|
+
'* ' + $1.gsub(/ /, '').gsub(/\n/, ' ')
|
|
44
|
+
else
|
|
45
|
+
paragraph
|
|
46
|
+
end
|
|
47
|
+
end.join("\n\n")
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Dradis
|
|
2
|
+
module Plugins
|
|
3
|
+
module Nessus
|
|
4
|
+
# Returns the version of the currently loaded Nessus as a <tt>Gem::Version</tt>
|
|
5
|
+
def self.gem_version
|
|
6
|
+
Gem::Version.new VERSION::STRING
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module VERSION
|
|
10
|
+
MAJOR = 3
|
|
11
|
+
MINOR = 3
|
|
12
|
+
TINY = 0
|
|
13
|
+
PRE = nil
|
|
14
|
+
|
|
15
|
+
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
module Dradis::Plugins::Nessus
|
|
2
|
+
class Importer < Dradis::Plugins::Upload::Importer
|
|
3
|
+
|
|
4
|
+
# The framework will call this function if the user selects this plugin from
|
|
5
|
+
# the dropdown list and uploads a file.
|
|
6
|
+
# @returns true if the operation was successful, false otherwise
|
|
7
|
+
def import(params={})
|
|
8
|
+
file_content = File.read( params[:file] )
|
|
9
|
+
|
|
10
|
+
logger.info{'Parsing nessus output file...'}
|
|
11
|
+
doc = Nokogiri::XML( file_content )
|
|
12
|
+
logger.info{'Done.'}
|
|
13
|
+
|
|
14
|
+
if doc.xpath('/NessusClientData_v2/Report').empty?
|
|
15
|
+
error = "No reports were detected in the uploaded file (/NessusClientData_v2/Report). Ensure you uploaded a Nessus XML v2 (.nessus) report."
|
|
16
|
+
logger.fatal{ error }
|
|
17
|
+
content_service.create_note text: error
|
|
18
|
+
return false
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
doc.xpath('/NessusClientData_v2/Report').each do |xml_report|
|
|
22
|
+
report_label = xml_report.attributes['name'].value
|
|
23
|
+
logger.info{ "Processing report: #{report_label}" }
|
|
24
|
+
# No need to create a report node for each report. It may be good to
|
|
25
|
+
# create a plugin.output/nessus.reports with info for each scan, but
|
|
26
|
+
# for the time being we just append stuff to the Host
|
|
27
|
+
# report_node = parent.children.find_or_create_by_label(report_label)
|
|
28
|
+
|
|
29
|
+
xml_report.xpath('./ReportHost').each do |xml_host|
|
|
30
|
+
process_report_host(xml_host)
|
|
31
|
+
end #/ReportHost
|
|
32
|
+
logger.info{ "Report processed." }
|
|
33
|
+
end #/Report
|
|
34
|
+
|
|
35
|
+
return true
|
|
36
|
+
end # /import
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
# Internal: Parses the specific "Nessus SYN Scanner" and similar plugin into
|
|
42
|
+
# Dradis node properties.
|
|
43
|
+
#
|
|
44
|
+
# xml_host - The Nokogiri XML node representing the parent host for
|
|
45
|
+
# this issue.
|
|
46
|
+
# host_node - The Dradis Node that represents the host in the project.
|
|
47
|
+
# xml_report_item - The Nokogiri XML node representing the Service Detection
|
|
48
|
+
# <ReportItem> tag.
|
|
49
|
+
#
|
|
50
|
+
# Returns nothing.
|
|
51
|
+
#
|
|
52
|
+
# Plugins processed using this method:
|
|
53
|
+
# - [11219] Nessus SYN Scanner
|
|
54
|
+
# - [34220] Netstat Portscanner (WMI)
|
|
55
|
+
def process_nessus_syn_scanner(xml_host, host_node, xml_report_item)
|
|
56
|
+
port = xml_report_item['port'].to_i
|
|
57
|
+
protocol = xml_report_item['protocol']
|
|
58
|
+
logger.info{ "\t\t\t => Creating new service: #{protocol}/#{port}" }
|
|
59
|
+
|
|
60
|
+
host_node.set_property(:services, {
|
|
61
|
+
port: port,
|
|
62
|
+
protocol: protocol,
|
|
63
|
+
state: 'open',
|
|
64
|
+
name: xml_report_item['svc_name'],
|
|
65
|
+
x_nessus: xml_report_item.at_xpath('./plugin_output').text
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
host_node.save
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Internal: Process each /NessusClientData_v2/Report/ReportHost creating a
|
|
72
|
+
# Dradis node and adding some properties to it (:ip, :os, etc.).
|
|
73
|
+
#
|
|
74
|
+
# xml_host - The Nokogiri XML node representing the parent host for
|
|
75
|
+
# this issue.
|
|
76
|
+
#
|
|
77
|
+
# Returns nothing.
|
|
78
|
+
#
|
|
79
|
+
def process_report_host(xml_host)
|
|
80
|
+
|
|
81
|
+
# 1. Create host node
|
|
82
|
+
host_label = xml_host.attributes['name'].value
|
|
83
|
+
host_label += " (#{xml_host.attributes['fqdn'].value})" if xml_host.attributes['fqdn']
|
|
84
|
+
|
|
85
|
+
host_node = content_service.create_node(label: host_label, type: :host)
|
|
86
|
+
logger.info{ "\tHost: #{host_label}" }
|
|
87
|
+
|
|
88
|
+
# 2. Add host info note and host properties
|
|
89
|
+
host_note_text = template_service.process_template(template: 'report_host', data: xml_host)
|
|
90
|
+
content_service.create_note(text: host_note_text, node: host_node)
|
|
91
|
+
|
|
92
|
+
if host_node.respond_to?(:properties)
|
|
93
|
+
nh = ::Nessus::Host.new(xml_host)
|
|
94
|
+
host_node.set_property(:fqdn, nh.fqdn) if nh.try(:fqdn)
|
|
95
|
+
host_node.set_property(:ip, nh.ip) if nh.try(:ip)
|
|
96
|
+
host_node.set_property(:mac_address, nh.mac_address) if nh.try(:mac_address)
|
|
97
|
+
host_node.set_property(:netbios_name, nh.netbios_name) if nh.try(:netbios_name)
|
|
98
|
+
host_node.set_property(:os, nh.operating_system) if nh.try(:operating_system)
|
|
99
|
+
host_node.save
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# 3. Add Issue and associated Evidence for this host/port combination
|
|
104
|
+
xml_host.xpath('./ReportItem').each do |xml_report_item|
|
|
105
|
+
case xml_report_item.attributes['pluginID'].value
|
|
106
|
+
when '0'
|
|
107
|
+
when '11219', '34220' # Nessus SYN scanner, Netstat Portscanner (WMI)
|
|
108
|
+
process_nessus_syn_scanner(xml_host, host_node, xml_report_item)
|
|
109
|
+
when '22964' # Service Detection
|
|
110
|
+
process_service_detection(xml_host, host_node, xml_report_item)
|
|
111
|
+
else
|
|
112
|
+
process_report_item(xml_host, host_node, xml_report_item)
|
|
113
|
+
end
|
|
114
|
+
end #/ReportItem
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Internal: Process each /NessusClientData_v2/Report/ReportHost/ReportItem
|
|
118
|
+
# and creates the corresponding Issue and Evidence in Dradis.
|
|
119
|
+
#
|
|
120
|
+
# xml_host - The Nokogiri XML node representing the parent host for
|
|
121
|
+
# this issue.
|
|
122
|
+
# host_node - The Dradis Node that represents the host in the project.
|
|
123
|
+
# xml_report_item - The Nokogiri XML node representing the Service Detection
|
|
124
|
+
# <ReportItem> tag.
|
|
125
|
+
#
|
|
126
|
+
# Returns nothing.
|
|
127
|
+
#
|
|
128
|
+
def process_report_item(xml_host, host_node, xml_report_item)
|
|
129
|
+
# 3.1. Add Issue to the project
|
|
130
|
+
plugin_id = xml_report_item.attributes['pluginID'].value
|
|
131
|
+
logger.info{ "\t\t\t => Creating new issue (plugin_id: #{plugin_id})" }
|
|
132
|
+
|
|
133
|
+
issue_text = template_service.process_template(template: 'report_item', data: xml_report_item)
|
|
134
|
+
issue_text << "\n\n#[Host]#\n#{xml_host.attributes['name']}\n\n"
|
|
135
|
+
|
|
136
|
+
issue = content_service.create_issue(text: issue_text, id: plugin_id)
|
|
137
|
+
|
|
138
|
+
# 3.2. Add Evidence to link the port/protocol and Issue
|
|
139
|
+
port_info = xml_report_item.attributes['protocol'].value
|
|
140
|
+
port_info += "/"
|
|
141
|
+
port_info += xml_report_item.attributes['port'].value
|
|
142
|
+
|
|
143
|
+
logger.info{ "\t\t\t => Adding reference to this host" }
|
|
144
|
+
evidence_content = template_service.process_template(template: 'evidence', data: xml_report_item)
|
|
145
|
+
|
|
146
|
+
content_service.create_evidence(issue: issue, node: host_node, content: evidence_content)
|
|
147
|
+
|
|
148
|
+
# 3.3. Compliance check information
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Internal: Parses the specific "Service Detection" plugin into Dradis node
|
|
152
|
+
# properties.
|
|
153
|
+
#
|
|
154
|
+
# xml_host - The Nokogiri XML node representing the parent host for
|
|
155
|
+
# this issue.
|
|
156
|
+
# host_node - The Dradis Node that represents the host in the project.
|
|
157
|
+
# xml_report_item - The Nokogiri XML node representing the Service Detection
|
|
158
|
+
# <ReportItem> tag.
|
|
159
|
+
#
|
|
160
|
+
# Returns nothing.
|
|
161
|
+
#
|
|
162
|
+
def process_service_detection(xml_host, host_node, xml_report_item)
|
|
163
|
+
port = xml_report_item['port'].to_i
|
|
164
|
+
protocol = xml_report_item['protocol']
|
|
165
|
+
logger.info{ "\t\t\t => Creating new service: #{protocol}/#{port}" }
|
|
166
|
+
|
|
167
|
+
host_node.set_property(:services, {
|
|
168
|
+
port: port,
|
|
169
|
+
protocol: protocol,
|
|
170
|
+
state: 'open',
|
|
171
|
+
name: xml_report_item['svc_name'],
|
|
172
|
+
x_nessus: xml_report_item.at_xpath('./description').text
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
host_node.save
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
data/lib/nessus/host.rb
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module Nessus
|
|
2
|
+
# This class represents each of the /NessusClientData_v2/Report/ReportHost
|
|
3
|
+
# elements in the Nessus XML document.
|
|
4
|
+
#
|
|
5
|
+
# It provides a convenient way to access the information scattered all over
|
|
6
|
+
# the XML in attributes and nested tags.
|
|
7
|
+
#
|
|
8
|
+
# Instead of providing separate methods for each supported property we rely
|
|
9
|
+
# on Ruby's #method_missing to do most of the work.
|
|
10
|
+
class Host
|
|
11
|
+
# Accepts an XML node from Nokogiri::XML.
|
|
12
|
+
def initialize(xml_node)
|
|
13
|
+
@xml = xml_node
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# List of supported tags. They are all desdendents of the ./HostProperties
|
|
17
|
+
# node.
|
|
18
|
+
def supported_tags
|
|
19
|
+
[
|
|
20
|
+
# attributes
|
|
21
|
+
:name,
|
|
22
|
+
|
|
23
|
+
# simple tags
|
|
24
|
+
:ip, :fqdn, :operating_system, :mac_address, :netbios_name,
|
|
25
|
+
:scan_start_time, :scan_stop_time
|
|
26
|
+
]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Each of the entries associated with this host. Returns an array of
|
|
30
|
+
# Nessus::ReportItem objects
|
|
31
|
+
def report_items
|
|
32
|
+
@xml.xpath('./ReportItem').collect { |xml_report_item| ReportItem.new(xml_report_item) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# This allows external callers (and specs) to check for implemented
|
|
36
|
+
# properties
|
|
37
|
+
def respond_to?(method, include_private=false)
|
|
38
|
+
return true if supported_tags.include?(method.to_sym)
|
|
39
|
+
super
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# This method is invoked by Ruby when a method that is not defined in this
|
|
43
|
+
# instance is called.
|
|
44
|
+
#
|
|
45
|
+
# In our case we inspect the @method@ parameter and try to find the
|
|
46
|
+
# corresponding <tag/> element inside the ./HostProperties child.
|
|
47
|
+
def method_missing(method, *args)
|
|
48
|
+
# We could remove this check and return nil for any non-recognized tag.
|
|
49
|
+
# The problem would be that it would make tricky to debug problems with
|
|
50
|
+
# typos. For instance: <>.potr would return nil instead of raising an
|
|
51
|
+
# exception
|
|
52
|
+
unless supported_tags.include?(method)
|
|
53
|
+
super
|
|
54
|
+
return
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# first we try the attributes: name
|
|
58
|
+
translations_table = {}
|
|
59
|
+
method_name = translations_table.fetch(method, method.to_s)
|
|
60
|
+
return @xml.attributes[method_name].value if @xml.attributes.key?(method_name)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# translation of Host properties
|
|
64
|
+
translations_table = {
|
|
65
|
+
ip: 'host-ip',
|
|
66
|
+
fqdn: 'host-fqdn',
|
|
67
|
+
operating_system: 'operating-system',
|
|
68
|
+
mac_address: 'mac-address',
|
|
69
|
+
netbios_name: 'netbios-name',
|
|
70
|
+
scan_start_time: 'HOST_START',
|
|
71
|
+
scan_stop_time: 'HOST_END'
|
|
72
|
+
}
|
|
73
|
+
method_name = translations_table.fetch(method, method.to_s)
|
|
74
|
+
|
|
75
|
+
if property = @xml.at_xpath("./HostProperties/tag[@name='#{method_name}']")
|
|
76
|
+
return property.text
|
|
77
|
+
else
|
|
78
|
+
return nil
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module Nessus
|
|
2
|
+
# This class represents each of the /NessusClientData_v2/Report/ReportHost/ReportItem
|
|
3
|
+
# elements in the Nessus XML document.
|
|
4
|
+
#
|
|
5
|
+
# It provides a convenient way to access the information scattered all over
|
|
6
|
+
# the XML in attributes and nested tags.
|
|
7
|
+
#
|
|
8
|
+
# Instead of providing separate methods for each supported property we rely
|
|
9
|
+
# on Ruby's #method_missing to do most of the work.
|
|
10
|
+
class ReportItem
|
|
11
|
+
|
|
12
|
+
# Accepts an XML node from Nokogiri::XML.
|
|
13
|
+
def initialize(xml_node)
|
|
14
|
+
@xml = xml_node
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# List of supported tags. They can be attributes, simple descendans or
|
|
18
|
+
# collections (e.g. <bid/>, <cve/>, <xref/>)
|
|
19
|
+
def supported_tags
|
|
20
|
+
[
|
|
21
|
+
# attributes
|
|
22
|
+
:port, :svc_name, :protocol, :severity, :plugin_id, :plugin_name, :plugin_family,
|
|
23
|
+
# simple tags
|
|
24
|
+
:solution, :risk_factor, :description, :plugin_publication_date,
|
|
25
|
+
:metasploit_name, :cvss_vector, :cvss_temporal_vector, :synopsis,
|
|
26
|
+
:exploit_available, :patch_publication_date, :plugin_modification_date,
|
|
27
|
+
:cvss_temporal_score, :cvss_base_score, :plugin_output,
|
|
28
|
+
:plugin_version, :exploitability_ease, :vuln_publication_date,
|
|
29
|
+
:exploit_framework_canvas, :exploit_framework_metasploit,
|
|
30
|
+
:exploit_framework_core,
|
|
31
|
+
# multiple tags
|
|
32
|
+
:bid_entries, :cve_entries, :see_also_entries, :xref_entries,
|
|
33
|
+
# compliance tags
|
|
34
|
+
:cm_actual_value, :cm_audit_file, :cm_check_id, :cm_check_name, :cm_info,
|
|
35
|
+
:cm_output, :cm_policy_value, :cm_reference, :cm_result, :cm_see_also,
|
|
36
|
+
:cm_solution
|
|
37
|
+
]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# This allows external callers (and specs) to check for implemented
|
|
41
|
+
# properties
|
|
42
|
+
def respond_to?(method, include_private=false)
|
|
43
|
+
return true if supported_tags.include?(method.to_sym)
|
|
44
|
+
super
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# This method is invoked by Ruby when a method that is not defined in this
|
|
48
|
+
# instance is called.
|
|
49
|
+
#
|
|
50
|
+
# In our case we inspect the @method@ parameter and try to find the
|
|
51
|
+
# attribute, simple descendent or collection that it maps to in the XML
|
|
52
|
+
# tree.
|
|
53
|
+
def method_missing(method, *args)
|
|
54
|
+
|
|
55
|
+
# We could remove this check and return nil for any non-recognized tag.
|
|
56
|
+
# The problem would be that it would make tricky to debug problems with
|
|
57
|
+
# typos. For instance: <>.potr would return nil instead of raising an
|
|
58
|
+
# exception
|
|
59
|
+
unless supported_tags.include?(method)
|
|
60
|
+
super
|
|
61
|
+
return
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# first we try the attributes: port, svc_name, protocol, severity,
|
|
65
|
+
# plugin_id, plugin_name, plugin_family
|
|
66
|
+
translations_table = {
|
|
67
|
+
# @port = xml.attributes["port"]
|
|
68
|
+
# @svc_name = xml.attributes["svc_name"]
|
|
69
|
+
# @protocol = xml.attributes["protocol"]
|
|
70
|
+
# @severity = xml.attributes["severity"]
|
|
71
|
+
:plugin_id => 'pluginID',
|
|
72
|
+
:plugin_name => 'pluginName',
|
|
73
|
+
:plugin_family => 'pluginFamily'
|
|
74
|
+
}
|
|
75
|
+
method_name = translations_table.fetch(method, method.to_s)
|
|
76
|
+
return @xml.attributes[method_name].value if @xml.attributes.key?(method_name)
|
|
77
|
+
|
|
78
|
+
# then we try the children tags: solution, risk_factor, description,
|
|
79
|
+
# plugin_publication_date, metasploit_name, cvss_vector,
|
|
80
|
+
# cvss_temporal_vector, synopsis, exploit_available,
|
|
81
|
+
# patch_publication_date, plugin_modification_date, cvss_temporal_score,
|
|
82
|
+
# cvss_base_score, plugin_output, plugin_version, exploitability_ease,
|
|
83
|
+
# vuln_publication_date, exploit_framework_canvas,
|
|
84
|
+
# exploit_framework_metasploit, exploit_framework_core
|
|
85
|
+
tag = @xml.xpath("./#{method_name}").first
|
|
86
|
+
if tag
|
|
87
|
+
return tag.text
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# then the custom XML tags (cm: namespace)
|
|
91
|
+
if method_name.starts_with?('cm_')
|
|
92
|
+
method_name = method_name.sub(/cm_/, 'cm:compliance-').gsub(/_/, '-')
|
|
93
|
+
cm_value = @xml.at_xpath("./#{method_name}", { 'cm' => 'http://www.nessus.org/cm' })
|
|
94
|
+
if cm_value
|
|
95
|
+
return cm_value.text
|
|
96
|
+
else
|
|
97
|
+
return nil
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# finally the enumerations: bid_entries, cve_entries, xref_entries
|
|
103
|
+
translations_table = {
|
|
104
|
+
:bid_entries => 'bid',
|
|
105
|
+
:cve_entries => 'cve',
|
|
106
|
+
:see_also_entries => 'see_also',
|
|
107
|
+
:xref_entries => 'xref'
|
|
108
|
+
}
|
|
109
|
+
method_name = translations_table.fetch(method, nil)
|
|
110
|
+
if method_name
|
|
111
|
+
@xml.xpath("./#{method_name}").collect(&:text)
|
|
112
|
+
else
|
|
113
|
+
# nothing found, the tag is valid but not present in this ReportItem
|
|
114
|
+
return nil
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|