nexpose 0.6.3 → 0.6.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a7bb33f6e513e5e433ca6ce6595e2e5c57362605
4
- data.tar.gz: bb1e25e94229c4079e9ad18f3acaf84cf584c697
3
+ metadata.gz: 4397794b70770fea503a7f1613d55350ecdb34e4
4
+ data.tar.gz: 94ca3aff891805148565fe6b868ea2c22f847038
5
5
  SHA512:
6
- metadata.gz: a1987527f194e406880839a82c6486d7cf1866cc0bb275506a8ca7aff75bb9a6b971af01c343979de2f395713e857904b5408bfaccadf1f0399bbca6d06f816e
7
- data.tar.gz: 275e2fdb7bed01c80d6d97f297235f0ca4ee36a23e4aa003b85156c8b46ce1010e3908af2a4eeccfcf8c7efc8a29740d89dbcc40aecba2de9ab84f870a9301c9
6
+ metadata.gz: 2c274049ae4574d6201fe233221c729aa23ab9a5df81397cfda75601f3f3cd59ce830bd8fd43573879b29ea6f74f7e18bca3fe6ce8da9f2e549c9efb0dbb7e15
7
+ data.tar.gz: c2113f68a3c3c06e6c3f070ed9114f8351b7b01948dfa540e12558b6157d2e5eb17a85f2e9276314f7dfb64147ec5b7f7e8651dbc85180b69cf18c84d4524381
data/lib/nexpose.rb CHANGED
@@ -61,6 +61,7 @@ require 'nexpose/alert'
61
61
  require 'nexpose/ajax'
62
62
  require 'nexpose/api_request'
63
63
  require 'nexpose/common'
64
+ require 'nexpose/console'
64
65
  require 'nexpose/creds'
65
66
  require 'nexpose/shared_cred'
66
67
  require 'nexpose/data_table'
@@ -0,0 +1,71 @@
1
+ module Nexpose
2
+
3
+ # Nexpose console configuration class.
4
+ #
5
+ # Changes to this object are not persisted until the #save method is called.
6
+ #
7
+ # Example usage:
8
+ # config = Nexpose::Console.load(nsc)
9
+ # config.session_timeout = 600
10
+ # config.save(nsc)
11
+ #
12
+ class Console
13
+
14
+ # Session timeout for the Nexpose web server (in seconds).
15
+ # The web interface enforces a value from 60 to 604,800 [1 minute to 7 days].
16
+ attr_accessor :session_timeout
17
+
18
+ # Impose a limit on the number of scan threads which an individual scan can use.
19
+ attr_accessor :scan_threads_limit
20
+
21
+ # Whether to retrieve incremental scan results from distributed engines.
22
+ attr_accessor :incremental_scan_results
23
+
24
+ # XML document representing the entire configuration.
25
+ attr_accessor :xml
26
+
27
+ # Construct a new Nexpose Security Console configuration object.
28
+ # Not meant to be called publicly.
29
+ # @see #load
30
+ #
31
+ # @param [REXML::Document] xml Parsed XML representation of the configuration.
32
+ #
33
+ def initialize(xml)
34
+ @xml = xml
35
+
36
+ nsc = REXML::XPath.first(@xml, 'NeXposeSecurityConsole')
37
+ @scan_threads_limit = nsc.attributes['scanThreadsLimit'].to_i
38
+ @incremental_scan_results = nsc.attributes['realtimeIntegration'] == '1'
39
+
40
+ web_server = REXML::XPath.first(nsc, 'WebServer')
41
+ @session_timeout = web_server.attributes['sessionTimeout'].to_i
42
+ end
43
+
44
+ # Load existing Nexpose security console configuration.
45
+ #
46
+ # @param [Connection] connection Nexpose connection.
47
+ #
48
+ def self.load(connection)
49
+ xml = REXML::Document.new(Nexpose::AJAX.get(connection, '/ajax/nsc_config.txml'))
50
+ new(xml)
51
+ end
52
+
53
+ # Save modifications to the Nexpose security console.
54
+ #
55
+ # @param [Connection] connection Nexpose connection.
56
+ # @return [Boolean] true if configuration successfully saved.
57
+ #
58
+ def save(connection)
59
+ nsc = REXML::XPath.first(@xml, 'NeXposeSecurityConsole')
60
+ nsc.attributes['scanThreadsLimit'] = @scan_threads_limit.to_i
61
+ nsc.attributes['realtimeIntegration'] = @incremental_scan_results ? '1' : '0'
62
+
63
+ web_server = REXML::XPath.first(nsc, 'WebServer')
64
+ web_server.attributes['sessionTimeout'] = @session_timeout.to_i
65
+
66
+ response = REXML::Document.new(Nexpose::AJAX.post(connection, '/ajax/save_nsc_config.txml', @xml))
67
+ saved = REXML::XPath.first(response, 'SaveConfig')
68
+ saved.attributes['success'] == '1'
69
+ end
70
+ end
71
+ end
data/lib/nexpose/creds.rb CHANGED
@@ -9,6 +9,26 @@ module Nexpose
9
9
  class Credential
10
10
  include XMLUtils
11
11
 
12
+ DEFAULT_PORTS = { 'cvs' => 2401,
13
+ 'ftp' => 21,
14
+ 'http' => 80,
15
+ 'as400' => 449,
16
+ 'notes' => 1352,
17
+ 'tds' => 1433,
18
+ 'sybase' => 5000,
19
+ 'cifs' => 445,
20
+ 'cifshash' => 445,
21
+ 'oracle' => 1521,
22
+ 'pop' => 110,
23
+ 'postgresql' => 5432,
24
+ 'remote execution' => 512,
25
+ 'snmp' => 161,
26
+ 'ssh' => 22,
27
+ 'ssh-key' => 22,
28
+ 'telnet' => 23,
29
+ 'mysql' => 3306,
30
+ 'db2' => 50000 }
31
+
12
32
  # Security blob for an existing set of credentials
13
33
  attr_accessor :blob
14
34
  # The service for these credentials. Can be All.
@@ -62,6 +62,19 @@ module Nexpose
62
62
  alias_method :assets, :list_site_devices
63
63
  alias_method :list_assets, :list_site_devices
64
64
 
65
+ # Get a list of all assets currently associated with a group.
66
+ #
67
+ # @param [Fixnum] dev_id Unique identifier of a device (asset).
68
+ # @return [Array[Asset]] List of group assets.
69
+ #
70
+ def group_assets(group_id)
71
+ payload = { 'sort' => 'assetName',
72
+ 'table-id' => 'group-assets',
73
+ 'groupID' => group_id }
74
+ results = DataTable._get_json_table(self, '/data/asset/group', payload)
75
+ results.map { |a| Asset.new(a) }
76
+ end
77
+
65
78
  # List the vulnerability findings for a given device ID.
66
79
  #
67
80
  # @param [Fixnum] dev_id Unique identifier of a device (asset).
@@ -101,6 +101,10 @@ module Nexpose
101
101
  # Valid Operators: IN, NOT_IN
102
102
  IP_RANGE = 'IP_RANGE'
103
103
 
104
+ # Valid Operators: IS, IS_NOT, IN_RANGE
105
+ # Valid Values: Integers from 1 to 65535
106
+ OPEN_PORT = 'OPEN_PORT'
107
+
104
108
  # Valid Operators: CONTAINS, NOT_CONTAINS, IS_EMPTY, IS_NOT_EMPTY
105
109
  OS = 'OS'
106
110
 
@@ -130,6 +134,10 @@ module Nexpose
130
134
  # Valid Operators: CONTAINS, NOT_CONTAINS
131
135
  SOFTWARE = 'SOFTWARE'
132
136
 
137
+ # Valid Operators: ARE
138
+ # Valid Values: PRESENT, NOT_PRESENT
139
+ VALIDATED_VULNERABILITIES = 'VULNERABILITY_VALIDATED_STATUS'
140
+
133
141
  # Search against vulnerability titles that an asset contains.
134
142
  # Valid Operators: CONTAINS, NOT_CONTAINS
135
143
  VULNERABILITY = 'VULNERABILITY'
@@ -146,6 +154,7 @@ module Nexpose
146
154
  NOT_CONTAINS = 'NOT_CONTAINS'
147
155
  IS = 'IS'
148
156
  IS_NOT = 'IS_NOT'
157
+ ARE = 'ARE'
149
158
  IN = 'IN'
150
159
  NOT_IN = 'NOT_IN'
151
160
  IN_RANGE = 'IN_RANGE'
@@ -214,6 +223,11 @@ module Nexpose
214
223
  FORMAT = '%m/%d/%Y'
215
224
  end
216
225
 
226
+ module ValidatedVulnerability
227
+ NOT_PRESENT = 1
228
+ PRESENT = 0
229
+ end
230
+
217
231
  module VulnerabilityExposure
218
232
  MALWARE = 'type:"malware_type", name:"malwarekit"'
219
233
  # TODO: A problem in Nexpose causes these values to not be constant.
@@ -146,6 +146,30 @@ module Nexpose
146
146
  gen.attributes['disableWebSpider'] = enable ? '0' : '1'
147
147
  end
148
148
 
149
+ # Add custom TCP ports to scan for services
150
+ # @param [Array] ports to scan
151
+ def tcp_service_ports=(ports)
152
+ service_ports = REXML::XPath.first(@xml, 'ScanTemplate/ServiceDiscovery/TCPPortScan')
153
+ service_ports.attributes['mode'] = "custom"
154
+ service_ports.attributes['method'] = "syn"
155
+ REXML::XPath.first(service_ports, './portList').text = ports.join(",")
156
+ end
157
+
158
+ # Add custom UDP ports to scan for services
159
+ # @param [Array] posts to scan
160
+ def udp_service_ports=(ports)
161
+ service_ports = REXML::XPath.first(@xml, 'ScanTemplate/ServiceDiscovery/UDPPortScan')
162
+ service_ports.attributes['mode'] = "custom"
163
+ REXML::XPath.first(service_ports, './portList').text = ports.join(",")
164
+ end
165
+
166
+ # Disable UDP port scan
167
+ # @param [Boolean] enable or disable UDP ports
168
+ def enable_udp_ports=(enable)
169
+ service_ports = REXML::XPath.first(@xml, 'ScanTemplate/ServiceDiscovery/UDPPortScan')
170
+ service_ports.attributes['mode'] = 'none' unless enable
171
+ end
172
+
149
173
  # @return [Boolean] Whether to correlate reliable checks with regular checks.
150
174
  def correlate?
151
175
  vuln_checks = REXML::XPath.first(@xml, 'ScanTemplate/VulnerabilityChecks')
@@ -111,46 +111,93 @@ module Nexpose
111
111
  !!(response =~ /success="1"/)
112
112
  end
113
113
 
114
- def to_xml
115
- xml = '<Credential '
116
- xml << %( id="#{@id}">)
117
-
118
- xml << %(<Name>#{@name}</Name>)
119
- xml << %(<Description>#{@description}</Description>)
120
-
121
- xml << %(<Services><Service type="#{@type}"></Service></Services>)
122
-
123
- xml << '<Account type="nexpose">'
124
- xml << %(<Field name="database">#{@database}</Field>)
125
- xml << %(<Field name="domain">#{@domain}</Field>)
126
- xml << %(<Field name="username">#{@username}</Field>)
127
- xml << %(<Field name="ntlmhash">#{@ntlm_hash}</Field>) if @ntlm_hash
128
- xml << %(<Field name="password">#{@password}</Field>) if @password
129
- xml << %(<Field name="pemkey">#{@pem_key}</Field>) if @pem_key
130
- xml << %(<Field name="privilegeelevationusername">#{@privilege_username}</Field>)
131
- xml << %(<Field name="privilegeelevationpassword">#{@privilege_password}</Field>) if @privilege_password
132
- xml << %(<Field name="privilegeelevationtype">#{@privilege_type}</Field>) if @privilege_type
133
- xml << '</Account>'
134
-
135
- xml << '<Restrictions>'
136
- xml << %(<Restriction type="host">#{@host}</Restriction>) if @host
137
- xml << %(<Restriction type="port">#{@port}</Restriction>) if @port
138
- xml << '</Restrictions>'
139
-
140
- xml << %(<Sites all="#{@all_sites ? 1 : 0}">)
141
- @sites.each do |site|
142
- xml << %(<Site id="#{site}")
143
- xml << ' enabled="0"' if @disabled.member? site
144
- xml << '></Site>'
114
+ def as_xml
115
+ xml = REXML::Element.new('Credential')
116
+ xml.add_attribute('id', @id)
117
+
118
+ name = xml.add_element('Name').add_text(@name)
119
+
120
+ desc = xml.add_element('Description').add_text(@description)
121
+
122
+ services = xml.add_element('Services')
123
+ service = services.add_element('Service').add_attribute('type', @type)
124
+
125
+ (account = xml.add_element('Account')).add_attribute('type', 'nexpose')
126
+ account.add_element('Field', { 'name' => 'database' }).add_text(@database)
127
+
128
+ account.add_element('Field', { 'name' => 'domain' }).add_text(@domain)
129
+ account.add_element('Field', { 'name' => 'username' }).add_text(@username)
130
+ account.add_element('Field', { 'name' => 'ntlmhash' }).add_text(@ntlm_hash) if @ntlm_hash
131
+ account.add_element('Field', { 'name' => 'password' }).add_text(@password) if @password
132
+ account.add_element('Field', { 'name' => 'pemkey' }).add_text(@pem_key) if @pem_key
133
+ account.add_element('Field', { 'name' => 'privilegeelevationusername' }).add_text(@privilege_username)
134
+ account.add_element('Field', { 'name' => 'privilegeelevationpassword' }).add_text(@privilege_password) if @privilege_password
135
+ account.add_element('Field', { 'name' => 'privilegeelevationtype' }).add_text(@privilege_type) if @privilege_type
136
+
137
+ restrictions = xml.add_element('Restrictions')
138
+ restrictions.add_element('Restriction', { 'type' => 'host' }).add_text(@host) if @host
139
+ restrictions.add_element('Restriction', { 'type' => 'port' }).add_text(@port) if @port
140
+
141
+ sites = xml.add_element('Sites')
142
+ sites.add_attribute('all', @all_sites ? 1 : 0)
143
+ @sites.each do |s|
144
+ site = sites.add_element('Site')
145
+ site.add_attribute('id', s)
146
+ site.add_attribute('enabled', 0) if @disabled.member? s
145
147
  end
146
148
  if @sites.empty?
147
- @disabled.each do |site|
148
- xml << %(<Site id="#{site}" enabled="0"></Site>)
149
+ @disabled.each do |s|
150
+ site = sites.add_element('Site')
151
+ site.add_attribute('id', s)
152
+ site.add_attribute('enabled', 0)
149
153
  end
150
154
  end
151
- xml << '</Sites>'
152
155
 
153
- xml << '</Credential>'
156
+ xml
157
+ end
158
+
159
+ def to_xml
160
+ as_xml.to_s
161
+ end
162
+
163
+ # Test this credential against a target where the credentials should apply.
164
+ # Only works for a newly created credential. Loading an existing credential
165
+ # will likely fail.
166
+ #
167
+ # @param [Connection] nsc An active connection to the security console.
168
+ # @param [String] target Target host to check credentials against.
169
+ # @param [Fixnum] engine_id ID of the engine to use for testing credentials.
170
+ # Will default to the local engine if none is provided.
171
+ #
172
+ def test(nsc, target, engine_id = nil)
173
+ unless engine_id
174
+ local_engine = nsc.engines.find { |e| e.name == 'Local scan engine' }
175
+ engine_id = local_engine.id
176
+ end
177
+
178
+ parameters = _to_param(target, engine_id)
179
+ xml = AJAX.form_post(nsc, '/ajax/test_admin_credentials.txml', parameters)
180
+ result = REXML::XPath.first(REXML::Document.new(xml), 'TestAdminCredentialsResult')
181
+ result.attributes['success'].to_i == 1
182
+ end
183
+
184
+ def _to_param(target, engine_id)
185
+ port = @port
186
+ port = Credential::DEFAULT_PORTS[@type] if port.nil?
187
+
188
+ { engineid: engine_id,
189
+ sc_creds_dev: target,
190
+ sc_creds_svc: @type,
191
+ sc_creds_database: @database,
192
+ sc_creds_domain: @domain,
193
+ sc_creds_uname: @username,
194
+ sc_creds_password: @password,
195
+ sc_creds_pemkey: @pem_key,
196
+ sc_creds_port: port,
197
+ sc_creds_privilegeelevationusername: @privilege_username,
198
+ sc_creds_privilegeelevationpassword: @privilege_password,
199
+ sc_creds_privilegeelevationtype: @privilege_type,
200
+ siteid: -1 }
154
201
  end
155
202
 
156
203
  def self.parse(xml)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nexpose
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.6.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - HD Moore
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-02-25 00:00:00.000000000 Z
13
+ date: 2014-03-10 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: librex
@@ -72,6 +72,7 @@ files:
72
72
  - lib/nexpose/api_request.rb
73
73
  - lib/nexpose/common.rb
74
74
  - lib/nexpose/connection.rb
75
+ - lib/nexpose/console.rb
75
76
  - lib/nexpose/creds.rb
76
77
  - lib/nexpose/dag.rb
77
78
  - lib/nexpose/data_table.rb
@@ -116,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
117
  version: '0'
117
118
  requirements: []
118
119
  rubyforge_project:
119
- rubygems_version: 2.2.0
120
+ rubygems_version: 2.2.2
120
121
  signing_key:
121
122
  specification_version: 4
122
123
  summary: Ruby API for Rapid7 Nexpose