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