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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0cdf3e6d6508a016228cb316d7ba3c19b4e7d3f8
4
- data.tar.gz: c4df403c70467bb4ef0b781250ae4c1e22f49bd6
3
+ metadata.gz: 5906571b0939ca05af44ed77f903eca17d542fe8
4
+ data.tar.gz: 4172453a4ed16226603a3d50805f8bfe96b6974d
5
5
  SHA512:
6
- metadata.gz: 5cd20b1775001e1590f1c1917d99df5149ca8fc06c5ba5e6a5f455a4c3d2d7376bcbb502b72c790b307d49d59a2e99296d805e55bd8c967036e1a9aa8837fc0b
7
- data.tar.gz: 67a3b673a71da3de579fcee576d6bbf4fbf6cf5c47ee00d67f22e59ab8c00f2d2574a9b641685e8e1eb6b40cb2abde57b7ef0039d758dcad6eab5f2525da932d
6
+ metadata.gz: 99d93a7c9ea22931e5860e0595b5cc04226212ff283e1ff710ab8a524b00ffde7cacc103934bc896a09637ce7ba28bb3de019fc33c716b17abc621f12e46e898
7
+ data.tar.gz: 82bd8f4ae1a88e9b2cddfc0a046733b9e1d2f632d09dad925fef45d2f07d0bcdd98fb764a16e446128cf08407981b4a8b06984cd41fc0c1577bc390c1ea97f24
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
- ## Dradis Framework 3.6 (March XX, 2017) ##
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 == 'scan')
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( "<host>#{nexpose_node.address}</host>")
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( "<host>#{nexpose_node.address}</host>")
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[:content]
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(template: 'full_vulnerability', data: xml_vulnerability)
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 = evidence[id][host_name]
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
 
@@ -8,7 +8,7 @@ module Dradis
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 3
11
- MINOR = 6
11
+ MINOR = 7
12
12
  TINY = 0
13
13
  PRE = nil
14
14
 
@@ -7,6 +7,7 @@ require 'dradis/plugins/nexpose'
7
7
  # Non-dradis related files
8
8
  require 'nexpose/endpoint'
9
9
  require 'nexpose/node'
10
- require 'nexpose/scan'
11
10
  require 'nexpose/service'
11
+ require 'nexpose/scan'
12
+ require 'nexpose/test'
12
13
  require 'nexpose/vulnerability'
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
 
@@ -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').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
- }
32
+ @xml.xpath('./tests/test').map do |xml_test|
33
+ Nexpose::Test.new(xml_test)
43
34
  end
44
35
  end
45
36
 
@@ -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
- @xml.xpath("./references/reference").collect{|entry| {:source => entry['source'], :text => entry.text} }
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
- else
90
- # nothing found, the tag is valid but not present in this ReportItem
91
- return nil
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
@@ -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(logger: logger)
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
@@ -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(plugin: plugin)
15
- template_service = Dradis::Plugins::TemplateService.new(plugin: plugin)
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("123/udp (open)")
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("123/udp (open)")
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("161/udp (open)")
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("161/udp (open)")
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/a")
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,3 @@
1
+ evidence.id
2
+ evidence.status
3
+ evidence.content
@@ -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: &lt;?xml version="1.0" encoding="UTF-8"?&gt;
13
+ 2: &lt;wsdl:definitions name="xfdregistry"</Paragraph></ContainerBlockElement>
14
+ </ContainerBlockElement>
15
+ </Paragraph>
16
+ </Paragraph>
17
+ </test>
@@ -0,0 +1,8 @@
1
+ #[ID]#
2
+ %evidence.id%
3
+
4
+ #[Status]#
5
+ %evidence.status%
6
+
7
+ #[Content]#
8
+ %evidence.content%
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.6.0
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-04-06 00:00:00.000000000 Z
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.4.5
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.