prenus 0.0.3 → 0.0.4

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.
@@ -0,0 +1,595 @@
1
+ module Nessus
2
+ module Version2
3
+
4
+ class Host
5
+ include Enumerable
6
+
7
+ #
8
+ # Creates A New Host Object
9
+ #
10
+ # @param [Object] Host Object
11
+ #
12
+ # @example
13
+ # Host.new(object)
14
+ #
15
+ def initialize(host)
16
+ @host = host
17
+ end
18
+
19
+ def to_s
20
+ "#{ip}"
21
+ end
22
+
23
+ #
24
+ # Return the Host Object hostname.
25
+ #
26
+ # @return [String]
27
+ # The Host Object Hostname
28
+ #
29
+ # @example
30
+ # host.hostname #=> "example.com"
31
+ #
32
+ def hostname
33
+ if (host = @host.at('tag[name=host-fqdn]'))
34
+ host.inner_text
35
+ end
36
+ end
37
+ alias name hostname
38
+ alias fqdn hostname
39
+ alias dns_name hostname
40
+
41
+ #
42
+ # Return the Host Object IP.
43
+ #
44
+ # @return [String]
45
+ # The Host Object IP
46
+ #
47
+ # @example
48
+ # host.ip #=> "127.0.0.1"
49
+ #
50
+ def ip
51
+ if (ip = @host.at('tag[name=host-ip]'))
52
+ ip.inner_text
53
+ end
54
+ end
55
+
56
+ #
57
+ # Return the host scan start time.
58
+ #
59
+ # @return [DateTime]
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
+ DateTime.strptime(start_time.inner_text, fmt='%a %b %d %H:%M:%S %Y')
68
+ else
69
+ false
70
+ end
71
+ end
72
+
73
+ #
74
+ # Return the host scan stop time.
75
+ #
76
+ # @return [DateTime]
77
+ # The Host Scan Stop Time
78
+ #
79
+ # @example
80
+ # scan.scan_start_time #=> 'Fri Nov 11 23:36:54 1985'
81
+ #
82
+ def stop_time
83
+ if (stop_time = @host.at('tag[name=HOST_END]'))
84
+ DateTime.strptime(stop_time.inner_text, fmt='%a %b %d %H:%M:%S %Y')
85
+ else
86
+ false
87
+ end
88
+ end
89
+
90
+ #
91
+ # Return the host run time.
92
+ #
93
+ # @return [String]
94
+ # The Host Scan Run Time
95
+ #
96
+ # @example
97
+ # scan.scan_run_time #=> '2 hours 5 minutes and 16 seconds'
98
+ #
99
+ def runtime
100
+ get_runtime
101
+ end
102
+ alias scan_runtime runtime
103
+
104
+ #
105
+ # Return the Host Netbios Name.
106
+ #
107
+ # @return [String]
108
+ # The Host Netbios Name
109
+ #
110
+ # @example
111
+ # host.netbios_name #=> "SOMENAME4243"
112
+ #
113
+ def netbios_name
114
+ if (netbios = @host.at('tag[name=netbios-name]'))
115
+ netbios.inner_text
116
+ end
117
+ end
118
+
119
+ #
120
+ # Return the Host Mac Address.
121
+ #
122
+ # @return [String]
123
+ # Return the Host Mac Address
124
+ #
125
+ # @example
126
+ # host.mac_addr #=> "00:11:22:33:44:55"
127
+ #
128
+ def mac_addr
129
+ if (mac_addr = @host.at('tag[name=mac-addr]'))
130
+ mac_addr.inner_text
131
+ end
132
+ end
133
+ alias mac_address mac_addr
134
+
135
+ #
136
+ # Return the Host OS Name.
137
+ #
138
+ # @return [String]
139
+ # Return the Host OS Name
140
+ #
141
+ # @example
142
+ # host.dns_name #=> "Microsoft Windows 2000, Microsoft Windows Server 2003"
143
+ #
144
+ def os_name
145
+ if (os_name = @host.at('tag[name=operating-system]'))
146
+ os_name.inner_text
147
+ end
148
+ end
149
+ alias os os_name
150
+ alias operating_system os_name
151
+
152
+ #
153
+ # Return the open ports for a given host object.
154
+ #
155
+ # @return [Integer]
156
+ # Return the open ports for a given host object.
157
+ #
158
+ # @example
159
+ # host.open_ports #=> 213
160
+ #
161
+ def open_ports
162
+ @scanned_ports ||= host_stats[:open_ports].to_i
163
+ end
164
+
165
+ #
166
+ # Returns All Informational Event Objects For A Given Host.
167
+ #
168
+ # @yield [prog] If a block is given, it will be passed the newly
169
+ # created Event object.
170
+ #
171
+ # @yieldparam [EVENT] prog The newly created Event object.
172
+ #
173
+ # @return [Integer]
174
+ # Return The Informational Event Count For A Given Host.
175
+ #
176
+ # @example
177
+ # host.informational_severity_events do |info|
178
+ # puts info.port
179
+ # puts info.data if info.data
180
+ # end
181
+ #
182
+ def informational_severity_events(&block)
183
+ unless @informational_events
184
+ @informational_events = []
185
+
186
+ @host.xpath("ReportItem").each do |event|
187
+ next if event['severity'].to_i != 0
188
+ @informational_events << Event.new(event)
189
+ end
190
+
191
+ end
192
+
193
+ @informational_events.each(&block)
194
+ end
195
+
196
+ #
197
+ # Returns All Low Event Objects For A Given Host.
198
+ #
199
+ # @yield [prog] If a block is given, it will be passed the newly
200
+ # created Event object.
201
+ #
202
+ # @yieldparam [EVENT] prog The newly created Event object.
203
+ #
204
+ # @return [Integer]
205
+ # Return The Low Event Count For A Given Host.
206
+ #
207
+ # @example
208
+ # host.low_severity_events do |low|
209
+ # puts low.name if low.name
210
+ # end
211
+ #
212
+ def low_severity_events(&block)
213
+
214
+ unless @low_severity_events
215
+ @low_severity_events = []
216
+
217
+ @host.xpath("ReportItem").each do |event|
218
+ next if event['severity'].to_i != 1
219
+ @low_severity_events << Event.new(event)
220
+ end
221
+
222
+ end
223
+
224
+ @low_severity_events.each(&block)
225
+ end
226
+
227
+ #
228
+ # Returns All Medium Event Objects For A Given Host.
229
+ #
230
+ # @yield [prog] If a block is given, it will be passed the newly
231
+ # created Event object.
232
+ # @yieldparam [EVENT] prog The newly created Event object.
233
+ #
234
+ # @return [Integer]
235
+ # Return The Medium Event Count For A Given Host.
236
+ #
237
+ # @example
238
+ # host.medium_severity_events do |medium|
239
+ # puts medium.name if medium.name
240
+ # end
241
+ #
242
+ def medium_severity_events(&block)
243
+
244
+ unless @medium_severity_events
245
+ @medium_severity_events = []
246
+
247
+ @host.xpath("ReportItem").each do |event|
248
+ next if event['severity'].to_i != 2
249
+ @medium_severity_events << Event.new(event)
250
+ end
251
+
252
+ end
253
+
254
+ @medium_severity_events.each(&block)
255
+ end
256
+
257
+ def medium_severity
258
+ Enumerator.new(self,:medium_severity_events).to_a
259
+ end
260
+
261
+ #
262
+ # Returns All High Event Objects For A Given Host.
263
+ #
264
+ # @yield [prog] If a block is given, it will be passed the newly
265
+ # created Event object.
266
+ #
267
+ # @yieldparam [EVENT] prog The newly created Event object.
268
+ #
269
+ # @return [Integer]
270
+ # Return The High Event Count For A Given Host.
271
+ #
272
+ # @example
273
+ # host.high_severity_events do |high|
274
+ # puts high.name if high.name
275
+ # end
276
+ #
277
+ def high_severity_events(&block)
278
+
279
+ unless @high_severity_events
280
+ @high_severity_events = []
281
+
282
+ @host.xpath("ReportItem").each do |event|
283
+ next if event['severity'].to_i != 3
284
+ @high_severity_events << Event.new(event)
285
+ end
286
+
287
+ end
288
+
289
+ @high_severity_events.each(&block)
290
+ end
291
+
292
+ #
293
+ # Returns All Critical Event Objects For A Given Host.
294
+ #
295
+ # @yield [prog] If a block is given, it will be passed the newly
296
+ # created Event object.
297
+ #
298
+ # @yieldparam [EVENT] prog The newly created Event object.
299
+ #
300
+ # @return [Integer]
301
+ # Return The Critical Event Count For A Given Host.
302
+ #
303
+ # @example
304
+ # host.critical_severity_events do |critical|
305
+ # puts critical.name if critical.name
306
+ # end
307
+ #
308
+ def critical_severity_events(&block)
309
+
310
+ unless @critical_severity_events
311
+ @critical_severity_events = []
312
+
313
+ @host.xpath("ReportItem").each do |event|
314
+ next if event['severity'].to_i != 4
315
+ @critical_severity_events << Event.new(event)
316
+ end
317
+
318
+ end
319
+
320
+ @critical_severity_events.each(&block)
321
+ end
322
+
323
+ #
324
+ # Return the total event count for a given host.
325
+ #
326
+ # @return [Integer]
327
+ # Return the total event count for a given host.
328
+ #
329
+ # @example
330
+ # host.event_count #=> 3456
331
+ #
332
+ def event_count
333
+ ((low_severity_events.to_i) + (medium_severity_events.to_i) + (high_severity_events.to_i) + (critical_severity_events.to_i)).to_i
334
+ end
335
+
336
+ #
337
+ # Creates a new Event object to be parser
338
+ #
339
+ # @yield [prog] If a block is given, it will be passed the newly
340
+ # created Event object.
341
+ # @yieldparam [EVENT] prog The newly created Event object.
342
+ #
343
+ # @example
344
+ # host.each_event do |event|
345
+ # puts event.name if event.name
346
+ # puts event.port
347
+ # end
348
+ #
349
+ def each_event(&block)
350
+ @host.xpath("ReportItem").each do |event|
351
+ block.call(Event.new(event)) if block
352
+ end
353
+ end
354
+
355
+ #
356
+ # Parses the events of the host.
357
+ #
358
+ # @return [Array<String>]
359
+ # The events of the host.
360
+ #
361
+ def events
362
+ Enumerator.new(self,:each_event).to_a
363
+ end
364
+
365
+ #
366
+ # Return the Open Ports count.
367
+ #
368
+ # @return [Array]
369
+ # The Open Ports Count
370
+ #
371
+ # @example
372
+ # scan.ports #=> ['22', '80', '443']
373
+ #
374
+ def ports
375
+ unless @ports
376
+ @ports = []
377
+ @host.xpath("ReportItem").each do |port|
378
+ @ports << port['port']
379
+ end
380
+ @ports.uniq!
381
+ @ports.sort!
382
+ end
383
+ @ports
384
+ end
385
+
386
+ #
387
+ # Return the TCP Event Count.
388
+ #
389
+ # @return [Integer]
390
+ # The TCP Event Count
391
+ #
392
+ # @example
393
+ # scan.tcp_count #=> 3
394
+ #
395
+ def tcp_count
396
+ host_stats[:tcp].to_i
397
+ end
398
+
399
+ #
400
+ # Return the UDP Event Count.
401
+ #
402
+ # @return [Integer]
403
+ # The UDP Event Count
404
+ #
405
+ # @example
406
+ # scan.udp_count #=> 3
407
+ #
408
+ def udp_count
409
+ host_stats[:udp].to_i
410
+ end
411
+
412
+ #
413
+ # Return the ICMP Event Count.
414
+ #
415
+ # @return [Integer]
416
+ # The ICMP Event Count
417
+ #
418
+ # @example
419
+ # scan.icmp_count #=> 3
420
+ #
421
+ def icmp_count
422
+ host_stats[:icmp].to_i
423
+ end
424
+
425
+ #
426
+ # Return the informational severity count.
427
+ #
428
+ # @return [Integer]
429
+ # The Informational Severity Count
430
+ #
431
+ # @example
432
+ # scan.informational_severity_count #=> 1203
433
+ #
434
+ def informational_severity_count
435
+ host_stats[:informational].to_i
436
+ end
437
+
438
+ #
439
+ # Return the Critical severity count.
440
+ #
441
+ # @return [Integer]
442
+ # The Critical Severity Count
443
+ #
444
+ # @example
445
+ # scan.critical_severity_count #=> 10
446
+ #
447
+ def critical_severity_count
448
+ host_stats[:critical].to_i
449
+ end
450
+
451
+ #
452
+ # Return the High severity count.
453
+ #
454
+ # @return [Integer]
455
+ # The High Severity Count
456
+ #
457
+ # @example
458
+ # scan.high_severity_count #=> 10
459
+ #
460
+ def high_severity_count
461
+ host_stats[:high].to_i
462
+ end
463
+
464
+ #
465
+ # Return the Medium severity count.
466
+ #
467
+ # @return [Integer]
468
+ # The Medium Severity Count
469
+ #
470
+ # @example
471
+ # scan.medium_severity_count #=> 234
472
+ #
473
+ def medium_severity_count
474
+ host_stats[:medium].to_i
475
+ end
476
+
477
+ #
478
+ # Return the Low severity count.
479
+ #
480
+ # @return [Integer]
481
+ # The Low Severity Count
482
+ #
483
+ # @example
484
+ # scan.low_severity_count #=> 114
485
+ #
486
+ def low_severity_count
487
+ host_stats[:low].to_i
488
+ end
489
+
490
+ #
491
+ # Return the Total severity count. [high, medium, low, informational]
492
+ #
493
+ # @return [Integer]
494
+ # The Total Severity Count
495
+ #
496
+ # @example
497
+ # scan.total_event_count #=> 1561
498
+ #
499
+ def total_event_count(count_informational = false)
500
+ if count_informational
501
+ host_stats[:all].to_i + informational_severity_count
502
+ else
503
+ host_stats[:all].to_i
504
+ end
505
+ end
506
+
507
+ #
508
+ # Return the Total severity count.
509
+ #
510
+ # @param [String] severity the severity in which to calculate percentage for.
511
+ #
512
+ # @param [true, false] round round the result to the nearest whole number.
513
+ #
514
+ # @raise [ExceptionClass] One of the following severity options must be passed. [high, medium, low, informational, all]
515
+ #
516
+ # @return [Integer]
517
+ # The Percentage Of Events For A Passed Severity
518
+ #
519
+ # @example
520
+ # scan.event_percentage_for("low", true) #=> 11%
521
+ #
522
+ def event_percentage_for(type, round_percentage=false)
523
+ @sc ||= host_stats
524
+ if %W(high medium low tcp udp icmp all).include?(type)
525
+ calc = ((@sc[:"#{type}"].to_f / (@sc[:all].to_f)) * 100)
526
+ if round_percentage
527
+ return "#{calc.round}"
528
+ else
529
+ return "#{calc}"
530
+ end
531
+ else
532
+ raise "Error: #{type} is not an acceptable severity. Possible options include: all, tdp, udp, icmp, high, medium and low."
533
+ end
534
+ end
535
+
536
+ private
537
+
538
+ def get_runtime
539
+ if stop_time && start_time
540
+ h = ("#{Time.parse(stop_time.to_s).strftime('%H').to_i - Time.parse(start_time.to_s).strftime('%H').to_i}").gsub('-', '')
541
+ m = ("#{Time.parse(stop_time.to_s).strftime('%M').to_i - Time.parse(start_time.to_s).strftime('%M').to_i}").gsub('-', '')
542
+ s = ("#{Time.parse(stop_time.to_s).strftime('%S').to_i - Time.parse(start_time.to_s).strftime('%S').to_i}").gsub('-', '')
543
+ return "#{h} hours #{m} minutes and #{s} seconds"
544
+ else
545
+ false
546
+ end
547
+ end
548
+
549
+ def host_stats
550
+
551
+ unless @host_stats
552
+ @host_stats = {}
553
+ @open_ports, @tcp, @udp, @icmp, @informational, @low, @medium, @high, @critical = 0,0,0,0,0,0,0,0,0
554
+
555
+ @host.xpath("ReportItem").each do |s|
556
+ case s['severity'].to_i
557
+ when 0
558
+ @informational += 1
559
+ when 1
560
+ @low += 1
561
+ when 2
562
+ @medium += 1
563
+ when 3
564
+ @high += 1
565
+ when 4
566
+ @critical += 1
567
+ end
568
+
569
+ unless s['severity'].to_i == 0
570
+ @tcp += 1 if s['protocol'] == 'tcp'
571
+ @udp += 1 if s['protocol'] == 'udp'
572
+ @icmp += 1 if s['protocol'] == 'icmp'
573
+ end
574
+
575
+ @open_ports += 1 if s['port'].to_i != 0
576
+ end
577
+
578
+ @host_stats = {:open_ports => @open_ports,
579
+ :tcp => @tcp,
580
+ :udp => @udp,
581
+ :icmp => @icmp,
582
+ :informational => @informational,
583
+ :low => @low,
584
+ :medium => @medium,
585
+ :high => @high,
586
+ :critical => @critical,
587
+ :all => (@low + @medium + @high + @critical)}
588
+
589
+ end
590
+ @host_stats
591
+ end
592
+
593
+ end
594
+ end
595
+ end