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