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 +4 -4
- data/lib/nexpose.rb +1 -0
- data/lib/nexpose/console.rb +71 -0
- data/lib/nexpose/creds.rb +20 -0
- data/lib/nexpose/device.rb +13 -0
- data/lib/nexpose/filter.rb +14 -0
- data/lib/nexpose/scan_template.rb +24 -0
- data/lib/nexpose/shared_cred.rb +82 -35
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4397794b70770fea503a7f1613d55350ecdb34e4
|
4
|
+
data.tar.gz: 94ca3aff891805148565fe6b868ea2c22f847038
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c274049ae4574d6201fe233221c729aa23ab9a5df81397cfda75601f3f3cd59ce830bd8fd43573879b29ea6f74f7e18bca3fe6ce8da9f2e549c9efb0dbb7e15
|
7
|
+
data.tar.gz: c2113f68a3c3c06e6c3f070ed9114f8351b7b01948dfa540e12558b6157d2e5eb17a85f2e9276314f7dfb64147ec5b7f7e8651dbc85180b69cf18c84d4524381
|
data/lib/nexpose.rb
CHANGED
@@ -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.
|
data/lib/nexpose/device.rb
CHANGED
@@ -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).
|
data/lib/nexpose/filter.rb
CHANGED
@@ -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')
|
data/lib/nexpose/shared_cred.rb
CHANGED
@@ -111,46 +111,93 @@ module Nexpose
|
|
111
111
|
!!(response =~ /success="1"/)
|
112
112
|
end
|
113
113
|
|
114
|
-
def
|
115
|
-
xml = '
|
116
|
-
xml
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
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 |
|
148
|
-
|
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
|
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.
|
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-
|
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.
|
120
|
+
rubygems_version: 2.2.2
|
120
121
|
signing_key:
|
121
122
|
specification_version: 4
|
122
123
|
summary: Ruby API for Rapid7 Nexpose
|