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.
- checksums.yaml +7 -0
- data/.github/issue_template.md +16 -0
- data/.github/pull_request_template.md +36 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +8 -0
- data/CHANGELOG.template +12 -0
- data/CONTRIBUTING.md +3 -0
- data/Gemfile +23 -0
- data/LICENSE +339 -0
- data/README.md +27 -0
- data/Rakefile +1 -0
- data/dradis-coreimpact.gemspec +30 -0
- data/lib/coreimpact/module.rb +41 -0
- data/lib/coreimpact/vulnerability.rb +52 -0
- data/lib/dradis/plugins/coreimpact/engine.rb +13 -0
- data/lib/dradis/plugins/coreimpact/field_processor.rb +26 -0
- data/lib/dradis/plugins/coreimpact/gem_version.rb +19 -0
- data/lib/dradis/plugins/coreimpact/importer.rb +112 -0
- data/lib/dradis/plugins/coreimpact/version.rb +13 -0
- data/lib/dradis/plugins/coreimpact.rb +11 -0
- data/lib/dradis-coreimpact.rb +9 -0
- data/lib/tasks/thorfile.rb +22 -0
- data/spec/coreimpact/importer_spec.rb +88 -0
- data/spec/coreimpact_upload_spec.rb +5 -0
- data/spec/fixtures/files/example.xml +536 -0
- data/spec/spec_helper.rb +9 -0
- data/templates/evidence.fields +4 -0
- data/templates/evidence.sample +8 -0
- data/templates/evidence.template +11 -0
- data/templates/issue.fields +6 -0
- data/templates/issue.sample +12 -0
- data/templates/issue.template +17 -0
- metadata +150 -0
@@ -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,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,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
|