Class: Nexpose::VulnException

Inherits:
Object
  • Object
show all
Defined in:
lib/nexpose/vuln_exception.rb

Overview

A vulnerability exception.

Certain attributes are necessary for some exception scopes, even though they are optional otherwise. • An exception for all instances of a vulnerability on all assets only

requires the vuln_id attribute. The asset_id, vuln_key and port
attributes are ignored for this scope type.

• An exception for all instances on a specific asset requires the vuln_id

and asset_id attributes. The vuln_key and port attributes are ignored for
this scope type.

• An exception for a specific instance of a vulnerability on a specific

asset requires the vuln_id, asset_id. Additionally, the port and/or the
key attribute must be specified.

Defined Under Namespace

Modules: Reason, Scope, Status

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(vuln_id, scope, reason, status = nil) ⇒ VulnException

Returns a new instance of VulnException.



133
134
135
# File 'lib/nexpose/vuln_exception.rb', line 133

def initialize(vuln_id, scope, reason, status = nil)
  @vuln_id, @scope, @reason, @status = vuln_id, scope, reason, status
end

Instance Attribute Details

#asset_idObject Also known as: device_id

ID of asset, if this exception applies to only one asset.



115
116
117
# File 'lib/nexpose/vuln_exception.rb', line 115

def asset_id
  @asset_id
end

#expirationObject

The date an exception will expire, causing the vulnerability to be included in report risk scores.



127
128
129
# File 'lib/nexpose/vuln_exception.rb', line 127

def expiration
  @expiration
end

#idObject

Unique identifier assigned to an exception.



98
99
100
# File 'lib/nexpose/vuln_exception.rb', line 98

def id
  @id
end

#portObject

Port on a asset, if this exception applies to a specific port.



120
121
122
# File 'lib/nexpose/vuln_exception.rb', line 120

def port
  @port
end

#reasonObject

The reason for the exception status.

See Also:



110
111
112
# File 'lib/nexpose/vuln_exception.rb', line 110

def reason
  @reason
end

#reviewerObject

The name of the reviewer of the exception.



104
105
106
# File 'lib/nexpose/vuln_exception.rb', line 104

def reviewer
  @reviewer
end

#reviewer_commentObject

Any comment provided by the reviewer.



131
132
133
# File 'lib/nexpose/vuln_exception.rb', line 131

def reviewer_comment
  @reviewer_comment
end

#scopeObject

The scope of the exception.

See Also:



113
114
115
# File 'lib/nexpose/vuln_exception.rb', line 113

def scope
  @scope
end

#statusObject

The state of the exception in the work flow process.

See Also:



107
108
109
# File 'lib/nexpose/vuln_exception.rb', line 107

def status
  @status
end

#submitterObject

The name of submitter of the exception.



102
103
104
# File 'lib/nexpose/vuln_exception.rb', line 102

def submitter
  @submitter
end

#submitter_commentObject

Any comment provided by the submitter.



129
130
131
# File 'lib/nexpose/vuln_exception.rb', line 129

def submitter_comment
  @submitter_comment
end

#vuln_idObject

Unique identifier of a vulnerability.



100
101
102
# File 'lib/nexpose/vuln_exception.rb', line 100

def vuln_id
  @vuln_id
end

#vuln_keyObject

The specific vulnerable component in a discovered instance of the vulnerability referenced by the vuln_id, such as a program, file or user account.



124
125
126
# File 'lib/nexpose/vuln_exception.rb', line 124

def vuln_key
  @vuln_key
end

Class Method Details

.parse(xml) ⇒ Object



321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/nexpose/vuln_exception.rb', line 321

def self.parse(xml)
  exception = new(xml.attributes['vuln-id'],
                  xml.attributes['scope'],
                  xml.attributes['reason'],
                  xml.attributes['status'])

  exception.id = xml.attributes['exception-id']
  exception.submitter = xml.attributes['submitter']
  exception.reviewer = xml.attributes['reviewer']
  exception.asset_id = xml.attributes['device-id']
  exception.port = xml.attributes['port-no']
  exception.vuln_key = xml.attributes['vuln-key']
  # TODO: Convert to Date/Time object?
  exception.expiration = xml.attributes['expiration-date']

  submitter_comment = xml.elements['submitter-comment']
  exception.submitter_comment = submitter_comment.text if submitter_comment
  reviewer_comment = xml.elements['reviewer-comment']
  exception.reviewer_comment = reviewer_comment.text if reviewer_comment

  exception
end

Instance Method Details

#approve(connection, comment = nil) ⇒ Boolean

Approve a vulnerability exception request, update comments and expiration dates on vulnerability exceptions that are “Under Review”.

Parameters:

  • connection (Connection)

    Connection to security console.

  • comment (String) (defaults to: nil)

    Comment to accompany the approval.

Returns:

  • (Boolean)

    Whether or not the approval was accepted by the console.



206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/nexpose/vuln_exception.rb', line 206

def approve(connection, comment = nil)
  xml = connection.make_xml('VulnerabilityExceptionApproveRequest',
                            { 'exception-id' => @id })
  if comment
    cxml = REXML::Element.new('comment')
    cxml.add_text(comment)
    xml.add_element(cxml)
    @reviewer_comment = comment
  end

  connection.execute(xml, '1.2').success
end

#delete(connection) ⇒ Boolean

Deletes this vulnerability exception.

Parameters:

  • connection (Connection)

    Connection to security console.

Returns:

  • (Boolean)

    Whether or not deletion was successful.



243
244
245
# File 'lib/nexpose/vuln_exception.rb', line 243

def delete(connection)
  connection.delete_vuln_exception(@id)
end

#recall(connection) ⇒ Boolean

Recall a vulnerability exception. Recall is used by a submitter to undo an exception request that has not been approved yet.

You can only recall a vulnerability exception that has ‘Under Review’ status.

Parameters:

  • connection (Connection)

    Connection to security console.

Returns:

  • (Boolean)

    Whether or not the recall was accepted by the console.



195
196
197
# File 'lib/nexpose/vuln_exception.rb', line 195

def recall(connection)
  connection.recall_vuln_exception(id)
end

#reject(connection, comment = nil) ⇒ Boolean

Reject a vulnerability exception request and update comments for the vulnerability exception request.

Parameters:

  • connection (Connection)

    Connection to security console.

  • comment (String) (defaults to: nil)

    Comment to accompany the rejection.

Returns:

  • (Boolean)

    Whether or not the reject was accepted by the console.



226
227
228
229
230
231
232
233
234
235
236
# File 'lib/nexpose/vuln_exception.rb', line 226

def reject(connection, comment = nil)
  xml = connection.make_xml('VulnerabilityExceptionRejectRequest',
                            { 'exception-id' => @id })
  if comment
    cxml = REXML::Element.new('comment')
    cxml.add_text(comment)
    xml.add_element(cxml)
  end

  connection.execute(xml, '1.2').success
end

#resubmit(connection) ⇒ Boolean

Resubmit a vulnerability exception request with a new comment and reason after an exception has been rejected.

You can only resubmit a request that has a “Rejected” status; if an exception is “Approved” or “Under Review” you will receive an error message stating that the exception request cannot be resubmitted.

This call will use the object’s current state to resubmit.

Parameters:

  • connection (Connection)

    Connection to security console.

Returns:

  • (Boolean)

    Whether or not the resubmission was valid.

Raises:

  • (ArgumentError)


181
182
183
184
# File 'lib/nexpose/vuln_exception.rb', line 181

def resubmit(connection)
  raise ArgumentError.new('Only Rejected exceptions can be resubmitted.') unless @status == Status::REJECTED
  connection.resubmit_vuln_exception(@id, @submitter_comment, @reason)
end

#save(connection, comment = nil) ⇒ Fixnum

Submit this exception on the security console.

Parameters:

  • connection (Connection)

    Connection to security console.

Returns:

  • (Fixnum)

    Newly assigned exception ID.



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/nexpose/vuln_exception.rb', line 142

def save(connection, comment = nil)
  validate

  xml = connection.make_xml('VulnerabilityExceptionCreateRequest')
  xml.add_attributes({ 'vuln-id' => @vuln_id,
                       'scope' => @scope,
                       'reason' => @reason })
  case @scope
  when Scope::ALL_INSTANCES_ON_A_SPECIFIC_ASSET
    xml.add_attributes({ 'device-id' => @asset_id })
  when Scope::SPECIFIC_INSTANCE_OF_SPECIFIC_ASSET
    xml.add_attributes({ 'device-id' => @asset_id,
                         'port-no' => @port,
                         'vuln-key' => @vuln_key })
  end

  @submitter_comment = comment if comment
  if @submitter_comment
    comment_elem = REXML::Element.new('comment')
    comment_elem.add_text(@submitter_comment)
    xml.add_element(comment_elem)
  end

  response = connection.execute(xml, '1.2')
  @id = response.attributes['exception-id'].to_i if response.success
end

#update_expiration_date(connection, new_date) ⇒ Boolean

Update the expiration date for this exception. The expiration time cannot be in the past.

Parameters:

  • connection (Connection)

    Connection to security console.

  • new_date (String)

    Date in the format “YYYY-MM-DD”.

Returns:

  • (Boolean)

    Whether the update was successfully submitted.



293
294
295
296
297
298
# File 'lib/nexpose/vuln_exception.rb', line 293

def update_expiration_date(connection, new_date)
  xml = connection.make_xml('VulnerabilityExceptionUpdateExpirationDateRequest',
                            { 'exception-id' => @id,
                              'expiration-date' => new_date })
  connection.execute(xml, '1.2').success
end

#update_reviewer_comment(connection, comment) ⇒ Boolean

Update security console with reviewer comment on this vulnerability exceptions.

Parameters:

  • connection (Connection)

    Connection to security console.

  • comment (String)

    Reviewer comment on this exception.

Returns:

  • (Boolean)

    Whether the comment was successfully submitted.



275
276
277
278
279
280
281
282
283
284
# File 'lib/nexpose/vuln_exception.rb', line 275

def update_reviewer_comment(connection, comment)
  xml = connection.make_xml('VulnerabilityExceptionUpdateCommentRequest',
                            { 'exception-id' => @id })
  cxml = REXML::Element.new('reviewer-comment')
  cxml.add_text(comment)
  xml.add_element(cxml)
  @reviewer_comment = comment

  connection.execute(xml, '1.2').success
end

#update_submitter_comment(connection, comment) ⇒ Boolean

Update security console with submitter comment on this vulnerability exceptions.

Cannot update a submit comment unless exception is under review or has expired.

Parameters:

  • connection (Connection)

    Connection to security console.

  • comment (String)

    Submitter comment on this exception.

Returns:

  • (Boolean)

    Whether the comment was successfully submitted.



257
258
259
260
261
262
263
264
265
266
# File 'lib/nexpose/vuln_exception.rb', line 257

def update_submitter_comment(connection, comment)
  xml = connection.make_xml('VulnerabilityExceptionUpdateCommentRequest',
                            { 'exception-id' => @id })
  cxml = REXML::Element.new('submitter-comment')
  cxml.add_text(comment)
  xml.add_element(cxml)
  @submitter_comment = comment

  connection.execute(xml, '1.2').success
end

#validateObject

Validate that this exception meets to requires for the assigned scope.

Raises:

  • (ArgumentError)


302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'lib/nexpose/vuln_exception.rb', line 302

def validate
  raise ArgumentError.new('No vuln_id.') unless @vuln_id
  raise ArgumentError.new('No scope.') unless @scope
  raise ArgumentError.new('No reason.') unless @reason

  case @scope
  when Scope::ALL_INSTANCES
    @asset_id = @port = @vuln_key = nil
  when Scope::ALL_INSTANCES_ON_A_SPECIFIC_ASSET
    raise ArgumentError.new('No asset_id.') unless @asset_id
    @port = @vuln_key = nil
  when Scope::SPECIFIC_INSTANCE_OF_SPECIFIC_ASSET
    raise ArgumentError.new('No asset_id.') unless @asset_id
    raise ArgumentError.new('Port or vuln_key is required.') unless @port || @vuln_key
  else
    raise ArgumentError.new("Invalid scope: #{@scope}")
  end
end