dradis-coreimpact 4.5.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.
@@ -0,0 +1,19 @@
1
+ module Dradis
2
+ module Plugins
3
+ module Coreimpact
4
+ # Returns the version of the currently loaded Dradis 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 = 4
11
+ MINOR = 5
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,112 @@
1
+ module Dradis::Plugins::Coreimpact
2
+ class Importer < Dradis::Plugins::Upload::Importer
3
+ # The framework will call this function if the user selects this plugin from
4
+ # the dropdown list and uploads a file.
5
+ # @returns true if the operation was successful, false otherwise
6
+ def import(params={})
7
+
8
+ file_content = File.read( params[:file] )
9
+
10
+ # Parse the uploaded file XML
11
+ logger.info { "Parsing CORE Impact output file... #{params[:file]}" }
12
+ @doc = Nokogiri::XML( file_content )
13
+ logger.info { 'Done.' }
14
+
15
+ if @doc.xpath('/entities').empty?
16
+ logger.error "ERROR: no '<entities>' root element present in the provided "\
17
+ "data. Are you sure you uploaded a CORE Impact file?"
18
+ return false
19
+ end
20
+
21
+ @doc.xpath('/entities/entity[@class="host"]').each do |xml_entity|
22
+ add_host(xml_entity)
23
+ end
24
+ end
25
+
26
+ private
27
+ def add_host(xml_entity)
28
+ label = xml_entity.at_xpath('./property[@key="display_name"]').text
29
+ node = content_service.create_node(label: label, type: :host)
30
+
31
+ logger.info{ "\tNew Host: #{label}" }
32
+
33
+ node.set_property(:ip, xml_entity.at_xpath('./property[@key="ip"]').text)
34
+ node.set_property(:os, xml_entity.at_xpath('./property[@type="os"]/property[@key="entity name"]').text)
35
+
36
+ # port and service info
37
+ add_ports(xml_entity, node)
38
+ add_services(xml_entity, node)
39
+
40
+ # vulns and exposures
41
+ xml_entity.xpath('.//property[@key="Vulnerabilities"]').each do |xml_container|
42
+ add_vulnerability(xml_container, node)
43
+ end
44
+ end
45
+
46
+ def add_ports(xml_entity, node)
47
+ xml_entity.xpath('./property[@type="ports"]').each do |xml_ports|
48
+ protocol = xml_ports['key'].split('_').first
49
+
50
+ xml_ports.xpath('./property[@type="port"]').each do |xml_port|
51
+
52
+ logger.info{ "\t\tNew Port: #{protocol}/#{xml_port['key']}"}
53
+
54
+ node.set_service(
55
+ port: xml_port['key'],
56
+ protocol: protocol,
57
+ source: :coreimpact,
58
+ state: (xml_port.text == 'listen') ? :open : xml_port.text
59
+ )
60
+ end
61
+ end
62
+
63
+ # Save node properties
64
+ node.save
65
+ end
66
+
67
+ def add_services(xml_entity, node)
68
+ xml_entity.xpath('./property[@key="services"]').each do |xml_services|
69
+
70
+ xml_services.xpath('./property').each do |xml_container|
71
+
72
+ name = xml_container['key']
73
+
74
+ # Each service container can have multiple ports/protocols.
75
+ xml_container.xpath('./property').each do |xml_service|
76
+
77
+ port, protocol = xml_service['key'].split('-')
78
+
79
+ logger.info{ "\t\tNew Service: #{protocol}/#{port} - #{name}"}
80
+
81
+ node.set_service(
82
+ name: name,
83
+ port: port,
84
+ protocol: protocol,
85
+ source: :coreimpact
86
+ )
87
+ end
88
+ end
89
+ end
90
+ # Save node properties
91
+ node.save
92
+ end
93
+
94
+ def add_vulnerability(xml_container, node)
95
+ plugin_id = xml_container.at_xpath('./property[@type="container"]')['key']
96
+
97
+ issue_text = template_service.process_template(data: xml_container, template: 'issue')
98
+ issue = content_service.create_issue(id: plugin_id, text: issue_text)
99
+ logger.info{ "\tCreating new issue (plugin_id: #{plugin_id})"}
100
+
101
+ evidence_content = template_service.process_template(
102
+ data: xml_container.at_xpath('./property[@type="container"]/property[@key="Modules"]'),
103
+ template: 'evidence'
104
+ )
105
+ content_service.create_evidence(content: evidence_content, issue: issue, node: node)
106
+ logger.info{ "\t\tAdding reference to this host"}
107
+
108
+
109
+
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'gem_version'
2
+
3
+ module Dradis
4
+ module Plugins
5
+ module Coreimpact
6
+ # Returns the version of the currently loaded CORE Impact as a
7
+ # <tt>Gem::Version</tt>.
8
+ def self.version
9
+ gem_version
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Dradis
2
+ module Plugins
3
+ module Coreimpact
4
+ end
5
+ end
6
+ end
7
+
8
+ require 'dradis/plugins/coreimpact/engine'
9
+ require 'dradis/plugins/coreimpact/field_processor'
10
+ require 'dradis/plugins/coreimpact/importer'
11
+ require 'dradis/plugins/coreimpact/version'
@@ -0,0 +1,9 @@
1
+ # Hook to the framework base clases
2
+ require 'dradis-plugins'
3
+
4
+ # Load this add-on's engine
5
+ require 'dradis/plugins/coreimpact'
6
+
7
+ # Require supporting CORE Impact library
8
+ require 'coreimpact/module'
9
+ require 'coreimpact/vulnerability'
@@ -0,0 +1,22 @@
1
+ class CoreimpactTasks < Thor
2
+ include Rails.application.config.dradis.thor_helper_module
3
+
4
+ namespace "dradis:plugins:coreimpact"
5
+
6
+ desc "upload FILE", "upload CORE Impact results in XML format"
7
+ long_desc "This plugin expect a XML file generated by CORE Impact"
8
+ def upload(file_path)
9
+ require 'config/environment'
10
+
11
+ unless File.exists?(file_path)
12
+ $stderr.puts "** the file [#{file_path}] does not exist"
13
+ exit(-1)
14
+ end
15
+
16
+ detect_and_set_project_scope
17
+
18
+ importer = Dradis::Plugins::Coreimpact::Importer.new(task_options)
19
+ importer.import(file: file_path)
20
+ end
21
+
22
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ module Dradis::Plugins
4
+ describe 'Qualys upload plugin' do
5
+ let(:xml) { 'spec/fixtures/files/example.xml' }
6
+
7
+ before(:each) do
8
+ # Stub template service
9
+ templates_dir = File.expand_path('../../../templates', __FILE__)
10
+ expect_any_instance_of(Dradis::Plugins::TemplateService)
11
+ .to receive(:default_templates_dir).and_return(templates_dir)
12
+
13
+ plugin = Dradis::Plugins::Coreimpact
14
+
15
+ @content_service = Dradis::Plugins::ContentService::Base.new(
16
+ logger: Logger.new(STDOUT),
17
+ plugin: plugin
18
+ )
19
+
20
+ @importer = Dradis::Plugins::Coreimpact::Importer.new(
21
+ content_service: @content_service
22
+ )
23
+
24
+ # Stub dradis-plugins methods
25
+ #
26
+ # They return their argument hashes as objects mimicking
27
+ # Nodes, Issues, etc
28
+ allow(@content_service).to receive(:create_node) do |args|
29
+ obj = OpenStruct.new(args)
30
+ obj.define_singleton_method(:set_property) { |*| }
31
+ obj.define_singleton_method(:set_service) { |*| }
32
+ obj
33
+ end
34
+ allow(@content_service).to receive(:create_issue) do |args|
35
+ OpenStruct.new(args)
36
+ end
37
+ allow(@content_service).to receive(:create_evidence) do |args|
38
+ OpenStruct.new(args)
39
+ end
40
+ end
41
+
42
+ it 'creates nodes' do
43
+ expect(@content_service).to receive(:create_node).with(
44
+ hash_including(label: '10.0.10.41')
45
+ ).once
46
+
47
+ expect(@content_service).to receive(:create_node).with(
48
+ hash_including(label: '10.0.10.53')
49
+ ).once
50
+
51
+ @importer.import(file: xml)
52
+ end
53
+
54
+ it 'creates issues' do
55
+ expect(@content_service).to receive(:create_issue) do |args|
56
+ expect(args[:text]).to include 'OpenSSL ChangeCipherSpec Message Vulnerability Checker'
57
+ expect(args[:text]).to include 'CVE-2014-0224'
58
+ expect(args[:text]).to include 'OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCipherSpec messages'
59
+ OpenStruct.new(args)
60
+ end.once
61
+
62
+ expect(@content_service).to receive(:create_issue) do |args|
63
+ expect(args[:text]).to include 'SNMP Identity Verifier'
64
+ expect(args[:text]).to include 'CVE-1999-0516'
65
+ expect(args[:text]).to include 'An SNMP community name is guessable.'
66
+ OpenStruct.new(args)
67
+ end.once
68
+
69
+ @importer.import(file: xml)
70
+ end
71
+
72
+ it 'creates evidence' do
73
+ expect(@content_service).to receive(:create_evidence) do |args|
74
+ expect(args[:content]).to include "#[AgentDeployed]#\nfalse\n\n#[TriedToInstallAgent]#\nfalse\n\n#[Port]#\n443\n"
75
+ expect(args[:issue].text).to include 'OpenSSL ChangeCipherSpec Message Vulnerability Checker'
76
+ expect(args[:node].label).to eq '10.0.10.41'
77
+ end.once
78
+
79
+ expect(@content_service).to receive(:create_evidence) do |args|
80
+ expect(args[:content]).to include "#[AgentDeployed]#\nfalse\n\n#[TriedToInstallAgent]#\nfalse\n\n#[Port]#\n161\n"
81
+ expect(args[:issue].text).to include 'SNMP Identity Verifier'
82
+ expect(args[:node].label).to eq '10.0.10.53'
83
+ end.once
84
+
85
+ @importer.import(file: xml)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Coreimpact plugin' do
4
+ pending 'describe the behaviour of the Coreimpact plugin'
5
+ end