nexpose 7.0.0 → 7.0.1

Sign up to get free protection for your applications and to get access to all the features.
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