heimdall_tools 1.3.41 → 1.3.46
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +51 -2
- data/lib/data/aws-config-mapping.csv +107 -107
- data/lib/data/scoutsuite-nist-mapping.csv +140 -0
- data/lib/heimdall_tools.rb +2 -0
- data/lib/heimdall_tools/aws_config_mapper.rb +35 -17
- data/lib/heimdall_tools/burpsuite_mapper.rb +1 -2
- data/lib/heimdall_tools/cli.rb +23 -11
- data/lib/heimdall_tools/dbprotect_mapper.rb +5 -9
- data/lib/heimdall_tools/fortify_mapper.rb +1 -2
- data/lib/heimdall_tools/help/sarif_mapper.md +12 -0
- data/lib/heimdall_tools/help/scoutsuite_mapper.md +7 -0
- data/lib/heimdall_tools/jfrog_xray_mapper.rb +1 -2
- data/lib/heimdall_tools/nessus_mapper.rb +3 -3
- data/lib/heimdall_tools/netsparker_mapper.rb +9 -13
- data/lib/heimdall_tools/nikto_mapper.rb +1 -2
- data/lib/heimdall_tools/sarif_mapper.rb +198 -0
- data/lib/heimdall_tools/scoutsuite_mapper.rb +180 -0
- data/lib/heimdall_tools/snyk_mapper.rb +1 -2
- data/lib/heimdall_tools/zap_mapper.rb +1 -4
- metadata +10 -5
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'csv'
|
3
|
+
require 'heimdall_tools/hdf'
|
4
|
+
|
5
|
+
RESOURCE_DIR = Pathname.new(__FILE__).join('../../data')
|
6
|
+
|
7
|
+
SCOUTSUITE_NIST_MAPPING_FILE = File.join(RESOURCE_DIR, 'scoutsuite-nist-mapping.csv')
|
8
|
+
|
9
|
+
IMPACT_MAPPING = {
|
10
|
+
danger: 0.7,
|
11
|
+
warning: 0.5
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
DEFAULT_NIST_TAG = %w{SA-11 RA-5}.freeze
|
15
|
+
|
16
|
+
INSPEC_INPUTS_MAPPING = {
|
17
|
+
string: 'String',
|
18
|
+
numeric: 'Numeric',
|
19
|
+
regexp: 'Regexp',
|
20
|
+
array: 'Array',
|
21
|
+
hash: 'Hash',
|
22
|
+
boolean: 'Boolean',
|
23
|
+
any: 'Any'
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
# Loading spinner sign
|
27
|
+
$spinner = Enumerator.new do |e|
|
28
|
+
loop do
|
29
|
+
e.yield '|'
|
30
|
+
e.yield '/'
|
31
|
+
e.yield '-'
|
32
|
+
e.yield '\\'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module HeimdallTools
|
37
|
+
# currently only tested against an AWS based result, but ScoutSuite supports many other cloud providers such as Azure
|
38
|
+
class ScoutSuiteMapper
|
39
|
+
def initialize(scoutsuite_js)
|
40
|
+
begin
|
41
|
+
@scoutsuite_nist_mapping = parse_mapper
|
42
|
+
rescue StandardError => e
|
43
|
+
raise "Invalid Scout Suite to NIST mapping file:\nException: #{e}"
|
44
|
+
end
|
45
|
+
|
46
|
+
begin
|
47
|
+
@scoutsuite_json = scoutsuite_js.lines[1] # first line is `scoutsuite_results =\n` and second line is json
|
48
|
+
@report = JSON.parse(@scoutsuite_json)
|
49
|
+
rescue StandardError => e
|
50
|
+
raise "Invalid Scout Suite JavaScript file provided:\nException: #{e}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def parse_mapper
|
55
|
+
csv_data = CSV.read(SCOUTSUITE_NIST_MAPPING_FILE, { encoding: 'UTF-8', headers: true, header_converters: :symbol })
|
56
|
+
csv_data.map(&:to_hash)
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_attribute(name, value, required = nil, sensitive = nil, type = nil)
|
60
|
+
{ name: name, options: { value: value, required: required, sensitive: sensitive, type: type }.compact }
|
61
|
+
end
|
62
|
+
|
63
|
+
def extract_scaninfo(report)
|
64
|
+
info = {}
|
65
|
+
begin
|
66
|
+
info['name'] = 'Scout Suite Multi-Cloud Security Auditing Tool'
|
67
|
+
info['version'] = report['last_run']['version']
|
68
|
+
info['title'] = "Scout Suite Report using #{report['last_run']['ruleset_name']} ruleset on #{report['provider_name']} with account #{report['account_id']}"
|
69
|
+
info['target_id'] = "#{report['last_run']['ruleset_name']} ruleset:#{report['provider_name']}:#{report['account_id']}"
|
70
|
+
info['summary'] = report['last_run']['ruleset_about']
|
71
|
+
info['attributes'] = [
|
72
|
+
create_attribute('account_id', report['account_id'], true, false, INSPEC_INPUTS_MAPPING[:string]),
|
73
|
+
create_attribute('environment', report['environment']),
|
74
|
+
create_attribute('ruleset', report['ruleset_name']),
|
75
|
+
# think at least these run_parameters are aws only
|
76
|
+
create_attribute('run_parameters_excluded_regions', report['last_run']['run_parameters']['excluded_regions'].join(', ')),
|
77
|
+
create_attribute('run_parameters_regions', report['last_run']['run_parameters']['regions'].join(', ')),
|
78
|
+
create_attribute('run_parameters_services', report['last_run']['run_parameters']['services'].join(', ')),
|
79
|
+
create_attribute('run_parameters_skipped_services', report['last_run']['run_parameters']['skipped_services'].join(', ')),
|
80
|
+
create_attribute('time', report['last_run']['time']),
|
81
|
+
create_attribute('partition', report['partition']), # think this is aws only
|
82
|
+
create_attribute('provider_code', report['provider_code']),
|
83
|
+
create_attribute('provider_name', report['provider_name']),
|
84
|
+
]
|
85
|
+
|
86
|
+
info
|
87
|
+
rescue StandardError => e
|
88
|
+
raise "Error extracting report info from Scout Suite JS->JSON file:\nException: #{e}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def nist_tag(rule)
|
93
|
+
entries = @scoutsuite_nist_mapping.select { |x| rule.eql?(x[:rule].to_s) && !x[:nistid].nil? }
|
94
|
+
tags = entries.map { |x| x[:nistid].split('|') }
|
95
|
+
tags.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq
|
96
|
+
end
|
97
|
+
|
98
|
+
def impact(severity)
|
99
|
+
IMPACT_MAPPING[severity.to_sym]
|
100
|
+
end
|
101
|
+
|
102
|
+
def desc_tags(data, label)
|
103
|
+
{ data: data || NA_STRING, label: label || NA_STRING }
|
104
|
+
end
|
105
|
+
|
106
|
+
def findings(details)
|
107
|
+
finding = {}
|
108
|
+
if (details['checked_items']).zero?
|
109
|
+
finding['status'] = 'skipped'
|
110
|
+
finding['skip_message'] = 'Skipped because no items were checked'
|
111
|
+
elsif (details['flagged_items']).zero?
|
112
|
+
finding['status'] = 'passed'
|
113
|
+
finding['message'] = "0 flagged items out of #{details['checked_items']} checked items"
|
114
|
+
else # there are checked items and things were flagged
|
115
|
+
finding['status'] = 'failed'
|
116
|
+
finding['message'] = "#{details['flagged_items']} flagged items out of #{details['checked_items']} checked items:\n#{details['items'].join("\n")}"
|
117
|
+
end
|
118
|
+
finding['code_desc'] = details['description']
|
119
|
+
finding['start_time'] = @report['last_run']['time']
|
120
|
+
[finding]
|
121
|
+
end
|
122
|
+
|
123
|
+
def compliance(arr)
|
124
|
+
str = 'Compliant with '
|
125
|
+
arr.map do |val|
|
126
|
+
info = "#{val['name']}, reference #{val['reference']}, version #{val['version']}"
|
127
|
+
str + info
|
128
|
+
end.join("\n")
|
129
|
+
end
|
130
|
+
|
131
|
+
def to_hdf
|
132
|
+
controls = []
|
133
|
+
@report['services'].each_key do |service|
|
134
|
+
@report['services'][service]['findings'].each_key do |finding|
|
135
|
+
printf("\rProcessing: %s", $spinner.next)
|
136
|
+
|
137
|
+
finding_id = finding
|
138
|
+
finding_details = @report['services'][service]['findings'][finding]
|
139
|
+
|
140
|
+
item = {}
|
141
|
+
item['id'] = finding_id
|
142
|
+
item['title'] = finding_details['description']
|
143
|
+
|
144
|
+
item['tags'] = { nist: nist_tag(finding_id) }
|
145
|
+
|
146
|
+
item['impact'] = impact(finding_details['level'])
|
147
|
+
|
148
|
+
item['desc'] = finding_details['rationale']
|
149
|
+
|
150
|
+
item['descriptions'] = []
|
151
|
+
item['descriptions'] << desc_tags(finding_details['remediation'], 'fix') unless finding_details['remediation'].nil?
|
152
|
+
item['descriptions'] << desc_tags(finding_details['service'], 'service')
|
153
|
+
item['descriptions'] << desc_tags(finding_details['path'], 'path')
|
154
|
+
item['descriptions'] << desc_tags(finding_details['id_suffix'], 'id_suffix')
|
155
|
+
|
156
|
+
item['refs'] = []
|
157
|
+
item['refs'] += finding_details['references'].map { |link| { url: link } } unless finding_details['references'].nil? || finding_details['references'].empty?
|
158
|
+
item['refs'] << { ref: compliance(finding_details['compliance']) } unless finding_details['compliance'].nil?
|
159
|
+
|
160
|
+
item['source_location'] = NA_HASH
|
161
|
+
item['code'] = NA_STRING
|
162
|
+
|
163
|
+
item['results'] = findings(finding_details)
|
164
|
+
|
165
|
+
controls << item
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
scaninfo = extract_scaninfo(@report)
|
170
|
+
results = HeimdallDataFormat.new(profile_name: scaninfo['name'],
|
171
|
+
version: scaninfo['version'],
|
172
|
+
title: scaninfo['title'],
|
173
|
+
summary: scaninfo['summary'],
|
174
|
+
controls: controls,
|
175
|
+
target_id: scaninfo['target_id'],
|
176
|
+
attributes: scaninfo['attributes'])
|
177
|
+
results.to_hdf
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -8,13 +8,10 @@ RESOURCE_DIR = Pathname.new(__FILE__).join('../../data')
|
|
8
8
|
CWE_NIST_MAPPING_FILE = File.join(RESOURCE_DIR, 'cwe-nist-mapping.csv')
|
9
9
|
DEFAULT_NIST_TAG = %w{SA-11 RA-5}.freeze
|
10
10
|
|
11
|
-
# rubocop:disable Metrics/AbcSize
|
12
|
-
|
13
11
|
module HeimdallTools
|
14
12
|
class ZapMapper
|
15
|
-
def initialize(zap_json, name
|
13
|
+
def initialize(zap_json, name)
|
16
14
|
@zap_json = zap_json
|
17
|
-
@verbose = verbose
|
18
15
|
|
19
16
|
begin
|
20
17
|
data = JSON.parse(zap_json, symbolize_names: true)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: heimdall_tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.46
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Thew
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2021-
|
13
|
+
date: 2021-05-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: aws-sdk-configservice
|
@@ -88,14 +88,14 @@ dependencies:
|
|
88
88
|
requirements:
|
89
89
|
- - "~>"
|
90
90
|
- !ruby/object:Gem::Version
|
91
|
-
version: 1.
|
91
|
+
version: '1.11'
|
92
92
|
type: :runtime
|
93
93
|
prerelease: false
|
94
94
|
version_requirements: !ruby/object:Gem::Requirement
|
95
95
|
requirements:
|
96
96
|
- - "~>"
|
97
97
|
- !ruby/object:Gem::Version
|
98
|
-
version: 1.
|
98
|
+
version: '1.11'
|
99
99
|
- !ruby/object:Gem::Dependency
|
100
100
|
name: openssl
|
101
101
|
requirement: !ruby/object:Gem::Requirement
|
@@ -214,6 +214,7 @@ files:
|
|
214
214
|
- lib/data/nessus-plugins-nist-mapping.csv
|
215
215
|
- lib/data/nikto-nist-mapping.csv
|
216
216
|
- lib/data/owasp-nist-mapping.csv
|
217
|
+
- lib/data/scoutsuite-nist-mapping.csv
|
217
218
|
- lib/heimdall_tools.rb
|
218
219
|
- lib/heimdall_tools/aws_config_mapper.rb
|
219
220
|
- lib/heimdall_tools/burpsuite_mapper.rb
|
@@ -231,6 +232,8 @@ files:
|
|
231
232
|
- lib/heimdall_tools/help/nessus_mapper.md
|
232
233
|
- lib/heimdall_tools/help/netsparker_mapper.md
|
233
234
|
- lib/heimdall_tools/help/nikto_mapper.md
|
235
|
+
- lib/heimdall_tools/help/sarif_mapper.md
|
236
|
+
- lib/heimdall_tools/help/scoutsuite_mapper.md
|
234
237
|
- lib/heimdall_tools/help/snyk_mapper.md
|
235
238
|
- lib/heimdall_tools/help/sonarqube_mapper.md
|
236
239
|
- lib/heimdall_tools/help/zap_mapper.md
|
@@ -238,6 +241,8 @@ files:
|
|
238
241
|
- lib/heimdall_tools/nessus_mapper.rb
|
239
242
|
- lib/heimdall_tools/netsparker_mapper.rb
|
240
243
|
- lib/heimdall_tools/nikto_mapper.rb
|
244
|
+
- lib/heimdall_tools/sarif_mapper.rb
|
245
|
+
- lib/heimdall_tools/scoutsuite_mapper.rb
|
241
246
|
- lib/heimdall_tools/snyk_mapper.rb
|
242
247
|
- lib/heimdall_tools/sonarqube_mapper.rb
|
243
248
|
- lib/heimdall_tools/version.rb
|
@@ -262,7 +267,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
262
267
|
- !ruby/object:Gem::Version
|
263
268
|
version: '0'
|
264
269
|
requirements: []
|
265
|
-
rubygems_version: 3.2.
|
270
|
+
rubygems_version: 3.2.15
|
266
271
|
signing_key:
|
267
272
|
specification_version: 4
|
268
273
|
summary: Convert Forify, Openzap and Sonarqube results to HDF
|