nexpose 0.0.9 → 0.0.91
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/nexpose.rb +13 -3236
- data/lib/nexpose/api_request.rb +144 -0
- data/lib/nexpose/connection.rb +106 -0
- data/lib/nexpose/creds.rb +189 -0
- data/lib/nexpose/error.rb +21 -0
- data/lib/nexpose/misc.rb +122 -0
- data/lib/nexpose/report.rb +570 -0
- data/lib/nexpose/scan.rb +280 -0
- data/lib/nexpose/scan_engine.rb +147 -0
- data/lib/nexpose/silo.rb +347 -0
- data/lib/nexpose/site.rb +877 -0
- data/lib/nexpose/ticket.rb +108 -0
- data/lib/nexpose/util.rb +35 -0
- data/lib/nexpose/vuln.rb +520 -0
- data/nexpose.gemspec +3 -3
- metadata +22 -11
data/lib/nexpose/site.rb
ADDED
@@ -0,0 +1,877 @@
|
|
1
|
+
module Nexpose
|
2
|
+
module NexposeAPI
|
3
|
+
include XMLUtils
|
4
|
+
|
5
|
+
#
|
6
|
+
#
|
7
|
+
#
|
8
|
+
def site_device_listing(site_id)
|
9
|
+
r = execute(make_xml('SiteDeviceListingRequest', {'site-id' => site_id.to_s}))
|
10
|
+
|
11
|
+
if (r.success)
|
12
|
+
res = []
|
13
|
+
r.res.elements.each("//device") do |device|
|
14
|
+
res << {
|
15
|
+
:device_id => device.attributes['id'].to_i,
|
16
|
+
:address => device.attributes['address'].to_s,
|
17
|
+
:risk_factor => device.attributes['risk_factor'].to_f,
|
18
|
+
:risk_score => device.attributes['risk_score'].to_f,
|
19
|
+
}
|
20
|
+
end
|
21
|
+
res
|
22
|
+
else
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
#
|
29
|
+
#
|
30
|
+
def site_delete(param)
|
31
|
+
r = execute(make_xml('SiteDeleteRequest', {'site-id' => param}))
|
32
|
+
r.success
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
#
|
37
|
+
#
|
38
|
+
def site_listing
|
39
|
+
r = execute(make_xml('SiteListingRequest', {}))
|
40
|
+
|
41
|
+
if (r.success)
|
42
|
+
res = []
|
43
|
+
r.res.elements.each("//SiteSummary") do |site|
|
44
|
+
res << {
|
45
|
+
:site_id => site.attributes['id'].to_i,
|
46
|
+
:name => site.attributes['name'].to_s,
|
47
|
+
:risk_factor => site.attributes['riskfactor'].to_f,
|
48
|
+
:risk_score => site.attributes['riskscore'].to_f,
|
49
|
+
}
|
50
|
+
end
|
51
|
+
res
|
52
|
+
else
|
53
|
+
false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
#-----------------------------------------------------------------------
|
58
|
+
# TODO: Needs to be expanded to included details
|
59
|
+
#-----------------------------------------------------------------------
|
60
|
+
def site_scan_history(site_id)
|
61
|
+
r = execute(make_xml('SiteScanHistoryRequest', {'site-id' => site_id.to_s}))
|
62
|
+
|
63
|
+
if (r.success)
|
64
|
+
res = []
|
65
|
+
r.res.elements.each("//ScanSummary") do |site_scan_history|
|
66
|
+
res << {
|
67
|
+
:site_id => site_scan_history.attributes['site-id'].to_i,
|
68
|
+
:scan_id => site_scan_history.attributes['scan-id'].to_i,
|
69
|
+
:engine_id => site_scan_history.attributes['engine-id'].to_i,
|
70
|
+
:start_time => site_scan_history.attributes['startTime'].to_s,
|
71
|
+
:end_time => site_scan_history.attributes['endTime'].to_s
|
72
|
+
}
|
73
|
+
end
|
74
|
+
res
|
75
|
+
else
|
76
|
+
false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
#-----------------------------------------------------------------------
|
81
|
+
# Starts device specific site scanning.
|
82
|
+
#
|
83
|
+
# devices - An Array of device IDs
|
84
|
+
# hosts - An Array of Hashes [o]=>{:range=>"to,from"} [1]=>{:host=>host}
|
85
|
+
#-----------------------------------------------------------------------
|
86
|
+
def site_device_scan_start(site_id, devices, hosts)
|
87
|
+
|
88
|
+
if hosts == nil and devices == nil
|
89
|
+
raise ArgumentError.new("Both the device and host list is nil")
|
90
|
+
end
|
91
|
+
|
92
|
+
xml = make_xml('SiteDevicesScanRequest', {'site-id' => site_id})
|
93
|
+
|
94
|
+
if devices != nil
|
95
|
+
inner_xml = REXML::Element.new 'Devices'
|
96
|
+
for device_id in devices
|
97
|
+
inner_xml.add_element 'device', {'id' => "#{device_id}"}
|
98
|
+
end
|
99
|
+
xml.add_element inner_xml
|
100
|
+
end
|
101
|
+
|
102
|
+
if hosts != nil
|
103
|
+
inner_xml = REXML::Element.new 'Hosts'
|
104
|
+
hosts.each_index do |x|
|
105
|
+
if hosts[x].key? :range
|
106
|
+
to = hosts[x][:range].split(',')[0]
|
107
|
+
from = hosts[x][:range].split(',')[1]
|
108
|
+
inner_xml.add_element 'range', {'to' => "#{to}", 'from' => "#{from}"}
|
109
|
+
end
|
110
|
+
if hosts[x].key? :host
|
111
|
+
host_element = REXML::Element.new 'host'
|
112
|
+
host_element.text = "#{hosts[x][:host]}"
|
113
|
+
inner_xml.add_element host_element
|
114
|
+
end
|
115
|
+
end
|
116
|
+
xml.add_element inner_xml
|
117
|
+
end
|
118
|
+
|
119
|
+
r = execute xml
|
120
|
+
if r.success
|
121
|
+
r.res.elements.each('//Scan') do |scan_info|
|
122
|
+
return {
|
123
|
+
:scan_id => scan_info.attributes['scan-id'].to_i,
|
124
|
+
:engine_id => scan_info.attributes['engine-id'].to_i
|
125
|
+
}
|
126
|
+
end
|
127
|
+
else
|
128
|
+
false
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
#-------------------------------------------------------------------------------------------------------------------
|
134
|
+
# === Description
|
135
|
+
# Object that represents a site, including the site configuration, scan history, and device listing.
|
136
|
+
#
|
137
|
+
# === Example
|
138
|
+
# # Create a new Nexpose Connection on the default port and Login
|
139
|
+
# nsc = Connection.new("10.1.40.10","nxadmin","password")
|
140
|
+
# nsc.login()
|
141
|
+
#
|
142
|
+
# # Get an Existing Site
|
143
|
+
# site_existing = Site.new(nsc,184)
|
144
|
+
#
|
145
|
+
# # Create a New Site, add some hosts, and save it to the NSC
|
146
|
+
# site = Site.new(nsc)
|
147
|
+
# site.setSiteConfig("New Site", "New Site Created in the API")
|
148
|
+
#
|
149
|
+
# # Add the hosts
|
150
|
+
# site.site_config.addHost(HostName.new("localhost"))
|
151
|
+
# site.site_config.addHost(IPRange.new("192.168.7.1","192.168.7.255"))
|
152
|
+
# site.site_config.addHost(IPRange.new("10.1.20.30"))
|
153
|
+
#
|
154
|
+
# status = site.saveSite()
|
155
|
+
#-------------------------------------------------------------------------------------------------------------------
|
156
|
+
class Site
|
157
|
+
# true if an error condition exists; false otherwise
|
158
|
+
attr_reader :error
|
159
|
+
# Error message string
|
160
|
+
attr_reader :error_msg
|
161
|
+
# The last XML request sent by this object
|
162
|
+
attr_reader :request_xml
|
163
|
+
# The last XML response received by this object
|
164
|
+
attr_reader :response_xml
|
165
|
+
# The NSC Connection associated with this object
|
166
|
+
attr_reader :connection
|
167
|
+
# The Site ID
|
168
|
+
# site_id = -1 means create a new site. The NSC will assign a new site_id on SiteSave.
|
169
|
+
attr_reader :site_id
|
170
|
+
# A summary overview of this site
|
171
|
+
# SiteSummary Object
|
172
|
+
attr_reader :site_summary
|
173
|
+
# The configuration of this site
|
174
|
+
# SiteConfig Object
|
175
|
+
attr_reader :site_config
|
176
|
+
# The device listing for this site
|
177
|
+
# SiteDeviceListing Object
|
178
|
+
attr_reader :site_device_listing
|
179
|
+
# The scan history of this site
|
180
|
+
# SiteScanHistory Object
|
181
|
+
attr_reader :site_scan_history
|
182
|
+
|
183
|
+
def initialize(connection, site_id = -1)
|
184
|
+
@error = false
|
185
|
+
@connection = connection
|
186
|
+
@site_id = site_id
|
187
|
+
|
188
|
+
# If site_id > 0 then get SiteConfig
|
189
|
+
if (@site_id.to_i > 0)
|
190
|
+
# Create new SiteConfig object
|
191
|
+
@site_config = SiteConfig.new()
|
192
|
+
# Populate SiteConfig Obect with Data from the NSC
|
193
|
+
@site_config.getSiteConfig(@connection, @site_id)
|
194
|
+
@site_summary = SiteSummary.new(@site_id, @site_config.site_name, @site_config.description, @site_config.riskfactor)
|
195
|
+
@site_scan_history = SiteScanHistory.new(@connection, @site_id)
|
196
|
+
@site_device_listing = SiteDeviceListing.new(@connection, @site_id)
|
197
|
+
|
198
|
+
else
|
199
|
+
# Just in case user enters a number > -1 or = 0
|
200
|
+
@site_id = -1
|
201
|
+
|
202
|
+
@site_config = SiteConfig.new()
|
203
|
+
setSiteConfig("New Site " + rand(999999999999).to_s, "")
|
204
|
+
@site_summary = nil
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
# Creates a new site summary
|
211
|
+
def setSiteSummary(site_name, description, riskfactor = 1)
|
212
|
+
@site_summary = SiteSummary.new(-1, site_name, description, riskfactor)
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
# Creates a new site configuration
|
217
|
+
def setSiteConfig(site_name, description, riskfactor = 1)
|
218
|
+
setSiteSummary(site_name, description, riskfactor)
|
219
|
+
@site_config = SiteConfig.new()
|
220
|
+
@site_config._set_site_id(-1)
|
221
|
+
@site_config._set_site_name(site_name)
|
222
|
+
@site_config._set_description(description)
|
223
|
+
@site_config._set_riskfactor(riskfactor)
|
224
|
+
@site_config._set_scanConfig(ScanConfig.new(-1, "tmp", "full-audit"))
|
225
|
+
@site_config._set_connection(@connection)
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
# Initiates a scan of this site. If successful returns scan_id and engine_id in an associative array. Returns false if scan is unsuccessful.
|
230
|
+
def scanSite()
|
231
|
+
r = @connection.execute('<SiteScanRequest session-id="' + "#{@connection.session_id}" + '" site-id="' + "#{@site_id}" + '"/>')
|
232
|
+
if (r.success)
|
233
|
+
res = {}
|
234
|
+
r.res.elements.each('//Scan/') do |s|
|
235
|
+
res[:scan_id] = s.attributes['scan-id']
|
236
|
+
res[:engine_id] = s.attributes['engine-id']
|
237
|
+
end
|
238
|
+
return res
|
239
|
+
else
|
240
|
+
return false
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# Saves this site in the NSC
|
245
|
+
def saveSite()
|
246
|
+
r = @connection.execute('<SiteSaveRequest session-id="' + @connection.session_id + '">' + getSiteXML() + ' </SiteSaveRequest>')
|
247
|
+
if (r.success)
|
248
|
+
@site_id = r.attributes['site-id']
|
249
|
+
@site_config._set_site_id(@site_id)
|
250
|
+
@site_config.scanConfig._set_configID(@site_id)
|
251
|
+
@site_config.scanConfig._set_name(@site_id)
|
252
|
+
return true
|
253
|
+
else
|
254
|
+
return false
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def deleteSite()
|
259
|
+
r = @connection.execute('<SiteDeleteRequest session-id="' + @connection.session_id.to_s + '" site-id="' + @site_id + '"/>')
|
260
|
+
r.success
|
261
|
+
end
|
262
|
+
|
263
|
+
|
264
|
+
def printSite()
|
265
|
+
puts "Site ID: " + @site_summary.id
|
266
|
+
puts "Site Name: " + @site_summary.site_name
|
267
|
+
puts "Site Description: " + @site_summary.description
|
268
|
+
puts "Site Risk Factor: " + @site_summary.riskfactor
|
269
|
+
end
|
270
|
+
|
271
|
+
def getSiteXML()
|
272
|
+
|
273
|
+
xml = '<Site id="' + "#{@site_config.site_id}" + '" name="' + "#{@site_config.site_name}" + '" description="' + "#{@site_config.description}" + '" riskfactor="' + "#{@site_config.riskfactor}" + '">'
|
274
|
+
|
275
|
+
xml << ' <Hosts>'
|
276
|
+
@site_config.hosts.each do |h|
|
277
|
+
xml << h.to_xml if h.respond_to? :to_xml
|
278
|
+
end
|
279
|
+
xml << '</Hosts>'
|
280
|
+
|
281
|
+
xml << '<Credentials>'
|
282
|
+
@site_config.credentials.each do |c|
|
283
|
+
xml << c.to_xml if c.respond_to? :to_xml
|
284
|
+
end
|
285
|
+
xml << ' </Credentials>'
|
286
|
+
|
287
|
+
xml << ' <Alerting>'
|
288
|
+
@site_config.alerts.each do |a|
|
289
|
+
xml << a.to_xml if a.respond_to? :to_xml
|
290
|
+
end
|
291
|
+
xml << ' </Alerting>'
|
292
|
+
|
293
|
+
xml << ' <ScanConfig configID="' + "#{@site_config.scanConfig.configID}" + '" name="' + "#{@site_config.scanConfig.name}" + '" templateID="' + "#{@site_config.scanConfig.templateID}" + '" configVersion="' + "#{@site_config.scanConfig.configVersion}" + '">'
|
294
|
+
|
295
|
+
xml << ' <Schedules>'
|
296
|
+
@site_config.scanConfig.schedules.each do |s|
|
297
|
+
xml << ' <Schedule enabled="' + s.enabled + '" type="' + s.type + '" interval="' + s.interval + '" start="' + s.start + '"/>'
|
298
|
+
end
|
299
|
+
xml << ' </Schedules>'
|
300
|
+
|
301
|
+
xml << ' <ScanTriggers>'
|
302
|
+
@site_config.scanConfig.scanTriggers.each do |s|
|
303
|
+
|
304
|
+
if (s.class.to_s == "Nexpose::AutoUpdate")
|
305
|
+
xml << ' <autoUpdate enabled="' + s.enabled + '" incremental="' + s.incremental + '"/>'
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
xml << ' </ScanTriggers>'
|
310
|
+
|
311
|
+
xml << ' </ScanConfig>'
|
312
|
+
|
313
|
+
xml << ' </Site>'
|
314
|
+
|
315
|
+
xml
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
# === Description
|
320
|
+
# Object that represents a listing of all of the sites available on an NSC.
|
321
|
+
#
|
322
|
+
# === Example
|
323
|
+
# # Create a new Nexpose Connection on the default port and Login
|
324
|
+
# nsc = Connection.new("10.1.40.10","nxadmin","password")
|
325
|
+
# nsc->login();
|
326
|
+
#
|
327
|
+
# # Get Site Listing
|
328
|
+
# sitelisting = SiteListing.new(nsc)
|
329
|
+
#
|
330
|
+
# # Enumerate through all of the SiteSummaries
|
331
|
+
# sitelisting.sites.each do |sitesummary|
|
332
|
+
# # Do some operation on each site
|
333
|
+
# end
|
334
|
+
#
|
335
|
+
class SiteListing
|
336
|
+
# true if an error condition exists; false otherwise
|
337
|
+
attr_reader :error
|
338
|
+
# Error message string
|
339
|
+
attr_reader :error_msg
|
340
|
+
# The last XML request sent by this object
|
341
|
+
attr_reader :request_xml
|
342
|
+
# The last XML response received by this object
|
343
|
+
attr_reader :response_xml
|
344
|
+
# The NSC Connection associated with this object
|
345
|
+
attr_reader :connection
|
346
|
+
# Array containing SiteSummary objects for each site in the connection
|
347
|
+
attr_reader :sites
|
348
|
+
# The number of sites
|
349
|
+
attr_reader :site_count
|
350
|
+
|
351
|
+
# Constructor
|
352
|
+
# SiteListing (connection)
|
353
|
+
def initialize(connection)
|
354
|
+
@sites = []
|
355
|
+
|
356
|
+
@connection = connection
|
357
|
+
|
358
|
+
r = @connection.execute('<SiteListingRequest session-id="' + @connection.session_id.to_s + '"/>')
|
359
|
+
|
360
|
+
if (r.success)
|
361
|
+
parse(r.res)
|
362
|
+
else
|
363
|
+
raise APIError.new(r, "Failed to get site listing")
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
def parse(r)
|
368
|
+
r.elements.each('SiteListingResponse/SiteSummary') do |s|
|
369
|
+
site_summary = SiteSummary.new(
|
370
|
+
s.attributes['id'].to_s,
|
371
|
+
s.attributes['name'].to_s,
|
372
|
+
s.attributes['description'].to_s,
|
373
|
+
s.attributes['riskfactor'].to_s
|
374
|
+
)
|
375
|
+
@sites.push(site_summary)
|
376
|
+
end
|
377
|
+
@site_count = @sites.length
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
# === Description
|
382
|
+
# Object that represents the summary of a NeXpose Site.
|
383
|
+
#
|
384
|
+
class SiteSummary
|
385
|
+
# The Site ID
|
386
|
+
attr_reader :id
|
387
|
+
# The Site Name
|
388
|
+
attr_reader :site_name
|
389
|
+
# A Description of the Site
|
390
|
+
attr_reader :description
|
391
|
+
# User assigned risk multiplier
|
392
|
+
attr_reader :riskfactor
|
393
|
+
|
394
|
+
# Constructor
|
395
|
+
# SiteSummary(id, site_name, description, riskfactor = 1)
|
396
|
+
def initialize(id, site_name, description, riskfactor = 1)
|
397
|
+
@id = id
|
398
|
+
@site_name = site_name
|
399
|
+
@description = description
|
400
|
+
@riskfactor = riskfactor
|
401
|
+
end
|
402
|
+
|
403
|
+
def _set_id(id)
|
404
|
+
@id = id
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
# === Description
|
409
|
+
# Object that represents the configuration of a Site. This object is automatically created when a new Site object is instantiated.
|
410
|
+
#
|
411
|
+
class SiteConfig
|
412
|
+
# true if an error condition exists; false otherwise
|
413
|
+
attr_reader :error
|
414
|
+
# Error message string
|
415
|
+
attr_reader :error_msg
|
416
|
+
# The last XML request sent by this object
|
417
|
+
attr_reader :request_xml
|
418
|
+
# The last XML response received by this object
|
419
|
+
attr_reader :response_xml
|
420
|
+
# The NSC Connection associated with this object
|
421
|
+
attr_reader :connection
|
422
|
+
# The Site ID
|
423
|
+
attr_reader :site_id
|
424
|
+
# The Site Name
|
425
|
+
attr_reader :site_name
|
426
|
+
# A Description of the Site
|
427
|
+
attr_reader :description
|
428
|
+
# User assigned risk multiplier
|
429
|
+
attr_reader :riskfactor
|
430
|
+
# Array containing ((IPRange|HostName)*)
|
431
|
+
attr_reader :hosts
|
432
|
+
# Array containing (AdminCredentials*)
|
433
|
+
attr_reader :credentials
|
434
|
+
# Array containing ((SmtpAlera|SnmpAlert|SyslogAlert)*)
|
435
|
+
attr_reader :alerts
|
436
|
+
# ScanConfig object which holds Schedule and ScanTrigger Objects
|
437
|
+
attr_reader :scanConfig
|
438
|
+
|
439
|
+
def initialize()
|
440
|
+
@xml_tag_stack = Array.new()
|
441
|
+
@hosts = Array.new()
|
442
|
+
@credentials = Array.new()
|
443
|
+
@alerts = Array.new()
|
444
|
+
@error = false
|
445
|
+
end
|
446
|
+
|
447
|
+
# Adds a new host to the hosts array
|
448
|
+
def addHost(host)
|
449
|
+
@hosts.push(host)
|
450
|
+
end
|
451
|
+
|
452
|
+
# Adds a new alert to the alerts array
|
453
|
+
def addAlert(alert)
|
454
|
+
@alerts.push(alert)
|
455
|
+
end
|
456
|
+
|
457
|
+
# Adds a new set of credentials to the credentials array
|
458
|
+
def addCredentials(credential)
|
459
|
+
@credentials.push(credential)
|
460
|
+
end
|
461
|
+
|
462
|
+
# TODO
|
463
|
+
def getSiteConfig(connection, site_id)
|
464
|
+
@connection = connection
|
465
|
+
@site_id = site_id
|
466
|
+
|
467
|
+
r = APIRequest.execute(@connection.url, '<SiteConfigRequest session-id="' + @connection.session_id + '" site-id="' + "#{@site_id}" + '"/>')
|
468
|
+
parse(r.res)
|
469
|
+
end
|
470
|
+
|
471
|
+
def _set_site_id(site_id)
|
472
|
+
@site_id = site_id
|
473
|
+
end
|
474
|
+
|
475
|
+
def _set_site_name(site_name)
|
476
|
+
@site_name = site_name
|
477
|
+
end
|
478
|
+
|
479
|
+
def _set_description(description)
|
480
|
+
@description = description
|
481
|
+
end
|
482
|
+
|
483
|
+
def _set_riskfactor(riskfactor)
|
484
|
+
@riskfactor = riskfactor
|
485
|
+
end
|
486
|
+
|
487
|
+
def _set_scanConfig(scanConfig)
|
488
|
+
@scanConfig = scanConfig
|
489
|
+
end
|
490
|
+
|
491
|
+
def _set_connection(connection)
|
492
|
+
@connection = connection
|
493
|
+
end
|
494
|
+
|
495
|
+
|
496
|
+
def parse(response)
|
497
|
+
response.elements.each('SiteConfigResponse/Site') do |s|
|
498
|
+
@site_id = s.attributes['id']
|
499
|
+
@site_name = s.attributes['name']
|
500
|
+
@description = s.attributes['description']
|
501
|
+
@riskfactor = s.attributes['riskfactor']
|
502
|
+
s.elements.each('Hosts/range') do |r|
|
503
|
+
@hosts.push(IPRange.new(r.attributes['from'], r.attributes['to']))
|
504
|
+
end
|
505
|
+
s.elements.each('ScanConfig') do |c|
|
506
|
+
@scanConfig = ScanConfig.new(c.attributes['configID'],
|
507
|
+
c.attributes['name'],
|
508
|
+
c.attributes['templateID'],
|
509
|
+
c.attributes['configVersion'])
|
510
|
+
s.elements.each('Schedule') do |schedule|
|
511
|
+
schedule = new Schedule(schedule.attributes["type"], schedule.attributes["interval"], schedule.attributes["start"], schedule.attributes["enabled"])
|
512
|
+
@scanConfig.addSchedule(schedule)
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
s.elements.each('Alerting/Alert') do |a|
|
517
|
+
|
518
|
+
a.elements.each('smtpAlert') do |smtp|
|
519
|
+
smtp_alert = SmtpAlert.new(a.attributes["name"], smtp.attributes["sender"], smtp.attributes["limitText"], a.attributes["enabled"])
|
520
|
+
|
521
|
+
smtp.elements.each('recipient') do |recipient|
|
522
|
+
smtp_alert.addRecipient(recipient.text)
|
523
|
+
end
|
524
|
+
@alerts.push(smtp_alert)
|
525
|
+
end
|
526
|
+
|
527
|
+
a.elements.each('snmpAlert') do |snmp|
|
528
|
+
snmp_alert = SnmpAlert.new(a.attributes["name"], snmp.attributes["community"], snmp.attributes["server"], a.attributes["enabled"])
|
529
|
+
@alerts.push(snmp_alert)
|
530
|
+
end
|
531
|
+
a.elements.each('syslogAlert') do |syslog|
|
532
|
+
syslog_alert = SyslogAlert.new(a.attributes["name"], syslog.attributes["server"], a.attributes["enabled"])
|
533
|
+
@alerts.push(syslog_alert)
|
534
|
+
end
|
535
|
+
|
536
|
+
a.elements.each('vulnFilter') do |vulnFilter|
|
537
|
+
|
538
|
+
#vulnfilter = new VulnFilter.new(a.attributes["typemask"], a.attributes["severityThreshold"], $attrs["MAXALERTS"])
|
539
|
+
# Pop off the top alert on the stack
|
540
|
+
#$alert = @alerts.pop()
|
541
|
+
# Add the new recipient string to the Alert Object
|
542
|
+
#$alert.setVulnFilter($vulnfilter)
|
543
|
+
# Push the alert back on to the alert stack
|
544
|
+
#array_push($this->alerts, $alert)
|
545
|
+
end
|
546
|
+
|
547
|
+
a.elements.each('scanFilter') do |scanFilter|
|
548
|
+
#<scanFilter scanStop='0' scanFailed='0' scanStart='1'/>
|
549
|
+
#scanfilter = ScanFilter.new(scanFilter.attributes['scanStop'],scanFilter.attributes['scanFailed'],scanFilter.attributes['scanStart'])
|
550
|
+
#alert = @alerts.pop()
|
551
|
+
#alert.setScanFilter(scanfilter)
|
552
|
+
#@alerts.push(alert)
|
553
|
+
end
|
554
|
+
end
|
555
|
+
end
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
# === Description
|
560
|
+
# Object that represents the scan history of a site.
|
561
|
+
#
|
562
|
+
class SiteScanHistory
|
563
|
+
# true if an error condition exists; false otherwise
|
564
|
+
attr_reader :error
|
565
|
+
# Error message string
|
566
|
+
attr_reader :error_msg
|
567
|
+
# The last XML request sent by this object
|
568
|
+
attr_reader :request_xml
|
569
|
+
# The last XML response received by this object
|
570
|
+
attr_reader :response_xml
|
571
|
+
# The NSC Connection associated with this object
|
572
|
+
attr_reader :connection
|
573
|
+
# The Site ID
|
574
|
+
attr_reader :site_id
|
575
|
+
# //Array containing (ScanSummary*)
|
576
|
+
attr_reader :scan_summaries
|
577
|
+
|
578
|
+
def initialize(connection, id)
|
579
|
+
@site_id = id
|
580
|
+
@error = false
|
581
|
+
@connection = connection
|
582
|
+
@scan_summaries = Array.new()
|
583
|
+
|
584
|
+
r = @connection.execute('<SiteScanHistoryRequest' + ' session-id="' + @connection.session_id + '" site-id="' + "#{@site_id}" + '"/>')
|
585
|
+
status = r.success
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
# === Description
|
590
|
+
# Object that represents a listing of devices for a site or the entire NSC. Note that only devices which are accessible to the account used to create the connection object will be returned. This object is created and populated automatically with the instantiation of a new Site object.
|
591
|
+
#
|
592
|
+
class SiteDeviceListing
|
593
|
+
|
594
|
+
# true if an error condition exists; false otherwise
|
595
|
+
attr_reader :error
|
596
|
+
# Error message string
|
597
|
+
attr_reader :error_msg
|
598
|
+
# The last XML request sent by this object
|
599
|
+
attr_reader :request_xml
|
600
|
+
# The last XML response received by this object
|
601
|
+
attr_reader :response_xml
|
602
|
+
# The NSC Connection associated with this object
|
603
|
+
attr_reader :connection
|
604
|
+
# The Site ID. 0 if all sites are specified.
|
605
|
+
attr_reader :site_id
|
606
|
+
# //Array of (Device)*
|
607
|
+
attr_reader :devices
|
608
|
+
|
609
|
+
def initialize(connection, site_id = 0)
|
610
|
+
|
611
|
+
@site_id = site_id
|
612
|
+
@error = false
|
613
|
+
@connection = connection
|
614
|
+
@devices = Array.new()
|
615
|
+
|
616
|
+
r = nil
|
617
|
+
if (@site_id)
|
618
|
+
r = @connection.execute('<SiteDeviceListingRequest session-id="' + connection.session_id + '" site-id="' + "#{@site_id}" + '"/>')
|
619
|
+
else
|
620
|
+
r = @connection.execute('<SiteDeviceListingRequest session-id="' + connection.session_id + '"/>')
|
621
|
+
end
|
622
|
+
|
623
|
+
if (r.success)
|
624
|
+
r.res.elements.each('SiteDeviceListingResponse/SiteDevices/device') do |d|
|
625
|
+
@devices.push(Device.new(d.attributes['id'], @site_id, d.attributes["address"], d.attributes["riskfactor"], d.attributes['riskscore']))
|
626
|
+
end
|
627
|
+
end
|
628
|
+
end
|
629
|
+
end
|
630
|
+
|
631
|
+
# === Description
|
632
|
+
# Object that represents a single device in an NSC.
|
633
|
+
#
|
634
|
+
class Device
|
635
|
+
|
636
|
+
# A unique device ID (assigned by the NSC)
|
637
|
+
attr_reader :id
|
638
|
+
# The site ID of this devices site
|
639
|
+
attr_reader :site_id
|
640
|
+
# IP Address or Hostname of this device
|
641
|
+
attr_reader :address
|
642
|
+
# User assigned risk multiplier
|
643
|
+
attr_reader :riskfactor
|
644
|
+
# NeXpose risk score
|
645
|
+
attr_reader :riskscore
|
646
|
+
|
647
|
+
def initialize(id, site_id, address, riskfactor=1, riskscore=0)
|
648
|
+
@id = id
|
649
|
+
@site_id = site_id
|
650
|
+
@address = address
|
651
|
+
@riskfactor = riskfactor
|
652
|
+
@riskscore = riskscore
|
653
|
+
|
654
|
+
end
|
655
|
+
end
|
656
|
+
|
657
|
+
# === Description
|
658
|
+
# Object that holds a scan schedule
|
659
|
+
#
|
660
|
+
class Schedule
|
661
|
+
# Type of Schedule (daily|hourly|monthly|weekly)
|
662
|
+
attr_reader :type
|
663
|
+
# The schedule interval
|
664
|
+
attr_reader :interval
|
665
|
+
# The date and time to start the first scan
|
666
|
+
attr_reader :start
|
667
|
+
# Enable or disable this schedule
|
668
|
+
attr_reader :enabled
|
669
|
+
# The date and time to disable to schedule. If null then the schedule will run forever.
|
670
|
+
attr_reader :notValidAfter
|
671
|
+
# Scan on the same date each time
|
672
|
+
attr_reader :byDate
|
673
|
+
|
674
|
+
def initialize(type, interval, start, enabled = 1)
|
675
|
+
|
676
|
+
@type = type
|
677
|
+
@interval = interval
|
678
|
+
@start = start
|
679
|
+
@enabled = enabled
|
680
|
+
|
681
|
+
end
|
682
|
+
end
|
683
|
+
|
684
|
+
# === Description
|
685
|
+
# Object that represents a Syslog Alert.
|
686
|
+
#
|
687
|
+
class SyslogAlert
|
688
|
+
|
689
|
+
# A unique name for this alert
|
690
|
+
attr_reader :name
|
691
|
+
# If this alert is enabled or not
|
692
|
+
attr_reader :enabled
|
693
|
+
# The Syslog server to sent this alert
|
694
|
+
attr_reader :server
|
695
|
+
# The vulnerability filter to trigger the alert
|
696
|
+
attr_reader :vulnFilter
|
697
|
+
# The alert type
|
698
|
+
attr_reader :type
|
699
|
+
|
700
|
+
def initialize(name, server, enabled = 1)
|
701
|
+
@type = :syslog
|
702
|
+
@name = name
|
703
|
+
@server = server
|
704
|
+
@enabled = enabled
|
705
|
+
# Sets default vuln filter - All Events
|
706
|
+
setVulnFilter(VulnFilter.new("50790400", 1))
|
707
|
+
|
708
|
+
end
|
709
|
+
|
710
|
+
# Sets the Vulnerability Filter for this alert.
|
711
|
+
def setVulnFilter(vulnFilter)
|
712
|
+
@vulnFilter = vulnFilter
|
713
|
+
end
|
714
|
+
|
715
|
+
include Sanitize
|
716
|
+
|
717
|
+
def to_xml
|
718
|
+
xml = "<syslogAlert"
|
719
|
+
xml << %Q{ name="#{replace_entities(name)}"}
|
720
|
+
xml << %Q{ enabled="#{replace_entities(enabled)}"}
|
721
|
+
xml << %Q{ server="#{replace_entities(server)}">}
|
722
|
+
xml << vulnFilter.to_xml
|
723
|
+
xml << "</syslogAlert>"
|
724
|
+
xml
|
725
|
+
end
|
726
|
+
|
727
|
+
end
|
728
|
+
|
729
|
+
# === Description
|
730
|
+
# Object that represents an SNMP Alert.
|
731
|
+
#
|
732
|
+
class SnmpAlert
|
733
|
+
include Sanitize
|
734
|
+
|
735
|
+
# A unique name for this alert
|
736
|
+
attr_reader :name
|
737
|
+
# If this alert is enabled or not
|
738
|
+
attr_reader :enabled
|
739
|
+
# The community string
|
740
|
+
attr_reader :community
|
741
|
+
# The SNMP server to sent this alert
|
742
|
+
attr_reader :server
|
743
|
+
# The vulnerability filter to trigger the alert
|
744
|
+
attr_reader :vulnFilter
|
745
|
+
# The alert type
|
746
|
+
attr_reader :type
|
747
|
+
|
748
|
+
def initialize(name, community, server, enabled = 1)
|
749
|
+
@type = :snmp
|
750
|
+
@name = name
|
751
|
+
@community = community
|
752
|
+
@server = server
|
753
|
+
@enabled = enabled
|
754
|
+
# Sets default vuln filter - All Events
|
755
|
+
setVulnFilter(VulnFilter.new("50790400", 1))
|
756
|
+
end
|
757
|
+
|
758
|
+
# Sets the Vulnerability Filter for this alert.
|
759
|
+
def setVulnFilter(vulnFilter)
|
760
|
+
@vulnFilter = vulnFilter
|
761
|
+
end
|
762
|
+
|
763
|
+
def to_xml
|
764
|
+
xml = "<snmpAlert"
|
765
|
+
xml << %Q{ name="#{replace_entities(name)}"}
|
766
|
+
xml << %Q{ enabled="#{replace_entities(enabled)}"}
|
767
|
+
xml << %Q{ community="#{replace_entities(community)}"}
|
768
|
+
xml << %Q{ server="#{replace_entities(server)}">}
|
769
|
+
xml << vulnFilter.to_xml
|
770
|
+
xml << "</snmpAlert>"
|
771
|
+
xml
|
772
|
+
end
|
773
|
+
|
774
|
+
end
|
775
|
+
|
776
|
+
# === Description
|
777
|
+
# Object that represents an SMTP (Email) Alert.
|
778
|
+
#
|
779
|
+
class SmtpAlert
|
780
|
+
# A unique name for this alert
|
781
|
+
attr_reader :name
|
782
|
+
# If this alert is enabled or not
|
783
|
+
attr_reader :enabled
|
784
|
+
# The email address of the sender
|
785
|
+
attr_reader :sender
|
786
|
+
# Limit the text for mobile devices
|
787
|
+
attr_reader :limitText
|
788
|
+
# Array containing Strings of email addresses
|
789
|
+
# Array of strings with the email addresses of the intended recipients
|
790
|
+
attr_reader :recipients
|
791
|
+
# The vulnerability filter to trigger the alert
|
792
|
+
attr_reader :vulnFilter
|
793
|
+
# The alert type
|
794
|
+
attr_reader :type
|
795
|
+
|
796
|
+
def initialize(name, sender, limitText, enabled = 1)
|
797
|
+
@type = :smtp
|
798
|
+
@name = name
|
799
|
+
@sender = sender
|
800
|
+
@enabled = enabled
|
801
|
+
@limitText = limitText
|
802
|
+
@recipients = Array.new()
|
803
|
+
# Sets default vuln filter - All Events
|
804
|
+
setVulnFilter(VulnFilter.new("50790400", 1))
|
805
|
+
end
|
806
|
+
|
807
|
+
# Adds a new Recipient to the recipients array
|
808
|
+
def addRecipient(recipient)
|
809
|
+
@recipients.push(recipient)
|
810
|
+
end
|
811
|
+
|
812
|
+
# Sets the Vulnerability Filter for this alert.
|
813
|
+
def setVulnFilter(vulnFilter)
|
814
|
+
@vulnFilter = vulnFilter
|
815
|
+
end
|
816
|
+
|
817
|
+
include Sanitize
|
818
|
+
|
819
|
+
def to_xml
|
820
|
+
xml = "<smtpAlert"
|
821
|
+
xml << %Q{ name="#{replace_entities(name)}"}
|
822
|
+
xml << %Q{ enabled="#{replace_entities(enabled)}"}
|
823
|
+
xml << %Q{ sender="#{replace_entities(sender)}"}
|
824
|
+
xml << %Q{ limitText="#{replace_entities(limitText)}">}
|
825
|
+
recipients.each do |recpt|
|
826
|
+
xml << "<recipient>#{replace_entities(recpt)}</recipient>"
|
827
|
+
end
|
828
|
+
xml << vulnFilter.to_xml
|
829
|
+
xml << "</smtpAlert>"
|
830
|
+
xml
|
831
|
+
end
|
832
|
+
end
|
833
|
+
|
834
|
+
# === Description
|
835
|
+
# Object that represents a hostname to be added to a site.
|
836
|
+
class HostName
|
837
|
+
|
838
|
+
# The hostname
|
839
|
+
attr_reader :hostname
|
840
|
+
|
841
|
+
def initialize(hostname)
|
842
|
+
@hostname = hostname
|
843
|
+
end
|
844
|
+
|
845
|
+
include Sanitize
|
846
|
+
|
847
|
+
def to_xml
|
848
|
+
"<hostname>#{replace_entities(hostname)}</hostname>"
|
849
|
+
end
|
850
|
+
end
|
851
|
+
|
852
|
+
# === Description
|
853
|
+
# Object that represents a single IP address or an inclusive range of IP addresses.
|
854
|
+
# If to is nil then the from field will be used to specify a single IP Address only.
|
855
|
+
#
|
856
|
+
class IPRange
|
857
|
+
# Start of Range *Required
|
858
|
+
attr_reader :from
|
859
|
+
# End of Range *Optional (If Null then IPRange is a single IP Address)
|
860
|
+
attr_reader :to
|
861
|
+
|
862
|
+
def initialize(from, to = nil)
|
863
|
+
@from = from
|
864
|
+
@to = to
|
865
|
+
end
|
866
|
+
|
867
|
+
include Sanitize
|
868
|
+
|
869
|
+
def to_xml
|
870
|
+
if (to and not to.empty?)
|
871
|
+
return %Q{<range from="#{from}" to="#{to}"/>}
|
872
|
+
else
|
873
|
+
return %Q{<range from="#{from}"/>}
|
874
|
+
end
|
875
|
+
end
|
876
|
+
end
|
877
|
+
end
|