dradis-nexpose 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/CHANGELOG.md +3 -0
  5. data/CONTRIBUTING.md +3 -0
  6. data/Gemfile +19 -0
  7. data/LICENSE +339 -0
  8. data/README.md +29 -0
  9. data/Rakefile +1 -0
  10. data/dradis-nexpose.gemspec +35 -0
  11. data/lib/dradis-nexpose.rb +12 -0
  12. data/lib/dradis/plugins/nexpose.rb +11 -0
  13. data/lib/dradis/plugins/nexpose/engine.rb +9 -0
  14. data/lib/dradis/plugins/nexpose/field_processor.rb +89 -0
  15. data/lib/dradis/plugins/nexpose/formats/full.rb +152 -0
  16. data/lib/dradis/plugins/nexpose/formats/simple.rb +76 -0
  17. data/lib/dradis/plugins/nexpose/gem_version.rb +19 -0
  18. data/lib/dradis/plugins/nexpose/importer.rb +34 -0
  19. data/lib/dradis/plugins/nexpose/version.rb +13 -0
  20. data/lib/nexpose/endpoint.rb +81 -0
  21. data/lib/nexpose/node.rb +117 -0
  22. data/lib/nexpose/scan.rb +65 -0
  23. data/lib/nexpose/service.rb +101 -0
  24. data/lib/nexpose/vulnerability.rb +95 -0
  25. data/lib/tasks/thorfile.rb +26 -0
  26. data/spec/fixtures/files/full.xml +144 -0
  27. data/spec/fixtures/files/simple.xml +53 -0
  28. data/spec/nexpose_upload_spec.rb +154 -0
  29. data/spec/spec_helper.rb +13 -0
  30. data/templates/full_node.fields +8 -0
  31. data/templates/full_node.sample +65 -0
  32. data/templates/full_node.template +13 -0
  33. data/templates/full_scan.fields +5 -0
  34. data/templates/full_scan.sample +6 -0
  35. data/templates/full_scan.template +9 -0
  36. data/templates/full_service.fields +4 -0
  37. data/templates/full_service.sample +17 -0
  38. data/templates/full_service.template +11 -0
  39. data/templates/full_vulnerability.fields +13 -0
  40. data/templates/full_vulnerability.sample +59 -0
  41. data/templates/full_vulnerability.template +34 -0
  42. data/templates/simple_port.fields +2 -0
  43. data/templates/simple_port.sample +23 -0
  44. data/templates/simple_port.template +5 -0
  45. metadata +176 -0
@@ -0,0 +1,117 @@
1
+ module Nexpose
2
+ # This class represents each of the /NexposeReport[@version='1.0']/nodes/node
3
+ # elements in the Nexpose Full 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 Node
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 can be attributes, simple descendans or
17
+ # collections (e.g. <references/>, <tags/>)
18
+ def supported_tags
19
+ [
20
+ # attributes
21
+ :address, :status, :device_id, :hardware_address,
22
+
23
+ # simple tags
24
+
25
+ # multiple tags
26
+ :names, :fingerprints,
27
+
28
+ # compounded tags
29
+ :software, :tests, :endpoints
30
+ ]
31
+ end
32
+
33
+ # Convert each ./test/test entry into a simple hash
34
+ def tests(*args)
35
+ @xml.xpath('./tests/test').collect do |xml_test|
36
+ {
37
+ :id => xml_test.attributes['id'],
38
+ :status => xml_test.attributes['status'],
39
+ # in some cases Nexpose doesn't include text content (e.g. udp-ipid-zero)
40
+ :content => if (xml_para = xml_test.xpath('./Paragraph').first)
41
+ xml_para.text.split("\n").collect(&:strip).reject{|line| line.empty?}.join("\n")
42
+ else
43
+ ""
44
+ end
45
+ }
46
+ end
47
+ end
48
+
49
+ # Each of the endpoints associated with this node. Returns an array of
50
+ # Nexpose::Endpoint objects
51
+ def endpoints
52
+ @xml.xpath('./endpoints/endpoint').collect { |xml_endpoint| Endpoint.new(xml_endpoint) }
53
+ end
54
+
55
+
56
+ # This allows external callers (and specs) to check for implemented
57
+ # properties
58
+ def respond_to?(method, include_private=false)
59
+ return true if supported_tags.include?(method.to_sym)
60
+ super
61
+ end
62
+
63
+ # This method is invoked by Ruby when a method that is not defined in this
64
+ # instance is called.
65
+ #
66
+ # In our case we inspect the @method@ parameter and try to find the
67
+ # attribute, simple descendent or collection that it maps to in the XML
68
+ # tree.
69
+ def method_missing(method, *args)
70
+
71
+ # We could remove this check and return nil for any non-recognized tag.
72
+ # The problem would be that it would make tricky to debug problems with
73
+ # typos. For instance: <>.potr would return nil instead of raising an
74
+ # exception
75
+ unless supported_tags.include?(method)
76
+ super
77
+ return
78
+ end
79
+
80
+ # First we try the attributes. In Ruby we use snake_case, but in XML
81
+ # hyphenated-case is used for some attributes
82
+ translations_table = {
83
+ :device_id => 'device-id',
84
+ :hardware_address => 'hardware-address'
85
+ }
86
+
87
+ method_name = translations_table.fetch(method, method.to_s)
88
+ return @xml.attributes[method_name].value if @xml.attributes.key?(method_name)
89
+
90
+ # Then we try simple children tags: description, solution
91
+
92
+ # Finally the enumerations: names
93
+ if method_name == 'names'
94
+ @xml.xpath("./names/name").collect(&:text)
95
+
96
+ elsif ['fingerprints', 'software'].include?(method_name)
97
+
98
+ xpath_selector = {
99
+ 'fingerprints' => './fingerprints/os',
100
+ 'software' => './software/fingerprint'
101
+ }[method_name]
102
+
103
+ @xml.xpath(xpath_selector).collect do |xml_os|
104
+ Hash[
105
+ xml_os.attributes.collect do |name, xml_attribute|
106
+ next if name == 'arch'
107
+ [name.sub(/-/,'_').to_sym, xml_attribute.value]
108
+ end
109
+ ]
110
+ end
111
+ else
112
+ # nothing found, the tag is valid but not present in this ReportItem
113
+ return nil
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,65 @@
1
+ module Nexpose
2
+ # This class represents each of the /NexposeReport[@version='1.0']/scans/scan
3
+ # elements in the Nexpose Full 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 Scan
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 can be attributes, simple descendans or
17
+ # collections (e.g. <references/>, <tags/>)
18
+ def supported_tags
19
+ [
20
+ # attributes
21
+ :scan_id, :name, :start_time, :end_time, :status
22
+ ]
23
+ end
24
+
25
+
26
+ # This allows external callers (and specs) to check for implemented
27
+ # properties
28
+ def respond_to?(method, include_private=false)
29
+ return true if supported_tags.include?(method.to_sym)
30
+ super
31
+ end
32
+
33
+ # This method is invoked by Ruby when a method that is not defined in this
34
+ # instance is called.
35
+ #
36
+ # In our case we inspect the @method@ parameter and try to find the
37
+ # attribute, simple descendent or collection that it maps to in the XML
38
+ # tree.
39
+ def method_missing(method, *args)
40
+
41
+ # We could remove this check and return nil for any non-recognized tag.
42
+ # The problem would be that it would make tricky to debug problems with
43
+ # typos. For instance: <>.potr would return nil instead of raising an
44
+ # exception
45
+ unless supported_tags.include?(method)
46
+ super
47
+ return
48
+ end
49
+
50
+ # First we try the attributes. In Ruby we use snake_case, but in XML
51
+ # CamelCase is used for some attributes
52
+ translations_table = {
53
+ :scan_id => 'id',
54
+ :start_time => 'startTime',
55
+ :end_time => 'endTime'
56
+ }
57
+
58
+ method_name = translations_table.fetch(method, method.to_s)
59
+ return @xml.attributes[method_name].value if @xml.attributes.key?(method_name)
60
+
61
+ # not found
62
+ return nil
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,101 @@
1
+ module Nexpose
2
+ # This class represents each of the /NexposeReport[@version='1.0']/nodes/node/endpoints/endpoint/services/service
3
+ # elements in the Nexpose Full 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 Service
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 can be attributes, simple descendans or
17
+ # collections (e.g. <references/>, <tags/>)
18
+ def supported_tags
19
+ [
20
+ # attributes
21
+ :name,
22
+
23
+ # simple tags
24
+
25
+ # multiple tags
26
+ :fingerprints, :configurations, :tests
27
+ ]
28
+ end
29
+
30
+ # Convert each ./test/test entry into a simple hash
31
+ def tests(*args)
32
+ @xml.xpath('./tests/test').collect do |xml_test|
33
+ content = if xml_test.at_xpath('./Paragraph')
34
+ xml_test.at_xpath('./Paragraph').text.split("\n").collect(&:strip).reject{|line| line.empty?}.join("\n")
35
+ else
36
+ 'n/a'
37
+ end
38
+ {
39
+ id: xml_test.attributes['id'],
40
+ status: xml_test.attributes['status'],
41
+ content: content
42
+ }
43
+ end
44
+ end
45
+
46
+
47
+ # This allows external callers (and specs) to check for implemented
48
+ # properties
49
+ def respond_to?(method, include_private=false)
50
+ return true if supported_tags.include?(method.to_sym)
51
+ super
52
+ end
53
+
54
+ # This method is invoked by Ruby when a method that is not defined in this
55
+ # instance is called.
56
+ #
57
+ # In our case we inspect the @method@ parameter and try to find the
58
+ # attribute, simple descendent or collection that it maps to in the XML
59
+ # tree.
60
+ def method_missing(method, *args)
61
+
62
+ # We could remove this check and return nil for any non-recognized tag.
63
+ # The problem would be that it would make tricky to debug problems with
64
+ # typos. For instance: <>.potr would return nil instead of raising an
65
+ # exception
66
+ unless supported_tags.include?(method)
67
+ super
68
+ return
69
+ end
70
+
71
+ # First we try the attributes. In Ruby we use snake_case, but in XML
72
+ # CamelCase is used for some attributes
73
+ translations_table = {
74
+ }
75
+
76
+ method_name = translations_table.fetch(method, method.to_s)
77
+ return @xml.attributes[method_name].value if @xml.attributes.key?(method_name)
78
+
79
+ # Finally the enumerations: references, tags
80
+ if ['fingerprints', 'configurations'].include?(method_name)
81
+ xpath_selector = {
82
+ 'fingerprints' => './fingerprints/fingerprint',
83
+ 'configurations' => './configuration/config'
84
+ }[method_name]
85
+
86
+ @xml.xpath(xpath_selector).collect do |xml_item|
87
+ {:text => xml_item.text}.merge(
88
+ Hash[
89
+ xml_item.attributes.collect do |name, xml_attribute|
90
+ [name.sub(/-/,'_').to_sym, xml_attribute.value]
91
+ end
92
+ ]
93
+ )
94
+ end
95
+ else
96
+ # nothing found, the tag is valid but not present in this ReportItem
97
+ return nil
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,95 @@
1
+ module Nexpose
2
+ # This class represents each of the /NexposeReport[@version='1.0']/VulnerabilityDefinitions/vulnerability
3
+ # elements in the Nexpose Full 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 Vulnerability
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 can be attributes, simple descendans or
17
+ # collections (e.g. <references/>, <tags/>)
18
+ def supported_tags
19
+ [
20
+ # attributes
21
+ :nexpose_id, :title, :severity, :pci_severity, :cvss_score, :cvss_vector,
22
+ :published, :added, :modified,
23
+
24
+ # simple tags
25
+ :description, :solution,
26
+
27
+ # multiple tags
28
+ :references, :tags
29
+ ]
30
+ end
31
+
32
+
33
+ # This allows external callers (and specs) to check for implemented
34
+ # properties
35
+ def respond_to?(method, include_private=false)
36
+ return true if supported_tags.include?(method.to_sym)
37
+ super
38
+ end
39
+
40
+ # This method is invoked by Ruby when a method that is not defined in this
41
+ # instance is called.
42
+ #
43
+ # In our case we inspect the @method@ parameter and try to find the
44
+ # attribute, simple descendent or collection that it maps to in the XML
45
+ # tree.
46
+ def method_missing(method, *args)
47
+
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. In Ruby we use snake_case, but in XML
58
+ # CamelCase is used for some attributes
59
+ translations_table = {
60
+ :nexpose_id => 'id',
61
+ :pci_severity => 'pciSeverity',
62
+ :cvss_score => 'cvssScore',
63
+ :cvss_vector =>'cvssVector'
64
+ }
65
+
66
+ method_name = translations_table.fetch(method, method.to_s)
67
+ return @xml.attributes[method_name].value if @xml.attributes.key?(method_name)
68
+
69
+ # Then we try simple children tags: description, solution
70
+ tag = @xml.xpath("./#{method_name}/ContainerBlockElement").first
71
+ if tag
72
+ lines = []
73
+
74
+ # Go through Paragraphs and extract them.
75
+ # FIXME: we're using .//. to get paragraphs nested in Nexpose lists,
76
+ # ideally we'd convert this lists into Textile bullet point lists.
77
+ tag.xpath(".//Paragraph").each do |xml_paragraph|
78
+ lines << xml_paragraph.text.split("\n").collect(&:strip).join(' ').strip
79
+ end
80
+
81
+ return lines.join("\n\n")
82
+ end
83
+
84
+ # Finally the enumerations: references, tags
85
+ if method_name == 'references'
86
+ @xml.xpath("./references/reference").collect{|entry| {:source => entry['source'], :text => entry.text} }
87
+ elsif method == 'tags'
88
+ @xml.xpath("./tags/tag").collect(&:text)
89
+ else
90
+ # nothing found, the tag is valid but not present in this ReportItem
91
+ return nil
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,26 @@
1
+ class NexposeTasks < Thor
2
+ include Rails.application.config.dradis.thor_helper_module
3
+
4
+ namespace "dradis:plugins:nexpose"
5
+
6
+ desc "upload FILE", "upload NeXpose results"
7
+ def upload(file_path)
8
+ require 'config/environment'
9
+
10
+ logger = Logger.new(STDOUT)
11
+ logger.level = Logger::DEBUG
12
+
13
+ unless File.exists?(file_path)
14
+ $stderr.puts "** the file [#{file_path}] does not exist"
15
+ exit -1
16
+ end
17
+
18
+ detect_and_set_project_scope
19
+
20
+ importer = Dradis::Plugins::Nexpose::Importer.new(logger: logger)
21
+ importer.import(file: file_path)
22
+
23
+ logger.close
24
+ end
25
+
26
+ end
@@ -0,0 +1,144 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <NexposeReport version="2.0">
3
+ <scans>
4
+ <scan endTime="20141110T175832478" id="4" name="USDA_Internal" startTime="20141110T094538362" status="finished"/>
5
+ </scans>
6
+ <nodes>
7
+ <node address="1.1.1.1" device-id="75" risk-score="0.0" scan-template="Edge Standard" site-importance="Normal" site-name="USDA_Internal" status="alive">
8
+ <fingerprints>
9
+ <os certainty="0.80" family="IOS" product="IOS" vendor="Cisco"/>
10
+ </fingerprints>
11
+ <tests/>
12
+ <endpoints>
13
+ <endpoint port="123" protocol="udp" status="open">
14
+ <services>
15
+ <service name="NTP">
16
+ <fingerprints>
17
+ <fingerprint certainty="0.90" family="NTP" product="NTP" vendor="Cisco"/>
18
+ </fingerprints>
19
+ <configuration>
20
+ <config name="ntp.variables">system=&quot;cisco&quot;, leap=0, stratum=5, rootdelay=88.21,
21
+
22
+ rootdispersion=108.54, peer=24960, refid=135.89.100.96,
23
+
24
+ reftime=0xD80BB6B5.715ACDD8, poll=10, clock=0xD80BB78F.8931F3F6,
25
+
26
+ phase=8.259, freq=-141.24, error=11.32</config>
27
+ </configuration>
28
+ <tests>
29
+ <test id="ntp-clock-variables-disclosure" pci-compliance-status="pass" scan-id="4" status="vulnerable-exploited" vulnerable-since="20141110T161846666">
30
+ <Paragraph>
31
+ <Paragraph>The following NTP variables were found from a readvar request: system=&quot;cisco&quot;, leap=0, stratum=5, rootdelay=88.21,
32
+ rootdispersion=108.54, peer=24960, refid=135.89.100.96,
33
+ reftime=0xD80BB6B5.715ACDD8, poll=10, clock=0xD80BB78F.8931F3F6,
34
+ phase=8.259, freq=-141.24, error=11.32</Paragraph>
35
+ </Paragraph>
36
+ </test>
37
+ </tests>
38
+ </service>
39
+ </services>
40
+ </endpoint>
41
+ <endpoint port="161" protocol="udp" status="open">
42
+ <services>
43
+ <service name="SNMP">
44
+ <tests/>
45
+ </service>
46
+ </services>
47
+ </endpoint>
48
+ </endpoints>
49
+ </node>
50
+ </nodes>
51
+ <VulnerabilityDefinitions>
52
+ <vulnerability added="20120412T000000000" cvssScore="4.3" cvssVector="(AV:N/AC:M/Au:N/C:P/I:N/A:N)" id="ntp-clock-variables-disclosure" modified="20131205T000000000" pciSeverity="3" published="20120127T000000000" riskScore="378.27377" severity="4" title="Apache HTTPD: error responses can expose cookies (CVE-2012-0053)">
53
+ <malware/>
54
+ <exploits>
55
+ <exploit id="3479" link="http://www.exploit-db.com/exploits/18442" skillLevel="Expert" title="Apache httpOnly Cookie Disclosure" type="exploitdb"/>
56
+ </exploits>
57
+ <description>
58
+ <ContainerBlockElement>
59
+ <Paragraph>A flaw was found in the default error response for status code 400. This flaw could be used by an attacker to expose &quot;httpOnly&quot; cookies when no custom ErrorDocument is specified.</Paragraph>
60
+ </ContainerBlockElement>
61
+ </description>
62
+ <references>
63
+ <reference source="APPLE">APPLE-SA-2012-09-19-2</reference>
64
+ <reference source="BID">51706</reference>
65
+ <reference source="CVE">CVE-2012-0053</reference>
66
+ <reference source="REDHAT">RHSA-2012:0128</reference>
67
+ <reference source="SECUNIA">48551</reference>
68
+ <reference source="URL">http://httpd.apache.org/security/vulnerabilities_20.html</reference>
69
+ <reference source="URL">http://httpd.apache.org/security/vulnerabilities_22.html</reference>
70
+ </references>
71
+ <tags>
72
+ <tag>Apache</tag>
73
+ <tag>Apache HTTP Server</tag>
74
+ <tag>Web</tag>
75
+ </tags>
76
+ <solution>
77
+ <ContainerBlockElement>
78
+ <Paragraph>Apache HTTPD &gt;= 2.0 and &lt; 2.0.65</Paragraph>
79
+ <Paragraph>Download and apply the upgrade from:
80
+
81
+ <URLLink LinkTitle="http://archive.apache.org/dist/httpd/httpd-2.0.65.tar.gz" LinkURL="http://archive.apache.org/dist/httpd/httpd-2.0.65.tar.gz"/></Paragraph>
82
+ <Paragraph>Many platforms and distributions provide pre-built binary packages for Apache HTTP server. These pre-built packages are usually customized and optimized for a particular distribution, therefore we recommend that you use the packages if they are available for your operating system.</Paragraph>
83
+ </ContainerBlockElement>
84
+ </solution>
85
+ </vulnerability>
86
+ <vulnerability added="20120412T000000000" cvssScore="4.3" cvssVector="(AV:N/AC:M/Au:N/C:P/I:N/A:N)" id="ntp-clock-variables-disclosure" modified="20130828T000000000" pciSeverity="3" published="20031231T000000000" riskScore="549.07043" severity="4" title="Apache HTTPD: ETag Inode Information Leakage (CVE-2003-1418)">
87
+ <malware/>
88
+ <exploits/>
89
+ <description>
90
+ <ContainerBlockElement>
91
+ <Paragraph>Apache HTTP server in certain configurations allows remote attackers to obtain sensitive information via (1) the ETag header, which reveals the inode number, or (2) multipart MIME boundary, which reveals child proccess IDs (PID).</Paragraph>
92
+ </ContainerBlockElement>
93
+ </description>
94
+ <references>
95
+ <reference source="BID">6939</reference>
96
+ <reference source="BID">6943</reference>
97
+ <reference source="CVE">CVE-2003-1418</reference>
98
+ <reference source="XF">11438</reference>
99
+ </references>
100
+ <tags>
101
+ <tag>Apache</tag>
102
+ <tag>Apache HTTP Server</tag>
103
+ <tag>Web</tag>
104
+ </tags>
105
+ <solution>
106
+ <ContainerBlockElement>
107
+ <UnorderedList>
108
+ <ListItem>
109
+ <Paragraph>
110
+ <Paragraph>You can remove inode information from the ETag header by adding the
111
+ following directive to your Apache config:</Paragraph>
112
+ <Paragraph preformat="true">FileETag MTime Size</Paragraph>
113
+ </Paragraph>
114
+ </ListItem>
115
+ <ListItem>
116
+ <Paragraph>OpenBSD</Paragraph>
117
+ <Paragraph>Download and apply the patch from:
118
+
119
+
120
+
121
+
122
+
123
+ <URLLink LinkTitle="http://www.openbsd.org/errata32.html#httpd" LinkURL="http://www.openbsd.org/errata32.html#httpd"/></Paragraph>
124
+ <Paragraph>
125
+ <Paragraph>The OpenBSD team has released a
126
+
127
+
128
+
129
+
130
+
131
+ <URLLink LinkTitle="http://www.openbsd.org/errata32.html#httpd" LinkURL="http://www.openbsd.org/errata32.html#httpd" href="http://www.openbsd.org/errata32.html#httpd">
132
+ patch</URLLink>for the Apache inode and pid leak problem. This patch can be applied
133
+ cleanly to 3.2 stable and rebuilt. Restart httpd for the changes to
134
+ take effect. OpenBSD 3.3 will ship with the patched httpd by default.
135
+ The patch can be applied to earlier 3.x versions of OpenBSD, but it
136
+ may require editing of the source code.</Paragraph>
137
+ </Paragraph>
138
+ </ListItem>
139
+ </UnorderedList>
140
+ </ContainerBlockElement>
141
+ </solution>
142
+ </vulnerability>
143
+ </VulnerabilityDefinitions>
144
+ </NexposeReport>