heimdall_tools 1.3.39 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f629e9d519b119329b6bfd8a8eeb7826420262f654cbe127e6efe05b88fc9ac3
4
- data.tar.gz: 1d66b4d6505221cbd2fbb06dc4d856c179d8db11566148386b2f67bd0110e851
3
+ metadata.gz: 1a306a3ebf9a2755760b9cc825f1123a62291723d92d215c03d3e9d958d22497
4
+ data.tar.gz: 5e551876a20872c32126a6c96d08e3c6cd6acdf73bc31abf1ba918693764d4e9
5
5
  SHA512:
6
- metadata.gz: 6f7898ac0e5b94f3efaeda24117c4f8ff6dc06bf1140786d6c99eccffbdc1fa9792c93eda05847c7e6a9a1d2e5d70596a486ba4fe53bc931eace7bb6dff45146
7
- data.tar.gz: 34b4302cae0fad8bcec837e2b81df578aade9e3850a1040a0cadf1510e57078a7f110bdae8c74fd4974bec079b7c9115f1ff573536a32221936ba93e4eaf9280
6
+ metadata.gz: 4ed8a026a5fbbd63d3da4ebb4211d8ee8cc371ae29e57f4deb10f9e188491af29b2988e17524aa5ab4c064f62a44349edfa9b626641c89d6a958ff040df39e40
7
+ data.tar.gz: 2874bbd8f062e601ed1fb65b53ec53ee5267d7c17457cef91f936dd28936bac6f35b4387c3d452c301c593cdb13e01ea6d587c1885a88b1a6f025ac3ee38bdaa
data/README.md CHANGED
@@ -15,6 +15,7 @@ HeimdallTools supplies several methods to convert output from various tools to "
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
+ - **netsparker_mapper** - web application security scanner
18
19
 
19
20
  Ruby 2.4 or higher (check using "ruby -v")
20
21
 
@@ -234,6 +235,23 @@ FLAGS:
234
235
  example: heimdall_tools aws_config_mapper -o aws_config_results_hdf.json
235
236
  ```
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
+
237
255
  ## version
238
256
 
239
257
  Prints out the gem version
@@ -15,4 +15,5 @@ module HeimdallTools
15
15
  autoload :JfrogXrayMapper, 'heimdall_tools/jfrog_xray_mapper'
16
16
  autoload :DBProtectMapper, 'heimdall_tools/dbprotect_mapper'
17
17
  autoload :AwsConfigMapper, 'heimdall_tools/aws_config_mapper'
18
+ autoload :NetsparkerMapper, 'heimdall_tools/netsparker_mapper'
18
19
  end
@@ -122,6 +122,18 @@ module HeimdallTools
122
122
  puts "\r\HDF Generated:\n"
123
123
  puts "#{options[:output]}"
124
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
125
137
 
126
138
  desc 'version', 'prints version'
127
139
  def version
@@ -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,6 +57,14 @@ 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
69
  entries = @cwe_nist_mapping.select { |x| cweid.include?(x[:cweid].to_s) && !x[:nistid].nil? }
62
70
  tags = entries.map { |x| x[:nistid] }
@@ -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['component_versions']['more_details']['description'].to_s
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)
@@ -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
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.39
4
+ version: 1.3.40
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-03-11 00:00:00.000000000 Z
13
+ date: 2021-03-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: aws-sdk-configservice
@@ -215,12 +215,14 @@ files:
215
215
  - lib/heimdall_tools/help/fortify_mapper.md
216
216
  - lib/heimdall_tools/help/jfrog_xray_mapper.md
217
217
  - lib/heimdall_tools/help/nessus_mapper.md
218
+ - lib/heimdall_tools/help/netsparker_mapper.md
218
219
  - lib/heimdall_tools/help/nikto_mapper.md
219
220
  - lib/heimdall_tools/help/snyk_mapper.md
220
221
  - lib/heimdall_tools/help/sonarqube_mapper.md
221
222
  - lib/heimdall_tools/help/zap_mapper.md
222
223
  - lib/heimdall_tools/jfrog_xray_mapper.rb
223
224
  - lib/heimdall_tools/nessus_mapper.rb
225
+ - lib/heimdall_tools/netsparker_mapper.rb
224
226
  - lib/heimdall_tools/nikto_mapper.rb
225
227
  - lib/heimdall_tools/snyk_mapper.rb
226
228
  - lib/heimdall_tools/sonarqube_mapper.rb