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
data/lib/ruby-nessus/event.rb
DELETED
@@ -1,87 +0,0 @@
|
|
1
|
-
require 'ruby-nessus/port'
|
2
|
-
|
3
|
-
module Nessus
|
4
|
-
class Event
|
5
|
-
# Event
|
6
|
-
attr_reader :event
|
7
|
-
|
8
|
-
# Return the total event count for a given host.
|
9
|
-
# @return [Integer]
|
10
|
-
# Return the total event count for a given host.
|
11
|
-
# @example
|
12
|
-
# host.event_count #=> 3456
|
13
|
-
def initialize(event)
|
14
|
-
@event = event
|
15
|
-
end
|
16
|
-
|
17
|
-
# Return the event port.
|
18
|
-
# @return [Object]
|
19
|
-
# Return the event port object or port string.
|
20
|
-
# @example
|
21
|
-
# event.port #=> "https (443/tcp)"
|
22
|
-
# event.port.number #=> 443
|
23
|
-
# event.port.service #=> "https"
|
24
|
-
# event.port.protocol #=> "tcp"
|
25
|
-
def port
|
26
|
-
@port ||= Port.parse(@event.at('port').inner_text)
|
27
|
-
end
|
28
|
-
|
29
|
-
# Return the event severity.
|
30
|
-
# @return [String]
|
31
|
-
# Return the event severity.
|
32
|
-
# @example
|
33
|
-
# event.severity #=> 3
|
34
|
-
# event.severity.in_words #=> "High Severity"
|
35
|
-
# @see String#in_words
|
36
|
-
def severity
|
37
|
-
@severity ||= @event.at('severity').inner_text.to_i
|
38
|
-
end
|
39
|
-
|
40
|
-
# Return the event object nessus plugin id
|
41
|
-
# @return [String]
|
42
|
-
# Return the event object nessus plugin id
|
43
|
-
# @example
|
44
|
-
# event.plugin_id #=> 3245
|
45
|
-
def plugin_id
|
46
|
-
@plugin_id ||= @event.at('pluginID').inner_text.to_i
|
47
|
-
end
|
48
|
-
|
49
|
-
# Return the event name (plugin_name)
|
50
|
-
# @return [String]
|
51
|
-
# Return the event name (plugin_name)
|
52
|
-
# @example
|
53
|
-
# event.plugin_name #=> "PHP < 5.2.4 Multiple Vulnerabilities"
|
54
|
-
# event.name #=> "PHP < 5.2.4 Multiple Vulnerabilities"
|
55
|
-
def plugin_name
|
56
|
-
s = @event.at('pluginName').inner_text
|
57
|
-
|
58
|
-
@plugin_name ||= unless s.empty?
|
59
|
-
@event.at('pluginName').inner_text || "N/A"
|
60
|
-
else
|
61
|
-
false
|
62
|
-
end
|
63
|
-
|
64
|
-
return @plugin_name
|
65
|
-
end
|
66
|
-
alias name plugin_name
|
67
|
-
|
68
|
-
# Return the event plugin output data
|
69
|
-
# @return [String]
|
70
|
-
# Return the event plugin output data
|
71
|
-
# @example
|
72
|
-
# event.output #=> "..."
|
73
|
-
# event.data #=> "..."
|
74
|
-
def data
|
75
|
-
d = "#{@event.at('data')}" || ""
|
76
|
-
|
77
|
-
@data ||= unless d.empty?
|
78
|
-
@event.at('data').inner_text || "N/A"
|
79
|
-
else
|
80
|
-
false
|
81
|
-
end
|
82
|
-
return @data
|
83
|
-
end
|
84
|
-
alias output data
|
85
|
-
|
86
|
-
end
|
87
|
-
end
|
data/lib/ruby-nessus/host.rb
DELETED
@@ -1,254 +0,0 @@
|
|
1
|
-
module Nessus
|
2
|
-
class Host
|
3
|
-
include Enumerable
|
4
|
-
|
5
|
-
# Host
|
6
|
-
attr_reader :host
|
7
|
-
|
8
|
-
# Creates A New Host Object
|
9
|
-
# @param [Object] Host Object
|
10
|
-
# @example
|
11
|
-
# Host.new(object)
|
12
|
-
def initialize(host)
|
13
|
-
@host = host
|
14
|
-
end
|
15
|
-
|
16
|
-
# Return the Host Object hostname.
|
17
|
-
# @return [String]
|
18
|
-
# The Host Object Hostname
|
19
|
-
# @example
|
20
|
-
# host.hostname #=> "127.0.0.1"
|
21
|
-
def hostname
|
22
|
-
@hostname ||= @host.at('HostName').inner_text
|
23
|
-
end
|
24
|
-
|
25
|
-
# Return the host scan start time.
|
26
|
-
# @return [DateTime]
|
27
|
-
# The Host Scan Start Time
|
28
|
-
# @example
|
29
|
-
# scan.scan_start_time #=> 'Fri Nov 11 23:36:54 1985'
|
30
|
-
def scan_start_time
|
31
|
-
if @host.at('startTime').inner_text.blank?
|
32
|
-
return false
|
33
|
-
else
|
34
|
-
@host_scan_time = DateTime.strptime(@host.at('startTime').inner_text, fmt='%a %b %d %H:%M:%S %Y')
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Return the host scan stop time.
|
39
|
-
# @return [DateTime]
|
40
|
-
# The Host Scan Stop Time
|
41
|
-
# @example
|
42
|
-
# scan.scan_start_time #=> 'Fri Nov 11 23:36:54 1985'
|
43
|
-
def scan_stop_time
|
44
|
-
if @host.at('stopTime').inner_text.blank?
|
45
|
-
return false
|
46
|
-
else
|
47
|
-
@host_scan_time = DateTime.strptime(@host.at('stopTime').inner_text, fmt='%a %b %d %H:%M:%S %Y')
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# Return the host run time.
|
52
|
-
# @return [String]
|
53
|
-
# The Host Scan Run Time
|
54
|
-
# @example
|
55
|
-
# scan.scan_run_time #=> '2 hours 5 minutes and 16 seconds'
|
56
|
-
def scan_runtime
|
57
|
-
h = ("#{Time.parse(scan_stop_time.to_s).strftime('%H').to_i - Time.parse(scan_start_time.to_s).strftime('%H').to_i}").gsub('-', '')
|
58
|
-
m = ("#{Time.parse(scan_stop_time.to_s).strftime('%M').to_i - Time.parse(scan_start_time.to_s).strftime('%M').to_i}").gsub('-', '')
|
59
|
-
s = ("#{Time.parse(scan_stop_time.to_s).strftime('%S').to_i - Time.parse(scan_start_time.to_s).strftime('%S').to_i}").gsub('-', '')
|
60
|
-
return "#{h} hours #{m} minutes and #{s} seconds"
|
61
|
-
end
|
62
|
-
|
63
|
-
# Return the Host Netbios Name.
|
64
|
-
# @return [String]
|
65
|
-
# The Host Netbios Name
|
66
|
-
# @example
|
67
|
-
# host.netbios_name #=> "SOMENAME4243"
|
68
|
-
def netbios_name
|
69
|
-
@netbios_name ||= @host.at('netbios_name').inner_text
|
70
|
-
end
|
71
|
-
|
72
|
-
# Return the Host Mac Address.
|
73
|
-
# @return [String]
|
74
|
-
# Return the Host Mac Address
|
75
|
-
# @example
|
76
|
-
# host.mac_addr #=> "00:11:22:33:44:55"
|
77
|
-
def mac_addr
|
78
|
-
@mac_addr ||= @host.at('mac_addr').inner_text
|
79
|
-
end
|
80
|
-
alias mac_address mac_addr
|
81
|
-
|
82
|
-
# Return the Host DNS Name.
|
83
|
-
# @return [String]
|
84
|
-
# Return the Host DNS Name
|
85
|
-
# @example
|
86
|
-
# host.dns_name #=> "snorby.org"
|
87
|
-
def dns_name
|
88
|
-
@dns_name ||= @host.at('dns_name').inner_text
|
89
|
-
end
|
90
|
-
|
91
|
-
# Return the Host OS Name.
|
92
|
-
# @return [String]
|
93
|
-
# Return the Host OS Name
|
94
|
-
# @example
|
95
|
-
# host.dns_name #=> "Microsoft Windows 2000, Microsoft Windows Server 2003"
|
96
|
-
def os_name
|
97
|
-
@os_name ||= @host.at('os_name').inner_text
|
98
|
-
end
|
99
|
-
alias operating_system os_name
|
100
|
-
|
101
|
-
# Return the open ports for a given host object.
|
102
|
-
# @return [Integer]
|
103
|
-
# Return the open ports for a given host object.
|
104
|
-
# @example
|
105
|
-
# host.open_ports #=> 213
|
106
|
-
def open_ports
|
107
|
-
@scanned_ports ||= @host.at('num_ports').inner_text.to_i
|
108
|
-
end
|
109
|
-
|
110
|
-
# Returns All Informational Event Objects For A Given Host.
|
111
|
-
# @yield [prog] If a block is given, it will be passed the newly
|
112
|
-
# created Event object.
|
113
|
-
# @yieldparam [EVENT] prog The newly created Event object.
|
114
|
-
# @return [Integer]
|
115
|
-
# Return The Informational Event Count For A Given Host.
|
116
|
-
# @example
|
117
|
-
# host.informational_events do |info|
|
118
|
-
# puts info.port
|
119
|
-
# puts info.data if info.data
|
120
|
-
# end
|
121
|
-
def informational_events(&block)
|
122
|
-
unless @informational_events
|
123
|
-
@informational_events = []
|
124
|
-
@informational_event_count = 0
|
125
|
-
|
126
|
-
@host.xpath("ReportItem").each do |event|
|
127
|
-
next if event.at('severity').inner_text.to_i != 0
|
128
|
-
@informational_events << Event.new(event)
|
129
|
-
@informational_event_count += 1
|
130
|
-
end
|
131
|
-
|
132
|
-
end
|
133
|
-
|
134
|
-
@informational_events.each(&block)
|
135
|
-
return @informational_event_count
|
136
|
-
end
|
137
|
-
|
138
|
-
# Returns All Low Event Objects For A Given Host.
|
139
|
-
# @yield [prog] If a block is given, it will be passed the newly
|
140
|
-
# created Event object.
|
141
|
-
# @yieldparam [EVENT] prog The newly created Event object.
|
142
|
-
# @return [Integer]
|
143
|
-
# Return The Low Event Count For A Given Host.
|
144
|
-
# @example
|
145
|
-
# host.low_severity_events do |low|
|
146
|
-
# puts low.name if low.name
|
147
|
-
# end
|
148
|
-
def low_severity_events(&block)
|
149
|
-
|
150
|
-
@low_severity_count = @host.at('num_lo').inner_text.to_i
|
151
|
-
|
152
|
-
unless @low_severity_events
|
153
|
-
@low_severity_events = []
|
154
|
-
|
155
|
-
@host.xpath("ReportItem").each do |event|
|
156
|
-
next if event.at('severity').inner_text.to_i != 1
|
157
|
-
@low_severity_events << Event.new(event)
|
158
|
-
end
|
159
|
-
|
160
|
-
end
|
161
|
-
|
162
|
-
@low_severity_events.each(&block)
|
163
|
-
return @low_severity_count
|
164
|
-
end
|
165
|
-
|
166
|
-
# Returns All Medium Event Objects For A Given Host.
|
167
|
-
# @yield [prog] If a block is given, it will be passed the newly
|
168
|
-
# created Event object.
|
169
|
-
# @yieldparam [EVENT] prog The newly created Event object.
|
170
|
-
# @return [Integer]
|
171
|
-
# Return The Medium Event Count For A Given Host.
|
172
|
-
# @example
|
173
|
-
# host.medium_severity_events do |medium|
|
174
|
-
# puts medium.name if medium.name
|
175
|
-
# end
|
176
|
-
def medium_severity_events(&block)
|
177
|
-
|
178
|
-
@high_severity_count = @host.at('num_med').inner_text.to_i
|
179
|
-
|
180
|
-
unless @medium_severity_events
|
181
|
-
@medium_severity_events = []
|
182
|
-
|
183
|
-
@host.xpath("ReportItem").each do |event|
|
184
|
-
next if event.at('severity').inner_text.to_i != 2
|
185
|
-
@medium_severity_events << Event.new(event)
|
186
|
-
end
|
187
|
-
|
188
|
-
end
|
189
|
-
|
190
|
-
@medium_severity_events.each(&block)
|
191
|
-
return @high_severity_count
|
192
|
-
end
|
193
|
-
|
194
|
-
# Returns All High Event Objects For A Given Host.
|
195
|
-
# @yield [prog] If a block is given, it will be passed the newly
|
196
|
-
# created Event object.
|
197
|
-
# @yieldparam [EVENT] prog The newly created Event object.
|
198
|
-
# @return [Integer]
|
199
|
-
# Return The High Event Count For A Given Host.
|
200
|
-
# @example
|
201
|
-
# host.high_severity_events do |high|
|
202
|
-
# puts high.name if high.name
|
203
|
-
# end
|
204
|
-
def high_severity_events(&block)
|
205
|
-
|
206
|
-
@high_severity_count = @host.at('num_hi').inner_text.to_i
|
207
|
-
|
208
|
-
unless @high_severity_events
|
209
|
-
@high_severity_events = []
|
210
|
-
|
211
|
-
@host.xpath("ReportItem").each do |event|
|
212
|
-
next if event.at('severity').inner_text.to_i != 3
|
213
|
-
@high_severity_events << Event.new(event)
|
214
|
-
end
|
215
|
-
|
216
|
-
end
|
217
|
-
|
218
|
-
@high_severity_events.each(&block)
|
219
|
-
return @high_severity_count
|
220
|
-
end
|
221
|
-
|
222
|
-
# Return the total event count for a given host.
|
223
|
-
# @return [Integer]
|
224
|
-
# Return the total event count for a given host.
|
225
|
-
# @example
|
226
|
-
# host.event_count #=> 3456
|
227
|
-
def event_count
|
228
|
-
((low_severity_events.to_i) + (medium_severity_events.to_i) + (high_severity_events.to_i)).to_i
|
229
|
-
end
|
230
|
-
|
231
|
-
# Creates a new Event object to be parser
|
232
|
-
# @yield [prog] If a block is given, it will be passed the newly
|
233
|
-
# created Event object.
|
234
|
-
# @yieldparam [EVENT] prog The newly created Event object.
|
235
|
-
# @example
|
236
|
-
# host.events do |event|
|
237
|
-
# puts event.name if event.name
|
238
|
-
# puts event.port
|
239
|
-
# end
|
240
|
-
def events(&block)
|
241
|
-
@host.xpath("ReportItem").each do |event|
|
242
|
-
block.call(Event.new(event)) if block
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
# Parses the events of the host.
|
247
|
-
# @return [Array<String>]
|
248
|
-
# The events of the host.
|
249
|
-
def all_events
|
250
|
-
Enumerator.new(self,:events).to_a
|
251
|
-
end
|
252
|
-
|
253
|
-
end
|
254
|
-
end
|
data/lib/ruby-nessus/port.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
module Nessus
|
2
|
-
class Port
|
3
|
-
|
4
|
-
# Port Service
|
5
|
-
attr_reader :service
|
6
|
-
# Port number
|
7
|
-
attr_reader :number
|
8
|
-
# Port Protocol
|
9
|
-
attr_reader :protocol
|
10
|
-
# Raw output string from nessus
|
11
|
-
attr_reader :raw_string
|
12
|
-
|
13
|
-
# Creates A New Port Object
|
14
|
-
# @param [String] service The Port Service.
|
15
|
-
# @param [Integer] number The Port number.
|
16
|
-
# @param [String] protocol The Port protocol.
|
17
|
-
# @param [String] raw output string from nessus.
|
18
|
-
# @example
|
19
|
-
# Port.new("ssh",22,"tcp", str)
|
20
|
-
def initialize(service,number,protocol,raw_string)
|
21
|
-
@service = service
|
22
|
-
@number = number
|
23
|
-
@protocol = protocol
|
24
|
-
@raw_string = raw_string
|
25
|
-
end
|
26
|
-
|
27
|
-
# Parse A passed port string and return a Port Object.
|
28
|
-
# @return [Object]
|
29
|
-
# New Port Object
|
30
|
-
# @example
|
31
|
-
# Port.parse(port)
|
32
|
-
def Port.parse(str)
|
33
|
-
begin
|
34
|
-
@full_port = str
|
35
|
-
components = str.match(/^([^\(]+)\((\d+)\/([^\)]+)\)/)
|
36
|
-
|
37
|
-
if components
|
38
|
-
return Port.new(components[1].strip, components[2].strip, components[3].strip, str)
|
39
|
-
else
|
40
|
-
return Port.new(false, false, false, str)
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
# Return true iF port protocol Ii tcp.
|
48
|
-
# @return [Boolean]
|
49
|
-
# Return True If The Port Protocol Is TCP.
|
50
|
-
def tcp?
|
51
|
-
@protocol == 'tcp'
|
52
|
-
end
|
53
|
-
|
54
|
-
# Return true iF port protocol Ii udp.
|
55
|
-
# @return [Boolean]
|
56
|
-
# Return True If The Port Protocol Is UDP.
|
57
|
-
def udp?
|
58
|
-
@protocol == 'udp'
|
59
|
-
end
|
60
|
-
|
61
|
-
# Return the port as a string.
|
62
|
-
# @return [String]
|
63
|
-
# Return The Port As A String
|
64
|
-
# @example
|
65
|
-
# port.to_s #=> https (443/tcp)
|
66
|
-
def to_s
|
67
|
-
if @service && @number && @protocol
|
68
|
-
"#{@service} (#{@number}/#{@protocol})"
|
69
|
-
else
|
70
|
-
"#{@raw_string}"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Return false if the port object number is nil
|
75
|
-
# @return [Boolean]
|
76
|
-
# Return false if the port object number is nil
|
77
|
-
def number
|
78
|
-
if @number
|
79
|
-
return @number
|
80
|
-
else
|
81
|
-
false
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
end
|
data/lib/ruby-nessus/xml.rb
DELETED
@@ -1,298 +0,0 @@
|
|
1
|
-
require 'ruby-nessus/host'
|
2
|
-
require 'ruby-nessus/event'
|
3
|
-
|
4
|
-
require 'nokogiri'
|
5
|
-
require 'enumerator'
|
6
|
-
require 'time'
|
7
|
-
|
8
|
-
module Nessus
|
9
|
-
# File to parse
|
10
|
-
attr_reader :file
|
11
|
-
|
12
|
-
class XML
|
13
|
-
|
14
|
-
include Enumerable
|
15
|
-
|
16
|
-
# Creates a new .Nessus (XML) object to be parser
|
17
|
-
# @param [String] file The Nessus xml results file to parse.
|
18
|
-
# @yield [prog] If a block is given, it will be passed the newly
|
19
|
-
# created XML object.
|
20
|
-
# @yieldparam [XML] prog The newly created XML object.
|
21
|
-
# @example
|
22
|
-
# Nessus::XML.new(nessus_scan_file) do |scan|
|
23
|
-
# scan.report_name
|
24
|
-
# end
|
25
|
-
def initialize(file, &block)
|
26
|
-
|
27
|
-
@file = File.open(file)
|
28
|
-
@xml = Nokogiri::XML.parse(@file.read)
|
29
|
-
|
30
|
-
block.call(self) if block
|
31
|
-
end
|
32
|
-
|
33
|
-
# Return the nessus report title.
|
34
|
-
# @return [String]
|
35
|
-
# The Nessus Report Title
|
36
|
-
# @example
|
37
|
-
# scan.report_name #=> "My Super Cool Nessus Report"
|
38
|
-
def title
|
39
|
-
@report_name ||= @xml.xpath("//NessusClientData//Report//ReportName").inner_text.split(' - ').last
|
40
|
-
end
|
41
|
-
|
42
|
-
# Return the nessus report time.
|
43
|
-
# @return [String]
|
44
|
-
# The Nessus Report Time
|
45
|
-
# @example
|
46
|
-
# scan.report_time #=> "09/11/08 02:21:22 AM"
|
47
|
-
def time
|
48
|
-
#09/11/08 02:21:22 AM
|
49
|
-
datetime = @xml.xpath("//NessusClientData//Report//ReportName").inner_text.split(' - ').first
|
50
|
-
@report_time ||= DateTime.strptime(datetime, fmt='%y/%m/%d %I:%M:%S %p')
|
51
|
-
end
|
52
|
-
|
53
|
-
# Return the scan start time.
|
54
|
-
# @return [DateTime]
|
55
|
-
# The Nessus Scan Start Time
|
56
|
-
# @example
|
57
|
-
# scan.start_time #=> 'Fri Nov 11 23:36:54 1985'
|
58
|
-
def start_time
|
59
|
-
@start_time = DateTime.strptime(@xml.xpath("//NessusClientData//Report//StartTime").inner_text, fmt='%a %b %d %H:%M:%S %Y')
|
60
|
-
end
|
61
|
-
|
62
|
-
# Return the scan stop time.
|
63
|
-
# @return [DateTime]
|
64
|
-
# The Nessus Scan Stop Time
|
65
|
-
# @example
|
66
|
-
# scan.stop_time #=> 'Mon Nov 11 23:36:54 1985'
|
67
|
-
def stop_time
|
68
|
-
@stop_time = DateTime.strptime(@xml.xpath("//NessusClientData//Report//StopTime").inner_text, fmt='%a %b %d %H:%M:%S %Y')
|
69
|
-
end
|
70
|
-
|
71
|
-
# Return the scan run time.
|
72
|
-
# @return [String]
|
73
|
-
# The Nessus Scan Run Time
|
74
|
-
# @example
|
75
|
-
# scan.runtime #=> '2 hours 5 minutes and 16 seconds'
|
76
|
-
def runtime
|
77
|
-
h = ("#{Time.parse(stop_time.to_s).strftime('%H').to_i - Time.parse(start_time.to_s).strftime('%H').to_i}").gsub('-', '')
|
78
|
-
m = ("#{Time.parse(stop_time.to_s).strftime('%M').to_i - Time.parse(start_time.to_s).strftime('%M').to_i}").gsub('-', '')
|
79
|
-
s = ("#{Time.parse(stop_time.to_s).strftime('%S').to_i - Time.parse(start_time.to_s).strftime('%S').to_i}").gsub('-', '')
|
80
|
-
return "#{h} hours #{m} minutes and #{s} seconds"
|
81
|
-
end
|
82
|
-
|
83
|
-
# Return the nessus scan policy name. When creating a nessus policy this is usually the title field.
|
84
|
-
# @return [String]
|
85
|
-
# The Nessus Scan Policy Name
|
86
|
-
def policy_title
|
87
|
-
@policy_name ||= @xml.xpath("//NessusClientData//Report//policyName").inner_text
|
88
|
-
end
|
89
|
-
|
90
|
-
# Return the nessus scan policy comments. This is the description field when creating a new policy with the Nessus GUI client.
|
91
|
-
# @return [String]
|
92
|
-
# The Nessus Scan Policy Comments
|
93
|
-
def policy_notes
|
94
|
-
@policy_comments ||= @xml.xpath("//NessusClientData//Report//policyComments").inner_text
|
95
|
-
end
|
96
|
-
|
97
|
-
# Returns and array of the plugin ids userd for the passed .nessus scan.
|
98
|
-
# @return [Array]
|
99
|
-
# The Nessus Scan Plugin Ids
|
100
|
-
# @example
|
101
|
-
# scan.plugin_ids #=> [1234,2343,9742,5452,5343,2423,1233]
|
102
|
-
def plugin_ids
|
103
|
-
unless @plugin_ids
|
104
|
-
@plugin_ids = []
|
105
|
-
|
106
|
-
@xml.xpath("//PluginSelection").last.text.split(';').each do |id|
|
107
|
-
@plugin_ids << id
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
@plugin_ids
|
112
|
-
end
|
113
|
-
|
114
|
-
# Returns and array of the plugin names userd for the passed .nessus scan.
|
115
|
-
# @return [Array]
|
116
|
-
# The Nessus Scan Plugin Names
|
117
|
-
# @example
|
118
|
-
# scan.plugins #=> ["PHP < 5.2.1 Multiple Vulnerabilities", "PHP < 4.4.1 / 5.0.6 Multiple Vulnerabilities"]
|
119
|
-
def plugins
|
120
|
-
unless @plugins
|
121
|
-
# get elements with attribute:
|
122
|
-
@plugins = []
|
123
|
-
|
124
|
-
@xml.xpath("//pluginName").each do |x|
|
125
|
-
@plugins << x.inner_text unless x.inner_text.empty?
|
126
|
-
end
|
127
|
-
|
128
|
-
@plugins.uniq!
|
129
|
-
@plugins.sort!
|
130
|
-
end
|
131
|
-
|
132
|
-
return @plugins
|
133
|
-
end
|
134
|
-
|
135
|
-
# Creates a new Host object to be parser
|
136
|
-
# @yield [prog] If a block is given, it will be passed the newly
|
137
|
-
# created Host object.
|
138
|
-
# @yieldparam [XML] prog The newly created Host object.
|
139
|
-
# @example
|
140
|
-
# scan.hosts do |host|
|
141
|
-
# puts host.hostname
|
142
|
-
# end
|
143
|
-
def hosts(&block)
|
144
|
-
hosts = []
|
145
|
-
@xml.xpath("//ReportHost").each do |host|
|
146
|
-
hosts << host.at('HostName').inner_text if host.at('HostName').inner_text
|
147
|
-
block.call(Host.new(host)) if block
|
148
|
-
end
|
149
|
-
hosts
|
150
|
-
end
|
151
|
-
|
152
|
-
# Parses the hosts of the scan.
|
153
|
-
# @return [Array<String>]
|
154
|
-
# The Hosts of the scan.
|
155
|
-
def all_hosts
|
156
|
-
Enumerator.new(self,:hosts).to_a
|
157
|
-
end
|
158
|
-
|
159
|
-
# Return the nessus scan host count.
|
160
|
-
# @return [Integer]
|
161
|
-
# The Nessus Scan Host Count
|
162
|
-
# @example
|
163
|
-
# scan.host_count #=> 23
|
164
|
-
def host_count
|
165
|
-
hosts.size
|
166
|
-
end
|
167
|
-
|
168
|
-
# Retunrs an array of all unique ports.
|
169
|
-
# @return [Array]
|
170
|
-
# @example
|
171
|
-
# scan.unique_ports #=> 234
|
172
|
-
def unique_ports
|
173
|
-
unless @unique_ports
|
174
|
-
@unique_ports = []
|
175
|
-
@xml.xpath("//ReportItem//port").each do |port|
|
176
|
-
@unique_ports << port.inner_text
|
177
|
-
end
|
178
|
-
@unique_ports.uniq!
|
179
|
-
@unique_ports.sort!
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
# Return the informational severity count.
|
184
|
-
# @return [Integer]
|
185
|
-
# The Informational Severity Count
|
186
|
-
# @example
|
187
|
-
# scan.informational_severity_count #=> 1203
|
188
|
-
def open_ports_count
|
189
|
-
count_severity[:open_ports].to_i
|
190
|
-
end
|
191
|
-
|
192
|
-
# Return the High severity count.
|
193
|
-
# @return [Integer]
|
194
|
-
# The High Severity Count
|
195
|
-
# @example
|
196
|
-
# scan.high_severity_count #=> 10
|
197
|
-
def high_severity_count
|
198
|
-
count_severity[:high].to_i
|
199
|
-
end
|
200
|
-
|
201
|
-
# Return the Medium severity count.
|
202
|
-
# @return [Integer]
|
203
|
-
# The Medium Severity Count
|
204
|
-
# @example
|
205
|
-
# scan.medium_severity_count #=> 234
|
206
|
-
def medium_severity_count
|
207
|
-
count_severity[:medium].to_i
|
208
|
-
end
|
209
|
-
|
210
|
-
# Return the Low severity count.
|
211
|
-
# @return [Integer]
|
212
|
-
# The Low Severity Count
|
213
|
-
# @example
|
214
|
-
# scan.low_severity_count #=> 114
|
215
|
-
def low_severity_count
|
216
|
-
count_severity[:low].to_i
|
217
|
-
end
|
218
|
-
|
219
|
-
# Return the Total severity count. [high, medium, low, informational]
|
220
|
-
# @return [Integer]
|
221
|
-
# The Total Severity Count
|
222
|
-
# @example
|
223
|
-
# scan.total_event_count #=> 1561
|
224
|
-
def total_event_count
|
225
|
-
count_severity[:all].to_i
|
226
|
-
end
|
227
|
-
|
228
|
-
# Return the Total severity count.
|
229
|
-
# @param [String] severity the severity in which to calculate percentage for.
|
230
|
-
# @param [Boolean] round round the result to the nearest whole number.
|
231
|
-
# @raise [ExceptionClass] One of the following severity options must be passed. [high, medium, low, informational, all]
|
232
|
-
# @return [Integer]
|
233
|
-
# The Percentage Of Events For A Passed Severity
|
234
|
-
# @example
|
235
|
-
# scan.event_percentage_for("low", true) #=> 11%
|
236
|
-
def event_percentage_for(type, round_percentage=false)
|
237
|
-
@sc ||= count_severity
|
238
|
-
if %W(high medium low all).include?(type)
|
239
|
-
calc = ((@sc[:"#{type}"].to_f / @sc[:all].to_f) * 100)
|
240
|
-
if round_percentage
|
241
|
-
return "#{calc.round}"
|
242
|
-
else
|
243
|
-
return "#{calc}"
|
244
|
-
end
|
245
|
-
else
|
246
|
-
raise "Error: #{type} is not an acceptable severity. Possible options include: all, high, medium, low and informational."
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
# Creates a new Host object to be parser from a passed search param.
|
251
|
-
# @param [String] hostname the hostname to build a Host object for.
|
252
|
-
# @yield [prog] If a block is given, it will be passed the newly
|
253
|
-
# created Host object.
|
254
|
-
# @yieldparam [XML] prog The newly created Host object.
|
255
|
-
# @example
|
256
|
-
# scan.find_by_hostname('127.0.0.1') do |host|
|
257
|
-
# puts host.hostname
|
258
|
-
# end
|
259
|
-
def find_by_hostname(hostname, &block)
|
260
|
-
raise "Error: hostname can't be blank." if hostname.blank?
|
261
|
-
@xml.xpath('//ReportHost[HostName]').each do |host|
|
262
|
-
next unless host.inner_text.match(hostname)
|
263
|
-
block.call(Host.new(host)) if block
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
|
-
private
|
268
|
-
|
269
|
-
# Calculates an event hash of totals for severity counts.
|
270
|
-
# @return [hash]
|
271
|
-
# The Event Totals For Severity
|
272
|
-
def count_severity
|
273
|
-
unless @count
|
274
|
-
@count = {}
|
275
|
-
@open_ports = 0
|
276
|
-
@low = 0
|
277
|
-
@medium = 0
|
278
|
-
@high = 0
|
279
|
-
|
280
|
-
@xml.xpath("//ReportHost").each do |s|
|
281
|
-
@open_ports += s.at('num_ports').inner_text.to_i
|
282
|
-
@low += s.at('num_lo').inner_text.to_i
|
283
|
-
@medium += s.at('num_med').inner_text.to_i
|
284
|
-
@high += s.at('num_hi').inner_text.to_i
|
285
|
-
end
|
286
|
-
|
287
|
-
@count = { :open_ports => @open_ports,
|
288
|
-
:low => @low,
|
289
|
-
:medium => @medium,
|
290
|
-
:high => @high,
|
291
|
-
:all => (@low + @medium + @high) }
|
292
|
-
end
|
293
|
-
|
294
|
-
return @count
|
295
|
-
end
|
296
|
-
|
297
|
-
end
|
298
|
-
end
|