heimdall_tools 1.3.39 → 1.3.40

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: 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