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.



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

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.



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

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.



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

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.



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

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

#site_idObject

Id of the site, if this exception applies to all instances on a site



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

def site_id
  @site_id
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.



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

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.



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

def vuln_key
  @vuln_key
end

Class Method Details

.parse(xml) ⇒ Object



326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/nexpose/vuln_exception.rb', line 326

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.



209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/nexpose/vuln_exception.rb', line 209

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.



246
247
248
# File 'lib/nexpose/vuln_exception.rb', line 246

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.



198
199
200
# File 'lib/nexpose/vuln_exception.rb', line 198

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.



229
230
231
232
233
234
235
236
237
238
239
# File 'lib/nexpose/vuln_exception.rb', line 229

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)


184
185
186
187
# File 'lib/nexpose/vuln_exception.rb', line 184

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.



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
168
169
170
# File 'lib/nexpose/vuln_exception.rb', line 143

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 })
  when Scope::ALL_INSTANCES_IN_A_SPECIFIC_SITE
    xml.add_attributes({ 'site-id ' => @site_id })
  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.



296
297
298
299
300
301
# File 'lib/nexpose/vuln_exception.rb', line 296

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.



278
279
280
281
282
283
284
285
286
287
# File 'lib/nexpose/vuln_exception.rb', line 278

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.



260
261
262
263
264
265
266
267
268
269
# File 'lib/nexpose/vuln_exception.rb', line 260

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)


305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/nexpose/vuln_exception.rb', line 305

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
  when Scope::ALL_INSTANCES_IN_A_SPECIFIC_SITE
    raise ArgumentError.new('No site_id.') unless @site_id
  else
    raise ArgumentError.new("Invalid scope: #{@scope}")
  end
end