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
@@ -6,7 +6,7 @@ module Nexpose
6
6
  def list_tickets
7
7
  # TODO: Should take in filters as arguments.
8
8
  xml = make_xml('TicketListingRequest')
9
- r = execute(xml, '1.2')
9
+ r = execute(xml, '1.2')
10
10
  tickets = []
11
11
  if r.success
12
12
  r.res.elements.each('TicketListingResponse/TicketSummary') do |summary|
@@ -16,7 +16,7 @@ module Nexpose
16
16
  tickets
17
17
  end
18
18
 
19
- alias_method :tickets, :list_tickets
19
+ alias tickets list_tickets
20
20
 
21
21
  # Deletes a Nexpose ticket.
22
22
  #
@@ -57,8 +57,8 @@ module Nexpose
57
57
 
58
58
  # The asset the ticket is created for.
59
59
  attr_accessor :asset_id
60
- alias :device_id :asset_id
61
- alias :device_id= :asset_id=
60
+ alias device_id asset_id
61
+ alias device_id= asset_id=
62
62
 
63
63
  # The login name of person to whom the ticket is assigned.
64
64
  # The user must have view asset privilege on the asset specified in the asset-id attribute.
@@ -78,43 +78,43 @@ module Nexpose
78
78
  attr_accessor :state
79
79
 
80
80
  def initialize(name, id)
81
- @id, @name = id, name
81
+ @id = id
82
+ @name = name
82
83
  end
83
84
 
84
85
  def self.parse(xml)
85
- ticket = new(xml.attributes['name'],
86
- xml.attributes['id'].to_i)
87
- ticket.asset_id = xml.attributes['device-id'].to_i
88
- ticket.assigned_to = xml.attributes['assigned-to']
89
- lookup = Ticket::Priority.constants.reduce({}) { |a, e| a[Ticket::Priority.const_get(e)] = e; a }
90
- ticket.priority = lookup[xml.attributes['priority']]
91
- ticket.author = xml.attributes['author']
92
- ticket.created_on = DateTime.parse(xml.attributes['created-on']).to_time
86
+ ticket = new(xml.attributes['name'], xml.attributes['id'].to_i)
87
+ ticket.asset_id = xml.attributes['device-id'].to_i
88
+ ticket.assigned_to = xml.attributes['assigned-to']
89
+ lookup = Ticket::Priority.constants.reduce({}) { |a, e| a[Ticket::Priority.const_get(e)] = e; a }
90
+ ticket.priority = lookup[xml.attributes['priority']]
91
+ ticket.author = xml.attributes['author']
92
+ ticket.created_on = DateTime.parse(xml.attributes['created-on']).to_time
93
93
  ticket.created_on -= ticket.created_on.gmt_offset
94
- lookup = Ticket::State.constants.reduce({}) { |a, e| a[Ticket::State.const_get(e)] = e; a }
95
- ticket.state = lookup[xml.attributes['state']]
94
+ lookup = Ticket::State.constants.reduce({}) { |a, e| a[Ticket::State.const_get(e)] = e; a }
95
+ ticket.state = lookup[xml.attributes['state']]
96
96
  ticket
97
97
  end
98
98
 
99
99
  module State
100
- OPEN = 'O'
101
- ASSIGNED = 'A'
102
- MODIFIED = 'M'
103
- FIXED = 'X'
104
- PARTIAL = 'P'
105
- REJECTED_FIX = 'R'
106
- PRIORITIZED = 'Z'
100
+ OPEN = 'O'
101
+ ASSIGNED = 'A'
102
+ MODIFIED = 'M'
103
+ FIXED = 'X'
104
+ PARTIAL = 'P'
105
+ REJECTED_FIX = 'R'
106
+ PRIORITIZED = 'Z'
107
107
  NOT_REPRODUCIBLE = 'F'
108
- NOT_ISSUE = 'I'
109
- CLOSED = 'C'
110
- UNKNOWN = 'U'
108
+ NOT_ISSUE = 'I'
109
+ CLOSED = 'C'
110
+ UNKNOWN = 'U'
111
111
  end
112
112
 
113
113
  module Priority
114
- LOW = 'low'
114
+ LOW = 'low'
115
115
  MODERATE = 'moderate'
116
- NORMAL = 'normal'
117
- HIGH = 'high'
116
+ NORMAL = 'normal'
117
+ HIGH = 'high'
118
118
  CRITICAL = 'critical'
119
119
  end
120
120
  end
@@ -131,11 +131,12 @@ module Nexpose
131
131
  attr_accessor :history
132
132
 
133
133
  def initialize(name, id = nil)
134
- @id, @name = id, name
135
- @priority = Priority::NORMAL
134
+ @id = id
135
+ @name = name
136
+ @priority = Priority::NORMAL
136
137
  @vulnerabilities = []
137
- @comments = []
138
- @history = []
138
+ @comments = []
139
+ @history = []
139
140
  end
140
141
 
141
142
  # Save this ticket to a Nexpose console.
@@ -213,7 +214,7 @@ module Nexpose
213
214
  ticket.history << Event.parse(entry)
214
215
  end
215
216
 
216
- ticket.comments = ticket.history.select { |h| h.description == 'Added comment' }.map { |e| e.comment }
217
+ ticket.comments = ticket.history.select { |h| h.description == 'Added comment' }.map(&:comment)
217
218
 
218
219
  ticket
219
220
  end
@@ -232,22 +233,24 @@ module Nexpose
232
233
  attr_accessor :comment
233
234
 
234
235
  def initialize(state, author, created)
235
- @state, @author, @created = state, author, created
236
+ @state = state
237
+ @author = author
238
+ @created = created
236
239
  end
237
240
 
238
241
  def self.parse(xml)
239
- author = xml.attributes['author']
240
- created_on = DateTime.parse(xml.attributes['created-on']).to_time
242
+ author = xml.attributes['author']
243
+ created_on = DateTime.parse(xml.attributes['created-on']).to_time
241
244
  created_on -= created_on.gmt_offset
242
245
 
243
- event = REXML::XPath.first(xml, 'Event')
244
- lookup = Ticket::State.constants.reduce({}) { |a, e| a[Ticket::State.const_get(e)] = e; a }
245
- state = lookup[event.attributes['state']]
246
- desc = event.text
246
+ event = REXML::XPath.first(xml, 'Event')
247
+ lookup = Ticket::State.constants.reduce({}) { |a, e| a[Ticket::State.const_get(e)] = e; a }
248
+ state = lookup[event.attributes['state']]
249
+ desc = event.text
247
250
 
248
- event = new(state, author, created_on)
251
+ event = new(state, author, created_on)
249
252
 
250
- comment = REXML::XPath.first(xml, 'Comment')
253
+ comment = REXML::XPath.first(xml, 'Comment')
251
254
  event.comment = comment.text if comment
252
255
 
253
256
  event.description = desc if desc
@@ -18,7 +18,7 @@ module Nexpose
18
18
  arr
19
19
  end
20
20
 
21
- alias_method :users, :list_users
21
+ alias users list_users
22
22
 
23
23
  # Retrieve the User ID based upon the user's login name.
24
24
  #
@@ -47,16 +47,16 @@ module Nexpose
47
47
  attr_reader :is_admin, :is_disabled, :is_locked, :site_count, :group_count
48
48
 
49
49
  def initialize(id, auth_source, auth_module, name, full_name, email, is_admin, is_disabled, is_locked, site_count, group_count)
50
- @id = id
50
+ @id = id
51
51
  @auth_source = auth_source
52
52
  @auth_module = auth_module
53
- @name = name
54
- @full_name = full_name
55
- @email = email
56
- @is_admin = is_admin
53
+ @name = name
54
+ @full_name = full_name
55
+ @email = email
56
+ @is_admin = is_admin
57
57
  @is_disabled = is_disabled
58
- @is_locked = is_locked
59
- @site_count = site_count
58
+ @is_locked = is_locked
59
+ @site_count = site_count
60
60
  @group_count = group_count
61
61
  end
62
62
 
@@ -97,41 +97,41 @@ module Nexpose
97
97
  attr_accessor :all_sites, :all_groups
98
98
 
99
99
  def initialize(name, full_name, password, role_name = 'user', id = -1, enabled = 1, email = nil, all_sites = false, all_groups = false, token = nil)
100
- @name = name
101
- @password = password
102
- @token = token
103
- @role_name = role_name
104
- @authsrcid = ('global-admin'.eql? @role_name) ? '1' : '2'
105
- @id = id
106
- @enabled = enabled
107
- @full_name = full_name
108
- @email = email
109
- @all_sites = all_sites || role_name == 'global-admin'
100
+ @name = name
101
+ @password = password
102
+ @token = token
103
+ @role_name = role_name
104
+ @authsrcid = 'global-admin'.eql?(@role_name) ? '1' : '2'
105
+ @id = id
106
+ @enabled = enabled
107
+ @full_name = full_name
108
+ @email = email
109
+ @all_sites = all_sites || role_name == 'global-admin'
110
110
  @all_groups = all_groups || role_name == 'global-admin'
111
- @sites = []
112
- @groups = []
111
+ @sites = []
112
+ @groups = []
113
113
  end
114
114
 
115
115
  def to_xml
116
116
  xml = '<UserConfig'
117
- xml << %Q{ id="#{@id}"}
118
- xml << %Q{ authsrcid="#{@authsrcid}"}
119
- xml << %Q{ name="#{replace_entities(@name)}"}
120
- xml << %Q{ fullname="#{replace_entities(@full_name)}"}
121
- xml << %Q{ role-name="#{replace_entities(@role_name)}"}
122
- xml << %Q{ password="#{replace_entities(@password)}"} if @password
123
- xml << %Q{ token="#{replace_entities(@token)}"} if @token
124
- xml << %Q{ email="#{replace_entities(@email)}"} if @email
125
- xml << %Q{ enabled="#{@enabled}"}
117
+ xml << %( id="#{@id}" )
118
+ xml << %( authsrcid="#{@authsrcid}" )
119
+ xml << %( name="#{replace_entities(@name)}" )
120
+ xml << %( fullname="#{replace_entities(@full_name)}" )
121
+ xml << %( role-name="#{replace_entities(@role_name)}" )
122
+ xml << %( password="#{replace_entities(@password)}" ) if @password
123
+ xml << %( token="#{replace_entities(@token)}" ) if @token
124
+ xml << %( email="#{replace_entities(@email)}" ) if @email
125
+ xml << %( enabled="#{@enabled}" )
126
126
  # These two fields are keying off role_name to work around a defect.
127
- xml << %Q{ allGroups="#{@all_groups || @role_name == 'global-admin'}"}
128
- xml << %Q{ allSites="#{@all_sites || @role_name == 'global-admin'}"}
127
+ xml << %( allGroups="#{@all_groups || @role_name == 'global-admin'}" )
128
+ xml << %( allSites="#{@all_sites || @role_name == 'global-admin'}" )
129
129
  xml << '>'
130
130
  @sites.each do |site|
131
- xml << %Q{<site id="#{site}" />}
131
+ xml << %( <site id="#{site}" /> )
132
132
  end
133
133
  @groups.each do |group|
134
- xml << %Q{<group id="#{group}" />}
134
+ xml << %( <group id="#{group}" /> )
135
135
  end
136
136
  xml << '</UserConfig>'
137
137
  end
@@ -155,22 +155,22 @@ module Nexpose
155
155
  # Issue a UserConfigRequest to load an existing UserConfig from Nexpose.
156
156
  def self.load(connection, user_id)
157
157
  xml = '<UserConfigRequest session-id="' + connection.session_id + '"'
158
- xml << %Q{ id="#{user_id}"}
158
+ xml << %( id="#{user_id}" )
159
159
  xml << ' />'
160
160
  r = connection.execute(xml, '1.1')
161
161
  if r.success
162
162
  r.res.elements.each('UserConfigResponse/UserConfig') do |config|
163
- id = config.attributes['id']
164
- role_name = config.attributes['role-name']
165
- #authsrcid = config.attributes['authsrcid']
166
- name = config.attributes['name']
167
- fullname = config.attributes['fullname']
168
-
169
- email = config.attributes['email']
170
- password = config.attributes['password']
171
- token = config.attributes['token']
172
- enabled = config.attributes['enabled'].to_i
173
- all_sites = config.attributes['allSites'] == 'true' ? true : false
163
+ id = config.attributes['id']
164
+ role_name = config.attributes['role-name']
165
+ # authsrcid = config.attributes['authsrcid']
166
+ name = config.attributes['name']
167
+ fullname = config.attributes['fullname']
168
+
169
+ email = config.attributes['email']
170
+ password = config.attributes['password']
171
+ token = config.attributes['token']
172
+ enabled = config.attributes['enabled'].to_i
173
+ all_sites = config.attributes['allSites'] == 'true' ? true : false
174
174
  all_groups = config.attributes['allGroups'] == 'true' ? true : false
175
175
  # Not trying to load sites and groups.
176
176
  # Looks like API currently doesn't return that info to load.
@@ -30,7 +30,7 @@ module Nexpose
30
30
  # '1' if the call succeeded.
31
31
  #
32
32
  def self.success?(xml_string)
33
- xml = ::REXML::Document.new(xml_string.to_s)
33
+ xml = ::REXML::Document.new(xml_string.to_s)
34
34
  success = ::REXML::XPath.first(xml, '//@success')
35
35
  !success.nil? && success.value.to_i == 1
36
36
  end
@@ -1,4 +1,4 @@
1
1
  module Nexpose
2
2
  # The latest version of the Nexpose gem
3
- VERSION = '7.0.0'
3
+ VERSION = '7.0.1'.freeze
4
4
  end
@@ -20,15 +20,15 @@ module Nexpose
20
20
  vulns << XML::VulnerabilitySummary.parse(vuln)
21
21
  else
22
22
  vulns << XML::Vulnerability.new(vuln.attributes['id'],
23
- vuln.attributes['title'],
24
- vuln.attributes['severity'].to_i)
23
+ vuln.attributes['title'],
24
+ vuln.attributes['severity'].to_i)
25
25
  end
26
26
  end
27
27
  end
28
28
  vulns
29
29
  end
30
30
 
31
- alias_method :vulns, :list_vulns
31
+ alias vulns list_vulns
32
32
 
33
33
  # Retrieve a list of the different vulnerability check categories.
34
34
  #
@@ -39,7 +39,7 @@ module Nexpose
39
39
  data.map { |c| c['Category'] }
40
40
  end
41
41
 
42
- alias_method :vuln_categories, :list_vuln_categories
42
+ alias vuln_categories list_vuln_categories
43
43
 
44
44
  # Retrieve a list of the different vulnerability check types.
45
45
  #
@@ -49,7 +49,7 @@ module Nexpose
49
49
  data = DataTable._get_dyn_table(self, '/data/vulnerability/checktypes/dyntable.xml?tableID=VulnCheckCategorySynopsis')
50
50
  data.map { |c| c['Category'] }
51
51
  end
52
- alias_method :list_vuln_types, :vuln_types
52
+ alias list_vuln_types vuln_types
53
53
 
54
54
  # Retrieve details for a vulnerability.
55
55
  #
@@ -111,7 +111,9 @@ module Nexpose
111
111
  attr_reader :severity
112
112
 
113
113
  def initialize(id, title, severity)
114
- @id, @title, @severity = id, title, severity.to_i
114
+ @id = id
115
+ @title = title
116
+ @severity = severity.to_i
115
117
  end
116
118
  end
117
119
 
@@ -126,10 +128,10 @@ module Nexpose
126
128
  attr_reader :check_type
127
129
 
128
130
  def initialize(json)
129
- @id = json['Vuln ID']
130
- @check_id = json['Vuln Check ID']
131
- @title = json['Vulnerability']
132
- @severity = json['Severity'].to_i
131
+ @id = json['Vuln ID']
132
+ @check_id = json['Vuln Check ID']
133
+ @title = json['Vulnerability']
134
+ @severity = json['Severity'].to_i
133
135
  @check_type = json['Check Type']
134
136
  @categories = json['Category'].split(/, */)
135
137
  end
@@ -165,15 +167,15 @@ module Nexpose
165
167
  xml.attributes['severity'].to_i)
166
168
 
167
169
  vuln.pci_severity = xml.attributes['pciSeverity'].to_i
168
- vuln.safe = xml.attributes['safe'] == 'true' # or xml.attributes['safe'] == '1'
169
- vuln.added = Date.parse(xml.attributes['added'])
170
- vuln.modified = Date.parse(xml.attributes['modified'])
171
- vuln.credentials = xml.attributes['requiresCredentials'] == 'true'
170
+ vuln.safe = xml.attributes['safe'] == 'true' # or xml.attributes['safe'] == '1'
171
+ vuln.added = Date.parse(xml.attributes['added'])
172
+ vuln.modified = Date.parse(xml.attributes['modified'])
173
+ vuln.credentials = xml.attributes['requiresCredentials'] == 'true'
172
174
 
173
175
  # These three fields are optional in the XSD.
174
- vuln.published = Date.parse(xml.attributes['published']) if xml.attributes['published']
175
- vuln.cvss_vector = xml.attributes['cvssVector'] if xml.attributes['cvssVector']
176
- vuln.cvss_score = xml.attributes['cvssScore'].to_f if xml.attributes['cvssScore']
176
+ vuln.published = Date.parse(xml.attributes['published']) if xml.attributes['published']
177
+ vuln.cvss_vector = xml.attributes['cvssVector'] if xml.attributes['cvssVector']
178
+ vuln.cvss_score = xml.attributes['cvssScore'].to_f if xml.attributes['cvssScore']
177
179
  vuln
178
180
  end
179
181
 
@@ -194,16 +196,16 @@ module Nexpose
194
196
  attr_accessor :solution
195
197
 
196
198
  def initialize(id, title, severity)
197
- @id, @title, @severity = id, title, severity
199
+ @id = id
200
+ @title = title
201
+ @severity = severity
198
202
  @references = []
199
203
  end
200
204
 
201
205
  def self.parse(xml)
202
- vuln = parse_attributes(xml)
203
-
206
+ vuln = parse_attributes(xml)
204
207
  vuln.description = REXML::XPath.first(xml, 'description').text
205
- vuln.solution = REXML::XPath.first(xml, 'solution').text
206
-
208
+ vuln.solution = REXML::XPath.first(xml, 'solution').text
207
209
  xml.elements.each('references/reference') do |ref|
208
210
  vuln.references << Reference.new(ref.attributes['source'], ref.text)
209
211
  end
@@ -218,7 +220,7 @@ module Nexpose
218
220
  attr_reader :reference
219
221
 
220
222
  def initialize(source, reference)
221
- @source = source
223
+ @source = source
222
224
  @reference = reference
223
225
  end
224
226
  end
@@ -251,18 +253,18 @@ module Nexpose
251
253
  attr_reader :verified
252
254
 
253
255
  def initialize(json)
254
- @id = json['nexVulnID']
255
- @console_id = json['vulnID']
256
- @title = json['title']
256
+ @id = json['nexVulnID']
257
+ @console_id = json['vulnID']
258
+ @title = json['title']
257
259
  @cvss_vector = json['cvssBase']
258
- @cvss_score = json['cvssScore']
259
- @risk = json['riskScore']
260
- @published = Time.at(json['publishedDate'] / 1000)
261
- @severity = json['severity']
262
- @instances = json['vulnInstanceCount']
263
- @exploit = json['mainExploit']
264
- @malware = json['malwareCount']
265
- @verified = DateTime.iso8601(json['verifiedDate'].slice(0, 15)).to_time if json['verifiedDate']
260
+ @cvss_score = json['cvssScore']
261
+ @risk = json['riskScore']
262
+ @published = Time.at(json['publishedDate'] / 1000)
263
+ @severity = json['severity']
264
+ @instances = json['vulnInstanceCount']
265
+ @exploit = json['mainExploit']
266
+ @malware = json['malwareCount']
267
+ @verified = DateTime.iso8601(json['verifiedDate'].slice(0, 15)).to_time if json['verifiedDate']
266
268
  end
267
269
  end
268
270
 
@@ -272,16 +274,16 @@ module Nexpose
272
274
  #
273
275
  class VulnSynopsis < VulnFinding
274
276
  def initialize(hash)
275
- @id = hash['Vuln ID'].to_i
276
- @title = hash['Vulnerability']
277
+ @id = hash['Vuln ID'].to_i
278
+ @title = hash['Vulnerability']
277
279
  @cvss_vector = hash['CVSS Base Vector']
278
- @cvss_score = hash['CVSS Score'].to_f
279
- @risk = hash['Risk'].to_f
280
- @published = Time.at(hash['Published On'].to_i / 1000)
281
- @severity = hash['Severity'].to_i
282
- @instances = hash['Instances'].to_i
283
- @exploit = hash['ExploitSource']
284
- @malware = hash['MalwareSource'] == 'true'
280
+ @cvss_score = hash['CVSS Score'].to_f
281
+ @risk = hash['Risk'].to_f
282
+ @published = Time.at(hash['Published On'].to_i / 1000)
283
+ @severity = hash['Severity'].to_i
284
+ @instances = hash['Instances'].to_i
285
+ @exploit = hash['ExploitSource']
286
+ @malware = hash['MalwareSource'] == 'true'
285
287
  end
286
288
  end
287
289