dradis-nexpose 3.6.0 → 3.7.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 +4 -4
- data/CHANGELOG.md +7 -1
- data/lib/dradis/plugins/nexpose/field_processor.rb +7 -5
- data/lib/dradis/plugins/nexpose/formats/full.rb +13 -6
- data/lib/dradis/plugins/nexpose/gem_version.rb +1 -1
- data/lib/dradis-nexpose.rb +2 -1
- data/lib/nexpose/node.rb +1 -10
- data/lib/nexpose/service.rb +2 -11
- data/lib/nexpose/test.rb +23 -0
- data/lib/nexpose/vulnerability.rb +23 -6
- data/lib/tasks/thorfile.rb +1 -6
- data/spec/nexpose_upload_spec.rb +9 -14
- data/templates/full_evidence.fields +3 -0
- data/templates/full_evidence.sample +17 -0
- data/templates/full_evidence.template +8 -0
- metadata +7 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5906571b0939ca05af44ed77f903eca17d542fe8
|
|
4
|
+
data.tar.gz: 4172453a4ed16226603a3d50805f8bfe96b6974d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 99d93a7c9ea22931e5860e0595b5cc04226212ff283e1ff710ab8a524b00ffde7cacc103934bc896a09637ce7ba28bb3de019fc33c716b17abc621f12e46e898
|
|
7
|
+
data.tar.gz: 82bd8f4ae1a88e9b2cddfc0a046733b9e1d2f632d09dad925fef45d2f07d0bcdd98fb764a16e446128cf08407981b4a8b06984cd41fc0c1577bc390c1ea97f24
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
## Dradis Framework 3.
|
|
1
|
+
## Dradis Framework 3.7 (July, 2017) ##
|
|
2
|
+
|
|
3
|
+
* Add full evidence template for exporting evidences.
|
|
4
|
+
* Fix issue resulting in Evidence with null content.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## Dradis Framework 3.6 (March, 2017) ##
|
|
2
8
|
|
|
3
9
|
* No changes.
|
|
@@ -6,21 +6,23 @@ module Dradis::Plugins::Nexpose
|
|
|
6
6
|
|
|
7
7
|
def post_initialize(args={})
|
|
8
8
|
if data.kind_of?(Hash) ||
|
|
9
|
-
data.kind_of?(Nexpose::Scan) ||
|
|
10
9
|
data.kind_of?(Nexpose::Node) ||
|
|
11
10
|
data.kind_of?(Nexpose::Service) ||
|
|
11
|
+
data.kind_of?(Nexpose::Scan) ||
|
|
12
12
|
data.kind_of?(Nexpose::Vulnerability)
|
|
13
13
|
@nexpose_object = data
|
|
14
14
|
else
|
|
15
15
|
# XML from Plugin Manager
|
|
16
|
-
if (data.name == '
|
|
17
|
-
@nexpose_object = Nexpose::Scan.new(data)
|
|
18
|
-
elsif (data.name == 'node')
|
|
16
|
+
if (data.name == 'node')
|
|
19
17
|
# Full - node
|
|
20
18
|
@nexpose_object = Nexpose::Node.new(data)
|
|
21
19
|
elsif (data.name == 'service')
|
|
22
20
|
# Full - service
|
|
23
21
|
@nexpose_object = Nexpose::Service.new(data)
|
|
22
|
+
elsif (data.name == 'scan')
|
|
23
|
+
@nexpose_object = Nexpose::Scan.new(data)
|
|
24
|
+
elsif (data.name == 'test')
|
|
25
|
+
@nexpose_object = Nexpose::Test.new(data)
|
|
24
26
|
else
|
|
25
27
|
if data['added']
|
|
26
28
|
# Full - vulnerability
|
|
@@ -86,4 +88,4 @@ module Dradis::Plugins::Nexpose
|
|
|
86
88
|
rows.join("\n")
|
|
87
89
|
end
|
|
88
90
|
end
|
|
89
|
-
end
|
|
91
|
+
end
|
|
@@ -9,7 +9,6 @@ module Dradis::Plugins::Nexpose::Formats
|
|
|
9
9
|
|
|
10
10
|
@vuln_list = []
|
|
11
11
|
evidence = Hash.new { |h, k| h[k] = {} }
|
|
12
|
-
hosts = Array.new
|
|
13
12
|
|
|
14
13
|
# First, extract scans
|
|
15
14
|
scan_node = content_service.create_node(label: 'Nexpose Scan Summary')
|
|
@@ -55,8 +54,10 @@ module Dradis::Plugins::Nexpose::Formats
|
|
|
55
54
|
xml_vuln.add_child("<hosts/>") unless xml_vuln.last_element_child.name == "hosts"
|
|
56
55
|
|
|
57
56
|
if xml_vuln.xpath("./hosts/host[text()='#{nexpose_node.address}']").empty?
|
|
58
|
-
xml_vuln.last_element_child.add_child(
|
|
57
|
+
xml_vuln.last_element_child.add_child("<host>#{nexpose_node.address}</host>")
|
|
59
58
|
end
|
|
59
|
+
|
|
60
|
+
evidence[test_id][nexpose_node.address] = node_test
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
nexpose_node.endpoints.each do |endpoint|
|
|
@@ -100,10 +101,10 @@ module Dradis::Plugins::Nexpose::Formats
|
|
|
100
101
|
xml_vuln.add_child("<hosts/>") unless xml_vuln.last_element_child.name == "hosts"
|
|
101
102
|
|
|
102
103
|
if xml_vuln.xpath("./hosts/host[text()='#{nexpose_node.address}']").empty?
|
|
103
|
-
xml_vuln.last_element_child.add_child(
|
|
104
|
+
xml_vuln.last_element_child.add_child("<host>#{nexpose_node.address}</host>")
|
|
104
105
|
end
|
|
105
106
|
|
|
106
|
-
evidence[test_id][nexpose_node.address] = service_test
|
|
107
|
+
evidence[test_id][nexpose_node.address] = service_test
|
|
107
108
|
end
|
|
108
109
|
end
|
|
109
110
|
end
|
|
@@ -119,7 +120,10 @@ module Dradis::Plugins::Nexpose::Formats
|
|
|
119
120
|
doc.xpath('//VulnerabilityDefinitions/vulnerability').each do |xml_vulnerability|
|
|
120
121
|
id = xml_vulnerability['id'].downcase
|
|
121
122
|
# if @vuln_list.include?(id)
|
|
122
|
-
issue_text = template_service.process_template(
|
|
123
|
+
issue_text = template_service.process_template(
|
|
124
|
+
template: 'full_vulnerability',
|
|
125
|
+
data: xml_vulnerability
|
|
126
|
+
)
|
|
123
127
|
|
|
124
128
|
# retrieve hosts affected by this issue (injected in step 2)
|
|
125
129
|
#
|
|
@@ -141,7 +145,10 @@ module Dradis::Plugins::Nexpose::Formats
|
|
|
141
145
|
# if the node exists, this just returns it
|
|
142
146
|
host_node = content_service.create_node(label: host_name, type: :host)
|
|
143
147
|
|
|
144
|
-
evidence_content =
|
|
148
|
+
evidence_content = template_service.process_template(
|
|
149
|
+
template: 'full_evidence',
|
|
150
|
+
data: evidence[id][host_name]
|
|
151
|
+
)
|
|
145
152
|
content_service.create_evidence(content: evidence_content, issue: issue, node: host_node)
|
|
146
153
|
end
|
|
147
154
|
|
data/lib/dradis-nexpose.rb
CHANGED
data/lib/nexpose/node.rb
CHANGED
|
@@ -33,16 +33,7 @@ module Nexpose
|
|
|
33
33
|
# Convert each ./test/test entry into a simple hash
|
|
34
34
|
def tests(*args)
|
|
35
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
|
-
}
|
|
36
|
+
Nexpose::Test.new(xml_test)
|
|
46
37
|
end
|
|
47
38
|
end
|
|
48
39
|
|
data/lib/nexpose/service.rb
CHANGED
|
@@ -29,17 +29,8 @@ module Nexpose
|
|
|
29
29
|
|
|
30
30
|
# Convert each ./test/test entry into a simple hash
|
|
31
31
|
def tests(*args)
|
|
32
|
-
@xml.xpath('./tests/test').
|
|
33
|
-
|
|
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
|
-
}
|
|
32
|
+
@xml.xpath('./tests/test').map do |xml_test|
|
|
33
|
+
Nexpose::Test.new(xml_test)
|
|
43
34
|
end
|
|
44
35
|
end
|
|
45
36
|
|
data/lib/nexpose/test.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Nexpose
|
|
2
|
+
class Test
|
|
3
|
+
def self.new(xml_node)
|
|
4
|
+
content =
|
|
5
|
+
if xml_node.at_xpath('./Paragraph')
|
|
6
|
+
xml_node.
|
|
7
|
+
at_xpath('./Paragraph').
|
|
8
|
+
text.
|
|
9
|
+
split("\n").
|
|
10
|
+
collect(&:strip).
|
|
11
|
+
reject { |line| line.empty? }.join("\n")
|
|
12
|
+
else
|
|
13
|
+
'n/a'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
{
|
|
17
|
+
id: xml_node.attributes['id'],
|
|
18
|
+
status: xml_node.attributes['status'],
|
|
19
|
+
content: content
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -25,7 +25,10 @@ module Nexpose
|
|
|
25
25
|
:description, :solution,
|
|
26
26
|
|
|
27
27
|
# multiple tags
|
|
28
|
-
:references, :tags
|
|
28
|
+
:references, :tags,
|
|
29
|
+
|
|
30
|
+
# evidence tag
|
|
31
|
+
:details
|
|
29
32
|
]
|
|
30
33
|
end
|
|
31
34
|
|
|
@@ -83,13 +86,27 @@ module Nexpose
|
|
|
83
86
|
|
|
84
87
|
# Finally the enumerations: references, tags
|
|
85
88
|
if method_name == 'references'
|
|
86
|
-
|
|
89
|
+
references =
|
|
90
|
+
@xml.xpath("./references/reference").map do |entry|
|
|
91
|
+
{:source => entry['source'], :text => entry.text}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
return references
|
|
87
95
|
elsif method == 'tags'
|
|
88
|
-
@xml.xpath("./tags/tag").collect(&:text)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
96
|
+
return @xml.xpath("./tags/tag").collect(&:text)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Handle evidence creation
|
|
100
|
+
if method_name == 'details'
|
|
101
|
+
vuln_id = @xml.attributes['id'].value
|
|
102
|
+
|
|
103
|
+
return @xml.xpath("//test[@id='#{vuln_id}']/Paragraph").
|
|
104
|
+
text.split("\n").
|
|
105
|
+
collect(&:strip).
|
|
106
|
+
reject{|line| line.empty?}.join("\n")
|
|
92
107
|
end
|
|
108
|
+
|
|
109
|
+
nil
|
|
93
110
|
end
|
|
94
111
|
end
|
|
95
112
|
end
|
data/lib/tasks/thorfile.rb
CHANGED
|
@@ -7,9 +7,6 @@ class NexposeTasks < Thor
|
|
|
7
7
|
def upload(file_path)
|
|
8
8
|
require 'config/environment'
|
|
9
9
|
|
|
10
|
-
logger = Logger.new(STDOUT)
|
|
11
|
-
logger.level = Logger::DEBUG
|
|
12
|
-
|
|
13
10
|
unless File.exists?(file_path)
|
|
14
11
|
$stderr.puts "** the file [#{file_path}] does not exist"
|
|
15
12
|
exit -1
|
|
@@ -17,10 +14,8 @@ class NexposeTasks < Thor
|
|
|
17
14
|
|
|
18
15
|
detect_and_set_project_scope
|
|
19
16
|
|
|
20
|
-
importer = Dradis::Plugins::Nexpose::Importer.new(
|
|
17
|
+
importer = Dradis::Plugins::Nexpose::Importer.new(task_options)
|
|
21
18
|
importer.import(file: file_path)
|
|
22
|
-
|
|
23
|
-
logger.close
|
|
24
19
|
end
|
|
25
20
|
|
|
26
21
|
end
|
data/spec/nexpose_upload_spec.rb
CHANGED
|
@@ -11,12 +11,13 @@ describe 'Nexpose upload plugin' do
|
|
|
11
11
|
# Init services
|
|
12
12
|
plugin = Dradis::Plugins::Nexpose
|
|
13
13
|
|
|
14
|
-
@content_service = Dradis::Plugins::ContentService.new(
|
|
15
|
-
|
|
14
|
+
@content_service = Dradis::Plugins::ContentService::Base.new(
|
|
15
|
+
logger: Logger.new(STDOUT),
|
|
16
|
+
plugin: plugin
|
|
17
|
+
)
|
|
16
18
|
|
|
17
19
|
@importer = plugin::Importer.new(
|
|
18
20
|
content_service: @content_service,
|
|
19
|
-
template_service: template_service
|
|
20
21
|
)
|
|
21
22
|
|
|
22
23
|
# Stub dradis-plugins methods
|
|
@@ -92,27 +93,23 @@ describe 'Nexpose upload plugin' do
|
|
|
92
93
|
end.once
|
|
93
94
|
|
|
94
95
|
expect(@content_service).to receive(:create_node) do |args|
|
|
95
|
-
expect(args[:label]).to eq("
|
|
96
|
-
expect(args[:parent].label).to eq("1.1.1.1")
|
|
96
|
+
expect(args[:label]).to eq("Definitions")
|
|
97
97
|
OpenStruct.new(args)
|
|
98
98
|
end.once
|
|
99
99
|
expect(@content_service).to receive(:create_note) do |args|
|
|
100
100
|
expect(args[:text]).to include("#[Title]#\nService name: NTP")
|
|
101
|
-
expect(args[:node].label).to eq("
|
|
101
|
+
expect(args[:node].label).to eq("1.1.1.1")
|
|
102
102
|
end.once
|
|
103
103
|
|
|
104
104
|
expect(@content_service).to receive(:create_node) do |args|
|
|
105
|
-
expect(args[:label]).to eq("
|
|
106
|
-
expect(args[:parent].label).to eq("1.1.1.1")
|
|
105
|
+
expect(args[:label]).to eq("1.1.1.1")
|
|
107
106
|
OpenStruct.new(args)
|
|
108
107
|
end.once
|
|
109
108
|
expect(@content_service).to receive(:create_note) do |args|
|
|
110
109
|
expect(args[:text]).to include("#[Title]#\nService name: SNMP")
|
|
111
|
-
expect(args[:node].label).to eq("
|
|
110
|
+
expect(args[:node].label).to eq("1.1.1.1")
|
|
112
111
|
end.once
|
|
113
112
|
|
|
114
|
-
expect(@content_service).to receive(:create_node).with(hash_including label: "Definitions").once
|
|
115
|
-
|
|
116
113
|
expect(@content_service).to receive(:create_issue) do |args|
|
|
117
114
|
expect(args[:text]).to include("#[Title]#\nApache HTTPD: error responses can expose cookies (CVE-2012-0053)")
|
|
118
115
|
expect(args[:id]).to eq("ntp-clock-variables-disclosure")
|
|
@@ -125,10 +122,8 @@ describe 'Nexpose upload plugin' do
|
|
|
125
122
|
OpenStruct.new(args)
|
|
126
123
|
end.once
|
|
127
124
|
|
|
128
|
-
expect(@content_service).to receive(:create_node).with(hash_including label: "1.1.1.1", type: :host).once
|
|
129
|
-
|
|
130
125
|
expect(@content_service).to receive(:create_evidence) do |args|
|
|
131
|
-
expect(args[:content]).to include("n
|
|
126
|
+
expect(args[:content]).to include("#[ID]#\nntp-clock-variables-disclosure\n\n")
|
|
132
127
|
expect(args[:issue].id).to eq("ntp-clock-variables-disclosure")
|
|
133
128
|
expect(args[:node].label).to eq("1.1.1.1")
|
|
134
129
|
end.once
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<test id="http-coldfusion-cfide-unprotected" key="/CFIDE/adminapi/base.cfc?wsdl" status="vulnerable-exploited" scan-id="4" vulnerable-since="20141110T165124356" pci-compliance-status="fail">
|
|
2
|
+
<Paragraph>
|
|
3
|
+
<UnorderedList>
|
|
4
|
+
<ListItem>Running HTTP service</ListItem>
|
|
5
|
+
</UnorderedList>
|
|
6
|
+
<Paragraph>
|
|
7
|
+
<ContainerBlockElement>
|
|
8
|
+
<ContainerBlockElement>
|
|
9
|
+
<Paragraph>HTTP GET request to
|
|
10
|
+
<URLLink LinkURL="http://10.0.0.1" LinkTitle="http://10.0.0.1"/>
|
|
11
|
+
</Paragraph>HTTP response code was an expected 200
|
|
12
|
+
<Paragraph preformat="true">2: <?xml version="1.0" encoding="UTF-8"?>
|
|
13
|
+
2: <wsdl:definitions name="xfdregistry"</Paragraph></ContainerBlockElement>
|
|
14
|
+
</ContainerBlockElement>
|
|
15
|
+
</Paragraph>
|
|
16
|
+
</Paragraph>
|
|
17
|
+
</test>
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dradis-nexpose
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel Martin
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-
|
|
11
|
+
date: 2017-07-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: dradis-plugins
|
|
@@ -124,12 +124,16 @@ files:
|
|
|
124
124
|
- lib/nexpose/node.rb
|
|
125
125
|
- lib/nexpose/scan.rb
|
|
126
126
|
- lib/nexpose/service.rb
|
|
127
|
+
- lib/nexpose/test.rb
|
|
127
128
|
- lib/nexpose/vulnerability.rb
|
|
128
129
|
- lib/tasks/thorfile.rb
|
|
129
130
|
- spec/fixtures/files/full.xml
|
|
130
131
|
- spec/fixtures/files/simple.xml
|
|
131
132
|
- spec/nexpose_upload_spec.rb
|
|
132
133
|
- spec/spec_helper.rb
|
|
134
|
+
- templates/full_evidence.fields
|
|
135
|
+
- templates/full_evidence.sample
|
|
136
|
+
- templates/full_evidence.template
|
|
133
137
|
- templates/full_node.fields
|
|
134
138
|
- templates/full_node.sample
|
|
135
139
|
- templates/full_node.template
|
|
@@ -165,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
165
169
|
version: '0'
|
|
166
170
|
requirements: []
|
|
167
171
|
rubyforge_project:
|
|
168
|
-
rubygems_version: 2.
|
|
172
|
+
rubygems_version: 2.6.8
|
|
169
173
|
signing_key:
|
|
170
174
|
specification_version: 4
|
|
171
175
|
summary: Nexpose add-on for the Dradis Framework.
|