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 device_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 device_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, device_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.



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

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

Instance Attribute Details

#device_idObject

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



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

def device_id
  @device_id
end

#expirationObject

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



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

def expiration
  @expiration
end

#idObject

Unique identifier assigned to an exception.



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

def id
  @id
end

#portObject

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



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

def port
  @port
end

#reasonObject

The reason for the exception status.

See Also:



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

def reason
  @reason
end

#reviewerObject

The name of the reviewer of the exception.



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

def reviewer
  @reviewer
end

#reviewer_commentObject

Any comment provided by the reviewer.



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

def reviewer_comment
  @reviewer_comment
end

#scopeObject

The scope of the exception.

See Also:



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

def scope
  @scope
end

#statusObject

The state of the exception in the work flow process.

See Also:



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

def status
  @status
end

#submitterObject

The name of submitter of the exception.



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

def submitter
  @submitter
end

#submitter_commentObject

Any comment provided by the submitter.



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

def submitter_comment
  @submitter_comment
end

#vuln_idObject

Unique identifier of a vulnerability.



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

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.



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

def vuln_key
  @vuln_key
end

Class Method Details

.parse(xml) ⇒ Object



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/nexpose/vuln_exception.rb', line 317

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.device_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.



202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/nexpose/vuln_exception.rb', line 202

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.



239
240
241
# File 'lib/nexpose/vuln_exception.rb', line 239

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.



191
192
193
# File 'lib/nexpose/vuln_exception.rb', line 191

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.



222
223
224
225
226
227
228
229
230
231
232
# File 'lib/nexpose/vuln_exception.rb', line 222

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)


177
178
179
180
# File 'lib/nexpose/vuln_exception.rb', line 177

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.



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

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' => @device_id })
  when Scope::SPECIFIC_INSTANCE_OF_SPECIFIC_ASSET
    xml.add_attributes({ 'device-id' => @device_id,
                         'port-no' => @port,
                         'vuln-key' => @vuln_key })
  end

  @submitter_comment = comment if comment
  if @submitter_comment
    comment = REXML::Element.new('comment')
    comment.add_text(comment)
    xml.add_element(comment)
  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.



289
290
291
292
293
294
# File 'lib/nexpose/vuln_exception.rb', line 289

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.



271
272
273
274
275
276
277
278
279
280
# File 'lib/nexpose/vuln_exception.rb', line 271

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.



253
254
255
256
257
258
259
260
261
262
# File 'lib/nexpose/vuln_exception.rb', line 253

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)


298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/nexpose/vuln_exception.rb', line 298

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
    @device_id = @port = @vuln_key = nil
  when Scope::ALL_INSTANCES_ON_A_SPECIFIC_ASSET
    raise ArgumentError.new('No device_id.') unless @device_id
    @port = @vuln_key = nil
  when Scope::SPECIFIC_INSTANCE_OF_SPECIFIC_ASSET
    raise ArgumentError.new('No device_id.') unless @device_id
    raise ArgumentError.new('Port or vuln_key is required.') unless @port || @vuln_key
  else
    raise ArgumentError.new("Invalid scope: #{@scope}")
  end
end