heimdall_tools 1.3.36 → 1.3.40
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 +4 -4
- data/README.md +39 -0
- data/lib/data/aws-config-mapping.csv +107 -0
- data/lib/heimdall_tools.rb +2 -0
- data/lib/heimdall_tools/aws_config_mapper.rb +284 -0
- data/lib/heimdall_tools/burpsuite_mapper.rb +1 -1
- data/lib/heimdall_tools/cli.rb +25 -1
- data/lib/heimdall_tools/hdf.rb +3 -1
- data/lib/heimdall_tools/help/aws_config_mapper.md +30 -0
- data/lib/heimdall_tools/help/netsparker_mapper.md +7 -0
- data/lib/heimdall_tools/jfrog_xray_mapper.rb +10 -2
- data/lib/heimdall_tools/nessus_mapper.rb +1 -1
- data/lib/heimdall_tools/netsparker_mapper.rb +167 -0
- data/lib/heimdall_tools/nikto_mapper.rb +1 -1
- data/lib/heimdall_tools/snyk_mapper.rb +1 -1
- data/lib/heimdall_tools/zap_mapper.rb +1 -1
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a306a3ebf9a2755760b9cc825f1123a62291723d92d215c03d3e9d958d22497
|
4
|
+
data.tar.gz: 5e551876a20872c32126a6c96d08e3c6cd6acdf73bc31abf1ba918693764d4e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ed8a026a5fbbd63d3da4ebb4211d8ee8cc371ae29e57f4deb10f9e188491af29b2988e17524aa5ab4c064f62a44349edfa9b626641c89d6a958ff040df39e40
|
7
|
+
data.tar.gz: 2874bbd8f062e601ed1fb65b53ec53ee5267d7c17457cef91f936dd28936bac6f35b4387c3d452c301c593cdb13e01ea6d587c1885a88b1a6f025ac3ee38bdaa
|
data/README.md
CHANGED
@@ -14,6 +14,8 @@ HeimdallTools supplies several methods to convert output from various tools to "
|
|
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
|
+
- **aws_config_mapper** - assess, audit, and evaluate AWS resources
|
18
|
+
- **netsparker_mapper** - web application security scanner
|
17
19
|
|
18
20
|
Ruby 2.4 or higher (check using "ruby -v")
|
19
21
|
|
@@ -213,6 +215,43 @@ FLAGS:
|
|
213
215
|
example: heimdall_tools dbprotect_mapper -x check_results_details_report.xml -o db_protect_hdf.json
|
214
216
|
```
|
215
217
|
|
218
|
+
## aws_config_mapper
|
219
|
+
|
220
|
+
aws_config_mapper pulls Ruby AWS SDK data to translate AWS Config Rule results into HDF format json to be viewable in Heimdall
|
221
|
+
|
222
|
+
### AWS Config Rule Mapping:
|
223
|
+
The mapping of AWS Config Rules to 800-53 Controls was sourced from [this link](https://docs.aws.amazon.com/config/latest/developerguide/operational-best-practices-for-nist-800-53_rev_4.html).
|
224
|
+
|
225
|
+
### Authentication with AWS:
|
226
|
+
[Developer Guide for configuring Ruby AWS SDK for authentication](https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html)
|
227
|
+
|
228
|
+
```
|
229
|
+
USAGE: heimdall_tools aws_config_mapper [OPTIONS] -o <hdf-scan-results.json>
|
230
|
+
|
231
|
+
FLAGS:
|
232
|
+
-o --output <scan-results> : path to output scan-results json.
|
233
|
+
-V --verbose : verbose run [optional].
|
234
|
+
|
235
|
+
example: heimdall_tools aws_config_mapper -o aws_config_results_hdf.json
|
236
|
+
```
|
237
|
+
|
238
|
+
## netsparker_mapper
|
239
|
+
|
240
|
+
netsparker_mapper translates an Netsparker XML results file into HDF format JSON to be viewable in Heimdall.
|
241
|
+
|
242
|
+
The current iteration only works with Netsparker Enterprise Vulnerabilities Scan.
|
243
|
+
|
244
|
+
```
|
245
|
+
USAGE: heimdall_tools netsparker_mapper [OPTIONS] -x <netsparker_results_xml> -o <hdf-scan-results.json>
|
246
|
+
|
247
|
+
FLAGS:
|
248
|
+
-x <netsparker_results_xml> : path to netsparker results XML file.
|
249
|
+
-o --output <scan-results> : path to output scan-results json.
|
250
|
+
-V --verbose : verbose run [optional].
|
251
|
+
|
252
|
+
example: heimdall_tools netsparker_mapper -x netsparker_results.xml -o netsparker_hdf.json
|
253
|
+
```
|
254
|
+
|
216
255
|
## version
|
217
256
|
|
218
257
|
Prints out the gem version
|
@@ -0,0 +1,107 @@
|
|
1
|
+
AwsConfigRuleName,NIST-ID,Rev
|
2
|
+
secretsmanager-scheduled-rotation-success-check,AC-2(1)|AC-2(j),4
|
3
|
+
iam-user-group-membership-check,AC-2(1)|AC-2(j)|AC-3|AC-6,4
|
4
|
+
iam-password-policy,AC-2(1)|AC-2(f)|AC-2(j)|IA-2|IA-5(1)(a)(d)(e)|IA-5(4),4
|
5
|
+
access-keys-rotated,AC-2(1)|AC-2(j),4
|
6
|
+
iam-user-unused-credentials-check,AC-2(1)|AC-2(3)|AC-2(f)|AC-3|AC-6,4
|
7
|
+
securityhub-enabled,AC-2(1)|AC-2(4)|AC-2(12)(a)|AC-2(g)|AC-17(1)|AU-6(1)(3)|CA-7(a)(b)|SA-10|SI-4(2)|SI-4(4)|SI-4(5)|SI-4(16)|SI-4(a)(b)(c),4
|
8
|
+
guardduty-enabled-centralized,AC-2(1)|AC-2(4)|AC-2(12)(a)|AC-2(g)|AC-17(1)|AU-6(1)(3)|CA-7(a)(b)|RA-5|SA-10|SI-4(1)|SI-4(2)|SI-4(4)|SI-4(5)|SI-4(16)|SI-4(a)(b)(c),4
|
9
|
+
cloud-trail-cloud-watch-logs-enabled,AC-2(4)|AC-2(g)|AU-2(a)(d)|AU-3|AU-6(1)(3)|AU-7(1)|AU-12(a)(c)|CA-7(a)(b)|SI-4(2)|SI-4(4)|SI-4(5)|SI-4(a)(b)(c),4
|
10
|
+
cloudtrail-enabled,AC-2(4)|AC-2(g)|AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
11
|
+
multi-region-cloudtrail-enabled,AC-2(4)|AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
12
|
+
rds-logging-enabled,AC-2(4)|AC-2(g)|AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
13
|
+
cloudwatch-alarm-action-check,AC-2(4)|AU-6(1)(3)|AU-7(1)|CA-7(a)(b)|IR-4(1)|SI-4(2)|SI-4(4)|SI-4(5)|SI-4(a)(b)(c),4
|
14
|
+
redshift-cluster-configuration-check,AC-2(4)|AC-2(g)|AU-2(a)(d)|AU-3|AU-12(a)(c)|SC-13|SC-28,4
|
15
|
+
iam-root-access-key-check,AC-2(f)|AC-2(j)|AC-3|AC-6|AC-6(10),4
|
16
|
+
s3-bucket-logging-enabled,AC-2(g)|AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
17
|
+
cloudtrail-s3-dataevents-enabled,AC-2(g)|AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
18
|
+
root-account-mfa-enabled,AC-2(j)|IA-2(1)(11),4
|
19
|
+
emr-kerberos-enabled,AC-2(j)|AC-3|AC-5(c)|AC-6,4
|
20
|
+
iam-group-has-users-check,AC-2(j)|AC-3|AC-5(c)|AC-6|SC-2,4
|
21
|
+
iam-policy-no-statements-with-admin-access,AC-2(j)|AC-3|AC-5(c)|AC-6|SC-2,4
|
22
|
+
iam-user-no-policies-check,AC-2(j)|AC-3|AC-5(c)|AC-6,4
|
23
|
+
s3-bucket-public-write-prohibited,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
24
|
+
lambda-function-public-access-prohibited,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
25
|
+
rds-snapshots-public-prohibited,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
26
|
+
redshift-cluster-public-access-check,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
27
|
+
s3-bucket-policy-grantee-check,AC-3|AC-6|SC-7|SC-7(3),4
|
28
|
+
s3-bucket-public-read-prohibited,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
29
|
+
s3-account-level-public-access-blocks,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
30
|
+
dms-replication-not-public,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
31
|
+
ebs-snapshot-public-restorable-check,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
32
|
+
sagemaker-notebook-no-direct-internet-access,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
33
|
+
rds-instance-public-access-check,AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
34
|
+
lambda-inside-vpc,AC-4|SC-7|SC-7(3),4
|
35
|
+
ec2-instances-in-vpc,AC-4|SC-7|SC-7(3),4
|
36
|
+
restricted-common-ports,AC-4|CM-2|SC-7|SC-7(3),4
|
37
|
+
restricted-ssh,AC-4|SC-7|SC-7(3),4
|
38
|
+
vpc-default-security-group-closed,AC-4|SC-7|SC-7(3),4
|
39
|
+
vpc-sg-open-only-to-authorized-ports,AC-4|SC-7|SC-7(3),4
|
40
|
+
acm-certificate-expiration-check,AC-4|AC-17(2)|SC-12,4
|
41
|
+
ec2-instance-no-public-ip,AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
42
|
+
elasticsearch-in-vpc-only,AC-4|SC-7|SC-7(3),4
|
43
|
+
emr-master-no-public-ip,AC-4|AC-21(b)|SC-7|SC-7(3),4
|
44
|
+
internet-gateway-authorized-vpc-only,AC-4|AC-17(3)|SC-7|SC-7(3),4
|
45
|
+
codebuild-project-envvar-awscred-check,AC-6|IA-5(7)|SA-3(a),4
|
46
|
+
ec2-imdsv2-check,AC-6,4
|
47
|
+
iam-no-inline-policy-check,AC-6,4
|
48
|
+
alb-http-to-https-redirection-check,AC-17(2)|SC-7|SC-8|SC-8(1)|SC-13|SC-23,4
|
49
|
+
redshift-require-tls-ssl,AC-17(2)|SC-7|SC-8|SC-8(1)|SC-13,4
|
50
|
+
s3-bucket-ssl-requests-only,AC-17(2)|SC-7|SC-8|SC-8(1)|SC-13,4
|
51
|
+
elb-acm-certificate-required,AC-17(2)|SC-7|SC-8|SC-8(1)|SC-13,4
|
52
|
+
alb-http-drop-invalid-header-enabled,AC-17(2)|SC-7|SC-8|SC-8(1)|SC-23,4
|
53
|
+
elb-tls-https-listeners-only,AC-17(2)|SC-7|SC-8|SC-8(1)|SC-23,4
|
54
|
+
api-gw-execution-logging-enabled,AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
55
|
+
elb-logging-enabled,AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
56
|
+
vpc-flow-logs-enabled,AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
57
|
+
wafv2-logging-enabled,AU-2(a)(d)|AU-3|AU-12(a)(c)|SC-7|SI-4(a)(b)(c),4
|
58
|
+
cloud-trail-encryption-enabled,AU-9|SC-13|SC-28,4
|
59
|
+
cloudwatch-log-group-encrypted,AU-9|SC-13|SC-28,4
|
60
|
+
s3-bucket-replication-enabled,AU-9(2)|CP-9(b)|CP-10|SC-5|SC-36,4
|
61
|
+
cw-loggroup-retention-period-check,AU-11|SI-12,4
|
62
|
+
ec2-instance-detailed-monitoring-enabled,CA-7(a)(b)|SI-4(2)|SI-4(a)(b)(c),4
|
63
|
+
rds-enhanced-monitoring-enabled,CA-7(a)(b),4
|
64
|
+
ec2-instance-managed-by-systems-manager,CM-2|CM-7(a)|CM-8(1)|CM-8(3)(a)|SA-3(a)|SA-10|SI-2(2)|SI-7(1),4
|
65
|
+
ec2-managedinstance-association-compliance-status-check,CM-2|CM-7(a)|CM-8(3)(a)|SI-2(2),4
|
66
|
+
ec2-stopped-instance,CM-2,4
|
67
|
+
ec2-volume-inuse-check,CM-2|SC-4,4
|
68
|
+
elb-deletion-protection-enabled,CM-2|CP-10,4
|
69
|
+
cloudtrail-security-trail-enabled,CM-2,4
|
70
|
+
ec2-managedinstance-patch-compliance-status-check,CM-8(3)(a)|SI-2(2)|SI-7(1),4
|
71
|
+
db-instance-backup-enabled,CP-9(b)|CP-10|SI-12,4
|
72
|
+
dynamodb-pitr-enabled,CP-9(b)|CP-10|SI-12,4
|
73
|
+
elasticache-redis-cluster-automatic-backup-check,CP-9(b)|CP-10|SI-12,4
|
74
|
+
dynamodb-in-backup-plan,CP-9(b)|CP-10|SI-12,4
|
75
|
+
ebs-in-backup-plan,CP-9(b)|CP-10|SI-12,4
|
76
|
+
efs-in-backup-plan,CP-9(b)|CP-10|SI-12,4
|
77
|
+
rds-in-backup-plan,CP-9(b)|CP-10|SI-12,4
|
78
|
+
dynamodb-autoscaling-enabled,CP-10|SC-5,4
|
79
|
+
rds-multi-az-support,CP-10|SC-5|SC-36,4
|
80
|
+
s3-bucket-versioning-enabled,CP-10|SI-12,4
|
81
|
+
vpc-vpn-2-tunnels-up,CP-10,4
|
82
|
+
elb-cross-zone-load-balancing-enabled,CP-10|SC-5,4
|
83
|
+
root-account-hardware-mfa-enabled,IA-2(1)(11),4
|
84
|
+
mfa-enabled-for-iam-console-access,IA-2(1)(2)(11),4
|
85
|
+
iam-user-mfa-enabled,IA-2(1)(2)(11),4
|
86
|
+
guardduty-non-archived-findings,IR-4(1)|IR-6(1)|IR-7(1)|RA-5|SA-10|SI-4(a)(b)(c),4
|
87
|
+
codebuild-project-source-repo-url-check,SA-3(a),4
|
88
|
+
autoscaling-group-elb-healthcheck-required,SC-5,4
|
89
|
+
rds-instance-deletion-protection-enabled,SC-5,4
|
90
|
+
alb-waf-enabled,SC-7|SI-4(a)(b)(c),4
|
91
|
+
elasticsearch-node-to-node-encryption-check,SC-7|SC-8|SC-8(1),4
|
92
|
+
cmk-backing-key-rotation-enabled,SC-12,4
|
93
|
+
kms-cmk-not-scheduled-for-deletion,SC-12|SC-28,4
|
94
|
+
api-gw-cache-enabled-and-encrypted,SC-13|SC-28,4
|
95
|
+
efs-encrypted-check,SC-13|SC-28,4
|
96
|
+
elasticsearch-encrypted-at-rest,SC-13|SC-28,4
|
97
|
+
encrypted-volumes,SC-13|SC-28,4
|
98
|
+
rds-storage-encrypted,SC-13|SC-28,4
|
99
|
+
s3-bucket-server-side-encryption-enabled,SC-13|SC-28,4
|
100
|
+
sagemaker-endpoint-configuration-kms-key-configured,SC-13|SC-28,4
|
101
|
+
sagemaker-notebook-instance-kms-key-configured,SC-13|SC-28,4
|
102
|
+
sns-encrypted-kms,SC-13|SC-28,4
|
103
|
+
dynamodb-table-encrypted-kms,SC-13,4
|
104
|
+
s3-bucket-default-lock-enabled,SC-28,4
|
105
|
+
ec2-ebs-encryption-by-default,SC-28,4
|
106
|
+
rds-snapshot-encrypted,SC-28,4
|
107
|
+
cloud-trail-log-file-validation-enabled,SI-7|SI-7(1),4
|
data/lib/heimdall_tools.rb
CHANGED
@@ -14,4 +14,6 @@ module HeimdallTools
|
|
14
14
|
autoload :NiktoMapper, 'heimdall_tools/nikto_mapper'
|
15
15
|
autoload :JfrogXrayMapper, 'heimdall_tools/jfrog_xray_mapper'
|
16
16
|
autoload :DBProtectMapper, 'heimdall_tools/dbprotect_mapper'
|
17
|
+
autoload :AwsConfigMapper, 'heimdall_tools/aws_config_mapper'
|
18
|
+
autoload :NetsparkerMapper, 'heimdall_tools/netsparker_mapper'
|
17
19
|
end
|
@@ -0,0 +1,284 @@
|
|
1
|
+
require 'aws-sdk-configservice'
|
2
|
+
require 'heimdall_tools/hdf'
|
3
|
+
require 'csv'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
RESOURCE_DIR = Pathname.new(__FILE__).join('../../data')
|
7
|
+
|
8
|
+
AWS_CONFIG_MAPPING_FILE = File.join(RESOURCE_DIR, 'aws-config-mapping.csv')
|
9
|
+
|
10
|
+
NOT_APPLICABLE_MSG = 'No AWS resources found to evaluate complaince for this rule'.freeze
|
11
|
+
INSUFFICIENT_DATA_MSG = 'Not enough data has been collectd to determine compliance yet.'.freeze
|
12
|
+
|
13
|
+
##
|
14
|
+
# HDF mapper for use with AWS Config rules.
|
15
|
+
#
|
16
|
+
# Ruby AWS Ruby SDK for ConfigService:
|
17
|
+
# - https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ConfigService/Client.html
|
18
|
+
#
|
19
|
+
# rubocop:disable Metrics/AbcSize, Metrics/ClassLength
|
20
|
+
module HeimdallTools
|
21
|
+
class AwsConfigMapper
|
22
|
+
def initialize(custom_mapping, verbose = false)
|
23
|
+
@verbose = verbose
|
24
|
+
@default_mapping = get_rule_mapping(AWS_CONFIG_MAPPING_FILE)
|
25
|
+
@custom_mapping = custom_mapping.nil? ? {} : get_rule_mapping(custom_mapping)
|
26
|
+
@client = Aws::ConfigService::Client.new
|
27
|
+
@issues = get_all_config_rules
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Convert to HDF
|
32
|
+
#
|
33
|
+
# If there is overlap in rule names from @default_mapping and @custom_mapping,
|
34
|
+
# then the tags from both will be added to the rule.
|
35
|
+
def to_hdf
|
36
|
+
controls = @issues.map do |issue|
|
37
|
+
@item = {}
|
38
|
+
@item['id'] = issue[:config_rule_name]
|
39
|
+
@item['title'] = issue[:config_rule_name]
|
40
|
+
@item['desc'] = issue[:description]
|
41
|
+
@item['impact'] = 0.5
|
42
|
+
@item['tags'] = hdf_tags(issue)
|
43
|
+
@item['descriptions'] = hdf_descriptions(issue)
|
44
|
+
@item['refs'] = NA_ARRAY
|
45
|
+
@item['source_location'] = { ref: issue[:config_rule_arn], line: 1 }
|
46
|
+
@item['code'] = ''
|
47
|
+
@item['results'] = issue[:results]
|
48
|
+
# Avoid duplicating rules that exist in the custom mapping as 'unmapped' in this loop
|
49
|
+
if @custom_mapping.include?(issue[:config_rule_name]) && !@default_mapping.include?(issue[:config_rule_name])
|
50
|
+
nil
|
51
|
+
else
|
52
|
+
@item
|
53
|
+
end
|
54
|
+
end
|
55
|
+
results = HeimdallDataFormat.new(
|
56
|
+
profile_name: 'AWS Config',
|
57
|
+
title: 'AWS Config',
|
58
|
+
summary: 'AWS Config',
|
59
|
+
controls: controls,
|
60
|
+
statistics: { aws_config_sdk_version: Aws::ConfigService::GEM_VERSION }
|
61
|
+
)
|
62
|
+
results.to_hdf
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
##
|
68
|
+
# Read in a config rule -> 800-53 control mapping CSV.
|
69
|
+
#
|
70
|
+
# Params:
|
71
|
+
# - path: The file path to the CSV file
|
72
|
+
#
|
73
|
+
# Returns: A mapped version of the csv in the format { rule_name: row, ... }
|
74
|
+
def get_rule_mapping(path)
|
75
|
+
Hash[CSV.read(path, headers: true).map { |row| [row[0], row] }]
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Fetches information on all of the config rules available to the
|
80
|
+
# AWS account.
|
81
|
+
#
|
82
|
+
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ConfigService/Client.html#describe_config_rules-instance_method
|
83
|
+
#
|
84
|
+
# Returns: list of hash for all config rules available
|
85
|
+
def get_all_config_rules
|
86
|
+
config_rules = []
|
87
|
+
|
88
|
+
# Fetch all rules with pagination
|
89
|
+
response = @client.describe_config_rules
|
90
|
+
config_rules += response.config_rules
|
91
|
+
while response.next_token
|
92
|
+
response = @client.describe_config_rules(next_token: response.next_token)
|
93
|
+
config_rules += response.config_rules
|
94
|
+
end
|
95
|
+
config_rules = config_rules.map(&:to_h)
|
96
|
+
|
97
|
+
# Add necessary data to rules using helpers
|
98
|
+
add_compliance_to_config_rules(config_rules)
|
99
|
+
add_results_to_config_rules(config_rules)
|
100
|
+
end
|
101
|
+
|
102
|
+
##
|
103
|
+
# Adds compliance information for config rules to the config rule hash
|
104
|
+
# from AwsConfigMapper::get_all_config_rules.
|
105
|
+
#
|
106
|
+
# `complaince_type` may be any of the following:
|
107
|
+
# ["COMPLIANT", "NON_COMPLIANT", "NOT_APPLICABLE", "INSUFFICIENT_DATA"]
|
108
|
+
#
|
109
|
+
# Params:
|
110
|
+
# - config_rules: The list of hash from AwsConfigMapper::get_all_config_rules
|
111
|
+
#
|
112
|
+
# Returns: The same config_rules array with `compliance` key added to each rule
|
113
|
+
def add_compliance_to_config_rules(config_rules)
|
114
|
+
mapped_compliance_results = fetch_all_compliance_info(config_rules)
|
115
|
+
|
116
|
+
# Add compliance to config_rules
|
117
|
+
config_rules.each do |rule|
|
118
|
+
rule[:compliance] = mapped_compliance_results[rule[:config_rule_name]]&.dig(:compliance, :compliance_type)
|
119
|
+
end
|
120
|
+
|
121
|
+
config_rules
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Fetch and combine all compliance information for the config rules.
|
126
|
+
#
|
127
|
+
# AWS allows passing up to 25 rules at a time to this endpoint.
|
128
|
+
#
|
129
|
+
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ConfigService/Client.html#describe_compliance_by_config_rule-instance_method
|
130
|
+
#
|
131
|
+
# Params:
|
132
|
+
# - config_rules: The list of hash from AwsConfigMapper::get_all_config_rules
|
133
|
+
#
|
134
|
+
# Returns: Results mapped by config rule in the format { name: {<response>}, ... }
|
135
|
+
def fetch_all_compliance_info(config_rules)
|
136
|
+
compliance_results = []
|
137
|
+
|
138
|
+
config_rules.each_slice(25).each do |slice|
|
139
|
+
config_rule_names = slice.map { |r| r[:config_rule_name] }
|
140
|
+
response = @client.describe_compliance_by_config_rule(config_rule_names: config_rule_names)
|
141
|
+
compliance_results += response.compliance_by_config_rules
|
142
|
+
end
|
143
|
+
|
144
|
+
# Map based on name for easy lookup
|
145
|
+
Hash[compliance_results.collect { |r| [r.config_rule_name, r.to_h] }]
|
146
|
+
end
|
147
|
+
|
148
|
+
##
|
149
|
+
# Takes in config rules and formats the results for hdf format.
|
150
|
+
#
|
151
|
+
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ConfigService/Client.html#get_compliance_details_by_config_rule-instance_method
|
152
|
+
#
|
153
|
+
# Example hdf results:
|
154
|
+
# [
|
155
|
+
# {
|
156
|
+
# "code_desc": "This rule...",
|
157
|
+
# "run_time": 0.314016,
|
158
|
+
# "start_time": "2018-11-18T20:21:40-05:00",
|
159
|
+
# "status": "passed"
|
160
|
+
# },
|
161
|
+
# ...
|
162
|
+
# ]
|
163
|
+
#
|
164
|
+
# Status may be any of the following: ['passed', 'failed', 'skipped', 'loaded']
|
165
|
+
#
|
166
|
+
# Params:
|
167
|
+
# - rule: Rules from AwsConfigMapper::get_all_config_rules
|
168
|
+
#
|
169
|
+
# Returns: The same config_rules array with `results` key added to each rule.
|
170
|
+
def add_results_to_config_rules(config_rules)
|
171
|
+
config_rules.each do |rule|
|
172
|
+
response = @client.get_compliance_details_by_config_rule(config_rule_name: rule[:config_rule_name], limit: 100)
|
173
|
+
rule_results = response.to_h[:evaluation_results]
|
174
|
+
while response.next_token
|
175
|
+
response = @client.get_compliance_details_by_config_rule(next_token: response.next_token, limit: 100)
|
176
|
+
rule_results += response.to_h[:evaluation_results]
|
177
|
+
end
|
178
|
+
|
179
|
+
rule[:results] = []
|
180
|
+
rule_results.each do |result|
|
181
|
+
hdf_result = {}
|
182
|
+
# code_desc
|
183
|
+
hdf_result['code_desc'] = result.dig(:evaluation_result_identifier, :evaluation_result_qualifier)&.map do |k, v|
|
184
|
+
"#{k}: #{v}"
|
185
|
+
end&.join(', ')
|
186
|
+
# start_time
|
187
|
+
hdf_result['start_time'] = if result.key?(:config_rule_invoked_time)
|
188
|
+
DateTime.parse(result[:config_rule_invoked_time].to_s).strftime('%Y-%m-%dT%H:%M:%S%:z')
|
189
|
+
end
|
190
|
+
# run_time
|
191
|
+
hdf_result['run_time'] = if result.key?(:result_recorded_time) && result.key?(:config_rule_invoked_time)
|
192
|
+
(result[:result_recorded_time] - result[:config_rule_invoked_time]).round(6)
|
193
|
+
end
|
194
|
+
# status
|
195
|
+
hdf_result['status'] = case result.dig(:compliance_type)
|
196
|
+
when 'COMPLIANT'
|
197
|
+
'passed'
|
198
|
+
when 'NON_COMPLIANT'
|
199
|
+
'failed'
|
200
|
+
else
|
201
|
+
'skipped'
|
202
|
+
end
|
203
|
+
hdf_result['message'] = "(#{hdf_result['code_desc']}): #{result[:annotation] || 'Rule does not pass rule compliance'}" if hdf_result['status'] == 'failed'
|
204
|
+
rule[:results] << hdf_result
|
205
|
+
end
|
206
|
+
next unless rule[:results].empty?
|
207
|
+
|
208
|
+
case rule[:compliance]
|
209
|
+
when 'NOT_APPLICABLE'
|
210
|
+
rule[:impact] = 0
|
211
|
+
rule[:results] << {
|
212
|
+
'run_time': 0,
|
213
|
+
'code_desc': NOT_APPLICABLE_MSG,
|
214
|
+
'skip_message': NOT_APPLICABLE_MSG,
|
215
|
+
'start_time': DateTime.now.strftime('%Y-%m-%dT%H:%M:%S%:z'),
|
216
|
+
'status': 'skipped'
|
217
|
+
}
|
218
|
+
when 'INSUFFICIENT_DATA'
|
219
|
+
rule[:results] << {
|
220
|
+
'run_time': 0,
|
221
|
+
'code_desc': INSUFFICIENT_DATA_MSG,
|
222
|
+
'skip_message': INSUFFICIENT_DATA_MSG,
|
223
|
+
'start_time': DateTime.now.strftime('%Y-%m-%dT%H:%M:%S%:z'),
|
224
|
+
'status': 'skipped'
|
225
|
+
}
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
config_rules
|
230
|
+
end
|
231
|
+
|
232
|
+
##
|
233
|
+
# Takes in a config rule and pulls out tags that are useful for HDF.
|
234
|
+
#
|
235
|
+
# Params:
|
236
|
+
# - config_rule: A single config rule from AwsConfigMapper::get_all_config_rules
|
237
|
+
#
|
238
|
+
# Returns: Hash containing all relevant HDF tags
|
239
|
+
def hdf_tags(config_rule)
|
240
|
+
result = {}
|
241
|
+
|
242
|
+
@default_mapping
|
243
|
+
@custom_mapping
|
244
|
+
|
245
|
+
# NIST tag
|
246
|
+
result['nist'] = []
|
247
|
+
default_mapping_match = @default_mapping[config_rule[:config_rule_name]]
|
248
|
+
|
249
|
+
result['nist'] += default_mapping_match[1].split('|') unless default_mapping_match.nil?
|
250
|
+
|
251
|
+
custom_mapping_match = @custom_mapping[config_rule[:config_rule_name]]
|
252
|
+
|
253
|
+
result['nist'] += custom_mapping_match[1].split('|').map { |name| "#{name} (user provided)" } unless custom_mapping_match.nil?
|
254
|
+
|
255
|
+
result['nist'] = ['unmapped'] if result['nist'].empty?
|
256
|
+
|
257
|
+
result
|
258
|
+
end
|
259
|
+
|
260
|
+
def check_text(config_rule)
|
261
|
+
params = (JSON.parse(config_rule[:input_parameters]).map { |key, value| "#{key}: #{value}" }).join('<br/>')
|
262
|
+
check_text = config_rule[:config_rule_arn]
|
263
|
+
check_text += "<br/>#{params}" unless params.empty?
|
264
|
+
check_text
|
265
|
+
end
|
266
|
+
|
267
|
+
##
|
268
|
+
# Takes in a config rule and pulls out information for the descriptions array
|
269
|
+
#
|
270
|
+
# Params:
|
271
|
+
# - config_rule: A single config rule from AwsConfigMapper::get_all_config_rules
|
272
|
+
#
|
273
|
+
# Returns: Array containing all relevant descriptions information
|
274
|
+
def hdf_descriptions(config_rule)
|
275
|
+
[
|
276
|
+
{
|
277
|
+
'label': 'check',
|
278
|
+
'data': check_text(config_rule)
|
279
|
+
}
|
280
|
+
]
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
# rubocop:enable Metrics/AbcSize, Metrics/ClassLength
|
@@ -63,7 +63,7 @@ module HeimdallTools
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def nist_tag(cweid)
|
66
|
-
entries = @cwe_nist_mapping.select { |x| cweid.include?
|
66
|
+
entries = @cwe_nist_mapping.select { |x| cweid.include?(x[:cweid].to_s) && !x[:nistid].nil? }
|
67
67
|
tags = entries.map { |x| [x[:nistid], "Rev_#{x[:rev]}"] }
|
68
68
|
tags.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq
|
69
69
|
end
|
data/lib/heimdall_tools/cli.rb
CHANGED
@@ -98,7 +98,7 @@ module HeimdallTools
|
|
98
98
|
puts "\r\HDF Generated:\n"
|
99
99
|
puts "#{options[:output]}"
|
100
100
|
end
|
101
|
-
|
101
|
+
|
102
102
|
desc 'dbprotect_mapper', 'dbprotect_mapper translates dbprotect results xml to HDF format Json be viewed on Heimdall'
|
103
103
|
long_desc Help.text(:dbprotect_mapper)
|
104
104
|
option :xml, required: true, aliases: '-x'
|
@@ -111,6 +111,30 @@ module HeimdallTools
|
|
111
111
|
puts "#{options[:output]}"
|
112
112
|
end
|
113
113
|
|
114
|
+
desc 'aws_config_mapper', 'aws_config_mapper pulls Ruby AWS SDK data to translate AWS Config Rule results into HDF format Json to be viewable in Heimdall'
|
115
|
+
long_desc Help.text(:aws_config_mapper)
|
116
|
+
# option :custom_mapping, required: false, aliases: '-m'
|
117
|
+
option :output, required: true, aliases: '-o'
|
118
|
+
option :verbose, type: :boolean, aliases: '-V'
|
119
|
+
def aws_config_mapper
|
120
|
+
hdf = HeimdallTools::AwsConfigMapper.new(options[:custom_mapping]).to_hdf
|
121
|
+
File.write(options[:output], hdf)
|
122
|
+
puts "\r\HDF Generated:\n"
|
123
|
+
puts "#{options[:output]}"
|
124
|
+
end
|
125
|
+
|
126
|
+
desc 'netsparker_mapper', 'netsparker_mapper translates netsparker enterprise results xml to HDF format Json be viewed on Heimdall'
|
127
|
+
long_desc Help.text(:netsparker_mapper)
|
128
|
+
option :xml, required: true, aliases: '-x'
|
129
|
+
option :output, required: true, aliases: '-o'
|
130
|
+
option :verbose, type: :boolean, aliases: '-V'
|
131
|
+
def netsparker_mapper
|
132
|
+
hdf = HeimdallTools::NetsparkerMapper.new(File.read(options[:xml])).to_hdf
|
133
|
+
File.write(options[:output], hdf)
|
134
|
+
puts "\r\HDF Generated:\n"
|
135
|
+
puts "#{options[:output]}"
|
136
|
+
end
|
137
|
+
|
114
138
|
desc 'version', 'prints version'
|
115
139
|
def version
|
116
140
|
puts VERSION
|
data/lib/heimdall_tools/hdf.rb
CHANGED
@@ -29,7 +29,8 @@ module HeimdallTools
|
|
29
29
|
groups: NA_ARRAY,
|
30
30
|
status: 'loaded',
|
31
31
|
controls: NA_TAG,
|
32
|
-
target_id: NA_TAG
|
32
|
+
target_id: NA_TAG,
|
33
|
+
statistics: NA_HASH)
|
33
34
|
|
34
35
|
@results_json = {}
|
35
36
|
@results_json['platform'] = {}
|
@@ -40,6 +41,7 @@ module HeimdallTools
|
|
40
41
|
|
41
42
|
@results_json['statistics'] = {}
|
42
43
|
@results_json['statistics']['duration'] = duration || NA_TAG
|
44
|
+
@results_json['statistics'].merge! statistics
|
43
45
|
|
44
46
|
@results_json['profiles'] = []
|
45
47
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
aws_config_mapper pulls Ruby AWS SDK data to translate AWS Config Rule results into HDF format json to be viewable in Heimdall
|
2
|
+
|
3
|
+
AWS Config Rule Mapping:
|
4
|
+
The mapping of AWS Config Rules to 800-53 Controls was sourced from [this link](https://docs.aws.amazon.com/config/latest/developerguide/operational-best-practices-for-nist-800-53_rev_4.html).
|
5
|
+
|
6
|
+
Authentication with AWS:
|
7
|
+
[Developer Guide for configuring Ruby AWS SDK for authentication](https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html)
|
8
|
+
|
9
|
+
Authentication Example:
|
10
|
+
|
11
|
+
- Create `~/.aws/credentials`
|
12
|
+
- Add contents to file, replacing with your access ID and key
|
13
|
+
|
14
|
+
```
|
15
|
+
[default]
|
16
|
+
aws_access_key_id = your_access_key_id
|
17
|
+
aws_secret_access_key = your_secret_access_key
|
18
|
+
```
|
19
|
+
|
20
|
+
- (optional) set AWS region through `~/.aws/config` file with contents
|
21
|
+
|
22
|
+
```
|
23
|
+
[default]
|
24
|
+
output = json
|
25
|
+
region = us-gov-west-1
|
26
|
+
```
|
27
|
+
|
28
|
+
Examples:
|
29
|
+
|
30
|
+
heimdall_tools aws_config_mapper -o aws_config_results.json
|
@@ -0,0 +1,7 @@
|
|
1
|
+
netsparker_mapper translates an Netsparker XML results file into HDF format json to be viewable in Heimdall
|
2
|
+
|
3
|
+
The current iteration only works with Netsparker Enterprise Vulnerabilities Scan.
|
4
|
+
|
5
|
+
Examples:
|
6
|
+
|
7
|
+
heimdall_tools netsparker_mapper -x netsparker_results.xml -o netsparker_hdf.json
|
@@ -57,8 +57,16 @@ module HeimdallTools
|
|
57
57
|
[finding]
|
58
58
|
end
|
59
59
|
|
60
|
+
def format_control_desc(vulnerability)
|
61
|
+
text = []
|
62
|
+
info = vulnerability['component_versions']['more_details']
|
63
|
+
text << info['description'].to_s
|
64
|
+
text << "cves: #{info['cves'].to_s }" unless info['cves'].nil?
|
65
|
+
text.join("<br>")
|
66
|
+
end
|
67
|
+
|
60
68
|
def nist_tag(cweid)
|
61
|
-
entries = @cwe_nist_mapping.select { |x| cweid.include?
|
69
|
+
entries = @cwe_nist_mapping.select { |x| cweid.include?(x[:cweid].to_s) && !x[:nistid].nil? }
|
62
70
|
tags = entries.map { |x| x[:nistid] }
|
63
71
|
tags.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq
|
64
72
|
end
|
@@ -119,7 +127,7 @@ module HeimdallTools
|
|
119
127
|
# If thats a case MD5 hash is used to collapse vulnerability findings of the same type.
|
120
128
|
item['id'] = vulnerability['id'].empty? ? OpenSSL::Digest::MD5.digest(vulnerability['summary'].to_s).unpack("H*")[0].to_s : vulnerability['id']
|
121
129
|
item['title'] = vulnerability['summary'].to_s
|
122
|
-
item['desc'] = vulnerability
|
130
|
+
item['desc'] = format_control_desc(vulnerability)
|
123
131
|
item['impact'] = impact(vulnerability['severity'].to_s)
|
124
132
|
item['code'] = NA_STRING
|
125
133
|
item['results'] = finding(vulnerability)
|
@@ -140,7 +140,7 @@ module HeimdallTools
|
|
140
140
|
end
|
141
141
|
|
142
142
|
def plugin_nist_tag(pluginfamily, pluginid)
|
143
|
-
entries = @cwe_nist_mapping.select { |x| (x[:pluginfamily].eql?(pluginfamily) && (x[:pluginid].eql?('*') || x[:pluginid].eql?(pluginid.to_i)) ) }
|
143
|
+
entries = @cwe_nist_mapping.select { |x| (x[:pluginfamily].eql?(pluginfamily) && (x[:pluginid].eql?('*') || x[:pluginid].eql?(pluginid.to_i)) ) && !x[:nistid].nil? }
|
144
144
|
tags = entries.map { |x| [x[:nistid].split('|'), "Rev_#{x[:rev]}"] }
|
145
145
|
tags.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq
|
146
146
|
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'csv'
|
3
|
+
require 'heimdall_tools/hdf'
|
4
|
+
require 'utilities/xml_to_hash'
|
5
|
+
|
6
|
+
RESOURCE_DIR = Pathname.new(__FILE__).join('../../data')
|
7
|
+
|
8
|
+
CWE_NIST_MAPPING_FILE = File.join(RESOURCE_DIR, 'cwe-nist-mapping.csv')
|
9
|
+
OWASP_NIST_MAPPING_FILE = File.join(RESOURCE_DIR, 'owasp-nist-mapping.csv')
|
10
|
+
|
11
|
+
IMPACT_MAPPING = {
|
12
|
+
Critical: 1.0,
|
13
|
+
High: 0.7,
|
14
|
+
Medium: 0.5,
|
15
|
+
Low: 0.3,
|
16
|
+
Best_Practice: 0.0,
|
17
|
+
Information: 0.0
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
DEFAULT_NIST_TAG = ["SA-11", "RA-5"].freeze
|
21
|
+
|
22
|
+
# rubocop:disable Metrics/AbcSize
|
23
|
+
|
24
|
+
module HeimdallTools
|
25
|
+
class NetsparkerMapper
|
26
|
+
def initialize(xml, name=nil, verbose = false)
|
27
|
+
@verbose = verbose
|
28
|
+
|
29
|
+
begin
|
30
|
+
@cwe_nist_mapping = parse_mapper(CWE_NIST_MAPPING_FILE)
|
31
|
+
@owasp_nist_mapping = parse_mapper(OWASP_NIST_MAPPING_FILE)
|
32
|
+
data = xml_to_hash(xml)
|
33
|
+
|
34
|
+
@vulnerabilities = data['netsparker-enterprise']['vulnerabilities']['vulnerability']
|
35
|
+
@scan_info = data['netsparker-enterprise']['target']
|
36
|
+
|
37
|
+
rescue StandardError => e
|
38
|
+
raise "Invalid Netsparker XML file provided Exception: #{e}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_hdf
|
43
|
+
controls = []
|
44
|
+
@vulnerabilities.each do |vulnerability|
|
45
|
+
@item = {}
|
46
|
+
@item['id'] = vulnerability['LookupId'].to_s
|
47
|
+
@item['title'] = vulnerability['name'].to_s
|
48
|
+
@item['desc'] = format_control_desc(vulnerability)
|
49
|
+
@item['impact'] = impact(vulnerability['severity'])
|
50
|
+
@item['tags'] = {}
|
51
|
+
@item['descriptions'] = []
|
52
|
+
|
53
|
+
@item['descriptions'] << desc_tags(format_check_text(vulnerability), 'check')
|
54
|
+
@item['descriptions'] << desc_tags(format_fix_text(vulnerability), 'fix')
|
55
|
+
@item['refs'] = NA_ARRAY
|
56
|
+
@item['source_location'] = NA_HASH
|
57
|
+
@item['tags']['nist'] = nist_tag(vulnerability['classification'])
|
58
|
+
@item['code'] = ''
|
59
|
+
@item['results'] = finding(vulnerability)
|
60
|
+
|
61
|
+
controls << @item
|
62
|
+
end
|
63
|
+
controls = collapse_duplicates(controls)
|
64
|
+
results = HeimdallDataFormat.new(profile_name: 'Netsparker Enterprise Scan',
|
65
|
+
title: "Netsparker Enterprise Scan ID: #{@scan_info['scan-id']} URL: #{@scan_info['url']}",
|
66
|
+
summary: "Netsparker Enterprise Scan",
|
67
|
+
target_id: @scan_info['url'],
|
68
|
+
controls: controls)
|
69
|
+
results.to_hdf
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def parse_html(block)
|
75
|
+
block['#cdata-section'].to_s.strip unless block.nil?
|
76
|
+
end
|
77
|
+
|
78
|
+
def finding(vulnerability)
|
79
|
+
finding = {}
|
80
|
+
finding['status'] = 'failed'
|
81
|
+
finding['code_desc'] = []
|
82
|
+
finding['code_desc'] << "http-request : #{parse_html(vulnerability['http-request']['content']) }"
|
83
|
+
finding['code_desc'] << "method : #{vulnerability['http-request']['method']}"
|
84
|
+
finding['code_desc'] = finding['code_desc'].join("\n")
|
85
|
+
|
86
|
+
finding['message'] = []
|
87
|
+
finding['message'] << "http-response : #{parse_html(vulnerability['http-response']['content']) }"
|
88
|
+
finding['message'] << "duration : #{vulnerability['http-response']['duration']}"
|
89
|
+
finding['message'] << "status-code : #{vulnerability['http-response']['status-code']}"
|
90
|
+
finding['message'] = finding['message'].join("\n")
|
91
|
+
finding['run_time'] = NA_FLOAT
|
92
|
+
|
93
|
+
finding['start_time'] = @scan_info['initiated']
|
94
|
+
[finding]
|
95
|
+
end
|
96
|
+
|
97
|
+
def format_control_desc(vulnerability)
|
98
|
+
text = []
|
99
|
+
text << "#{parse_html(vulnerability['description'])}" unless vulnerability['description'].nil?
|
100
|
+
text << "Exploitation-skills: #{parse_html(vulnerability['exploitation-skills'])}" unless vulnerability['exploitation-skills'].nil?
|
101
|
+
text << "Extra-information: #{vulnerability['extra-information']}" unless vulnerability['extra-information'].nil?
|
102
|
+
text << "Classification: #{vulnerability['classification']}" unless vulnerability['classification'].nil?
|
103
|
+
text << "Impact: #{parse_html(vulnerability['impact'])}" unless vulnerability['impact'].nil?
|
104
|
+
text << "FirstSeenDate: #{vulnerability['FirstSeenDate']}" unless vulnerability['FirstSeenDate'].nil?
|
105
|
+
text << "LastSeenDate: #{vulnerability['LastSeenDate']}" unless vulnerability['LastSeenDate'].nil?
|
106
|
+
text << "Certainty: #{vulnerability['certainty']}" unless vulnerability['certainty'].nil?
|
107
|
+
text << "Type: #{vulnerability['type']}" unless vulnerability['type'].nil?
|
108
|
+
text << "Confirmed: #{vulnerability['confirmed']}" unless vulnerability['confirmed'].nil?
|
109
|
+
text.join("<br>")
|
110
|
+
end
|
111
|
+
|
112
|
+
def format_check_text(vulnerability)
|
113
|
+
text = []
|
114
|
+
text << "Exploitation-skills: #{parse_html(vulnerability['exploitation-skills'])}" unless vulnerability['exploitation-skills'].nil?
|
115
|
+
text << "Proof-of-concept: #{parse_html(vulnerability['proof-of-concept'])}" unless vulnerability['proof-of-concept'].nil?
|
116
|
+
text.join("<br>")
|
117
|
+
end
|
118
|
+
|
119
|
+
def format_fix_text(vulnerability)
|
120
|
+
text = []
|
121
|
+
text << "Remedial-actions: #{parse_html(vulnerability['remedial-actions'])}" unless vulnerability['remedial-actions'].nil?
|
122
|
+
text << "Remedial-procedure: #{parse_html(vulnerability['remedial-procedure'])}" unless vulnerability['remedial-procedure'].nil?
|
123
|
+
text << "Remedy-references: #{parse_html(vulnerability['remedy-references'])}" unless vulnerability['remedy-references'].nil?
|
124
|
+
text.join("<br>")
|
125
|
+
end
|
126
|
+
|
127
|
+
def nist_tag(classification)
|
128
|
+
tags = []
|
129
|
+
entries = @cwe_nist_mapping.select { |x| classification['cwe'].include?(x[:cweid].to_s) && !x[:nistid].nil? }
|
130
|
+
tags << entries.map { |x| x[:nistid] }
|
131
|
+
entries = @owasp_nist_mapping.select { |x| classification['owasp'].include?(x[:owaspid].to_s) && !x[:nistid].nil? }
|
132
|
+
tags << entries.map { |x| x[:nistid] }
|
133
|
+
tags.flatten.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq
|
134
|
+
end
|
135
|
+
|
136
|
+
def impact(severity)
|
137
|
+
IMPACT_MAPPING[severity.to_sym]
|
138
|
+
end
|
139
|
+
|
140
|
+
def parse_mapper(mapping_file)
|
141
|
+
csv_data = CSV.read(mapping_file, { encoding: 'UTF-8',
|
142
|
+
headers: true,
|
143
|
+
header_converters: :symbol,
|
144
|
+
converters: :all })
|
145
|
+
csv_data.map(&:to_hash)
|
146
|
+
end
|
147
|
+
|
148
|
+
def desc_tags(data, label)
|
149
|
+
{ "data": data || NA_STRING, "label": label || NA_STRING }
|
150
|
+
end
|
151
|
+
|
152
|
+
# Netsparker report could have multiple issue entries for multiple findings of same issue type.
|
153
|
+
# The meta data is identical across entries
|
154
|
+
# method collapse_duplicates return unique controls with applicable findings collapsed into it.
|
155
|
+
def collapse_duplicates(controls)
|
156
|
+
unique_controls = []
|
157
|
+
|
158
|
+
controls.map { |x| x['id'] }.uniq.each do |id|
|
159
|
+
collapsed_results = controls.select { |x| x['id'].eql?(id) }.map {|x| x['results']}
|
160
|
+
unique_control = controls.find { |x| x['id'].eql?(id) }
|
161
|
+
unique_control['results'] = collapsed_results.flatten
|
162
|
+
unique_controls << unique_control
|
163
|
+
end
|
164
|
+
unique_controls
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -71,7 +71,7 @@ module HeimdallTools
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def nist_tag(niktoid)
|
74
|
-
entries = @nikto_nist_mapping.select { |x| niktoid.eql?(x[:niktoid].to_s) }
|
74
|
+
entries = @nikto_nist_mapping.select { |x| niktoid.eql?(x[:niktoid].to_s) && !x[:nistid].nil? }
|
75
75
|
tags = entries.map { |x| x[:nistid] }
|
76
76
|
tags.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq
|
77
77
|
end
|
@@ -74,7 +74,7 @@ module HeimdallTools
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def nist_tag(cweid)
|
77
|
-
entries = @cwe_nist_mapping.select { |x| cweid.include?
|
77
|
+
entries = @cwe_nist_mapping.select { |x| cweid.include?(x[:cweid].to_s) && !x[:nistid].nil? }
|
78
78
|
tags = entries.map { |x| x[:nistid] }
|
79
79
|
tags.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq
|
80
80
|
end
|
@@ -65,7 +65,7 @@ module HeimdallTools
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def nist_tag(cweid)
|
68
|
-
entries = @cwe_nist_mapping.select { |x| x[:cweid].to_s.eql?(cweid.to_s) }
|
68
|
+
entries = @cwe_nist_mapping.select { |x| x[:cweid].to_s.eql?(cweid.to_s) && !x[:nistid].nil? }
|
69
69
|
tags = entries.map { |x| [x[:nistid], "Rev_#{x[:rev]}"] }
|
70
70
|
tags.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq
|
71
71
|
end
|
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.40
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Thew
|
@@ -10,8 +10,22 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2021-03-
|
13
|
+
date: 2021-03-16 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: aws-sdk-configservice
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - "~>"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - "~>"
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '1'
|
15
29
|
- !ruby/object:Gem::Dependency
|
16
30
|
name: nokogiri
|
17
31
|
requirement: !ruby/object:Gem::Requirement
|
@@ -181,11 +195,13 @@ files:
|
|
181
195
|
- Rakefile
|
182
196
|
- exe/heimdall_tools
|
183
197
|
- lib/data/U_CCI_List.xml
|
198
|
+
- lib/data/aws-config-mapping.csv
|
184
199
|
- lib/data/cwe-nist-mapping.csv
|
185
200
|
- lib/data/nessus-plugins-nist-mapping.csv
|
186
201
|
- lib/data/nikto-nist-mapping.csv
|
187
202
|
- lib/data/owasp-nist-mapping.csv
|
188
203
|
- lib/heimdall_tools.rb
|
204
|
+
- lib/heimdall_tools/aws_config_mapper.rb
|
189
205
|
- lib/heimdall_tools/burpsuite_mapper.rb
|
190
206
|
- lib/heimdall_tools/cli.rb
|
191
207
|
- lib/heimdall_tools/command.rb
|
@@ -193,17 +209,20 @@ files:
|
|
193
209
|
- lib/heimdall_tools/fortify_mapper.rb
|
194
210
|
- lib/heimdall_tools/hdf.rb
|
195
211
|
- lib/heimdall_tools/help.rb
|
212
|
+
- lib/heimdall_tools/help/aws_config_mapper.md
|
196
213
|
- lib/heimdall_tools/help/burpsuite_mapper.md
|
197
214
|
- lib/heimdall_tools/help/dbprotect_mapper.md
|
198
215
|
- lib/heimdall_tools/help/fortify_mapper.md
|
199
216
|
- lib/heimdall_tools/help/jfrog_xray_mapper.md
|
200
217
|
- lib/heimdall_tools/help/nessus_mapper.md
|
218
|
+
- lib/heimdall_tools/help/netsparker_mapper.md
|
201
219
|
- lib/heimdall_tools/help/nikto_mapper.md
|
202
220
|
- lib/heimdall_tools/help/snyk_mapper.md
|
203
221
|
- lib/heimdall_tools/help/sonarqube_mapper.md
|
204
222
|
- lib/heimdall_tools/help/zap_mapper.md
|
205
223
|
- lib/heimdall_tools/jfrog_xray_mapper.rb
|
206
224
|
- lib/heimdall_tools/nessus_mapper.rb
|
225
|
+
- lib/heimdall_tools/netsparker_mapper.rb
|
207
226
|
- lib/heimdall_tools/nikto_mapper.rb
|
208
227
|
- lib/heimdall_tools/snyk_mapper.rb
|
209
228
|
- lib/heimdall_tools/sonarqube_mapper.rb
|