nexpose 7.0.0 → 7.0.1

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2 -3
  3. data/Gemfile.lock +1 -1
  4. data/lib/nexpose/ajax.rb +12 -16
  5. data/lib/nexpose/alert.rb +20 -21
  6. data/lib/nexpose/api.rb +3 -3
  7. data/lib/nexpose/asset.rb +23 -23
  8. data/lib/nexpose/blackout.rb +6 -14
  9. data/lib/nexpose/common.rb +87 -92
  10. data/lib/nexpose/connection.rb +8 -10
  11. data/lib/nexpose/console.rb +9 -9
  12. data/lib/nexpose/dag.rb +2 -2
  13. data/lib/nexpose/data_table.rb +8 -12
  14. data/lib/nexpose/device.rb +35 -34
  15. data/lib/nexpose/discovery.rb +69 -69
  16. data/lib/nexpose/discovery/filter.rb +7 -8
  17. data/lib/nexpose/engine.rb +22 -21
  18. data/lib/nexpose/error.rb +7 -5
  19. data/lib/nexpose/external.rb +21 -16
  20. data/lib/nexpose/filter.rb +51 -52
  21. data/lib/nexpose/global_blackout.rb +6 -7
  22. data/lib/nexpose/global_settings.rb +2 -3
  23. data/lib/nexpose/group.rb +25 -19
  24. data/lib/nexpose/json_serializer.rb +4 -14
  25. data/lib/nexpose/maint.rb +8 -9
  26. data/lib/nexpose/manage.rb +2 -2
  27. data/lib/nexpose/multi_tenant_user.rb +42 -42
  28. data/lib/nexpose/password_policy.rb +14 -14
  29. data/lib/nexpose/pool.rb +6 -5
  30. data/lib/nexpose/report.rb +30 -34
  31. data/lib/nexpose/report_template.rb +17 -18
  32. data/lib/nexpose/role.rb +64 -55
  33. data/lib/nexpose/scan.rb +77 -60
  34. data/lib/nexpose/scan_template.rb +17 -17
  35. data/lib/nexpose/scheduled_backup.rb +8 -8
  36. data/lib/nexpose/scheduled_maintenance.rb +9 -9
  37. data/lib/nexpose/shared_credential.rb +30 -33
  38. data/lib/nexpose/shared_secret.rb +5 -5
  39. data/lib/nexpose/silo.rb +68 -66
  40. data/lib/nexpose/silo_profile.rb +47 -50
  41. data/lib/nexpose/site.rb +101 -123
  42. data/lib/nexpose/site_credentials.rb +15 -17
  43. data/lib/nexpose/tag.rb +73 -80
  44. data/lib/nexpose/ticket.rb +45 -42
  45. data/lib/nexpose/user.rb +45 -45
  46. data/lib/nexpose/util.rb +1 -1
  47. data/lib/nexpose/version.rb +1 -1
  48. data/lib/nexpose/vuln.rb +45 -43
  49. data/lib/nexpose/vuln_def.rb +7 -7
  50. data/lib/nexpose/vuln_exception.rb +35 -36
  51. data/lib/nexpose/wait.rb +32 -28
  52. data/lib/nexpose/web_credentials.rb +34 -36
  53. metadata +2 -2
@@ -7,20 +7,20 @@ module Nexpose
7
7
  CLUSTER = 'CLUSTER'
8
8
 
9
9
  # Valid Operators: IS, IS_NOT
10
- DATACENTER ='DATACENTER'
10
+ DATACENTER = 'DATACENTER'
11
11
 
12
12
  # Valid Operators: CONTAINS, NOT_CONTAINS
13
- GUEST_OS_FAMILY = 'GUEST_OS_FAMILY' #Also AWS Filter
13
+ GUEST_OS_FAMILY = 'GUEST_OS_FAMILY' # Also AWS Filter
14
14
 
15
15
  # Valid Operators: IN, NOT_IN
16
- IP_ADDRESS_RANGE = 'IP_ADDRESS' #Also AWS Filter
16
+ IP_ADDRESS_RANGE = 'IP_ADDRESS' # Also AWS Filter
17
17
 
18
18
  # Valid Operators: IN, NOT_IN
19
19
  # Valid Values (See Value::PowerState): ON, OFF, SUSPENDED
20
20
  POWER_STATE = 'POWER_STATE'
21
21
 
22
22
  # Valid Operators: CONTAINS, NOT_CONTAINS
23
- RESOURCE_POOL_PATH ='RESOURCE_POOL_PATH'
23
+ RESOURCE_POOL_PATH = 'RESOURCE_POOL_PATH'
24
24
 
25
25
  # Valid Operators: IS, IS_NOT, CONTAINS, NOT_CONTAINS, STARTS_WITH
26
26
  VIRTUAL_MACHINE_NAME = 'VM'
@@ -45,7 +45,7 @@ module Nexpose
45
45
  INSTANCE_TYPE = 'INSTANCE_TYPE'
46
46
 
47
47
  # Valid Operators: IN, NOT_IN
48
- REGION ='REGION'
48
+ REGION = 'REGION'
49
49
 
50
50
  ###### Mobile or Active sync Filters ######
51
51
  # Valid Operators: CONTAINS, NOT_CONTAINS
@@ -54,13 +54,12 @@ module Nexpose
54
54
  # Valid Operators: IS, IS_NOT, CONTAINS, NOT_CONTAINS, STARTS_WITH
55
55
  USER = 'DEVICE_USER_DISPLAY_NAME'
56
56
 
57
-
58
57
  end
59
58
 
60
59
  module Value
61
60
  module PowerState
62
- ON = 'poweredOn'
63
- OFF = 'poweredOff'
61
+ ON = 'poweredOn'
62
+ OFF = 'poweredOff'
64
63
  SUSPENDED = 'suspended'
65
64
  end
66
65
  end
@@ -10,8 +10,7 @@ module Nexpose
10
10
  # @return [Boolean] true if engine successfully deleted.
11
11
  #
12
12
  def delete_engine(engine_id, scope = 'silo')
13
- xml = make_xml('EngineDeleteRequest',
14
- {'engine-id' => engine_id, 'scope' => scope})
13
+ xml = make_xml('EngineDeleteRequest', { 'engine-id' => engine_id, 'scope' => scope })
15
14
  response = execute(xml, '1.2')
16
15
  response.success
17
16
  end
@@ -27,9 +26,9 @@ module Nexpose
27
26
  # @return [Boolean] true if the connection is successfully reversed.
28
27
  #
29
28
  def reverse_engine_connection(engine_id)
30
- uri = "/api/2.1/engine/#{engine_id}/reverseConnection"
29
+ uri = "/api/2.1/engine/#{engine_id}/reverseConnection"
31
30
  response = AJAX.put(self, uri)
32
- response.eql?("true")
31
+ response.eql?('true')
33
32
  end
34
33
 
35
34
  # Kicks off an update on a single engine.
@@ -54,8 +53,8 @@ module Nexpose
54
53
  # each active scan on the engine.
55
54
  #
56
55
  def engine_activity(engine_id)
57
- xml = make_xml('EngineActivityRequest', {'engine-id' => engine_id})
58
- r = execute(xml)
56
+ xml = make_xml('EngineActivityRequest', { 'engine-id' => engine_id })
57
+ r = execute(xml)
59
58
  arr = []
60
59
  if r.success
61
60
  r.res.elements.each('//ScanSummary') do |scan_event|
@@ -72,7 +71,7 @@ module Nexpose
72
71
  #
73
72
  def list_engines
74
73
  response = execute(make_xml('EngineListingRequest'))
75
- arr = []
74
+ arr = []
76
75
  if response.success
77
76
  response.res.elements.each('//EngineSummary') do |engine|
78
77
  arr << EngineSummary.new(engine.attributes['id'].to_i,
@@ -86,7 +85,7 @@ module Nexpose
86
85
  arr
87
86
  end
88
87
 
89
- alias_method :engines, :list_engines
88
+ alias engines list_engines
90
89
  end
91
90
 
92
91
  # Object representing the current details of a scan engine attached to the
@@ -110,12 +109,12 @@ module Nexpose
110
109
  attr_reader :scope
111
110
 
112
111
  def initialize(id, name, address, port, status, scope = 'silo')
113
- @id = id
114
- @name = name
112
+ @id = id
113
+ @name = name
115
114
  @address = address
116
- @port = port
117
- @status = status
118
- @scope = scope
115
+ @port = port
116
+ @status = status
117
+ @scope = scope
119
118
  end
120
119
  end
121
120
 
@@ -143,13 +142,13 @@ module Nexpose
143
142
  attr_accessor :sites
144
143
 
145
144
  def initialize(address, name = nil, port = 40814)
146
- @id = -1
145
+ @id = -1
147
146
  @address = address
148
- @name = name
149
- @name ||= address
150
- @port = port
151
- @scope = 'silo'
152
- @sites = []
147
+ @name = name
148
+ @name ||= address
149
+ @port = port
150
+ @scope = 'silo'
151
+ @sites = []
153
152
  end
154
153
 
155
154
  def self.load(connection, id)
@@ -163,12 +162,14 @@ module Nexpose
163
162
  engine = Engine.new(config.attributes['address'],
164
163
  config.attributes['name'],
165
164
  config.attributes['port'])
166
- engine.id = config.attributes['id']
167
- engine.scope = config.attributes['scope'] if config.attributes['scope']
165
+ engine.id = config.attributes['id']
166
+ engine.scope = config.attributes['scope'] if config.attributes['scope']
168
167
  engine.priority = config.attributes['priority'] if config.attributes['priority']
168
+
169
169
  config.elements.each('Site') do |site|
170
170
  engine.sites << SiteSummary.new(site.attributes['id'], site.attributes['name'])
171
171
  end
172
+
172
173
  return engine
173
174
  end
174
175
  end
@@ -1,12 +1,13 @@
1
1
  module Nexpose
2
+
2
3
  class APIError < ::RuntimeError
3
4
  attr_accessor :req, :reason
4
5
  attr_reader :code
5
6
 
6
7
  def initialize(req, reason = '', code = 400)
7
- @req = req
8
+ @req = req
8
9
  @reason = reason
9
- @code = code
10
+ @code = code
10
11
  end
11
12
 
12
13
  def to_s
@@ -16,15 +17,16 @@ module Nexpose
16
17
 
17
18
  class AuthenticationFailed < APIError
18
19
  def initialize(req)
19
- @req = req
20
- @reason = "Login Failed"
20
+ @req = req
21
+ @reason = 'Login Failed'
21
22
  end
22
23
  end
23
24
 
24
25
  class PermissionError < APIError
25
26
  def initialize(req)
26
- @req = req
27
+ @req = req
27
28
  @reason = 'User does not have permission to perform this action.'
28
29
  end
29
30
  end
31
+
30
32
  end
@@ -27,10 +27,10 @@ module Nexpose
27
27
  # @return [Array[ImportResult]] collection of import results.
28
28
  #
29
29
  def import_assets_from_json(site_id, json)
30
- uri = "/api/2.1/sites/#{site_id}/assets"
30
+ uri = "/api/2.1/sites/#{site_id}/assets"
31
31
  # Wait up to 5 minutes for a response.
32
32
  resp = AJAX.post(self, uri, json, AJAX::CONTENT_TYPE::JSON, 300)
33
- arr = JSON.parse(resp, symbolize_names: true)
33
+ arr = JSON.parse(resp, symbolize_names: true)
34
34
  arr.map { |e| External::ImportResult.new.object_from_hash(self, e) }
35
35
  end
36
36
  end
@@ -87,15 +87,15 @@ module Nexpose
87
87
  attr_accessor :vulnerabilities
88
88
 
89
89
  def initialize
90
- @aliases = []
91
- @software = []
92
- @services = []
93
- @attributes = []
94
- @users = []
95
- @groups = []
96
- @files = []
90
+ @aliases = []
91
+ @software = []
92
+ @services = []
93
+ @attributes = []
94
+ @users = []
95
+ @groups = []
96
+ @files = []
97
97
  @unique_identifiers = []
98
- @vulnerabilities = []
98
+ @vulnerabilities = []
99
99
  end
100
100
 
101
101
  def to_json
@@ -123,10 +123,10 @@ module Nexpose
123
123
 
124
124
  # Valid host types for an asset.
125
125
  module HostType
126
- GUEST = 'GUEST'
126
+ GUEST = 'GUEST'
127
127
  HYPERVISOR = 'HYPERVISOR'
128
- PHYSICAL = 'PHYSICAL'
129
- MOBILE = 'MOBILE'
128
+ PHYSICAL = 'PHYSICAL'
129
+ MOBILE = 'MOBILE'
130
130
  end
131
131
  end
132
132
 
@@ -143,7 +143,9 @@ module Nexpose
143
143
  attr_accessor :vulnerabilities
144
144
 
145
145
  def initialize(port, protocol = Protocol::RAW, name = nil)
146
- @port, @protocol, @name = port, protocol, name
146
+ @port = port
147
+ @protocol = protocol
148
+ @name = name
147
149
  @vulnerabilities = []
148
150
  end
149
151
 
@@ -169,7 +171,10 @@ module Nexpose
169
171
  attr_accessor :proof
170
172
 
171
173
  def initialize(vuln_id, status = Status::EXPLOITED, proof = nil, key = nil)
172
- @vuln_id, @status, @proof, @key = vuln_id, status, proof, key
174
+ @vuln_id = vuln_id
175
+ @status = status
176
+ @proof = proof
177
+ @key = key
173
178
  end
174
179
 
175
180
  def to_h
@@ -185,7 +190,7 @@ module Nexpose
185
190
  EXPLOITED = 'vulnerable-exploited'
186
191
  # Vulnerable because the service or software version is associated with
187
192
  # a known vulnerability.
188
- VERSION = 'vulnerable-version'
193
+ VERSION = 'vulnerable-version'
189
194
  # A potential vulnerability.
190
195
  POTENTIAL = 'potential'
191
196
  end
@@ -14,7 +14,7 @@ module Nexpose
14
14
  #
15
15
  def filter(field, operator, value = '')
16
16
  criterion = Criterion.new(field, operator, value)
17
- criteria = Criteria.new(criterion)
17
+ criteria = Criteria.new(criterion)
18
18
  search(criteria)
19
19
  end
20
20
 
@@ -34,9 +34,7 @@ module Nexpose
34
34
  # @return [Array[FilteredAsset]] List of matching assets.
35
35
  #
36
36
  def search(criteria)
37
- results = DataTable._get_json_table(self,
38
- '/data/asset/filterAssets',
39
- criteria._to_payload)
37
+ results = DataTable._get_json_table(self, '/data/asset/filterAssets', criteria._to_payload)
40
38
  results.map { |a| FilteredAsset.new(a) }
41
39
  end
42
40
  end
@@ -173,32 +171,32 @@ module Nexpose
173
171
  # List of acceptable operators. Not all fields accept all operators.
174
172
  #
175
173
  module Operator
176
- CONTAINS = 'CONTAINS'
177
- NOT_CONTAINS = 'NOT_CONTAINS'
178
- IS = 'IS'
179
- IS_NOT = 'IS_NOT'
180
- ARE = 'ARE'
181
- IN = 'IN'
182
- NOT_IN = 'NOT_IN'
183
- IN_RANGE = 'IN_RANGE'
184
- NOT_IN_RANGE = 'NOT_IN_RANGE'
185
- STARTS_WITH = 'STARTS_WITH'
186
- ENDS_WITH = 'ENDS_WITH'
187
- ON_OR_BEFORE = 'ON_OR_BEFORE'
188
- ON_OR_AFTER = 'ON_OR_AFTER'
189
- BETWEEN = 'BETWEEN'
190
- EARLIER_THAN = 'EARLIER_THAN'
174
+ ARE = 'ARE'
175
+ BETWEEN = 'BETWEEN'
176
+ CONTAINS = 'CONTAINS'
177
+ DO_NOT_INCLUDE = 'DO_NOT_INCLUDE'
178
+ EARLIER_THAN = 'EARLIER_THAN'
179
+ ENDS_WITH = 'ENDS_WITH'
180
+ GREATER_THAN = 'GREATER_THAN'
181
+ IN = 'IN'
182
+ INCLUDE = 'INCLUDE'
183
+ IN_RANGE = 'IN_RANGE'
184
+ IS = 'IS'
185
+ IS_APPLIED = 'IS_APPLIED'
186
+ IS_EMPTY = 'IS_EMPTY'
187
+ IS_NOT = 'IS_NOT'
188
+ IS_NOT_APPLIED = 'IS_NOT_APPLIED'
189
+ IS_NOT_EMPTY = 'IS_NOT_EMPTY'
190
+ LESS_THAN = 'LESS_THAN'
191
+ LIKE = 'LIKE'
192
+ NOT_CONTAINS = 'NOT_CONTAINS'
193
+ NOT_IN = 'NOT_IN'
194
+ NOT_IN_RANGE = 'NOT_IN_RANGE'
195
+ NOT_LIKE = 'NOT_LIKE'
196
+ ON_OR_AFTER = 'ON_OR_AFTER'
197
+ ON_OR_BEFORE = 'ON_OR_BEFORE'
198
+ STARTS_WITH = 'STARTS_WITH'
191
199
  WITHIN_THE_LAST = 'WITHIN_THE_LAST'
192
- GREATER_THAN = 'GREATER_THAN'
193
- LESS_THAN = 'LESS_THAN'
194
- IS_EMPTY = 'IS_EMPTY'
195
- IS_NOT_EMPTY = 'IS_NOT_EMPTY'
196
- INCLUDE = 'INCLUDE'
197
- DO_NOT_INCLUDE = 'DO_NOT_INCLUDE'
198
- IS_APPLIED = 'IS_APPLIED'
199
- IS_NOT_APPLIED = 'IS_NOT_APPLIED'
200
- LIKE = 'LIKE'
201
- NOT_LIKE = 'NOT_LIKE'
202
200
  end
203
201
 
204
202
  # Specialized values used by certain search fields
@@ -206,36 +204,36 @@ module Nexpose
206
204
  module Value
207
205
  # Constants for filtering on access complexity.
208
206
  module AccessComplexity
209
- LOW = 'L'
207
+ LOW = 'L'
210
208
  MEDIUM = 'M'
211
- HIGH = 'H'
209
+ HIGH = 'H'
212
210
  end
213
211
 
214
212
  # Constants for filtering on access vector.
215
213
  module AccessVector
216
- LOCAL = 'L'
214
+ LOCAL = 'L'
217
215
  ADJACENT = 'A'
218
- NETWORK = 'N'
216
+ NETWORK = 'N'
219
217
  end
220
218
 
221
219
  # Constants for filtering on whether authentication is required.
222
220
  module AuthenticationRequired
223
- NONE = 'N'
224
- SINGLE = 'S'
221
+ NONE = 'N'
222
+ SINGLE = 'S'
225
223
  MULTIPLE = 'M'
226
224
  end
227
225
 
228
226
  # Constants for filtering on CVSS impact.
229
227
  module CVSSImpact
230
- NONE = 'N'
231
- PARTIAL = 'P'
228
+ NONE = 'N'
229
+ PARTIAL = 'P'
232
230
  COMPLETE = 'C'
233
231
  end
234
232
 
235
233
  # Constants for filtering on host type.
236
234
  module HostType
237
- UNKNOWN = '0'
238
- VIRTUAL = '1'
235
+ UNKNOWN = '0'
236
+ VIRTUAL = '1'
239
237
  HYPERVISOR = '2'
240
238
  BARE_METAL = '3'
241
239
  end
@@ -263,15 +261,15 @@ module Nexpose
263
261
  # Constants for filtering on vulnerability validations.
264
262
  module ValidatedVulnerability
265
263
  NOT_PRESENT = 1
266
- PRESENT = 0
264
+ PRESENT = 0
267
265
  end
268
266
 
269
267
  # Constants for filtering on vulnerability exposure.
270
268
  module VulnerabilityExposure
271
- MALWARE = 'type:"malware_type", name:"malwarekit"'
269
+ MALWARE = 'type:"malware_type", name:"malwarekit"'
272
270
  # TODO: A problem in Nexpose causes these values to not be constant.
273
271
  METASPLOIT = 'type:"exploit_source_type", name:"2"'
274
- DATABASE = 'type:"exploit_source_type", name:"1"'
272
+ DATABASE = 'type:"exploit_source_type", name:"1"'
275
273
  end
276
274
  end
277
275
  end
@@ -288,7 +286,8 @@ module Nexpose
288
286
  attr_accessor :value
289
287
 
290
288
  def initialize(field, operator, value = '')
291
- @field, @operator = field.upcase, operator.upcase
289
+ @field = field.upcase
290
+ @operator = operator.upcase
292
291
  if value.is_a? Array
293
292
  @value = value.map(&:to_s)
294
293
  else
@@ -384,17 +383,17 @@ module Nexpose
384
383
  attr_reader :last_scan
385
384
 
386
385
  def initialize(json)
387
- @id = json['assetID']
388
- @ip = json['assetIP']
389
- @name = json['assetName']
390
- @os = json['assetOSName']
386
+ @id = json['assetID']
387
+ @ip = json['assetIP']
388
+ @name = json['assetName']
389
+ @os = json['assetOSName']
391
390
  @exploit_count = json['exploitCount'].to_i
392
391
  @malware_count = json['malwareCount'].to_i
393
- @vuln_count = json['vulnCount'].to_i
394
- @risk_score = json['riskScore'].to_f
395
- @site_ids = json['sitePermissions'].map { |site| site['siteID'] }
396
- @site_id = @site_ids.first
397
- @last_scan = Time.at(json['lastScanDate'].to_i / 1000)
392
+ @vuln_count = json['vulnCount'].to_i
393
+ @risk_score = json['riskScore'].to_f
394
+ @site_ids = json['sitePermissions'].map { |site| site['siteID'] }
395
+ @site_id = @site_ids.first
396
+ @last_scan = Time.at(json['lastScanDate'].to_i / 1000)
398
397
  end
399
398
  end
400
399
  end
@@ -18,8 +18,7 @@ module Nexpose
18
18
 
19
19
  def to_h
20
20
  {
21
- blackouts:
22
- (@blackout || []).map { |blackout| blackout.to_h }
21
+ blackouts: (@blackout || []).map(&:to_h)
23
22
  }
24
23
  end
25
24
 
@@ -32,11 +31,11 @@ module Nexpose
32
31
  end
33
32
 
34
33
  def self.load(nsc)
35
- uri = '/api/2.1/silo_blackout/'
36
- resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON)
37
- hash = JSON.parse(resp, symbolize_names: true)
38
- blackout = self.json_initializer(hash).deserialize(hash)
39
- blackout.blackout = (hash[:blackouts] || []).map { |blackout| Nexpose::Blackout.from_hash(blackout) }
34
+ uri = '/api/2.1/silo_blackout/'
35
+ resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON)
36
+ hash = JSON.parse(resp, symbolize_names: true)
37
+ blackout = self.json_initializer(hash).deserialize(hash)
38
+ blackout.blackout = (hash[:blackouts] || []).map { |bout| Nexpose::Blackout.from_hash(bout) }
40
39
  blackout
41
40
  end
42
41
  end