heimdall_tools 1.3.32 → 1.3.33

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,4 +11,5 @@ module HeimdallTools
11
11
  autoload :BurpSuiteMapper, 'heimdall_tools/burpsuite_mapper'
12
12
  autoload :NessusMapper, 'heimdall_tools/nessus_mapper'
13
13
  autoload :SnykMapper, 'heimdall_tools/snyk_mapper'
14
+ autoload :NiktoMapper, 'heimdall_tools/nikto_mapper'
14
15
  end
@@ -61,8 +61,8 @@ module HeimdallTools
61
61
 
62
62
  end
63
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)
64
+ desc 'snyk_mapper', 'snyk_mapper translates Snyk results Json to HDF format Json be viewed on Heimdall'
65
+ long_desc Help.text(:snyk_mapper)
66
66
  option :json, required: true, aliases: '-j'
67
67
  option :output_prefix, required: true, aliases: '-o'
68
68
  option :verbose, type: :boolean, aliases: '-V'
@@ -75,6 +75,18 @@ module HeimdallTools
75
75
  end
76
76
  end
77
77
 
78
+ desc 'nikto_mapper', 'nikto_mapper translates Nikto results Json to HDF format Json be viewed on Heimdall'
79
+ long_desc Help.text(:nikto_mapper)
80
+ option :json, required: true, aliases: '-j'
81
+ option :output, required: true, aliases: '-o'
82
+ option :verbose, type: :boolean, aliases: '-V'
83
+ def nikto_mapper
84
+ hdf = HeimdallTools::NiktoMapper.new(File.read(options[:json])).to_hdf
85
+ File.write(options[:output], hdf)
86
+ puts "\r\HDF Generated:\n"
87
+ puts "#{options[:output]}"
88
+ end
89
+
78
90
  desc 'version', 'prints version'
79
91
  def version
80
92
  puts VERSION
@@ -0,0 +1,7 @@
1
+ nikto_mapper translates an Nikto results JSON file into HDF format JSON to be viewable in Heimdall
2
+
3
+ Note: Current this mapper only support single target Nikto Scans.
4
+
5
+ Examples:
6
+
7
+ heimdall_tools nikto_mapper [OPTIONS] -x <nikto-results-json> -o <hdf-scan-results.json>
@@ -0,0 +1,152 @@
1
+ require 'json'
2
+ require 'csv'
3
+ require 'heimdall_tools/hdf'
4
+
5
+ RESOURCE_DIR = Pathname.new(__FILE__).join('../../data')
6
+
7
+ NIKTO_NIST_MAPPING_FILE = File.join(RESOURCE_DIR, 'nikto-nist-mapping.csv')
8
+
9
+ IMPACT_MAPPING = {
10
+ high: 0.7,
11
+ medium: 0.5,
12
+ low: 0.3,
13
+ }.freeze
14
+
15
+ DEFAULT_NIST_TAG = ["SA-11", "RA-5"].freeze
16
+
17
+ # Loading spinner sign
18
+ $spinner = Enumerator.new do |e|
19
+ loop do
20
+ e.yield '|'
21
+ e.yield '/'
22
+ e.yield '-'
23
+ e.yield '\\'
24
+ end
25
+ end
26
+
27
+ module HeimdallTools
28
+ class NiktoMapper
29
+ def initialize(nikto_json, name=nil, verbose = false)
30
+ @nikto_json = nikto_json
31
+ @verbose = verbose
32
+
33
+ begin
34
+ @nikto_nist_mapping = parse_mapper
35
+ rescue StandardError => e
36
+ raise "Invalid Nikto to NIST mapping file: Exception: #{e}"
37
+ end
38
+
39
+ # TODO: Support Multi-target scan results
40
+ # Nikto multi-target scans generate invalid format JSONs
41
+ # Possible workaround to use https://stackoverflow.com/a/58209963/1670307
42
+
43
+ begin
44
+ @project = JSON.parse(nikto_json)
45
+ rescue StandardError => e
46
+ raise "Invalid Nikto JSON file provided Exception: #{e}"
47
+ end
48
+ end
49
+
50
+ def extract_scaninfo(project)
51
+ info = {}
52
+ begin
53
+ info['policy'] = 'Nikto Website Scanner'
54
+ info['version'] = NA_STRING
55
+ info['projectName'] = "Host: #{project['host']} Port: #{project['port']}"
56
+ info['summary'] = "Banner: #{project['banner']}"
57
+
58
+ info
59
+ rescue StandardError => e
60
+ raise "Error extracting project info from nikto JSON file provided Exception: #{e}"
61
+ end
62
+ end
63
+
64
+ def finding(vulnerability)
65
+ finding = {}
66
+ finding['status'] = 'failed'
67
+ finding['code_desc'] = "URL : #{vulnerability['url'].to_s } Method: #{vulnerability['method'].to_s}"
68
+ finding['run_time'] = NA_FLOAT
69
+
70
+ # Nikto results JSON does not profile scan timestamp; using current time to satisfy HDF format
71
+ finding['start_time'] = NA_STRING
72
+ [finding]
73
+ end
74
+
75
+ def nist_tag(niktoid)
76
+ entries = @nikto_nist_mapping.select { |x| niktoid.eql?(x[:niktoid].to_s) }
77
+ tags = entries.map { |x| x[:nistid] }
78
+ tags.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq
79
+ end
80
+
81
+ def impact(severity)
82
+ IMPACT_MAPPING[severity.to_sym]
83
+ end
84
+
85
+ def parse_mapper
86
+ csv_data = CSV.read(NIKTO_NIST_MAPPING_FILE, **{ encoding: 'UTF-8',
87
+ headers: true,
88
+ header_converters: :symbol})
89
+ csv_data.map(&:to_hash)
90
+ end
91
+
92
+ def desc_tags(data, label)
93
+ { "data": data || NA_STRING, "label": label || NA_STRING }
94
+ end
95
+
96
+ # Nikto report could have multiple vulnerability entries for multiple findings of same issue type.
97
+ # The meta data is identical across entries
98
+ # method collapse_duplicates return unique controls with applicable findings collapsed into it.
99
+ def collapse_duplicates(controls)
100
+ unique_controls = []
101
+
102
+ controls.map { |x| x['id'] }.uniq.each do |id|
103
+ collapsed_results = controls.select { |x| x['id'].eql?(id) }.map {|x| x['results']}
104
+ unique_control = controls.find { |x| x['id'].eql?(id) }
105
+ unique_control['results'] = collapsed_results.flatten
106
+ unique_controls << unique_control
107
+ end
108
+ unique_controls
109
+ end
110
+
111
+
112
+ def to_hdf
113
+ controls = []
114
+ @project['vulnerabilities'].each do | vulnerability |
115
+ printf("\rProcessing: %s", $spinner.next)
116
+
117
+ item = {}
118
+ item['tags'] = {}
119
+ item['descriptions'] = []
120
+ item['refs'] = NA_ARRAY
121
+ item['source_location'] = NA_HASH
122
+ item['descriptions'] = NA_ARRAY
123
+
124
+ item['title'] = vulnerability['msg'].to_s
125
+ item['id'] = vulnerability['id'].to_s
126
+
127
+ # Nikto results JSON does not description fields
128
+ # Duplicating vulnerability msg field
129
+ item['desc'] = vulnerability['msg'].to_s
130
+
131
+ # Nitko does not provide finding severity; hard-coding severity to medium
132
+ item['impact'] = impact('medium')
133
+ item['code'] = NA_STRING
134
+ item['results'] = finding(vulnerability)
135
+ item['tags']['nist'] = nist_tag( vulnerability['id'].to_s )
136
+ item['tags']['ösvdb'] = vulnerability['OSVDB']
137
+
138
+ controls << item
139
+ end
140
+
141
+ controls = collapse_duplicates(controls)
142
+ scaninfo = extract_scaninfo(@project)
143
+ results = HeimdallDataFormat.new(profile_name: scaninfo['policy'],
144
+ version: scaninfo['version'],
145
+ title: "Nikto Target: #{scaninfo['projectName']}",
146
+ summary: "Banner: #{scaninfo['summary']}",
147
+ controls: controls,
148
+ target_id: scaninfo['projectName'])
149
+ results.to_hdf
150
+ end
151
+ end
152
+ 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.32
4
+ version: 1.3.33
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-07-28 00:00:00.000000000 Z
13
+ date: 2020-08-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: nokogiri
@@ -211,6 +211,7 @@ files:
211
211
  - lib/data/U_CCI_List.xml
212
212
  - lib/data/cwe-nist-mapping.csv
213
213
  - lib/data/nessus-plugins-nist-mapping.csv
214
+ - lib/data/nikto-nist-mapping.csv
214
215
  - lib/data/owasp-nist-mapping.csv
215
216
  - lib/heimdall_tools.rb
216
217
  - lib/heimdall_tools/burpsuite_mapper.rb
@@ -222,10 +223,12 @@ files:
222
223
  - lib/heimdall_tools/help/burpsuite_mapper.md
223
224
  - lib/heimdall_tools/help/fortify_mapper.md
224
225
  - lib/heimdall_tools/help/nessus_mapper.md
226
+ - lib/heimdall_tools/help/nikto_mapper.md
225
227
  - lib/heimdall_tools/help/snyk_mapper.md
226
228
  - lib/heimdall_tools/help/sonarqube_mapper.md
227
229
  - lib/heimdall_tools/help/zap_mapper.md
228
230
  - lib/heimdall_tools/nessus_mapper.rb
231
+ - lib/heimdall_tools/nikto_mapper.rb
229
232
  - lib/heimdall_tools/snyk_mapper.rb
230
233
  - lib/heimdall_tools/sonarqube_mapper.rb
231
234
  - lib/heimdall_tools/version.rb