heimdall_tools 1.3.27 → 1.3.32

Sign up to get free protection for your applications and to get access to all the features.
@@ -46,6 +46,7 @@
46
46
  170, Improper Null Termination,SI-10,4,Information Input Validation
47
47
  176, Improper Handling of Unicode Encoding,,4,
48
48
  185, Incorrect Regular Expression,,4,
49
+ 189, Numeric Errors,SA-11,4,Developer Security Testing and Evaluation
49
50
  190, Integer Overflow or Wraparound,SI-10,4,Information Input Validation
50
51
  195, Signed to Unsigned Conversion Error,,4,
51
52
  200, Information Exposure,SC-8,4,Transmission Confidentiality and Integrity
@@ -79,6 +80,7 @@
79
80
  305, Authentication Bypass by Primary Weakness,IA-8,4,Identification and Authentication (Non-Organizational Users)
80
81
  306, Missing Authentication for Critical Function,AC-3,4,Access Enforcement
81
82
  307, Improper Restriction of Excessive Authentication Attempts,AC-7,4,Unsuccessful Logon Attempts
83
+ 310, Cryptographic Issues,SC-13,4,Cryptographic Protection
82
84
  311, Missing Encryption of Sensitive Data,SC-8,4,Transmission Confidentiality and Integrity
83
85
  321, Use of Hard-coded Cryptographic Key,SC-12,4,Cryptographic Key Establishment and Management
84
86
  325, Missing Required Cryptographic Step,SC-13,4,Cryptographic Protection
@@ -113,15 +115,16 @@
113
115
  401, Improper Release of Memory Before Removing Last Reference,,4,
114
116
  404, Improper Resource Shutdown or Release,,4,
115
117
  415, Double Free,,4,
116
- 416, Use after Free,,4,
118
+ 416, Use after Free,SC-4,4,Information in Shared Resources
117
119
  434, Unrestricted Upload of File with Dangerous Type,AC-6,4,Least Privilege: Privilege Levels for Code Execution
120
+ 444, Inconsistent Interpretation of HTTP Requests ('HTTP Request Smuggling'),SI-10,4,Information Input Validation
118
121
  457, Use of Uninitialized Variable,,4,
119
122
  466, Return of Pointer Value Outside of Expected Range,,4,
120
123
  470, Use of Externally-Controlled Input to Select Classes or Code ('Unsafe Reflection'),SI-10,4,Information Input Validation
121
124
  471, Modification of Assumed-Immutable DATA (MAID),AC-3,4,Access Enforcement
122
125
  474, Use of Function with Inconsistent Implementations,,4,
123
126
  475, Undefined Behavior for Input to API,,4,
124
- 476, NULL Pointer Dereference,,4,
127
+ 476, NULL Pointer Dereference,SI-10,4,Information Input Validation
125
128
  477, Use of Obsolete Functions,,4,
126
129
  478, Missing Default Case in Switch Statement,,4,
127
130
  492, Use of Inner Class Containing Sensitive Data,AC-3,4,Access Enforcement
@@ -130,6 +133,7 @@
130
133
  495, Private Array-Typed Field Returned From A Public Method,AC-3,4,Access Enforcement
131
134
  497, Exposure of System Data to an Unauthorized Control Sphere,SI-11,4,Error Handling
132
135
  501, Trust Boundary Violation,SI-10,4,Information Input Validation
136
+ 502, Deserialization of Untrusted Data,SI-10,4,Information Input Validation
133
137
  521, Weak Password Requirements,IA-5,4,Authenticator Management : -1 Password-based Authentication
134
138
  522, Insufficiently Protected Credentials,SC-8,4,Transmission Confidentiality and Integrity
135
139
  539, Information Exposure Through Persistent Cookies,SC-23,4,Session Authenticity
@@ -159,7 +163,7 @@
159
163
  601, URL Redirection to Untrusted Site ('Open Redirect'),SI-10,4,Information Input Validation
160
164
  607, Public Static Final Field References Mutable Object,,4,
161
165
  609, Double-Checked Locking,,4,
162
- 611, Improper Restriction of XML External Entity Reference ('XXE'),,4,
166
+ 611, Improper Restriction of XML External Entity Reference ('XXE'),SI-10,4,Information Input Validation
163
167
  613, Insufficient Session Expiration,AC-12,4,Session Termination
164
168
  614, Sensitive Cookie in HTTPS Session Without 'Secure' Attribute,SC-8,4,Transmission Confidentiality and Integrity
165
169
  615, Information Exposure Through Comments,AC-3,4,Access Enforcement : -5 Security-Relevant Information
@@ -192,4 +196,4 @@
192
196
  863, Incorrect Authorization,AC-3,4,Access Enforcement
193
197
  915, Improperly Controlled Modification of Dynamically-Determined Object Attributes,SI-10,4,Information Input Validation
194
198
  916, Use of Password Hash With Insufficient Computational Effort,SC-13,4,Cryptographic Protection
195
- 918, Server-Side Request Forgery (SSRF),SI-10,4,Information Input Validation
199
+ 918, Server-Side Request Forgery (SSRF),SI-10,4,Information Input Validation
@@ -10,4 +10,5 @@ module HeimdallTools
10
10
  autoload :SonarQubeMapper, 'heimdall_tools/sonarqube_mapper'
11
11
  autoload :BurpSuiteMapper, 'heimdall_tools/burpsuite_mapper'
12
12
  autoload :NessusMapper, 'heimdall_tools/nessus_mapper'
13
+ autoload :SnykMapper, 'heimdall_tools/snyk_mapper'
13
14
  end
@@ -53,13 +53,28 @@ module HeimdallTools
53
53
  def nessus_mapper
54
54
  hdfs = HeimdallTools::NessusMapper.new(File.read(options[:xml])).to_hdf
55
55
 
56
+ puts "\nHDF Generated:"
56
57
  hdfs.keys.each do | host |
57
58
  File.write("#{options[:output_prefix]}-#{host}.json", hdfs[host])
58
- puts "HDF Generated: #{options[:output_prefix]}-#{host}.json"
59
+ puts "#{options[:output_prefix]}-#{host}.json"
59
60
  end
60
61
 
61
62
  end
62
63
 
64
+ desc 'snyk_mapper', 'snyk_mapper translates Synk results Json to HDF format Json be viewed on Heimdall'
65
+ long_desc Help.text(:fortify_mapper)
66
+ option :json, required: true, aliases: '-j'
67
+ option :output_prefix, required: true, aliases: '-o'
68
+ option :verbose, type: :boolean, aliases: '-V'
69
+ def snyk_mapper
70
+ hdfs = HeimdallTools::SnykMapper.new(File.read(options[:json]), options[:name]).to_hdf
71
+ puts "\r\HDF Generated:\n"
72
+ hdfs.keys.each do | host |
73
+ File.write("#{options[:output_prefix]}-#{host}.json", hdfs[host])
74
+ puts "#{options[:output_prefix]}-#{host}.json"
75
+ end
76
+ end
77
+
63
78
  desc 'version', 'prints version'
64
79
  def version
65
80
  puts VERSION
@@ -0,0 +1,7 @@
1
+ snyk_mapper translates an Snyk results JSON file into HDF format json to be viewable in Heimdall
2
+
3
+ A separate HDF JSON is generated for each project reported in the Snyk Report.
4
+
5
+ Examples:
6
+
7
+ heimdall_tools snyk_mapper -j snyk_results.json -o output-file-prefix
@@ -2,10 +2,12 @@ require 'json'
2
2
  require 'csv'
3
3
  require 'heimdall_tools/hdf'
4
4
  require 'utilities/xml_to_hash'
5
+ require 'nokogiri'
5
6
 
6
7
  RESOURCE_DIR = Pathname.new(__FILE__).join('../../data')
7
8
 
8
9
  NESSUS_PLUGINS_NIST_MAPPING_FILE = File.join(RESOURCE_DIR, 'nessus-plugins-nist-mapping.csv')
10
+ U_CCI_LIST = File.join(RESOURCE_DIR, 'U_CCI_List.xml')
9
11
 
10
12
  IMPACT_MAPPING = {
11
13
  Info: 0.0,
@@ -17,20 +19,33 @@ IMPACT_MAPPING = {
17
19
 
18
20
  DEFAULT_NIST_TAG = ["unmapped"].freeze
19
21
 
22
+ # Nessus results file 800-53 refs does not contain Nist rev version. Using this default
23
+ # version in that case
24
+ DEFAULT_NIST_REV = 'Rev_4'.freeze
25
+
20
26
  NA_PLUGIN_OUTPUT = "This Nessus Plugin does not provide output message.".freeze
21
27
 
22
28
  # rubocop:disable Metrics/AbcSize
23
29
 
30
+ # Loading spinner sign
31
+ $spinner = Enumerator.new do |e|
32
+ loop do
33
+ e.yield '|'
34
+ e.yield '/'
35
+ e.yield '-'
36
+ e.yield '\\'
37
+ end
38
+ end
39
+
24
40
  module HeimdallTools
25
41
  class NessusMapper
26
42
  def initialize(nessus_xml, verbose = false)
27
43
  @nessus_xml = nessus_xml
28
44
  @verbose = verbose
29
-
45
+ read_cci_xml
30
46
  begin
31
47
  @cwe_nist_mapping = parse_mapper
32
48
  @data = xml_to_hash(nessus_xml)
33
-
34
49
  @reports = extract_report
35
50
  @scaninfo = extract_scaninfo
36
51
  rescue StandardError => e
@@ -51,6 +66,10 @@ module HeimdallTools
51
66
  end
52
67
  end
53
68
 
69
+ def parse_refs(refs, key)
70
+ refs.split(',').map { |x| x.split('|')[1] if x.include?(key) }.compact
71
+ end
72
+
54
73
  def extract_scaninfo
55
74
  begin
56
75
  policy = @data['NessusClientData_v2']['Policy']
@@ -82,28 +101,60 @@ module HeimdallTools
82
101
 
83
102
  def finding(issue, timestamp)
84
103
  finding = {}
85
- finding['status'] = 'failed'
86
- finding['code_desc'] = issue['plugin_output'] || NA_PLUGIN_OUTPUT
104
+ # if compliance-result field, this is a policy compliance result entry
105
+ # nessus policy compliance result provides a pass/fail data
106
+ # For non policy compliance results are defaulted to failed
107
+ if issue['compliance-result']
108
+ finding['status'] = issue['compliance-result'].eql?('PASSED') ? 'passed' : 'failed'
109
+ else
110
+ finding['status'] = 'failed'
111
+ end
112
+
113
+ if issue['description']
114
+ finding['code_desc'] = issue['description'].to_s || NA_PLUGIN_OUTPUT
115
+ else
116
+ finding['code_desc'] = issue['plugin_output'] || NA_PLUGIN_OUTPUT
117
+ end
87
118
  finding['run_time'] = NA_FLOAT
88
119
  finding['start_time'] = timestamp
89
120
  [finding]
90
121
  end
91
122
 
92
- def nist_tag(pluginfamily, pluginid)
123
+ def read_cci_xml
124
+ @cci_xml = Nokogiri::XML(File.open(U_CCI_LIST))
125
+ @cci_xml.remove_namespaces!
126
+ rescue StandardError => e
127
+ puts "Exception: #{e.message}"
128
+ end
129
+
130
+ def cci_nist_tag(cci_refs)
131
+ nist_tags = []
132
+ cci_refs.each do | cci_ref |
133
+ item_node = @cci_xml.xpath("//cci_list/cci_items/cci_item[@id='#{cci_ref}']")[0] unless @cci_xml.nil?
134
+ unless item_node.nil?
135
+ nist_ref = item_node.xpath('./references/reference[not(@version <= preceding-sibling::reference/@version) and not(@version <=following-sibling::reference/@version)]/@index').text
136
+ end
137
+ nist_tags << nist_ref
138
+ end
139
+ nist_tags
140
+ end
141
+
142
+ def plugin_nist_tag(pluginfamily, pluginid)
93
143
  entries = @cwe_nist_mapping.select { |x| (x[:pluginfamily].eql?(pluginfamily) && (x[:pluginid].eql?('*') || x[:pluginid].eql?(pluginid.to_i)) ) }
94
144
  tags = entries.map { |x| [x[:nistid].split('|'), "Rev_#{x[:rev]}"] }
95
145
  tags.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq
96
146
  end
97
147
 
98
148
  def impact(severity)
149
+ # Map CAT levels and Plugin severity to HDF impact levels
99
150
  case severity
100
151
  when "0"
101
152
  IMPACT_MAPPING[:Info]
102
- when "1"
153
+ when "1","III"
103
154
  IMPACT_MAPPING[:Low]
104
- when "2"
155
+ when "2","II"
105
156
  IMPACT_MAPPING[:Medium]
106
- when "3"
157
+ when "3","I"
107
158
  IMPACT_MAPPING[:High]
108
159
  when "4"
109
160
  IMPACT_MAPPING[:Critical]
@@ -142,21 +193,48 @@ module HeimdallTools
142
193
  def to_hdf
143
194
  host_results = {}
144
195
  @reports.each do | report|
145
- # Under current version of the converter `Policy Compliance` items are ignored
146
- report_items = report['ReportItem'].select {|x| !x['pluginFamily'].eql? 'Policy Compliance'}
147
-
148
196
  controls = []
149
- report_items.each do | item |
197
+ report['ReportItem'].each do | item |
198
+ printf("\rProcessing: %s", $spinner.next)
150
199
  @item = {}
151
- @item['id'] = item['pluginID'].to_s
152
- @item['title'] = item['pluginName'].to_s
153
- @item['desc'] = format_desc(item).to_s
154
- @item['impact'] = impact(item['severity'])
155
200
  @item['tags'] = {}
156
201
  @item['descriptions'] = []
157
202
  @item['refs'] = NA_ARRAY
158
203
  @item['source_location'] = NA_HASH
159
- @item['tags']['nist'] = nist_tag(item['pluginFamily'],item['pluginID'])
204
+
205
+ # Nessus results field set are different for 'Policy Compliance' plug-in family vs other plug-in families
206
+ # Following if conditions capture compliance* if it exists else it will default to plugin* fields
207
+ # Current version covers STIG based 'Policy Compliance' results
208
+ # TODO Cover cases for 'Policy Compliance' results based on CIS
209
+ if item['compliance-reference']
210
+ @item['id'] = parse_refs(item['compliance-reference'],'Vuln-ID').join.to_s
211
+ else
212
+ @item['id'] = item['pluginID'].to_s
213
+ end
214
+ if item['compliance-check-name']
215
+ @item['title'] = item['compliance-check-name'].to_s
216
+ else
217
+ @item['title'] = item['pluginName'].to_s
218
+ end
219
+ if item['compliance-info']
220
+ @item['desc'] = item['compliance-info'].to_s
221
+ else
222
+ @item['desc'] = format_desc(item).to_s
223
+ end
224
+ if item['compliance-reference']
225
+ @item['impact'] = impact(parse_refs(item['compliance-reference'],'CAT').join.to_s)
226
+ else
227
+ @item['impact'] = impact(item['severity'])
228
+ end
229
+ if item['compliance-reference']
230
+ @item['tags']['nist'] = cci_nist_tag(parse_refs(item['compliance-reference'],'CCI'))
231
+ else
232
+ @item['tags']['nist'] = plugin_nist_tag(item['pluginFamily'],item['pluginID'])
233
+ end
234
+ if item['compliance-solution']
235
+ @item['descriptions'] << desc_tags(item['compliance-solution'], 'check')
236
+ end
237
+
160
238
  @item['code'] = ''
161
239
  @item['results'] = finding(item, extract_timestamp(report))
162
240
  controls << @item
@@ -0,0 +1,161 @@
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
+
10
+ IMPACT_MAPPING = {
11
+ high: 0.7,
12
+ medium: 0.5,
13
+ low: 0.3,
14
+ }.freeze
15
+
16
+ SNYK_VERSION_REGEX = 'v(\d+.)(\d+.)(\d+)'.freeze
17
+
18
+ DEFAULT_NIST_TAG = ["SA-11", "RA-5"].freeze
19
+
20
+ # Loading spinner sign
21
+ $spinner = Enumerator.new do |e|
22
+ loop do
23
+ e.yield '|'
24
+ e.yield '/'
25
+ e.yield '-'
26
+ e.yield '\\'
27
+ end
28
+ end
29
+
30
+ module HeimdallTools
31
+ class SnykMapper
32
+ def initialize(synk_json, name=nil, verbose = false)
33
+ @synk_json = synk_json
34
+ @verbose = verbose
35
+
36
+ begin
37
+ @cwe_nist_mapping = parse_mapper
38
+ @projects = JSON.parse(synk_json)
39
+
40
+ # Cover single and multi-project scan use cases.
41
+ unless @projects.kind_of?(Array)
42
+ @projects = [ @projects ]
43
+ end
44
+
45
+ rescue StandardError => e
46
+ raise "Invalid Snyk JSON file provided Exception: #{e}"
47
+ end
48
+ end
49
+
50
+ def extract_scaninfo(project)
51
+ info = {}
52
+ begin
53
+ info['policy'] = project['policy']
54
+ reg = Regexp.new(SNYK_VERSION_REGEX, Regexp::IGNORECASE)
55
+ info['version'] = info['policy'].scan(reg).join
56
+ info['projectName'] = project['projectName']
57
+ info['summary'] = project['summary']
58
+
59
+ info
60
+ rescue StandardError => e
61
+ raise "Error extracting project info from Synk JSON file provided Exception: #{e}"
62
+ end
63
+ end
64
+
65
+ def finding(vulnerability)
66
+ finding = {}
67
+ finding['status'] = 'failed'
68
+ finding['code_desc'] = "From : [ #{vulnerability['from'].join(" , ").to_s } ]"
69
+ finding['run_time'] = NA_FLOAT
70
+
71
+ # Snyk results does not profile scan timestamp; using current time to satisfy HDF format
72
+ finding['start_time'] = NA_STRING
73
+ [finding]
74
+ end
75
+
76
+ def nist_tag(cweid)
77
+ entries = @cwe_nist_mapping.select { |x| cweid.include? x[:cweid].to_s }
78
+ tags = entries.map { |x| x[:nistid] }
79
+ tags.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq
80
+ end
81
+
82
+ def parse_identifiers(vulnerability, ref)
83
+ # Extracting id number from reference style CWE-297
84
+ vulnerability['identifiers'][ref].map { |e| e.split("#{ref}-")[1] }
85
+ rescue
86
+ return []
87
+ end
88
+
89
+ def impact(severity)
90
+ IMPACT_MAPPING[severity.to_sym]
91
+ end
92
+
93
+ def parse_mapper
94
+ csv_data = CSV.read(CWE_NIST_MAPPING_FILE, **{ encoding: 'UTF-8',
95
+ headers: true,
96
+ header_converters: :symbol,
97
+ converters: :all })
98
+ csv_data.map(&:to_hash)
99
+ end
100
+
101
+ def desc_tags(data, label)
102
+ { "data": data || NA_STRING, "label": label || NA_STRING }
103
+ end
104
+
105
+ # Snyk report could have multiple vulnerability entries for multiple findings of same issue type.
106
+ # The meta data is identical across entries
107
+ # method collapse_duplicates return unique controls with applicable findings collapsed into it.
108
+ def collapse_duplicates(controls)
109
+ unique_controls = []
110
+
111
+ controls.map { |x| x['id'] }.uniq.each do |id|
112
+ collapsed_results = controls.select { |x| x['id'].eql?(id) }.map {|x| x['results']}
113
+ unique_control = controls.find { |x| x['id'].eql?(id) }
114
+ unique_control['results'] = collapsed_results.flatten
115
+ unique_controls << unique_control
116
+ end
117
+ unique_controls
118
+ end
119
+
120
+
121
+ def to_hdf
122
+ project_results = {}
123
+ @projects.each do | project |
124
+ controls = []
125
+ project['vulnerabilities'].each do | vulnerability |
126
+ printf("\rProcessing: %s", $spinner.next)
127
+
128
+ item = {}
129
+ item['tags'] = {}
130
+ item['descriptions'] = []
131
+ item['refs'] = NA_ARRAY
132
+ item['source_location'] = NA_HASH
133
+ item['descriptions'] = NA_ARRAY
134
+
135
+ item['title'] = vulnerability['title'].to_s
136
+ item['id'] = vulnerability['id'].to_s
137
+ item['desc'] = vulnerability['description'].to_s
138
+ item['impact'] = impact(vulnerability['severity'])
139
+ item['code'] = ''
140
+ item['results'] = finding(vulnerability)
141
+ item['tags']['nist'] = nist_tag( parse_identifiers( vulnerability, 'CWE') )
142
+ item['tags']['cweid'] = parse_identifiers( vulnerability, 'CWE')
143
+ item['tags']['cveid'] = parse_identifiers( vulnerability, 'CVE')
144
+ item['tags']['ghsaid'] = parse_identifiers( vulnerability, 'GHSA')
145
+
146
+ controls << item
147
+ end
148
+ controls = collapse_duplicates(controls)
149
+ scaninfo = extract_scaninfo(project)
150
+ results = HeimdallDataFormat.new(profile_name: scaninfo['policy'],
151
+ version: scaninfo['version'],
152
+ title: "Snyk Project: #{scaninfo['projectName']}",
153
+ summary: "Snyk Summary: #{scaninfo['summary']}",
154
+ controls: controls,
155
+ target_id: scaninfo['projectName'])
156
+ project_results[scaninfo['projectName']] = results.to_hdf
157
+ end
158
+ project_results
159
+ end
160
+ end
161
+ 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.27
4
+ version: 1.3.32
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: 2020-05-22 00:00:00.000000000 Z
13
+ date: 2020-07-28 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: nokogiri
@@ -203,14 +203,13 @@ executables:
203
203
  extensions: []
204
204
  extra_rdoc_files: []
205
205
  files:
206
- - CHANGELOG.md
207
206
  - Guardfile
208
207
  - LICENSE.md
209
208
  - README.md
210
209
  - Rakefile
211
210
  - exe/heimdall_tools
211
+ - lib/data/U_CCI_List.xml
212
212
  - lib/data/cwe-nist-mapping.csv
213
- - lib/data/gitkeep
214
213
  - lib/data/nessus-plugins-nist-mapping.csv
215
214
  - lib/data/owasp-nist-mapping.csv
216
215
  - lib/heimdall_tools.rb
@@ -223,9 +222,11 @@ files:
223
222
  - lib/heimdall_tools/help/burpsuite_mapper.md
224
223
  - lib/heimdall_tools/help/fortify_mapper.md
225
224
  - lib/heimdall_tools/help/nessus_mapper.md
225
+ - lib/heimdall_tools/help/snyk_mapper.md
226
226
  - lib/heimdall_tools/help/sonarqube_mapper.md
227
227
  - lib/heimdall_tools/help/zap_mapper.md
228
228
  - lib/heimdall_tools/nessus_mapper.rb
229
+ - lib/heimdall_tools/snyk_mapper.rb
229
230
  - lib/heimdall_tools/sonarqube_mapper.rb
230
231
  - lib/heimdall_tools/version.rb
231
232
  - lib/heimdall_tools/zap_mapper.rb