nexpose 0.0.9 → 0.0.91
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/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
@@ -0,0 +1,108 @@
|
|
1
|
+
module Nexpose
|
2
|
+
module NexposeAPI
|
3
|
+
include XMLUtils
|
4
|
+
|
5
|
+
#
|
6
|
+
# Create a NeXpose ticket
|
7
|
+
#
|
8
|
+
# ticket_info: A hash of the data to be used to create a ticket in NeXpose:
|
9
|
+
# :name => The name of the ticket (Required)
|
10
|
+
# :device_id => The NeXpose device ID for the device being ticketed (Required)
|
11
|
+
# :assigned_to => The NeXpose user to whom this ticket is assigned (Required)
|
12
|
+
# :priority => "low,moderate,normal,high,critical" (Required)
|
13
|
+
#
|
14
|
+
# :vulnerabilities => An array of NeXpose vuln IDs. This is NOT the same as vuln ID. (Required)
|
15
|
+
# :comments => An array of comments to accompany this ticket
|
16
|
+
#
|
17
|
+
# @return The ticket ID if the ticket creation was successful, {@code false} otherwise
|
18
|
+
#
|
19
|
+
def create_ticket ticket_info
|
20
|
+
ticket_name = ticket_info[:name]
|
21
|
+
unless ticket_name
|
22
|
+
raise ArgumentError.new 'Ticket name is required'
|
23
|
+
end
|
24
|
+
|
25
|
+
device_id = ticket_info[:device_id]
|
26
|
+
unless device_id
|
27
|
+
raise ArgumentError.new 'Device ID is required'
|
28
|
+
end
|
29
|
+
|
30
|
+
assigned_to = ticket_info[:assigned_to]
|
31
|
+
unless assigned_to
|
32
|
+
raise ArgumentError.new 'Assignee name is required'
|
33
|
+
end
|
34
|
+
|
35
|
+
priority = ticket_info[:priority]
|
36
|
+
unless priority
|
37
|
+
raise ArgumentError.new 'Ticket priority is required'
|
38
|
+
end
|
39
|
+
|
40
|
+
vulnerabilities = ticket_info[:vulnerabilities]
|
41
|
+
if not vulnerabilities or vulnerabilities.count < 1
|
42
|
+
raise ArgumentError.new 'Vulnerabilities are required'
|
43
|
+
end
|
44
|
+
|
45
|
+
comments = ticket_info[:comments]
|
46
|
+
base_xml = make_xml 'TicketCreateRequest'
|
47
|
+
|
48
|
+
required_attributes = {
|
49
|
+
'name' => ticket_name,
|
50
|
+
'priority' => priority,
|
51
|
+
'device-id' => device_id,
|
52
|
+
'assigned-to' => assigned_to
|
53
|
+
}
|
54
|
+
|
55
|
+
create_request_xml = REXML::Element.new 'TicketCreate'
|
56
|
+
create_request_xml.add_attributes required_attributes
|
57
|
+
|
58
|
+
# Add vulnerabilities
|
59
|
+
vulnerabilities_xml = REXML::Element.new 'Vulnerabilities'
|
60
|
+
vulnerabilities.each do |vuln_id|
|
61
|
+
vulnerabilities_xml.add_element 'Vulnerability', {'id' => vuln_id}
|
62
|
+
end
|
63
|
+
create_request_xml.add_element vulnerabilities_xml
|
64
|
+
|
65
|
+
# Add comments
|
66
|
+
if comments and comments.count > 0
|
67
|
+
comments_xml = REXML::Element.new 'Comments'
|
68
|
+
comments.each do |comment|
|
69
|
+
comment_xml = REXML::Element.new 'Comment'
|
70
|
+
comment_xml.add_text comment
|
71
|
+
comments_xml.add_element comment_xml
|
72
|
+
end
|
73
|
+
|
74
|
+
create_request_xml.add_element comments_xml
|
75
|
+
end
|
76
|
+
|
77
|
+
base_xml.add_element create_request_xml
|
78
|
+
r = execute base_xml, '1.2'
|
79
|
+
if r.success
|
80
|
+
r.res.elements.each('TicketCreateResponse') do |group|
|
81
|
+
return group.attributes['id'].to_i
|
82
|
+
end
|
83
|
+
else
|
84
|
+
false
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# Deletes a NeXpose ticket.
|
90
|
+
#
|
91
|
+
# ticket_ids: An array of ticket IDs to be deleted.
|
92
|
+
#
|
93
|
+
# @returns {@code true} iff the call was successfull. {@code false} otherwise.
|
94
|
+
#
|
95
|
+
def delete_ticket ticket_ids
|
96
|
+
if not ticket_ids or ticket_ids.count < 1
|
97
|
+
raise ArgumentError.new 'The tickets to delete should not be null or empty'
|
98
|
+
end
|
99
|
+
|
100
|
+
base_xml = make_xml 'TicketDeleteRequest'
|
101
|
+
ticket_ids.each do |id|
|
102
|
+
base_xml.add_element 'Ticket', {'id' => id}
|
103
|
+
end
|
104
|
+
|
105
|
+
(execute base_xml, '1.2').success
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/lib/nexpose/util.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Nexpose
|
2
|
+
|
3
|
+
module Sanitize
|
4
|
+
def replace_entities(str)
|
5
|
+
ret = str.dup
|
6
|
+
ret.gsub!(/&/, "&")
|
7
|
+
ret.gsub!(/'/, "'")
|
8
|
+
ret.gsub!(/"/, """)
|
9
|
+
ret.gsub!(/</, "<")
|
10
|
+
ret.gsub!(/>/, ">")
|
11
|
+
ret
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module XMLUtils
|
16
|
+
def parse_xml(xml)
|
17
|
+
::REXML::Document.new(xml.to_s)
|
18
|
+
end
|
19
|
+
|
20
|
+
def make_xml(name, opts={}, data='', append_session_id=true)
|
21
|
+
xml = REXML::Element.new(name)
|
22
|
+
if (@session_id and append_session_id)
|
23
|
+
xml.attributes['session-id'] = @session_id
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.keys.each do |k|
|
27
|
+
xml.attributes[k] = "#{opts[k]}"
|
28
|
+
end
|
29
|
+
|
30
|
+
xml.text = data
|
31
|
+
|
32
|
+
xml
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/nexpose/vuln.rb
ADDED
@@ -0,0 +1,520 @@
|
|
1
|
+
module Nexpose
|
2
|
+
module NexposeAPI
|
3
|
+
include XMLUtils
|
4
|
+
|
5
|
+
###################
|
6
|
+
# VULN EXCEPTIONS #
|
7
|
+
###################
|
8
|
+
|
9
|
+
#-----------------------------------------------------------------------
|
10
|
+
# Returns an array of vulnerability exceptions and their associated
|
11
|
+
# attributes.
|
12
|
+
#
|
13
|
+
# @param status - (optional) The status of the vulnerability exception:
|
14
|
+
# "Under Review", "Approved", "Rejected"
|
15
|
+
#-----------------------------------------------------------------------
|
16
|
+
def vuln_listing status=nil
|
17
|
+
option = {}
|
18
|
+
|
19
|
+
if status && !status.empty?
|
20
|
+
if status =~ /Under Review|Approved|Rejected/
|
21
|
+
option['status'] = status
|
22
|
+
else
|
23
|
+
raise ArgumentError.new 'The vulnerability status passed in is invalid!'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
xml = make_xml('VulnerabilityExceptionListingRequest', option)
|
28
|
+
r = execute xml, '1.2'
|
29
|
+
|
30
|
+
if r.success
|
31
|
+
res = []
|
32
|
+
r.res.elements.each("//VulnerabilityException") do |ve|
|
33
|
+
submitter_comment = ve.elements['submitter-comment']
|
34
|
+
reviewer_comment = ve.elements['reviewer-comment']
|
35
|
+
res << {
|
36
|
+
:vuln_id => ve.attributes['vuln-id'],
|
37
|
+
:exception_id => ve.attributes['exception-id'],
|
38
|
+
:submitter => ve.attributes['submitter'],
|
39
|
+
:reviewer => ve.attributes['reviewer'],
|
40
|
+
:status => ve.attributes['status'],
|
41
|
+
:reason => ve.attributes['reason'],
|
42
|
+
:scope => ve.attributes['scope'],
|
43
|
+
:device_id => ve.attributes['device-id'],
|
44
|
+
:port_no => ve.attributes['port-no'],
|
45
|
+
:expiration_date => ve.attributes['expiration-date'],
|
46
|
+
:vuln_key => ve.attributes['vuln-key'],
|
47
|
+
:submitter_comment => submitter_comment.nil? ? '' : submitter_comment.text,
|
48
|
+
:reviewer_comment => reviewer_comment.nil? ? '' : reviewer_comment.text
|
49
|
+
}
|
50
|
+
end
|
51
|
+
res
|
52
|
+
else
|
53
|
+
false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
#-------------------------------------------------------------------------------------------------------------------
|
58
|
+
# Creates a vulnerability exception.
|
59
|
+
#
|
60
|
+
# @param input - data used to create the vulnerability exception:
|
61
|
+
# :vuln_id - The Nexpose vulnerability ID.
|
62
|
+
# :reason - The reason for the exception
|
63
|
+
# values - "False Positive", "Compensating Control", "Acceptable Use", "Acceptable Risk", "Other"
|
64
|
+
# :scope - The scope type (NOTE: The case is important)
|
65
|
+
# values - "All Instances", "All Instances on a Specific Asset", "Specific Instance of a specific Asset"
|
66
|
+
# :comment - A user comment
|
67
|
+
# :device-id - Used for specific instances related to "All Instances on a Specific Asset" AND "Specific Instance of Specific Asset"
|
68
|
+
# :port - All assets on this port related to "Specific Instance of a specific Asset"
|
69
|
+
# :vuln-key - The vulnerability key related to the "Specific Instance of a specific Asset"
|
70
|
+
#
|
71
|
+
# @returns exception-id - The Id associated with this create request
|
72
|
+
#-------------------------------------------------------------------------------------------------------------------
|
73
|
+
def vuln_exception_create input
|
74
|
+
options = {}
|
75
|
+
|
76
|
+
if input.nil?
|
77
|
+
raise ArgumentError.new 'The input element cannot be null'
|
78
|
+
end
|
79
|
+
|
80
|
+
vuln_id = input[:vuln_id]
|
81
|
+
if !vuln_id
|
82
|
+
raise ArgumentError.new 'The vulnerability ID is required'
|
83
|
+
end
|
84
|
+
options['vuln-id'] = vuln_id
|
85
|
+
|
86
|
+
reason = input[:reason]
|
87
|
+
if reason.nil? || reason.empty?
|
88
|
+
raise ArgumentError.new 'The reason is required'
|
89
|
+
end
|
90
|
+
|
91
|
+
unless reason =~ /False Positive|Compensating Control|Acceptable Use|Acceptable Risk|Other/
|
92
|
+
raise ArgumentError.new 'The reason type is invalid'
|
93
|
+
end
|
94
|
+
options['reason'] = reason
|
95
|
+
|
96
|
+
scope = input[:scope]
|
97
|
+
if scope.nil? || scope.empty?
|
98
|
+
raise ArgumentError.new 'The scope is required'
|
99
|
+
end
|
100
|
+
|
101
|
+
# For scope case matters.
|
102
|
+
unless scope =~ /All Instances|All Instances on a Specific Asset|Specific Instance of Specific Asset/
|
103
|
+
raise ArgumentError.new 'The scope type is invalid'
|
104
|
+
end
|
105
|
+
|
106
|
+
if scope =~ /All Instances on a Specific Asset|Specific Instance of Specific Asset/
|
107
|
+
device_id = input[:device_id]
|
108
|
+
vuln_key = input[:vuln_key]
|
109
|
+
port = input[:port]
|
110
|
+
if device_id
|
111
|
+
options['device-id'] = device_id
|
112
|
+
end
|
113
|
+
|
114
|
+
if (scope =~ /All Instances on a Specific Asset/ && (vuln_key || port))
|
115
|
+
raise ArgumentError.new "Vulnerability key or port cannot be used with the scope specified"
|
116
|
+
end
|
117
|
+
|
118
|
+
if vuln_key
|
119
|
+
options['vuln-key'] = vuln_key
|
120
|
+
end
|
121
|
+
|
122
|
+
if port
|
123
|
+
options['port-no'] = port
|
124
|
+
end
|
125
|
+
end
|
126
|
+
options['scope'] = scope
|
127
|
+
|
128
|
+
xml = make_xml('VulnerabilityExceptionCreateRequest', options)
|
129
|
+
|
130
|
+
comment = input[:comment]
|
131
|
+
if comment && !comment.empty?
|
132
|
+
comment_xml = make_xml('comment', {}, comment, false)
|
133
|
+
xml.add_element comment_xml
|
134
|
+
else
|
135
|
+
raise ArgumentError.new 'The comment cannot be empty'
|
136
|
+
end
|
137
|
+
|
138
|
+
r = execute xml, '1.2'
|
139
|
+
if r.success
|
140
|
+
r.res.elements.each("//VulnerabilityExceptionCreateResponse") do |vecr|
|
141
|
+
return vecr.attributes['exception-id']
|
142
|
+
end
|
143
|
+
else
|
144
|
+
false
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
#-------------------------------------------------------------------------------------------------------------------
|
149
|
+
# Resubmit a vulnerability exception.
|
150
|
+
#
|
151
|
+
# @param input - data used to create the vulnerability exception:
|
152
|
+
# :vuln_id - The Nexpose vulnerability ID. (required)
|
153
|
+
# :reason - The reason for the exception (optional)
|
154
|
+
# values - "False Positive", "Compensating Control", "Acceptable Use", "Acceptable Risk", "Other"
|
155
|
+
# :comment - A user comment (required)
|
156
|
+
#-------------------------------------------------------------------------------------------------------------------
|
157
|
+
def vuln_exception_resubmit input
|
158
|
+
options = {}
|
159
|
+
|
160
|
+
if input.nil?
|
161
|
+
raise ArgumentError.new 'The input element cannot be null'
|
162
|
+
end
|
163
|
+
|
164
|
+
exception_id = input[:exception_id]
|
165
|
+
if !exception_id
|
166
|
+
raise ArgumentError.new 'The exception ID is required'
|
167
|
+
end
|
168
|
+
options['exception-id'] = exception_id
|
169
|
+
|
170
|
+
reason = input[:reason]
|
171
|
+
if !reason.nil? && !reason.empty?
|
172
|
+
unless reason =~ /False Positive|Compensating Control|Acceptable Use|Acceptable Risk|Other/
|
173
|
+
raise ArgumentError.new 'The reason type is invalid'
|
174
|
+
end
|
175
|
+
options['reason'] = reason
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
xml = make_xml('VulnerabilityExceptionResubmitRequest', options)
|
180
|
+
|
181
|
+
comment = input[:comment]
|
182
|
+
if comment && !comment.empty?
|
183
|
+
comment_xml = make_xml('comment', {}, comment, false)
|
184
|
+
xml.add_element comment_xml
|
185
|
+
end
|
186
|
+
|
187
|
+
r = execute xml, '1.2'
|
188
|
+
r.success
|
189
|
+
end
|
190
|
+
|
191
|
+
#-------------------------------------------------------------------------------------------------------------------
|
192
|
+
# Allows a previously submitted exception that has not been approved to be withdrawn.
|
193
|
+
#
|
194
|
+
# @param exception_id - The exception id returned after the vuln exception was submitted for creation.
|
195
|
+
#-------------------------------------------------------------------------------------------------------------------
|
196
|
+
def vuln_exception_recall exception_id
|
197
|
+
xml = make_xml('VulnerabilityExceptionRecallRequest', {'exception-id' => exception_id})
|
198
|
+
r = execute xml, '1.2'
|
199
|
+
r.success
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
#-------------------------------------------------------------------------------------------------------------------
|
204
|
+
# Allows a submitted vulnerability exception to be approved.
|
205
|
+
#
|
206
|
+
# @param input:
|
207
|
+
# :exception_id - The exception id returned after the vuln exception was submitted for creation.
|
208
|
+
# :comment - An optional comment
|
209
|
+
#-------------------------------------------------------------------------------------------------------------------
|
210
|
+
def vuln_exception_approve input
|
211
|
+
exception_id = input[:exception_id]
|
212
|
+
if !exception_id
|
213
|
+
raise ArgumentError.new 'Exception Id is required'
|
214
|
+
end
|
215
|
+
|
216
|
+
xml = make_xml('VulnerabilityExceptionApproveRequest', {'exception-id' => exception_id})
|
217
|
+
comment = input[:comment]
|
218
|
+
if comment && !comment.empty?
|
219
|
+
comment_xml = make_xml('comment', {}, comment, false)
|
220
|
+
xml.add_element comment_xml
|
221
|
+
end
|
222
|
+
|
223
|
+
r = execute xml, '1.2'
|
224
|
+
r.success
|
225
|
+
end
|
226
|
+
|
227
|
+
#-------------------------------------------------------------------------------------------------------------------
|
228
|
+
# Rejects a submitted vulnerability exception to be approved.
|
229
|
+
#
|
230
|
+
# @param input:
|
231
|
+
# :exception_id - The exception id returned after the vuln exception was submitted for creation.
|
232
|
+
# :comment - An optional comment
|
233
|
+
#-------------------------------------------------------------------------------------------------------------------
|
234
|
+
def vuln_exception_reject input
|
235
|
+
exception_id = input[:exception_id]
|
236
|
+
if !exception_id
|
237
|
+
raise ArgumentError.new 'Exception Id is required'
|
238
|
+
end
|
239
|
+
|
240
|
+
xml = make_xml('VulnerabilityExceptionRejectRequest', {'exception-id' => exception_id})
|
241
|
+
comment = input[:comment]
|
242
|
+
if comment && !comment.empty?
|
243
|
+
comment_xml = make_xml('comment', {}, comment, false)
|
244
|
+
xml.add_element comment_xml
|
245
|
+
end
|
246
|
+
|
247
|
+
r = execute xml, '1.2'
|
248
|
+
r.success
|
249
|
+
end
|
250
|
+
|
251
|
+
#-------------------------------------------------------------------------------------------------------------------
|
252
|
+
# Updates a vulnerability exception comment.
|
253
|
+
#
|
254
|
+
# @param input:
|
255
|
+
# :exception_id - The exception id returned after the vuln exception was submitted for creation.
|
256
|
+
# :submitter_comment - The submitter comment
|
257
|
+
# :reviewer_comment - The reviewer comment
|
258
|
+
#-------------------------------------------------------------------------------------------------------------------
|
259
|
+
def vuln_exception_update_comment input
|
260
|
+
exception_id = input[:exception_id]
|
261
|
+
if !exception_id
|
262
|
+
raise ArgumentError.new 'Exception Id is required'
|
263
|
+
end
|
264
|
+
|
265
|
+
xml = make_xml('VulnerabilityExceptionUpdateCommentRequest', {'exception-id' => exception_id})
|
266
|
+
submitter_comment = input[:submitter_comment]
|
267
|
+
if submitter_comment && !submitter_comment.empty?
|
268
|
+
comment_xml = make_xml('submitter-comment', {}, submitter_comment, false)
|
269
|
+
xml.add_element comment_xml
|
270
|
+
end
|
271
|
+
|
272
|
+
reviewer_comment = input[:reviewer_comment]
|
273
|
+
if reviewer_comment && !reviewer_comment.empty?
|
274
|
+
comment_xml = make_xml('reviewer-comment', {}, reviewer_comment, false)
|
275
|
+
xml.add_element comment_xml
|
276
|
+
end
|
277
|
+
|
278
|
+
r = execute xml, '1.2'
|
279
|
+
r.success
|
280
|
+
end
|
281
|
+
|
282
|
+
#-------------------------------------------------------------------------------------------------------------------
|
283
|
+
# Update the expiration date for a vulnerability exception.
|
284
|
+
#
|
285
|
+
# @param input
|
286
|
+
# :exception_id - The exception id returned after the vulnerability exception was submitted for creation.
|
287
|
+
# :expiration_date - The new expiration date format: YYYY-MM-DD
|
288
|
+
#-------------------------------------------------------------------------------------------------------------------
|
289
|
+
def vuln_exception_update_expiration_date input
|
290
|
+
exception_id = input[:exception_id]
|
291
|
+
if !exception_id
|
292
|
+
raise ArgumentError.new 'Exception Id is required'
|
293
|
+
end
|
294
|
+
|
295
|
+
expiration_date = input[:expiration_date]
|
296
|
+
if expiration_date && !expiration_date.empty? && expiration_date =~ /\A\d{4}-(\d{2})-(\d{2})\z/
|
297
|
+
if $1.to_i > 12
|
298
|
+
raise ArgumentError.new 'The expiration date month value is invalid'
|
299
|
+
end
|
300
|
+
|
301
|
+
if $2.to_i > 31
|
302
|
+
raise ArgumentError.new 'The expiration date day value is invalid'
|
303
|
+
end
|
304
|
+
else
|
305
|
+
raise ArgumentError.new 'Expiration date is invalid'
|
306
|
+
end
|
307
|
+
|
308
|
+
options = {}
|
309
|
+
options['exception-id'] = exception_id
|
310
|
+
options['expiration-date'] = expiration_date
|
311
|
+
xml = make_xml('VulnerabilityExceptionUpdateExpirationDateRequest', options)
|
312
|
+
r = execute xml, '1.2'
|
313
|
+
r.success
|
314
|
+
end
|
315
|
+
|
316
|
+
#-------------------------------------------------------------------------------------------------------------------
|
317
|
+
# Deletes a submitted vulnerability exception to be approved.
|
318
|
+
#
|
319
|
+
# @param exception_id - The exception id returned after the vuln exception was submitted for creation.
|
320
|
+
#-------------------------------------------------------------------------------------------------------------------
|
321
|
+
def vuln_exception_delete exception_id
|
322
|
+
if !exception_id
|
323
|
+
raise ArgumentError.new 'Exception Id is required'
|
324
|
+
end
|
325
|
+
|
326
|
+
xml = make_xml('VulnerabilityExceptionDeleteRequest', {'exception-id' => exception_id})
|
327
|
+
r = execute xml, '1.2'
|
328
|
+
r.success
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
# === Description
|
333
|
+
# Object that represents a listing of all of the vulnerabilities in the vulnerability database
|
334
|
+
#
|
335
|
+
class VulnerabilityListing
|
336
|
+
|
337
|
+
# true if an error condition exists; false otherwise
|
338
|
+
attr_reader :error
|
339
|
+
# Error message string
|
340
|
+
attr_reader :error_msg
|
341
|
+
# The last XML request sent by this object
|
342
|
+
attr_reader :request_xml
|
343
|
+
# The last XML response received by this object
|
344
|
+
attr_reader :response_xml
|
345
|
+
# The NSC Connection associated with this object
|
346
|
+
attr_reader :connection
|
347
|
+
# Array containing (VulnerabilitySummary*)
|
348
|
+
attr_reader :vulnerability_summaries
|
349
|
+
# The number of vulnerability definitions
|
350
|
+
attr_reader :vulnerability_count
|
351
|
+
|
352
|
+
# Constructor
|
353
|
+
# VulnerabilityListing(connection)
|
354
|
+
def initialize(connection)
|
355
|
+
@error = false
|
356
|
+
@vulnerability_summaries = []
|
357
|
+
@connection = connection
|
358
|
+
|
359
|
+
r = @connection.execute('<VulnerabilityListingRequest session-id="' + @connection.session_id + '"/>')
|
360
|
+
|
361
|
+
if (r.success)
|
362
|
+
r.res.elements.each('VulnerabilityListingResponse/VulnerabilitySummary') do |v|
|
363
|
+
@vulnerability_summaries.push(VulnerabilitySummary.new(v.attributes['id'], v.attributes["title"], v.attributes["severity"]))
|
364
|
+
end
|
365
|
+
else
|
366
|
+
@error = true
|
367
|
+
@error_msg = 'VulnerabilitySummaryRequest Parse Error'
|
368
|
+
end
|
369
|
+
@vulnerability_count = @vulnerability_summaries.length
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
# === Description
|
374
|
+
# Object that represents the summary of an entry in the vulnerability database
|
375
|
+
#
|
376
|
+
class VulnerabilitySummary
|
377
|
+
|
378
|
+
# The unique ID string for this vulnerability
|
379
|
+
attr_reader :id
|
380
|
+
# The title of this vulnerability
|
381
|
+
attr_reader :title
|
382
|
+
# The severity of this vulnerability (1 – 10)
|
383
|
+
attr_reader :severity
|
384
|
+
|
385
|
+
# Constructor
|
386
|
+
# VulnerabilitySummary(id, title, severity)
|
387
|
+
def initialize(id, title, severity)
|
388
|
+
@id = id
|
389
|
+
@title = title
|
390
|
+
@severity = severity
|
391
|
+
|
392
|
+
end
|
393
|
+
|
394
|
+
end
|
395
|
+
|
396
|
+
# === Description
|
397
|
+
# Object that represents the details for an entry in the vulnerability database
|
398
|
+
#
|
399
|
+
class VulnerabilityDetail
|
400
|
+
# true if an error condition exists; false otherwise
|
401
|
+
attr_reader :error
|
402
|
+
# Error message string
|
403
|
+
attr_reader :error_msg
|
404
|
+
# The last XML request sent by this object
|
405
|
+
attr_reader :request_xml
|
406
|
+
# The last XML response received by this object
|
407
|
+
attr_reader :response_xml
|
408
|
+
# The NSC Connection associated with this object
|
409
|
+
attr_reader :connection
|
410
|
+
# The unique ID string for this vulnerability
|
411
|
+
attr_reader :id
|
412
|
+
# The title of this vulnerability
|
413
|
+
attr_reader :title
|
414
|
+
# The severity of this vulnerability (1 – 10)
|
415
|
+
attr_reader :severity
|
416
|
+
# The pciSeverity of this vulnerability
|
417
|
+
attr_reader :pciSeverity
|
418
|
+
# The CVSS score of this vulnerability
|
419
|
+
attr_reader :cvssScore
|
420
|
+
# The CVSS vector of this vulnerability
|
421
|
+
attr_reader :cvssVector
|
422
|
+
# The date this vulnerability was published
|
423
|
+
attr_reader :published
|
424
|
+
# The date this vulnerability was added to NeXpose
|
425
|
+
attr_reader :added
|
426
|
+
# The last date this vulnerability was modified
|
427
|
+
attr_reader :modified
|
428
|
+
# The HTML Description of this vulnerability
|
429
|
+
attr_reader :description
|
430
|
+
# External References for this vulnerability
|
431
|
+
# Array containing (Reference)
|
432
|
+
attr_reader :references
|
433
|
+
# The HTML Solution for this vulnerability
|
434
|
+
attr_reader :solution
|
435
|
+
|
436
|
+
# Constructor
|
437
|
+
# VulnerabilityListing(connection,id)
|
438
|
+
def initialize(connection, id)
|
439
|
+
|
440
|
+
@error = false
|
441
|
+
@connection = connection
|
442
|
+
@id = id
|
443
|
+
@references = []
|
444
|
+
|
445
|
+
r = @connection.execute('<VulnerabilityDetailsRequest session-id="' + @connection.session_id + '" vuln-id="' + @id + '"/>')
|
446
|
+
|
447
|
+
if (r.success)
|
448
|
+
r.res.elements.each('VulnerabilityDetailsResponse/Vulnerability') do |v|
|
449
|
+
@id = v.attributes['id']
|
450
|
+
@title = v.attributes["title"]
|
451
|
+
@severity = v.attributes["severity"]
|
452
|
+
@pciSeverity = v.attributes['pciSeverity']
|
453
|
+
@cvssScore = v.attributes['cvssScore']
|
454
|
+
@cvssVector = v.attributes['cvssVector']
|
455
|
+
@published = v.attributes['published']
|
456
|
+
@added = v.attributes['added']
|
457
|
+
@modified = v.attributes['modified']
|
458
|
+
|
459
|
+
v.elements.each('description') do |d|
|
460
|
+
@description = d.to_s.gsub(/\<\/?description\>/i, '')
|
461
|
+
end
|
462
|
+
|
463
|
+
v.elements.each('solution') do |s|
|
464
|
+
@solution = s.to_s.gsub(/\<\/?solution\>/i, '')
|
465
|
+
end
|
466
|
+
|
467
|
+
v.elements.each('references/reference') do |r|
|
468
|
+
@references.push(Reference.new(r.attributes['source'], r.text))
|
469
|
+
end
|
470
|
+
end
|
471
|
+
else
|
472
|
+
@error = true
|
473
|
+
@error_msg = 'VulnerabilitySummaryRequest Parse Error'
|
474
|
+
end
|
475
|
+
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
# === Description
|
480
|
+
#
|
481
|
+
class Reference
|
482
|
+
|
483
|
+
attr_reader :source
|
484
|
+
attr_reader :reference
|
485
|
+
|
486
|
+
def initialize(source, reference)
|
487
|
+
@source = source
|
488
|
+
@reference = reference
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
# TODO: review
|
493
|
+
# === Description
|
494
|
+
#
|
495
|
+
class VulnFilter
|
496
|
+
|
497
|
+
attr_reader :typeMask
|
498
|
+
attr_reader :maxAlerts
|
499
|
+
attr_reader :severityThreshold
|
500
|
+
|
501
|
+
def initialize(typeMask, severityThreshold, maxAlerts = -1)
|
502
|
+
@typeMask = typeMask
|
503
|
+
@maxAlerts = maxAlerts
|
504
|
+
@severityThreshold = severityThreshold
|
505
|
+
end
|
506
|
+
|
507
|
+
include Sanitize
|
508
|
+
|
509
|
+
def to_xml
|
510
|
+
xml = "<vulnFilter "
|
511
|
+
xml << %Q{ typeMask="#{replace_entities(typeMask)}"}
|
512
|
+
xml << %Q{ maxAlerts="#{replace_entities(maxAlerts)}"}
|
513
|
+
xml << %Q{ severityThreshold="#{replace_entities(severityThreshold)}"}
|
514
|
+
xml << "/>"
|
515
|
+
|
516
|
+
xml
|
517
|
+
end
|
518
|
+
|
519
|
+
end
|
520
|
+
end
|