ruby-nessus2 2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.drone.yml +51 -0
  3. data/.gitignore +5 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +4 -0
  6. data/.rubocop_todo.yml +124 -0
  7. data/.travis.yml +13 -0
  8. data/.yardopts +1 -0
  9. data/Gemfile +6 -0
  10. data/Gemfile.lock +75 -0
  11. data/LICENSE.txt +20 -0
  12. data/README.md +181 -0
  13. data/Rakefile +21 -0
  14. data/bin/recess +10 -0
  15. data/examples/example.rb +46 -0
  16. data/examples/example_bid.rb +28 -0
  17. data/examples/example_cpe.rb +28 -0
  18. data/examples/example_cve.rb +36 -0
  19. data/examples/example_v1.nessus +1 -0
  20. data/examples/example_v2.nessus +2076 -0
  21. data/examples/example_v3.nessus +7449 -0
  22. data/lib/ruby-nessus.rb +5 -0
  23. data/lib/ruby-nessus/cli.rb +126 -0
  24. data/lib/ruby-nessus/log.rb +84 -0
  25. data/lib/ruby-nessus/parse.rb +46 -0
  26. data/lib/ruby-nessus/ruby-nessus.rb +6 -0
  27. data/lib/ruby-nessus/version.rb +5 -0
  28. data/lib/ruby-nessus/version1/event.rb +85 -0
  29. data/lib/ruby-nessus/version1/host.rb +267 -0
  30. data/lib/ruby-nessus/version1/port.rb +84 -0
  31. data/lib/ruby-nessus/version1/scan.rb +404 -0
  32. data/lib/ruby-nessus/version2/event.rb +410 -0
  33. data/lib/ruby-nessus/version2/host.rb +522 -0
  34. data/lib/ruby-nessus/version2/port.rb +75 -0
  35. data/lib/ruby-nessus/version2/scan.rb +393 -0
  36. data/ruby-nessus.gemspec +28 -0
  37. data/spec/ruby-nessus/parse_spec.rb +40 -0
  38. data/spec/ruby-nessus/version1/event_spec.rb +69 -0
  39. data/spec/ruby-nessus/version1/host_spec.rb +75 -0
  40. data/spec/ruby-nessus/version1/scan_spec.rb +97 -0
  41. data/spec/ruby-nessus/version2/event_spec.rb +225 -0
  42. data/spec/ruby-nessus/version2/host_spec.rb +148 -0
  43. data/spec/ruby-nessus/version2/scan_spec.rb +96 -0
  44. data/spec/ruby-nessus/version_spec.rb +11 -0
  45. data/spec/spec_fixtures/example_v1.nessus +1 -0
  46. data/spec/spec_fixtures/example_v2.nessus +2080 -0
  47. data/spec/spec_fixtures/example_v_wrong.nessus +3 -0
  48. data/spec/spec_fixtures/xml.rb +15 -0
  49. data/spec/spec_helper.rb +7 -0
  50. metadata +190 -0
@@ -0,0 +1,410 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ruby-nessus/version2/port'
4
+
5
+ module RubyNessus
6
+ module Version2
7
+ class Event
8
+ def initialize(event)
9
+ @event = event
10
+ end
11
+
12
+ #
13
+ # Return the event port.
14
+ #
15
+ # @return [Object]
16
+ # Return the event port object or port string.
17
+ #
18
+ # @example
19
+ # event.port #=> "https (443/tcp)"
20
+ # event.port.number #=> 443
21
+ # event.port.service #=> "https"
22
+ # event.port.protocol #=> "tcp"
23
+ #
24
+ def port
25
+ @port ||= Port.new(@event.at('@port'), @event.at('@svc_name'), @event.at('@protocol'))
26
+ end
27
+
28
+ #
29
+ # Return the event severity.
30
+ #
31
+ # @return [Integer]
32
+ # Return the event severity.
33
+ #
34
+ # @example
35
+ # event.severity #=> 3
36
+ #
37
+ def severity
38
+ @severity ||= @event.at('@severity').inner_text.to_i
39
+ end
40
+
41
+ #
42
+ # Return true if event is of informational severity.
43
+ #
44
+ # @return [Boolean]
45
+ # Return true if the event is informational.
46
+ #
47
+ def informational?
48
+ severity == 0
49
+ end
50
+
51
+ #
52
+ # Return true if the event is of low severity.
53
+ #
54
+ # @return [Boolean]
55
+ # Return true if the event is low severity.
56
+ #
57
+ def low?
58
+ severity == 1
59
+ end
60
+
61
+ #
62
+ # Return true if the event is of medium severity.
63
+ #
64
+ # @return [Boolean]
65
+ # Return true if the event is medium severity.
66
+ #
67
+ def medium?
68
+ severity == 2
69
+ end
70
+
71
+ #
72
+ # Return true if the event is of high severity.
73
+ #
74
+ # @return [Boolean]
75
+ # Return true if the event is high severity.
76
+ #
77
+ def high?
78
+ severity == 3
79
+ end
80
+
81
+ #
82
+ # Return true if the event is of critical severity.
83
+ #
84
+ # @return [Boolean]
85
+ # Return true if the event is critical severity.
86
+ #
87
+ def critical?
88
+ severity == 4
89
+ end
90
+
91
+ #
92
+ # Return the event object nessus plugin id
93
+ #
94
+ # @return [Integer]
95
+ # Return the event object nessus plugin id
96
+ #
97
+ # @example
98
+ # event.plugin_id #=> 3245
99
+ #
100
+ def id
101
+ @plugin_id ||= @event.at('@pluginID').inner_text.to_i
102
+ end
103
+ alias plugin_id id
104
+
105
+ #
106
+ # Return the event object plugin family name.
107
+ #
108
+ # @return [String]
109
+ # Return the event object plugin family name.
110
+ #
111
+ # @example
112
+ # event.family #=> "Service detection"
113
+ #
114
+ def family
115
+ @plugin_family ||= @event.at('@pluginFamily').inner_text
116
+ end
117
+ alias plugin_family family
118
+
119
+ #
120
+ # Return the event name (plugin_name)
121
+ #
122
+ # @return [String, nil]
123
+ # Return the event name (plugin_name)
124
+ #
125
+ # @example
126
+ # event.plugin_name #=> "PHP < 5.2.4 Multiple Vulnerabilities"
127
+ # event.name #=> "PHP < 5.2.4 Multiple Vulnerabilities"
128
+ #
129
+ def plugin_name
130
+ @plugin_name ||= @event.at('@pluginName')&.inner_text unless @event.at('@pluginName').inner_text.empty?
131
+ end
132
+ alias name plugin_name
133
+
134
+ #
135
+ # Return the event object plugin type (plugin_type)
136
+ #
137
+ # @return [String, nil]
138
+ # Return the event object plugin type (plugin_type)
139
+ #
140
+ # @example
141
+ # event.plugin_type #=> "remote"
142
+ #
143
+ def plugin_type
144
+ @plugin_type ||= @event.at('plugin_type')&.inner_text
145
+ end
146
+
147
+ #
148
+ # Return the event synopsis.
149
+ #
150
+ # @return [String, nil]
151
+ # Return the event synopsis.
152
+ #
153
+ def synopsis
154
+ @synopsis ||= @event.at('synopsis')&.inner_text
155
+ end
156
+
157
+ #
158
+ # Return the event description.
159
+ #
160
+ # @return [String, nil]
161
+ # Return the event description.
162
+ #
163
+ def description
164
+ @description ||= @event.at('description')&.inner_text
165
+ end
166
+
167
+ #
168
+ # Return the event solution.
169
+ #
170
+ # @return [String, nil]
171
+ # Return the event solution.
172
+ #
173
+ def solution
174
+ @solution ||= @event.at('solution')&.inner_text
175
+ end
176
+
177
+ #
178
+ # Return the event risk.
179
+ #
180
+ # @return [String, nil]
181
+ # Return the event risk.
182
+ #
183
+ def risk
184
+ @risk_factor ||= @event.at('risk_factor')&.inner_text
185
+ end
186
+
187
+ #
188
+ # Return the event plugin output.
189
+ #
190
+ # @return [String, nil]
191
+ # Return the event plugin output.
192
+ #
193
+ def output
194
+ @plugin_output ||= @event.at('plugin_output')&.inner_text
195
+ end
196
+ alias data output
197
+ alias plugin_output output
198
+
199
+ #
200
+ # Return the event plugin version.
201
+ #
202
+ # @return [String, nil]
203
+ # Return the event plugin version.
204
+ #
205
+ def version
206
+ @plugin_version ||= @event.at('plugin_version')&.inner_text
207
+ end
208
+ alias plugin_version version
209
+
210
+ #
211
+ # Return the event reference links.
212
+ #
213
+ # @return [Array<String>]
214
+ # Return the event reference links.
215
+ #
216
+ def see_also
217
+ @see_also ||= @event.at('see_also')&.inner_text&.split("\n")
218
+ end
219
+ alias links see_also
220
+ alias more see_also
221
+ alias references see_also
222
+
223
+ #
224
+ # Return the event vulnerability publication date.
225
+ #
226
+ # @return [Time, nil]
227
+ # Return the event vulnerability publication date.
228
+ #
229
+ def vuln_publication_date
230
+ @vuln_publication_date ||= Time.parse(@event.at('vuln_publication_date').inner_text + ' UTC') if @event.at('vuln_publication_date')
231
+ end
232
+
233
+ #
234
+ # Return the event patch publication date.
235
+ #
236
+ # @return [Time, nil]
237
+ # Return the event patch publication date.
238
+ #
239
+ def patch_publication_date
240
+ @patch_publication_date ||= Time.parse(@event.at('patch_publication_date').inner_text + ' UTC') if @event.at('patch_publication_date')
241
+ end
242
+
243
+ #
244
+ # Return the event cvss base score.
245
+ #
246
+ # @return [float, nil]
247
+ # Return the event cvss base score.
248
+ #
249
+ def cvss_base_score
250
+ @cvss_base_score ||= @event.at('cvss_base_score')&.inner_text.to_f
251
+ end
252
+
253
+ #
254
+ # Return the event cvss temporal score.
255
+ #
256
+ # @return [float, nil]
257
+ # Return the event cvss temporal score.
258
+ #
259
+ def cvss_temporal_score
260
+ @cvss_temporal_score ||= @event.at('cvss_temporal_score')&.inner_text.to_f
261
+ end
262
+
263
+ #
264
+ # Return the event cve.
265
+ #
266
+ # @return [Array<String>, nil]
267
+ # Return the event cvss base score.
268
+ #
269
+ def cve
270
+ unless @cve
271
+ @cve = []
272
+ @event.xpath('cve').each do |cve|
273
+ @cve << cve.inner_text
274
+ end
275
+ @cve = nil if @cve.empty?
276
+ end
277
+ @cve
278
+ end
279
+
280
+ #
281
+ # Return the event bid.
282
+ #
283
+ # @return [Array<String>, nil]
284
+ # Return the event bid.
285
+ #
286
+ def bid
287
+ unless @bid
288
+ @bid = []
289
+ @event.xpath('bid').each do |bid|
290
+ @bid << bid.inner_text
291
+ end
292
+ @bid = nil if @bid.empty?
293
+ end
294
+ @bid
295
+ end
296
+
297
+ #
298
+ # Return other event related references.
299
+ #
300
+ # @return [Array<String>]
301
+ # Return the event related references.
302
+ #
303
+ def xref
304
+ unless @xref
305
+ @xref = []
306
+ @event.xpath('xref').each do |xref|
307
+ @xref << xref.inner_text
308
+ end
309
+ end
310
+ @xref
311
+ end
312
+
313
+ #
314
+ # Return other event cvss vector.
315
+ #
316
+ # @return [String, nil]
317
+ # Return the event cvss vector.
318
+ #
319
+ def cvss_vector
320
+ @cvss_vector ||= @event.at('cvss_vector')&.inner_text
321
+ end
322
+
323
+ #
324
+ # Return the event cpe.
325
+ #
326
+ # @return [Array<String>]
327
+ # Return the event cpe.
328
+ #
329
+ def cpe
330
+ unless @cpe
331
+ @cpe = []
332
+ @event.xpath('cpe').each do |cpe|
333
+ @cpe << cpe.inner_text
334
+ end
335
+ end
336
+ @cpe
337
+ end
338
+
339
+ #
340
+ # Return event exploitability ease.
341
+ #
342
+ # @return [String, nil]
343
+ # Return the event exploitability ease.
344
+ #
345
+ def exploitability_ease
346
+ @exploitability_ease ||= @event.at('exploitability_ease')&.inner_text
347
+ end
348
+
349
+ #
350
+ # Return event exploit available.
351
+ #
352
+ # @return [Boolean]
353
+ # Return the event exploit available.
354
+ #
355
+ def exploit_available
356
+ @exploit_available ||= @event.at('exploit_available')&.inner_text == "true"
357
+ end
358
+
359
+ #
360
+ # Return if an exploit exists in the Immunity CANVAS framework.
361
+ #
362
+ # @return [Boolean]
363
+ # Return the event exploit framework canvas.
364
+ #
365
+ def exploit_framework_canvas
366
+ @exploit_framework_canvas ||= @event.at('exploit_framework_canvas')&.inner_text == "true"
367
+ end
368
+
369
+ #
370
+ # Return the name of the CANVAS exploit package
371
+ #
372
+ # @return [String, nil]
373
+ # Return the canvas_package.
374
+ #
375
+ def canvas_package
376
+ @canvas_package ||= @event.at('canvas_package')&.inner_text
377
+ end
378
+
379
+ #
380
+ # Return if an exploit exploit exists in the Metasploit framework
381
+ #
382
+ # @return [Boolean]
383
+ # Return the event exploit framework metasploit.
384
+ #
385
+ def exploit_framework_metasploit
386
+ @exploit_framework_metasploit ||= @event.at('exploit_framework_metasploit')&.inner_text == "true"
387
+ end
388
+
389
+ #
390
+ # Return name of the Metasploit exploit module.
391
+ #
392
+ # @return [String, nil]
393
+ # Return the metasploit_name.
394
+ #
395
+ def metasploit_name
396
+ @metasploit_name ||= @event.at('metasploit_name')&.inner_text
397
+ end
398
+
399
+ #
400
+ # Return if an exploit exploit exists in the CORE Impact framework
401
+ #
402
+ # @return [Boolean]
403
+ # Return the event exploit framework core.
404
+ #
405
+ def exploit_framework_core
406
+ @exploit_framework_core ||= @event.at('exploit_framework_core')&.inner_text == "true"
407
+ end
408
+ end
409
+ end
410
+ end
@@ -0,0 +1,522 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyNessus
4
+ module Version2
5
+ class Host
6
+ include Enumerable
7
+
8
+ #
9
+ # Creates A New Host Object
10
+ #
11
+ # @param [Object] Host Object
12
+ #
13
+ # @example
14
+ # Host.new(object)
15
+ #
16
+ def initialize(host)
17
+ @host = host
18
+ end
19
+
20
+ def to_s
21
+ ip.to_s
22
+ end
23
+
24
+ def name
25
+ @host["name"]
26
+ end
27
+
28
+ #
29
+ # Return the Host Object hostname.
30
+ #
31
+ # @return [String]
32
+ # The Host Object Hostname
33
+ #
34
+ # @example
35
+ # host.hostname #=> "example.com"
36
+ #
37
+ def hostname
38
+ @host.at('tag[name=host-fqdn]')&.inner_text
39
+ end
40
+ alias fqdn hostname
41
+ alias dns_name hostname
42
+
43
+ #
44
+ # Return the Host Object IP.
45
+ #
46
+ # @return [String]
47
+ # The Host Object IP
48
+ #
49
+ # @example
50
+ # host.ip #=> "127.0.0.1"
51
+ #
52
+ def ip
53
+ @host.at('tag[name=host-ip]')&.inner_text
54
+ end
55
+
56
+ #
57
+ # Return the host scan start time.
58
+ #
59
+ # @return [Time]
60
+ # The Host Scan Start Time
61
+ #
62
+ # @example
63
+ # scan.scan_start_time #=> 'Fri Nov 11 23:36:54 1985'
64
+ #
65
+ def start_time
66
+ if (start_time = @host.at('tag[name=HOST_START]'))
67
+ Time.parse(start_time.inner_text + ' UTC')
68
+ end
69
+ end
70
+
71
+ #
72
+ # Return the host scan stop time.
73
+ #
74
+ # @return [Time]
75
+ # The Host Scan Stop Time
76
+ #
77
+ # @example
78
+ # scan.scan_start_time #=> 'Fri Nov 11 23:36:54 1985'
79
+ #
80
+ def stop_time
81
+ if (stop_time = @host.at('tag[name=HOST_END]'))
82
+ Time.parse(stop_time.inner_text + ' UTC')
83
+ end
84
+ end
85
+
86
+ #
87
+ # Return the host run time.
88
+ #
89
+ # @return [String]
90
+ # The Host Scan Run Time
91
+ #
92
+ # @example
93
+ # scan.scan_run_time #=> '2 hours 5 minutes and 16 seconds'
94
+ #
95
+ def runtime
96
+ return unless stop_time && start_time
97
+ Time.at(stop_time - start_time).utc.strftime('%H hours %M minutes and %S seconds')
98
+ end
99
+ alias scan_runtime runtime
100
+ alias get_runtime runtime
101
+
102
+ #
103
+ # Return the Host Netbios Name.
104
+ #
105
+ # @return [String, nil]
106
+ # The Host Netbios Name
107
+ #
108
+ # @example
109
+ # host.netbios_name #=> "SOMENAME4243"
110
+ #
111
+ def netbios_name
112
+ @host.at('tag[name=netbios-name]')&.inner_text
113
+ end
114
+
115
+ #
116
+ # Return the Host Mac Address.
117
+ #
118
+ # @return [String]
119
+ # Return the Host Mac Address
120
+ #
121
+ # @example
122
+ # host.mac_addr #=> "00:11:22:33:44:55"
123
+ #
124
+ def mac_addr
125
+ @host.at('tag[name=mac-address]')&.inner_text
126
+ end
127
+ alias mac_address mac_addr
128
+
129
+ #
130
+ # Return the Host OS Name.
131
+ #
132
+ # @return [String]
133
+ # Return the Host OS Name
134
+ #
135
+ # @example
136
+ # host.dns_name #=> "Microsoft Windows 2000, Microsoft Windows Server 2003"
137
+ #
138
+ def os_name
139
+ @host.at('tag[name=operating-system]')&.inner_text
140
+ end
141
+ alias os os_name
142
+ alias operating_system os_name
143
+
144
+ #
145
+ # Return the open ports for a given host object.
146
+ #
147
+ # @return [Integer]
148
+ # Return the open ports for a given host object.
149
+ #
150
+ # @example
151
+ # host.open_ports #=> 213
152
+ #
153
+ def open_ports
154
+ @scanned_ports ||= host_stats[:open_ports].to_i
155
+ end
156
+
157
+ #
158
+ # Returns All Informational Event Objects For A Given Host.
159
+ #
160
+ #
161
+ # @return [Event]
162
+ # Return The Informational Event For A Given Host.
163
+ #
164
+ # @example
165
+ # host.informational_severity_events.each do |info|
166
+ # puts info.port
167
+ # puts info.data if info.data
168
+ # end
169
+ #
170
+ def informational_severity_events
171
+ return if @informational_events
172
+ @informational_events = @host.xpath('ReportItem').select { |event| event['severity'].to_i.zero? }.map do |event|
173
+ Event.new(event)
174
+ end
175
+ @informational_events
176
+ end
177
+
178
+ #
179
+ # Returns All low_severity Event Objects For A Given Host.
180
+ #
181
+ #
182
+ # @return [Event]
183
+ # Return The low_severity Event For A Given Host.
184
+ #
185
+ # @example
186
+ # host.low_severity_events.each do |low|
187
+ # puts low.port
188
+ # puts low.data if low.data
189
+ # end
190
+ #
191
+ def low_severity_events
192
+ return if @low_severity_events
193
+ @low_severity_events = @host.xpath('ReportItem').select { |event| (event['severity'].to_i == 1) }.map do |event|
194
+ Event.new(event)
195
+ end
196
+ @low_severity_events
197
+ end
198
+
199
+ #
200
+ # Returns All medium severity Event Objects For A Given Host.
201
+ #
202
+ #
203
+ # @return [Event]
204
+ # Return The medium severity Event For A Given Host.
205
+ #
206
+ # @example
207
+ # host.medium_severity_events.each do |medium|
208
+ # puts medium.port
209
+ # puts medium.data if medium.data
210
+ # end
211
+ #
212
+ def medium_severity_events
213
+ return if @medium_severity_events
214
+ @medium_severity_events = @host.xpath('ReportItem').select { |event| (event['severity'].to_i == 2) }.map do |event|
215
+ Event.new(event)
216
+ end
217
+ @medium_severity_events
218
+ end
219
+
220
+ #
221
+ # Returns All high severity Event Objects For A Given Host.
222
+ #
223
+ #
224
+ # @return [Event]
225
+ # Return The high severity Event For A Given Host.
226
+ #
227
+ # @example
228
+ # host.high_severity_events.each do |high|
229
+ # puts high.port
230
+ # puts high.data if high.data
231
+ # end
232
+ #
233
+ def high_severity_events
234
+ return if @high_severity_events
235
+ @high_severity_events = @host.xpath('ReportItem').select { |event| (event['severity'].to_i == 3) }.map do |event|
236
+ Event.new(event)
237
+ end
238
+ @high_severity_events
239
+ end
240
+
241
+ #
242
+ # Returns All critical severity Event Objects For A Given Host.
243
+ #
244
+ #
245
+ # @return [Event]
246
+ # Return The critical For A Given Host.
247
+ #
248
+ # @example
249
+ # host.critical_severity_events.each do |critical|
250
+ # puts critical.port
251
+ # puts critical.data if info.data
252
+ # end
253
+ #
254
+ def critical_severity_events
255
+ return if @critical_events
256
+ @critical_events = @host.xpath('ReportItem').select { |event| (event['severity'].to_i == 4) }.map do |event|
257
+ Event.new(event)
258
+ end
259
+ @critical_events
260
+ end
261
+
262
+ #
263
+ # Return the total event count for a given host.
264
+ #
265
+ # @return [Integer]
266
+ # Return the total event count for a given host.
267
+ #
268
+ # @example
269
+ # host.event_count #=> 3456
270
+ #
271
+ def event_count
272
+ low_severity_events.count + medium_severity_events.count + high_severity_events.count + critical_severity_events.count
273
+ end
274
+
275
+ #
276
+ # Creates a new Event object to be parser
277
+ #
278
+ # @yield [prog] If a block is given, it will be passed the newly
279
+ # created Event object.
280
+ # @yieldparam [EVENT] prog The newly created Event object.
281
+ #
282
+ # @example
283
+ # host.each_event do |event|
284
+ # puts event.name if event.name
285
+ # puts event.port
286
+ # end
287
+ #
288
+ def each_event(&block)
289
+ events.each(&block)
290
+ end
291
+
292
+ #
293
+ # Parses the events of the host.
294
+ #
295
+ # @return [Array<String>]
296
+ # The events of the host.
297
+ #
298
+ def events
299
+ @host.xpath('ReportItem').map do |event|
300
+ Event.new(event)
301
+ end
302
+ end
303
+
304
+ #
305
+ # Return an Array of open ports.
306
+ #
307
+ # @return [Array]
308
+ # The open ports
309
+ #
310
+ # @example
311
+ # scan.ports #=> ['22', '80', '443']
312
+ #
313
+ def ports
314
+ return if @ports
315
+ @ports = @host.xpath('ReportItem').map { |port| port['port'] }.uniq.sort
316
+ end
317
+
318
+ #
319
+ # Return the TCP Event Count.
320
+ #
321
+ # @return [Integer]
322
+ # The TCP Event Count
323
+ #
324
+ # @example
325
+ # scan.tcp_count #=> 3
326
+ #
327
+ def tcp_count
328
+ host_stats[:tcp].to_i
329
+ end
330
+
331
+ #
332
+ # Return the UDP Event Count.
333
+ #
334
+ # @return [Integer]
335
+ # The UDP Event Count
336
+ #
337
+ # @example
338
+ # scan.udp_count #=> 3
339
+ #
340
+ def udp_count
341
+ host_stats[:udp].to_i
342
+ end
343
+
344
+ #
345
+ # Return the ICMP Event Count.
346
+ #
347
+ # @return [Integer]
348
+ # The ICMP Event Count
349
+ #
350
+ # @example
351
+ # scan.icmp_count #=> 3
352
+ #
353
+ def icmp_count
354
+ host_stats[:icmp].to_i
355
+ end
356
+
357
+ #
358
+ # Return the informational severity count.
359
+ #
360
+ # @return [Integer]
361
+ # The Informational Severity Count
362
+ #
363
+ # @example
364
+ # scan.informational_severity_count #=> 1203
365
+ #
366
+ def informational_severity_count
367
+ host_stats[:informational].to_i
368
+ end
369
+
370
+ #
371
+ # Return the Critical severity count.
372
+ #
373
+ # @return [Integer]
374
+ # The Critical Severity Count
375
+ #
376
+ # @example
377
+ # scan.critical_severity_count #=> 10
378
+ #
379
+ def critical_severity_count
380
+ host_stats[:critical].to_i
381
+ end
382
+
383
+ #
384
+ # Return the High severity count.
385
+ #
386
+ # @return [Integer]
387
+ # The High Severity Count
388
+ #
389
+ # @example
390
+ # scan.high_severity_count #=> 10
391
+ #
392
+ def high_severity_count
393
+ host_stats[:high].to_i
394
+ end
395
+
396
+ #
397
+ # Return the Medium severity count.
398
+ #
399
+ # @return [Integer]
400
+ # The Medium Severity Count
401
+ #
402
+ # @example
403
+ # scan.medium_severity_count #=> 234
404
+ #
405
+ def medium_severity_count
406
+ host_stats[:medium].to_i
407
+ end
408
+
409
+ #
410
+ # Return the Low severity count.
411
+ #
412
+ # @return [Integer]
413
+ # The Low Severity Count
414
+ #
415
+ # @example
416
+ # scan.low_severity_count #=> 114
417
+ #
418
+ def low_severity_count
419
+ host_stats[:low].to_i
420
+ end
421
+
422
+ #
423
+ # Return the Total severity count. [high, medium, low, informational]
424
+ #
425
+ # @return [Integer]
426
+ # The Total Severity Count
427
+ #
428
+ # @example
429
+ # scan.total_event_count #=> 1561
430
+ #
431
+ def total_event_count(count_informational = nil)
432
+ if count_informational
433
+ host_stats[:all].to_i + informational_severity_count
434
+ else
435
+ host_stats[:all].to_i
436
+ end
437
+ end
438
+
439
+ #
440
+ # Return the Total severity count.
441
+ #
442
+ # @param [String] severity the severity in which to calculate percentage for.
443
+ #
444
+ # @param [true, false] round round the result to the nearest whole number.
445
+ #
446
+ # @raise [ExceptionClass] One of the following severity options must be passed. [high, medium, low, informational, all]
447
+ #
448
+ # @return [Integer]
449
+ # The Percentage Of Events For A Passed Severity
450
+ #
451
+ # @example
452
+ # scan.event_percentage_for("low", true) #=> 11%
453
+ #
454
+ def event_percentage_for(type, round_percentage = false)
455
+ @sc ||= host_stats
456
+ if %w[high medium low tcp udp icmp all].include?(type)
457
+ calc = ((@sc[:"#{type}"].to_f / @sc[:all].to_f) * 100)
458
+ if round_percentage
459
+ return calc.round.to_s
460
+ else
461
+ return calc.to_s
462
+ end
463
+ else
464
+ raise "Error: #{type} is not an acceptable severity. Possible options include: all, tdp, udp, icmp, high, medium and low."
465
+ end
466
+ end
467
+
468
+ private
469
+
470
+ def host_stats
471
+ unless @host_stats
472
+ @host_stats = {}
473
+ @open_ports = 0
474
+ @tcp = 0
475
+ @udp = 0
476
+ @icmp = 0
477
+ @informational = 0
478
+ @low = 0
479
+ @medium = 0
480
+ @high = 0
481
+ @critical = 0
482
+
483
+ @host.xpath('ReportItem').each do |s|
484
+ case s['severity'].to_i
485
+ when 0
486
+ @informational += 1
487
+ when 1
488
+ @low += 1
489
+ when 2
490
+ @medium += 1
491
+ when 3
492
+ @high += 1
493
+ when 4
494
+ @critical += 1
495
+ end
496
+
497
+ unless s['severity'].to_i == 0
498
+ @tcp += 1 if s['protocol'] == 'tcp'
499
+ @udp += 1 if s['protocol'] == 'udp'
500
+ @icmp += 1 if s['protocol'] == 'icmp'
501
+ end
502
+
503
+ @open_ports += 1 if s['port'].to_i != 0
504
+ end
505
+
506
+ @host_stats = { open_ports: @open_ports,
507
+ tcp: @tcp,
508
+ udp: @udp,
509
+ icmp: @icmp,
510
+ informational: @informational,
511
+ low: @low,
512
+ medium: @medium,
513
+ high: @high,
514
+ critical: @critical,
515
+ all: (@low + @medium + @high + @critical) }
516
+
517
+ end
518
+ @host_stats
519
+ end
520
+ end
521
+ end
522
+ end