heimdall_tools 1.3.45 → 1.3.46

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87936a7488cf8da17690bb3c35d5138a2e9442d8d4c48b307307f4d44423b987
4
- data.tar.gz: 28f172cc25391e697910bb1b2b79fea29c82956cbca953f1e7978080b4e1d646
3
+ metadata.gz: 24ad070383569e79ac08bbc0cae7a049a0f48cbc971d6d897ee2b5aa0989affe
4
+ data.tar.gz: 993a995384452cf8457b3545e3aaddae4b6f6165453f139b9c33b35e3357ed82
5
5
  SHA512:
6
- metadata.gz: bf394cd989527e58e45755881a01ad5d91761201f0a054e5a92a69ae3ac9b943569ef400298d31afee4514b72f3f7b77212b8bcc189107e355c45e1c2758e41d
7
- data.tar.gz: 54c1a3447b631b28c024f0bc77559834464bccc518463a2fee0313d7b19f6252db9d624058eda3118423178f736e080ccffa5601b2cc7ec2daa98332a90d1e8f
6
+ metadata.gz: 65e3d1c2566de4d114f75a0de1659cc895b65045718300559179d86f33d2b9dd9110ee8b106944d1ef764ca89efb5a40bd67891534c095e7b1c37dd709f9c4a9
7
+ data.tar.gz: 2841a54f0abca5d37f4051800f29a90a410bf9599addbfe538d603dae9f725e0c99229c6129fadaee0401cc65a8d5abbbd54ea76d9996d317c4bf1199c4a483a
data/README.md CHANGED
@@ -9,13 +9,15 @@ HeimdallTools supplies several methods to convert output from various tools to "
9
9
  - **fortify_mapper** - commercial static code analysis tool
10
10
  - **zap_mapper** - OWASP ZAP - open-source dynamic code analysis tool
11
11
  - **burpsuite_mapper** - commercial dynamic analysis tool
12
- - **nessus_mapper** - commercial vulnerability scanner
12
+ - **nessus_mapper** - commercial security scanner (supports compliance and vulnerability scans from Tenable.sc and Tenable.io)
13
13
  - **snyk_mapper** - commercial package vulnerability scanner
14
14
  - **nikto_mapper** - open-source web server scanner
15
15
  - **jfrog_xray_mapper** - package vulnerability scanner
16
16
  - **dbprotect_mapper** - database vulnerability scanner
17
17
  - **aws_config_mapper** - assess, audit, and evaluate AWS resources
18
18
  - **netsparker_mapper** - web application security scanner
19
+ - **sarif_mapper** - static analysis results interchange format
20
+ - **scoutsuite_mapper** - multi-cloud security auditing tool
19
21
 
20
22
  ## Want to recommend a mapper for another tool? Please use these steps:
21
23
  1. Create an [issue](https://github.com/mitre/heimdall_tools/issues/new), and email saf@groups.mitre.org citing the issue link so we can help
@@ -151,7 +153,8 @@ example: heimdall_tools burpsuite_mapper -x burpsuite_results.xml -o scan_result
151
153
 
152
154
  ## nessus_mapper
153
155
 
154
- nessus_mapper translates a Nessus-exported XML results file into HDF format json to be viewable in Heimdall
156
+ nessus_mapper translates a Nessus-exported XML results file into HDF format json to be viewable in Heimdall.
157
+ Supports compliance and vulnerability scans from Tenable.sc and Tenable.io.
155
158
 
156
159
  Note: A separate HDF JSON file is generated for each host reported in the Nessus Report.
157
160
 
@@ -200,6 +203,22 @@ FLAGS:
200
203
  example: heimdall_tools nikto_mapper -j nikto_results.json -o nikto_results.json
201
204
  ```
202
205
 
206
+ ## scoutsuite_mapper
207
+
208
+ scoutsuite_mapper translates Scout Suite results from Javascript to HDF-formatted JSON so as to be viewable on Heimdall
209
+
210
+ Note: Currently this mapper only supports AWS.
211
+
212
+ ```
213
+ USAGE: heimdall_tools scoutsuite_mapper -i <scoutsuite-results-js> -o <hdf-scan-results-json>
214
+
215
+ FLAGS:
216
+ -i --input -j --javascript <scoutsuite-results-js> : path to Scout Suite results Javascript file.
217
+ -o --output <hdf-scan-results-json> : path to output scan-results json.
218
+
219
+ example: heimdall_tools scoutsuite_mapper -i scoutsuite_results.js -o scoutsuite_hdf.json
220
+ ```
221
+
203
222
  ## jfrog_xray_mapper
204
223
 
205
224
  jfrog_xray_mapper translates an JFrog Xray results JSON file into HDF format JSON to be viewable in Heimdall
@@ -267,6 +286,21 @@ FLAGS:
267
286
  example: heimdall_tools netsparker_mapper -x netsparker_results.xml -o netsparker_hdf.json
268
287
  ```
269
288
 
289
+ ## sarif_mapper
290
+
291
+ sarif_mapper translates a SARIF JSON file into HDF format JSON to be viewable in Heimdall
292
+
293
+ ```
294
+ USAGE: heimdall_tools sarif_mapper [OPTIONS] -j <sarif-results-json> -o <hdf-scan-results.json>
295
+
296
+ FLAGS:
297
+ -j <sarif_results_json> : path to SARIF results JSON file.
298
+ -o --output_prefix <prefix> : path to output scan-results json.
299
+ -V --verbose : verbose run [optional].
300
+
301
+ example: heimdall_tools sarif_mapper -j sarif_results.json -o sarif_results_hdf.json
302
+ ```
303
+
270
304
  ## version
271
305
 
272
306
  Prints out the gem version
@@ -0,0 +1,140 @@
1
+ rule,nistid
2
+ acm-certificate-with-close-expiration-date,SC-12
3
+ acm-certificate-with-transparency-logging-disabled,SC-12
4
+ cloudformation-stack-with-role,AC-6
5
+ cloudtrail-duplicated-global-services-logging,AU-6
6
+ cloudtrail-no-cloudwatch-integration,AU-12|SI-4(2)
7
+ cloudtrail-no-data-logging,AU-12
8
+ cloudtrail-no-encryption-with-kms,AU-6
9
+ cloudtrail-no-global-services-logging,AU-12
10
+ cloudtrail-no-log-file-validation,AU-6
11
+ cloudtrail-no-logging,AU-12
12
+ cloudtrail-not-configured,AU-12
13
+ cloudwatch-alarm-without-actions,AU-12
14
+ config-recorder-not-configured,CM-8|CM-8(2)|CM-8(6)
15
+ ec2-ami-public,AC-3
16
+ ec2-default-security-group-in-use,AC-3(3)
17
+ ec2-default-security-group-with-rules,AC-3(3)
18
+ ec2-ebs-snapshot-not-encrypted,SC-28
19
+ ec2-ebs-snapshot-public,AC-3
20
+ ec2-ebs-volume-not-encrypted,SC-28
21
+ ec2-instance-in-security-group,CM-7(1)
22
+ ec2-instance-type,CM-2
23
+ ec2-instance-types,CM-2
24
+ ec2-instance-with-public-ip,AC-3
25
+ ec2-instance-with-user-data-secrets,AC-3
26
+ ec2-security-group-opens-all-ports,CM-7(1)
27
+ ec2-security-group-opens-all-ports-to-all,CM-7(1)
28
+ ec2-security-group-opens-all-ports-to-self,CM-7(1)
29
+ ec2-security-group-opens-icmp-to-all,CM-7(1)
30
+ ec2-security-group-opens-known-port-to-all,CM-7(1)
31
+ ec2-security-group-opens-plaintext-port,CM-7(1)
32
+ ec2-security-group-opens-port-range,CM-7(1)
33
+ ec2-security-group-opens-port-to-all,CM-7(1)
34
+ ec2-security-group-whitelists-aws,CM-7(1)
35
+ ec2-security-group-whitelists-aws-ip-from-banned-region,CM-7(1)
36
+ ec2-security-group-whitelists-non-elastic-ips,CM-7(1)
37
+ ec2-security-group-whitelists-unknown-aws,CM-7(1)
38
+ ec2-security-group-whitelists-unknown-cidrs,CM-7(1)
39
+ ec2-unused-security-group,CM-7(1)
40
+ elb-listener-allowing-cleartext,SC-8
41
+ elb-no-access-logs,AU-12
42
+ elb-older-ssl-policy,SC-8
43
+ elbv2-http-request-smuggling,SC-8
44
+ elbv2-listener-allowing-cleartext,SC-8
45
+ elbv2-no-access-logs,AU-12
46
+ elbv2-no-deletion-protection,SI-7
47
+ elbv2-older-ssl-policy,SC-8
48
+ iam-assume-role-lacks-external-id-and-mfa,AC-17
49
+ iam-assume-role-no-mfa,AC-6
50
+ iam-assume-role-policy-allows-all,AC-6
51
+ iam-ec2-role-without-instances,AC-6
52
+ iam-group-with-inline-policies,AC-6
53
+ iam-group-with-no-users,AC-6
54
+ iam-human-user-with-policies,AC-6
55
+ iam-inline-policy-allows-non-sts-action,AC-6
56
+ iam-inline-policy-allows-NotActions,AC-6
57
+ iam-inline-policy-for-role,AC-6
58
+ iam-managed-policy-allows-full-privileges,AC-6
59
+ iam-managed-policy-allows-non-sts-action,AC-6
60
+ iam-managed-policy-allows-NotActions,AC-6
61
+ iam-managed-policy-for-role,AC-6
62
+ iam-managed-policy-no-attachments,AC-6
63
+ iam-no-support-role,IR-7
64
+ iam-password-policy-expiration-threshold,AC-2
65
+ iam-password-policy-minimum-length,AC-2
66
+ iam-password-policy-no-expiration,AC-2
67
+ iam-password-policy-no-lowercase-required,AC-2
68
+ iam-password-policy-no-number-required,AC-2
69
+ iam-password-policy-no-symbol-required,AC-2
70
+ iam-password-policy-no-uppercase-required,AC-2
71
+ iam-password-policy-reuse-enabled,IA-5(1)
72
+ iam-role-with-inline-policies,AC-6
73
+ iam-root-account-no-hardware-mfa,IA-2(1)
74
+ iam-root-account-no-mfa,IA-2(1)
75
+ iam-root-account-used-recently,AC-6(9)
76
+ iam-root-account-with-active-certs,AC-6(9)
77
+ iam-root-account-with-active-keys,AC-6(9)
78
+ iam-service-user-with-password,AC-2
79
+ iam-unused-credentials-not-disabled,AC-2
80
+ iam-user-no-key-rotation,AC-2
81
+ iam-user-not-in-category-group,AC-2
82
+ iam-user-not-in-common-group,AC-2
83
+ iam-user-unused-access-key-initial-setup,AC-2
84
+ iam-user-with-multiple-access-keys,IA-2
85
+ iam-user-without-mfa,IA-2(1)
86
+ iam-user-with-password-and-key,IA-2
87
+ iam-user-with-policies,AC-2
88
+ kms-cmk-rotation-disabled,SC-12
89
+ logs-no-alarm-aws-configuration-changes,CM-8|CM-8(2)|CM-8(6)
90
+ logs-no-alarm-cloudtrail-configuration-changes,AU-6
91
+ logs-no-alarm-cmk-deletion,AC-2
92
+ logs-no-alarm-console-authentication-failures,AC-2
93
+ logs-no-alarm-iam-policy-changes,AC-2
94
+ logs-no-alarm-nacl-changes,CM-6(2)
95
+ logs-no-alarm-network-gateways-changes,AU-12|CM-6(2)
96
+ logs-no-alarm-root-usage,AU-2
97
+ logs-no-alarm-route-table-changes,AU-12|CM-6(2)
98
+ logs-no-alarm-s3-policy-changes,AC-6|AU-12
99
+ logs-no-alarm-security-group-changes,AC-2(4)
100
+ logs-no-alarm-signin-without-mfa,AC-2
101
+ logs-no-alarm-unauthorized-api-calls,AU-6|SI-4(2)
102
+ logs-no-alarm-vpc-changes,CM-6(1)
103
+ rds-instance-backup-disabled,CP-9
104
+ rds-instance-ca-certificate-deprecated,SC-12
105
+ rds-instance-no-minor-upgrade,SI-2
106
+ rds-instance-short-backup-retention-period,CP-9
107
+ rds-instance-single-az,CP-7
108
+ rds-instance-storage-not-encrypted,SC-28
109
+ rds-postgres-instance-with-invalid-certificate,SC-12
110
+ rds-security-group-allows-all,CM-7(1)
111
+ rds-snapshot-public,SC-28
112
+ redshift-cluster-database-not-encrypted,SC-28
113
+ redshift-cluster-no-version-upgrade,SI-2
114
+ redshift-cluster-publicly-accessible,AC-3
115
+ redshift-parameter-group-logging-disabled,AU-12
116
+ redshift-parameter-group-ssl-not-required,SC-8
117
+ redshift-security-group-whitelists-all,CM-7(1)
118
+ route53-domain-no-autorenew,SC-2
119
+ route53-domain-no-transferlock,SC-2
120
+ route53-domain-transferlock-not-authorized,SC-2
121
+ s3-bucket-allowing-cleartext,SC-28
122
+ s3-bucket-no-default-encryption,SC-28
123
+ s3-bucket-no-logging,AU-2|AU-12
124
+ s3-bucket-no-mfa-delete,SI-7
125
+ s3-bucket-no-versioning,SI-7
126
+ s3-bucket-world-acl,AC-3(3)
127
+ s3-bucket-world-policy-arg,AC-3(3)
128
+ s3-bucket-world-policy-star,AC-3(3)
129
+ ses-identity-dkim-not-enabled,SC-23
130
+ ses-identity-dkim-not-verified,SC-23
131
+ ses-identity-world-policy,AC-6
132
+ sns-topic-world-policy,AC-6
133
+ sqs-queue-world-policy,AC-6
134
+ vpc-custom-network-acls-allow-all,SC-7
135
+ vpc-default-network-acls-allow-all,SC-7
136
+ vpc-network-acl-not-used,SC-7
137
+ vpc-routing-tables-with-peering,AC-3(3)
138
+ vpc-subnet-with-bad-acls,SC-7
139
+ vpc-subnet-with-default-acls,SC-7
140
+ vpc-subnet-without-flow-log,AU-12
@@ -16,4 +16,6 @@ module HeimdallTools
16
16
  autoload :DBProtectMapper, 'heimdall_tools/dbprotect_mapper'
17
17
  autoload :AwsConfigMapper, 'heimdall_tools/aws_config_mapper'
18
18
  autoload :NetsparkerMapper, 'heimdall_tools/netsparker_mapper'
19
+ autoload :SarifMapper, 'heimdall_tools/sarif_mapper'
20
+ autoload :ScoutSuiteMapper, 'heimdall_tools/scoutsuite_mapper'
19
21
  end
@@ -57,10 +57,10 @@ module HeimdallTools
57
57
 
58
58
  results = HeimdallDataFormat.new(
59
59
  profile_name: 'AWS Config',
60
- title: 'AWS Config',
61
- summary: 'AWS Config',
62
- controls: controls,
63
- statistics: { aws_config_sdk_version: Aws::ConfigService::GEM_VERSION },
60
+ title: 'AWS Config',
61
+ summary: 'AWS Config',
62
+ controls: controls,
63
+ statistics: { aws_config_sdk_version: Aws::ConfigService::GEM_VERSION },
64
64
  )
65
65
  results.to_hdf
66
66
  end
@@ -123,6 +123,29 @@ module HeimdallTools
123
123
  puts options[:output].to_s
124
124
  end
125
125
 
126
+ desc 'sarif_mapper', 'sarif_mapper translates a SARIF JSON file into HDF format JSON to be viewable in Heimdall'
127
+ long_desc Help.text(:sarif_mapper)
128
+ option :json, required: true, aliases: '-j'
129
+ option :output, required: true, aliases: '-o'
130
+ option :verbose, type: :boolean, aliases: '-V'
131
+ def sarif_mapper
132
+ hdf = HeimdallTools::SarifMapper.new(File.read(options[:json])).to_hdf
133
+ File.write(options[:output], hdf)
134
+ puts "\r\HDF Generated:\n"
135
+ puts options[:output].to_s
136
+ end
137
+
138
+ desc 'scoutsuite_mapper', 'scoutsuite_mapper translates Scout Suite results from Javascript to HDF-formatted JSON so as to be viewable on Heimdall'
139
+ long_desc Help.text(:scoutsuite_mapper)
140
+ option :javascript, required: true, banner: 'SCOUTSUITE-RESULTS-JS', aliases: ['-i', '--input', '-j']
141
+ option :output, required: true, banner: 'HDF-SCAN-RESULTS-JSON', aliases: '-o'
142
+ def scoutsuite_mapper
143
+ hdf = HeimdallTools::ScoutSuiteMapper.new(File.read(options[:javascript])).to_hdf
144
+ File.write(options[:output], hdf)
145
+ puts "\rHDF Generated:\n"
146
+ puts options[:output].to_s
147
+ end
148
+
126
149
  desc 'version', 'prints version'
127
150
  def version
128
151
  puts VERSION
@@ -0,0 +1,12 @@
1
+ sarif_mapper translates a SARIF JSON file into HDF format JSON to be viewable in Heimdall
2
+
3
+ SARIF level to HDF impact Mapping:
4
+ SARIF level error -> HDF impact 0.7
5
+ SARIF level warning -> HDF impact 0.5
6
+ SARIF level note -> HDF impact 0.3
7
+ SARIF level none -> HDF impact 0.1
8
+ SARIF level not provided -> HDF impact 0.1 as default
9
+
10
+ Examples:
11
+
12
+ heimdall_tools sarif_mapper [OPTIONS] -j <sarif-results-json> -o <hdf-scan-results.json>
@@ -0,0 +1,7 @@
1
+ scoutsuite_mapper translates Scout Suite results from Javascript to HDF-formatted JSON so as to be viewable on Heimdall
2
+
3
+ Note: Currently this mapper only supports AWS.
4
+
5
+ Examples:
6
+
7
+ heimdall_tools scoutsuite_mapper -i <scoutsuite-results-js> -o <hdf-scan-results-json>
@@ -0,0 +1,198 @@
1
+ require 'json'
2
+ require 'csv'
3
+ require 'heimdall_tools/hdf'
4
+
5
+ RESOURCE_DIR = Pathname.new(__FILE__).join('../../data')
6
+
7
+ CWE_NIST_MAPPING_FILE = File.join(RESOURCE_DIR, 'cwe-nist-mapping.csv')
8
+
9
+ IMPACT_MAPPING = {
10
+ error: 0.7,
11
+ warning: 0.5,
12
+ note: 0.3,
13
+ none: 0.0
14
+ }.freeze
15
+
16
+ DEFAULT_NIST_TAG = %w{SA-11 RA-5}.freeze
17
+
18
+ # Loading spinner sign
19
+ $spinner = Enumerator.new do |e|
20
+ loop do
21
+ e.yield '|'
22
+ e.yield '/'
23
+ e.yield '-'
24
+ e.yield '\\'
25
+ end
26
+ end
27
+
28
+ module HeimdallTools
29
+ class SarifMapper
30
+ def initialize(sarif_json, _name = nil, verbose = false)
31
+ @sarif_json = sarif_json
32
+ @verbose = verbose
33
+ begin
34
+ @cwe_nist_mapping = parse_mapper
35
+ @sarif_log = JSON.parse(@sarif_json)
36
+ rescue StandardError => e
37
+ raise "Invalid SARIF JSON file provided\n\nException: #{e}"
38
+ end
39
+ end
40
+
41
+ def extract_scaninfo(sarif_log)
42
+ info = {}
43
+ begin
44
+ info['policy'] = 'SARIF'
45
+ info['version'] = sarif_log['version']
46
+ info['projectName'] = 'Static Analysis Results Interchange Format'
47
+ info['summary'] = NA_STRING
48
+ info
49
+ rescue StandardError => e
50
+ raise "Error extracting project info from SARIF JSON file provided Exception: #{e}"
51
+ end
52
+ end
53
+
54
+ def finding(result)
55
+ finding = {}
56
+ finding['status'] = 'failed'
57
+ finding['code_desc'] = ''
58
+ if get_location(result)['uri']
59
+ finding['code_desc'] += " URL : #{get_location(result)['uri']}"
60
+ end
61
+ if get_location(result)['start_line']
62
+ finding['code_desc'] += " LINE : #{get_location(result)['start_line']}"
63
+ end
64
+ if get_location(result)['start_column']
65
+ finding['code_desc'] += " COLUMN : #{get_location(result)['start_column']}"
66
+ end
67
+ finding['code_desc'].strip!
68
+ finding['run_time'] = NA_FLOAT
69
+ finding['start_time'] = NA_STRING
70
+ finding
71
+ end
72
+
73
+ def add_nist_tag_from_cwe(cweid, taxonomy_name, tags_node)
74
+ entries = @cwe_nist_mapping.select { |x| cweid.include?(x[:cweid].to_s) && !x[:nistid].nil? }
75
+ tags = entries.map { |x| x[:nistid] }
76
+ result_tags = tags.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq
77
+ if result_tags.count.positive?
78
+ if !tags_node
79
+ tags_node = {}
80
+ end
81
+ if !tags_node.key?(taxonomy_name)
82
+ tags_node[taxonomy_name] = []
83
+ end
84
+ result_tags.each do |t|
85
+ tags_node[taxonomy_name] |= [t]
86
+ end
87
+ end
88
+ tags_node
89
+ end
90
+
91
+ def get_location(result)
92
+ location_info = {}
93
+ location_info['uri'] = result.dig('locations', 0, 'physicalLocation', 'artifactLocation', 'uri')
94
+ location_info['start_line'] = result.dig('locations', 0, 'physicalLocation', 'region', 'startLine')
95
+ location_info['start_column'] = result.dig('locations', 0, 'physicalLocation', 'region', 'startColumn')
96
+ location_info
97
+ end
98
+
99
+ def get_rule_info(run, result, rule_id)
100
+ finding = {}
101
+ driver = run.dig('tool', 'driver')
102
+ finding['driver_name'] = driver['name']
103
+ finding['driver_version'] = driver['version']
104
+ rules = driver['rules']
105
+ if rules
106
+ rule = rules.find { |x| x['id'].eql?(rule_id) }
107
+ if rule
108
+ finding['rule_name'] = rule&.[]('name')
109
+ finding['rule_short_description'] = rule&.[]('shortDescription')&.[]('text')
110
+ finding['rule_tags'] = get_tags(rule)
111
+ finding['rule_name'] = rule&.[]('messageStrings')&.[]('default')&.[]('text') unless finding['rule_name']
112
+ end
113
+ end
114
+ finding['rule_name'] = result&.[]('message')&.[]('text') unless finding['rule_name']
115
+ finding
116
+ end
117
+
118
+ def get_tags(rule)
119
+ result = {}
120
+ Array(rule&.[]('relationships')).each do |relationship|
121
+ taxonomy_name = relationship['target']['toolComponent']['name'].downcase
122
+ taxonomy_id = relationship['target']['id']
123
+ if !result.key?(taxonomy_name)
124
+ result[taxonomy_name] = []
125
+ end
126
+ result[taxonomy_name] |= [taxonomy_id]
127
+ end
128
+ result
129
+ end
130
+
131
+ def parse_identifiers(rule_tags, ref)
132
+ # Extracting id number from reference style CWE-297
133
+ rule_tags[ref.downcase].map { |e| e.downcase.split("#{ref.downcase}-")[1] }
134
+ rescue StandardError
135
+ []
136
+ end
137
+
138
+ def impact(severity)
139
+ severity_mapping = IMPACT_MAPPING[severity.to_sym]
140
+ severity_mapping.nil? ? 0.1 : severity_mapping
141
+ end
142
+
143
+ def parse_mapper
144
+ csv_data = CSV.read(CWE_NIST_MAPPING_FILE, **{ encoding: 'UTF-8',
145
+ headers: true,
146
+ header_converters: :symbol,
147
+ converters: :all })
148
+ csv_data.map(&:to_hash)
149
+ end
150
+
151
+ def desc_tags(data, label)
152
+ { data: data || NA_STRING, label: label || NA_STRING }
153
+ end
154
+
155
+ def process_item(run, result, controls)
156
+ printf("\rProcessing: %s", $spinner.next)
157
+ control = controls.find { |x| x['id'].eql?(result['ruleId']) }
158
+
159
+ if control
160
+ control['results'] << finding(result)
161
+ else
162
+ rule_info = get_rule_info(run, result, result['ruleId'])
163
+ item = {}
164
+ item['tags'] = rule_info['rule_tags']
165
+ item['descriptions'] = []
166
+ item['refs'] = NA_ARRAY
167
+ item['source_location'] = { ref: get_location(result)['uri'], line: get_location(result)['start_line'] }
168
+ item['descriptions'] = NA_ARRAY
169
+ item['title'] = rule_info['rule_name'].to_s
170
+ item['id'] = result['ruleId'].to_s
171
+ item['desc'] = rule_info['rule_short_description'].to_s
172
+ item['impact'] = impact(result['level'].to_s)
173
+ item['code'] = NA_STRING
174
+ item['results'] = [finding(result)]
175
+ item['tags'] = add_nist_tag_from_cwe(parse_identifiers(rule_info['rule_tags'], 'CWE'), 'nist', item['tags'])
176
+ controls << item
177
+ end
178
+ end
179
+
180
+ def to_hdf
181
+ controls = []
182
+ @sarif_log['runs'].each do |run|
183
+ run['results'].each do |result|
184
+ process_item(run, result, controls)
185
+ end
186
+ end
187
+
188
+ scaninfo = extract_scaninfo(@sarif_log)
189
+ results = HeimdallDataFormat.new(profile_name: scaninfo['policy'],
190
+ version: scaninfo['version'],
191
+ title: scaninfo['projectName'],
192
+ summary: scaninfo['summary'],
193
+ controls: controls,
194
+ target_id: scaninfo['projectName'])
195
+ results.to_hdf
196
+ end
197
+ end
198
+ end
@@ -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,8 +8,6 @@ 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
13
  def initialize(zap_json, name)
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.45
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-05-01 00:00:00.000000000 Z
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
@@ -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