Skip to content

Commit d414c3c

Browse files
author
Devin Riley
authored
Add VRT 1.4 and handling for CWE and Remediation Advice mappings (#20)
* Add VRT 1.4 * Add remediation advice mapping * Add CWE mapping * Update Changelog * Update mapping handlings to handle multiple keys and to merge arrays * Add mapping specs and mapping fixture data
1 parent 199aecd commit d414c3c

11 files changed

Lines changed: 377 additions & 19 deletions

File tree

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313
[submodule "lib/data/1.3.1"]
1414
path = lib/data/1.3.1
1515
url = git@github.com:bugcrowd/vulnerability-rating-taxonomy.git
16+
[submodule "lib/data/1.4"]
17+
path = lib/data/1.4
18+
url = git@github.com:bugcrowd/vulnerability-rating-taxonomy.git

CHANGELOG.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
55

66
## [Unreleased]
77
### Added
8-
9-
### Removed
8+
- VRT 1.4 data
9+
- Support for mappings with `keys` metadata
10+
- CWE mapping
11+
- Bugcrowd Remediation Advice mapping
1012

1113
### Changed
14+
- Mappings with array values now caolesce downwards.
15+
Child VRT nodes will include values from parent nodes if a mapping
16+
provides node data as an array.
1217

1318
## [v0.4.6](https://github.com/bugcrowd/vrt-ruby/compare/v0.4.5...v0.4.6) - 2018-02-05
1419
### Changed

lib/data/1.4

Submodule 1.4 added at 71f76e8

lib/vrt.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module VRT
1717
'name' => 'Other',
1818
'priority' => nil,
1919
'type' => 'category' }.freeze
20-
MAPPINGS = %i[cvss_v3].freeze
20+
MAPPINGS = %i[cvss_v3 remediation_advice cwe].freeze
2121

2222
@version_json = {}
2323
@last_update = {}

lib/vrt/mapping.rb

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,25 @@ def get(id_list, version)
1414
id_list = VRT.find_node(vrt_id: id_list.join('.'), preferred_version: @min_version).id_list
1515
version = @min_version
1616
end
17-
18-
# iterate through the id components, keeping track of where we are in the mapping file
19-
# and the most specific mapped value found so far
2017
mapping = @mappings[version]['content']
21-
best_guess = @mappings[version]['metadata']['default']
22-
id_list.each do |id|
23-
entry = mapping[id]
24-
break unless entry # mapping file doesn't go this deep, return previous value
25-
best_guess = entry[@scheme] if entry[@scheme]
26-
# use the children mapping for the next iteration
27-
mapping = entry['children'] || {}
18+
default = @mappings[version]['metadata']['default']
19+
keys = @mappings[version]['metadata']['keys']
20+
if keys
21+
# Convert mappings with multiple keys to be nested under a single
22+
# top-level key. Remediation advice has keys 'remediation_advice'
23+
# and 'references' so we convert it to look like
24+
# { remediation_advice: { remediation_advice: '...', references: [...] } }
25+
keys.each_with_object({}) do |key, acc|
26+
acc[key.to_sym] = get_key(
27+
id_list: id_list,
28+
mapping: mapping,
29+
key: key,
30+
default: default&.try(:[], key)
31+
)
32+
end
33+
else
34+
get_key(id_list: id_list, mapping: mapping, key: @scheme, default: default)
2835
end
29-
best_guess
3036
end
3137

3238
private
@@ -50,14 +56,35 @@ def load_mappings
5056
# becomes
5157
# {one: {'id': 'one', 'foo': 'bar'}, two: {'id': 'two', 'foo': 'baz'}}
5258
def key_by_id(mapping)
53-
case mapping
54-
when Array
59+
if mapping.is_a?(Array) && mapping.first.is_a?(Hash) && mapping.first.key?('id')
5560
mapping.each_with_object({}) { |entry, acc| acc[entry['id'].to_sym] = key_by_id(entry) }
56-
when Hash
61+
elsif mapping.is_a?(Hash)
5762
mapping.each_with_object({}) { |(key, value), acc| acc[key] = key_by_id(value) }
5863
else
5964
mapping
6065
end
6166
end
67+
68+
def get_key(id_list:, mapping:, key:, default:)
69+
# iterate through the id components, keeping track of where we are in the mapping file
70+
# and the most specific mapped value found so far
71+
best_guess = default
72+
id_list.each do |id|
73+
entry = mapping[id]
74+
break unless entry # mapping file doesn't go this deep, return previous value
75+
best_guess = merge_arrays(best_guess, entry[key]) if entry[key]
76+
# use the children mapping for the next iteration
77+
mapping = entry['children'] || {}
78+
end
79+
best_guess
80+
end
81+
82+
def merge_arrays(previous_value, new_value)
83+
if previous_value.is_a?(Array) && new_value.is_a?(Array)
84+
new_value | previous_value
85+
else
86+
new_value
87+
end
88+
end
6289
end
6390
end
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"metadata": {
3+
"default": ["CWE-2000"]
4+
},
5+
"content": [
6+
{
7+
"id": "server_security_misconfiguration",
8+
"cwe": ["CWE-933"],
9+
"children": [
10+
{
11+
"id": "unsafe_cross_origin_resource_sharing",
12+
"cwe": ["CWE-942"]
13+
},
14+
{
15+
"id": "path_traversal",
16+
"cwe": ["CWE-22", "CWE-73"]
17+
},
18+
{
19+
"id": "directory_listing_enabled",
20+
"cwe": ["CWE-548"]
21+
},
22+
{
23+
"id": "ssl_attack_breach_poodle_etc",
24+
"cwe": ["CWE-310"]
25+
},
26+
{
27+
"id": "using_default_credentials",
28+
"cwe": ["CWE-255", "CWE-521"]
29+
},
30+
{
31+
"id": "misconfigured_dns",
32+
"children": [
33+
{
34+
"id": "zone_transfer",
35+
"cwe": ["CWE-669"]
36+
}
37+
]
38+
},
39+
{
40+
"id": "dbms_misconfiguration",
41+
"children": [
42+
{
43+
"id": "excessively_privileged_user_dba",
44+
"cwe": ["CWE-250"]
45+
}
46+
]
47+
},
48+
{
49+
"id": "lack_of_password_confirmation",
50+
"children": [
51+
{
52+
"id": "change_password",
53+
"cwe": ["CWE-620"]
54+
}
55+
]
56+
}
57+
]
58+
}
59+
]
60+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"metadata": {
3+
"default": null,
4+
"keys": ["remediation_advice", "references"]
5+
},
6+
"content": [
7+
{
8+
"id": "server_security_misconfiguration",
9+
"references": [
10+
"https://www.owasp.org/index.php/Top_10_2013-A5-Security_Misconfiguration",
11+
"http://projects.webappsec.org/w/page/13246959/Server%20Misconfiguration"
12+
],
13+
"children": [
14+
{
15+
"id": "unsafe_cross_origin_resource_sharing",
16+
"remediation_advice": "This is advice",
17+
"references": [
18+
"https://www.owasp.org/index.php/HTML5_Security_Cheat_Sheet#Cross_Origin_Resource_Sharing",
19+
"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"
20+
]
21+
},
22+
{
23+
"id": "directory_listing_enabled",
24+
"remediation_advice": "Restrict directory listings being displayed from the server configuration. \n\nExample for Apache:\n\n1. Edit the server configuration file or edit/create directory .htaccess\n2. Add the following line:\nOptions -Indexes\n3. If it is the last line, make sure you have a new line after it.",
25+
"references": [
26+
"http://projects.webappsec.org/w/page/13246922/Directory%20Indexing"
27+
]
28+
},
29+
{
30+
"id": "misconfigured_dns",
31+
"children": [
32+
{
33+
"id": "subdomain_takeover",
34+
"remediation_advice": "1. Set up your external service so it fully listens to your wildcard DNS.\n2. Keep your DNS-entries constantly vetted and restricted.",
35+
"references": [
36+
"https://labs.detectify.com/2014/10/21/hostile-subdomain-takeover-using-herokugithubdesk-more/"
37+
]
38+
},
39+
{
40+
"id": "zone_transfer",
41+
"remediation_advice": "Do not allow DNS zone transfers.",
42+
"references": [
43+
"https://www.sans.org/reading-room/whitepapers/dns/securing-dns-zone-transfer-868",
44+
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-1999-0532"
45+
]
46+
},
47+
{
48+
"id": "missing_caa_record",
49+
"remediation_advice": "As the domain name holder you can modify the DNS zone file to specify one or more Certification Authorities (CAs) authorized to issue certificates for that domain.",
50+
"references": [
51+
"https://tools.ietf.org/html/rfc6844"
52+
]
53+
}
54+
]
55+
}
56+
]
57+
}
58+
]
59+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"metadata": {
3+
"default": ["CWE-2000"]
4+
},
5+
"content": [
6+
{
7+
"id": "server_security_misconfiguration",
8+
"cwe": ["CWE-933"],
9+
"children": [
10+
{
11+
"id": "unsafe_cross_origin_resource_sharing",
12+
"cwe": ["CWE-942"]
13+
},
14+
{
15+
"id": "path_traversal",
16+
"cwe": ["CWE-22", "CWE-73"]
17+
},
18+
{
19+
"id": "directory_listing_enabled",
20+
"cwe": ["CWE-548"]
21+
},
22+
{
23+
"id": "ssl_attack_breach_poodle_etc",
24+
"cwe": ["CWE-310"]
25+
},
26+
{
27+
"id": "using_default_credentials",
28+
"cwe": ["CWE-255", "CWE-521"]
29+
},
30+
{
31+
"id": "misconfigured_dns",
32+
"children": [
33+
{
34+
"id": "zone_transfer",
35+
"cwe": ["CWE-669"]
36+
}
37+
]
38+
},
39+
{
40+
"id": "dbms_misconfiguration",
41+
"children": [
42+
{
43+
"id": "excessively_privileged_user_dba",
44+
"cwe": ["CWE-250"]
45+
}
46+
]
47+
},
48+
{
49+
"id": "lack_of_password_confirmation",
50+
"children": [
51+
{
52+
"id": "change_password",
53+
"cwe": ["CWE-620"]
54+
}
55+
]
56+
}
57+
]
58+
}
59+
]
60+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"metadata": {
3+
"default": null,
4+
"keys": ["remediation_advice", "references"]
5+
},
6+
"content": [
7+
{
8+
"id": "server_security_misconfiguration",
9+
"references": [
10+
"https://www.owasp.org/index.php/Top_10_2013-A5-Security_Misconfiguration",
11+
"http://projects.webappsec.org/w/page/13246959/Server%20Misconfiguration"
12+
],
13+
"children": [
14+
{
15+
"id": "unsafe_cross_origin_resource_sharing",
16+
"remediation_advice": "This is advice",
17+
"references": [
18+
"https://www.owasp.org/index.php/HTML5_Security_Cheat_Sheet#Cross_Origin_Resource_Sharing",
19+
"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"
20+
]
21+
},
22+
{
23+
"id": "directory_listing_enabled",
24+
"remediation_advice": "Restrict directory listings being displayed from the server configuration. \n\nExample for Apache:\n\n1. Edit the server configuration file or edit/create directory .htaccess\n2. Add the following line:\nOptions -Indexes\n3. If it is the last line, make sure you have a new line after it.",
25+
"references": [
26+
"http://projects.webappsec.org/w/page/13246922/Directory%20Indexing"
27+
]
28+
},
29+
{
30+
"id": "misconfigured_dns",
31+
"children": [
32+
{
33+
"id": "subdomain_takeover",
34+
"remediation_advice": "1. Set up your external service so it fully listens to your wildcard DNS.\n2. Keep your DNS-entries constantly vetted and restricted.",
35+
"references": [
36+
"https://labs.detectify.com/2014/10/21/hostile-subdomain-takeover-using-herokugithubdesk-more/"
37+
]
38+
},
39+
{
40+
"id": "zone_transfer",
41+
"remediation_advice": "Do not allow DNS zone transfers.",
42+
"references": [
43+
"https://www.sans.org/reading-room/whitepapers/dns/securing-dns-zone-transfer-868",
44+
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-1999-0532"
45+
]
46+
},
47+
{
48+
"id": "missing_caa_record",
49+
"remediation_advice": "As the domain name holder you can modify the DNS zone file to specify one or more Certification Authorities (CAs) authorized to issue certificates for that domain.",
50+
"references": [
51+
"https://tools.ietf.org/html/rfc6844"
52+
]
53+
}
54+
]
55+
}
56+
]
57+
}
58+
]
59+
}

0 commit comments

Comments
 (0)