nexpose 0.8.18 → 0.9.0
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 +3 -2
- data/lib/nexpose/ajax.rb +2 -0
- data/lib/nexpose/api.rb +11 -3
- data/lib/nexpose/api_request.rb +32 -21
- data/lib/nexpose/connection.rb +1 -1
- data/lib/nexpose/credential.rb +108 -0
- data/lib/nexpose/dag.rb +1 -1
- data/lib/nexpose/filter.rb +6 -4
- data/lib/nexpose/report.rb +8 -8
- data/lib/nexpose/scan.rb +2 -2
- data/lib/nexpose/{shared_cred.rb → shared_credential.rb} +5 -46
- data/lib/nexpose/site.rb +2 -2
- data/lib/nexpose/{creds.rb → site_credential.rb} +13 -83
- data/lib/nexpose/tag.rb +1 -1
- data/lib/nexpose/util.rb +18 -6
- data/lib/nexpose/version.rb +1 -1
- data/nexpose.gemspec +24 -0
- metadata +11 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b26ec57d92c374454b5be75b30201eddfcf23e99
|
4
|
+
data.tar.gz: 621fad61669205dbf85052ee210019f00578fb50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27b3f31b2baa7db3637a65f5b9c2bfbdf9af2f8f0918ad7cf1af724c285a219b9e4e0faaf85a8a89b51c8a53ab079327f7d6029decf39dda1e489852271edd5a
|
7
|
+
data.tar.gz: 1fd837247c8a92f57d138712d8e7de1585f695353dc75fdaa14b16d5aac9ce4720dbbb480911867f6e2cede17dec9b3460621dd0d84bff06063669894b28b9de
|
data/lib/nexpose.rb
CHANGED
@@ -66,8 +66,9 @@ require 'nexpose/api'
|
|
66
66
|
require 'nexpose/api_request'
|
67
67
|
require 'nexpose/common'
|
68
68
|
require 'nexpose/console'
|
69
|
-
require 'nexpose/
|
70
|
-
require 'nexpose/
|
69
|
+
require 'nexpose/credential'
|
70
|
+
require 'nexpose/site_credential'
|
71
|
+
require 'nexpose/shared_credential'
|
71
72
|
require 'nexpose/data_table'
|
72
73
|
require 'nexpose/device'
|
73
74
|
require 'nexpose/discovery'
|
data/lib/nexpose/ajax.rb
CHANGED
data/lib/nexpose/api.rb
CHANGED
@@ -25,12 +25,13 @@ module Nexpose
|
|
25
25
|
next if k == :url # Do not store self-referential URL.
|
26
26
|
# Store resource URLs separately and create lazy accessors.
|
27
27
|
if v.is_a?(Hash) && v.key?(:url)
|
28
|
-
|
29
|
-
self.class.send(:define_method, k, proc { |conn = nsc| load_resource(conn, k, instance_variable_get("@#{k}_url")) })
|
28
|
+
self.class.send(:define_method, k, proc { |conn = nsc| load_resource(conn, k, v[:url].gsub(/.*\/api/, '/api')) })
|
30
29
|
else
|
31
30
|
# Convert timestamps.
|
32
31
|
if v.is_a?(String) && v.match(/^\d{8}T\d{6}\.\d{3}/)
|
33
32
|
instance_variable_set("@#{k}", ISO8601.to_time(v))
|
33
|
+
elsif v.is_a?(Array) && k == :attributes
|
34
|
+
instance_variable_set("@#{k}", v.map { |h| { h[:key] => h[:value] } })
|
34
35
|
else
|
35
36
|
instance_variable_set("@#{k}", v)
|
36
37
|
end
|
@@ -54,7 +55,13 @@ module Nexpose
|
|
54
55
|
obj = class_from_string(k)
|
55
56
|
resp = AJAX.get(nsc, url, AJAX::CONTENT_TYPE::JSON)
|
56
57
|
hash = JSON.parse(resp, symbolize_names: true)
|
57
|
-
|
58
|
+
if hash.is_a?(Array)
|
59
|
+
resources = hash.map { |e| obj.method(:new).call.object_from_hash(nsc, e) }
|
60
|
+
elsif hash.key?(:resources)
|
61
|
+
resources = hash[:resources].map { |e| obj.method(:new).call.object_from_hash(nsc, e) }
|
62
|
+
else
|
63
|
+
resources = obj.method(:new).call.object_from_hash(nsc, hash)
|
64
|
+
end
|
58
65
|
instance_variable_set("@#{k}", resources)
|
59
66
|
self.class.send(:define_method, k, proc { instance_variable_get("@#{k}") })
|
60
67
|
resources
|
@@ -70,6 +77,7 @@ module Nexpose
|
|
70
77
|
#
|
71
78
|
def class_from_string(field)
|
72
79
|
str = field.to_s.split('_').map(&:capitalize!).join
|
80
|
+
str = 'Vulnerability' if str == 'Vulnerabilities'
|
73
81
|
str.chop! if str.end_with?('s')
|
74
82
|
Object.const_get('Nexpose').const_get(str)
|
75
83
|
end
|
data/lib/nexpose/api_request.rb
CHANGED
@@ -47,34 +47,45 @@ module Nexpose
|
|
47
47
|
@http.read_timeout = options[:timeout] if options.key? :timeout
|
48
48
|
@raw_response = @http.post(@uri.path, @req, @headers)
|
49
49
|
@raw_response_data = @raw_response.read_body
|
50
|
-
@res = parse_xml(@raw_response_data)
|
51
50
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
# Allow the :raw keyword to bypass XML parsing.
|
52
|
+
if options[:raw]
|
53
|
+
if raw_response_data =~ /success="1"/
|
54
|
+
@success = true
|
55
|
+
else
|
56
|
+
@success = false
|
57
|
+
@error = "User requested raw XML response. Not parsing failures."
|
58
|
+
end
|
59
|
+
else
|
60
|
+
@res = parse_xml(@raw_response_data)
|
56
61
|
|
57
|
-
|
62
|
+
unless @res.root
|
63
|
+
@error = 'Nexpose service returned invalid XML.'
|
64
|
+
return @sid
|
65
|
+
end
|
58
66
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
@
|
67
|
+
@sid = attributes['session-id']
|
68
|
+
|
69
|
+
if (attributes['success'] and attributes['success'].to_i == 1)
|
70
|
+
@success = true
|
71
|
+
elsif @api_version =~ /1.2/ and @res and (@res.get_elements '//Exception').count < 1
|
72
|
+
@success = true
|
73
|
+
else
|
74
|
+
@success = false
|
75
|
+
if @api_version =~ /1.2/
|
76
|
+
@res.elements.each('//Exception/Message') do |message|
|
67
77
|
@error = message.text.sub(/.*Exception: */, '')
|
68
|
-
|
78
|
+
end
|
69
79
|
@res.elements.each('//Exception/Stacktrace') do |stacktrace|
|
70
80
|
@trace = stacktrace.text
|
71
81
|
end
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
82
|
+
else
|
83
|
+
@res.elements.each('//message') do |message|
|
84
|
+
@error = message.text.sub(/.*Exception: */, '')
|
85
|
+
end
|
86
|
+
@res.elements.each('//stacktrace') do |stacktrace|
|
87
|
+
@trace = stacktrace.text
|
88
|
+
end
|
78
89
|
end
|
79
90
|
end
|
80
91
|
end
|
data/lib/nexpose/connection.rb
CHANGED
@@ -0,0 +1,108 @@
|
|
1
|
+
module Nexpose
|
2
|
+
|
3
|
+
# Contains the shared methods for the SiteCredential and SharedCredential Objects.
|
4
|
+
# See Nexpose::SiteCredential or Nexpose::SharedCredential for additional info.
|
5
|
+
class Credential
|
6
|
+
|
7
|
+
# Mapping of Common Ports.
|
8
|
+
DEFAULT_PORTS = { 'cvs' => 2401,
|
9
|
+
'ftp' => 21,
|
10
|
+
'http' => 80,
|
11
|
+
'as400' => 449,
|
12
|
+
'notes' => 1352,
|
13
|
+
'tds' => 1433,
|
14
|
+
'sybase' => 5000,
|
15
|
+
'cifs' => 445,
|
16
|
+
'cifshash' => 445,
|
17
|
+
'oracle' => 1521,
|
18
|
+
'pop' => 110,
|
19
|
+
'postgresql' => 5432,
|
20
|
+
'remote execution' => 512,
|
21
|
+
'snmp' => 161,
|
22
|
+
'snmpv3' => 161,
|
23
|
+
'ssh' => 22,
|
24
|
+
'ssh-key' => 22,
|
25
|
+
'telnet' => 23,
|
26
|
+
'mysql' => 3306,
|
27
|
+
'db2' => 50000 }
|
28
|
+
|
29
|
+
|
30
|
+
# Credential Service/Type Options.
|
31
|
+
module Service
|
32
|
+
CVS = 'cvs' # Concurrent Versioning System (CVS)
|
33
|
+
FTP = 'ftp' # File Transfer Protocol (FTP)
|
34
|
+
HTTP = 'http' # Web Site HTTP Authentication
|
35
|
+
AS400 = 'as400' # IBM AS/400
|
36
|
+
NOTES = 'notes' # Lotus Notes/Domino
|
37
|
+
TDS = 'tds' # Microsoft SQL Server
|
38
|
+
SYBASE = 'sybase' # Sybase SQL Server
|
39
|
+
CIFS = 'cifs' # Microsoft Windows/Samba (SMB/CIFS)
|
40
|
+
CIFSHASH = 'cifshash' # Microsoft Windows/Samba LM/NTLM Hash (SMB/CIFS)
|
41
|
+
ORACLE = 'oracle' # Oracle
|
42
|
+
POP = 'pop' # Post Office Protocol (POP)
|
43
|
+
POSTGRESQL = 'postgresql' # PostgreSQL
|
44
|
+
REMOTE_EXECUTION = 'remote execution' # Remote Execution
|
45
|
+
SNMP = 'snmp' # Simple Network Management Protocol
|
46
|
+
SNMPV3 = 'snmpv3' # Simple Network Management Protocol v3
|
47
|
+
SSH = 'ssh' # Secure Shell (SSH)
|
48
|
+
SSH_KEY = 'ssh-key' # Secure Shell (SSH) Public Key
|
49
|
+
TELNET = 'telnet' # TELNET
|
50
|
+
MYSQL = 'mysql' # MySQL Server
|
51
|
+
DB2 = 'db2' # DB2
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# Permission Elevation / Privilege Escalation Types.
|
56
|
+
module ElevationType
|
57
|
+
NONE = 'NONE'
|
58
|
+
SUDO = 'SUDO'
|
59
|
+
SUDOSU = 'SUDOSU'
|
60
|
+
SU = 'SU'
|
61
|
+
PBRUN = 'PBRUN'
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Test this credential against a target where the credentials should apply.
|
66
|
+
# Only works for a newly created credential. Loading an existing credential
|
67
|
+
# will likely fail.
|
68
|
+
#
|
69
|
+
# @param [Connection] nsc An active connection to the security console.
|
70
|
+
# @param [String] target Target host to check credentials against.
|
71
|
+
# @param [Fixnum] engine_id ID of the engine to use for testing credentials.
|
72
|
+
# Will default to the local engine if none is provided.
|
73
|
+
#
|
74
|
+
def test(nsc, target, engine_id = nil, siteid = -1)
|
75
|
+
unless engine_id
|
76
|
+
engine_id = nsc.engines.find { |e| e.name == 'Local scan engine' }.id
|
77
|
+
end
|
78
|
+
@port = Credential::DEFAULT_PORTS[@service] if @port.nil?
|
79
|
+
parameters = _to_param(target, engine_id, @port, siteid)
|
80
|
+
xml = AJAX.form_post(nsc, '/ajax/test_admin_credentials.txml', parameters)
|
81
|
+
result = REXML::XPath.first(REXML::Document.new(xml), 'TestAdminCredentialsResult')
|
82
|
+
result.attributes['success'].to_i == 1
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def _to_param(target, engine_id, port, siteid)
|
87
|
+
{ engineid: engine_id,
|
88
|
+
sc_creds_dev: target,
|
89
|
+
sc_creds_svc: @service,
|
90
|
+
sc_creds_database: @database,
|
91
|
+
sc_creds_domain: @domain,
|
92
|
+
sc_creds_uname: @username,
|
93
|
+
sc_creds_password: @password,
|
94
|
+
sc_creds_pemkey: @pem_key,
|
95
|
+
sc_creds_port: port,
|
96
|
+
sc_creds_privilegeelevationusername: @privilege_username,
|
97
|
+
sc_creds_privilegeelevationpassword: @privilege_password,
|
98
|
+
sc_creds_privilegeelevationtype: @privilege_type,
|
99
|
+
sc_creds_snmpv3authtype: @auth_type,
|
100
|
+
sc_creds_snmpv3privtype: @privacy_type,
|
101
|
+
sc_creds_snmpv3privpassword: @privacy_password,
|
102
|
+
siteid: siteid }
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
end
|
data/lib/nexpose/dag.rb
CHANGED
data/lib/nexpose/filter.rb
CHANGED
@@ -283,11 +283,12 @@ module Nexpose
|
|
283
283
|
|
284
284
|
# Convert this object into the map format expected by Nexpose.
|
285
285
|
#
|
286
|
-
def
|
286
|
+
def to_hash
|
287
287
|
{ 'metadata' => { 'fieldName' => field },
|
288
288
|
'operator' => operator,
|
289
289
|
'values' => Array(value) }
|
290
290
|
end
|
291
|
+
alias_method :to_map, :to_hash
|
291
292
|
|
292
293
|
def self.parse(json)
|
293
294
|
Criterion.new(json['metadata']['fieldName'],
|
@@ -310,15 +311,16 @@ module Nexpose
|
|
310
311
|
@match = match.upcase
|
311
312
|
end
|
312
313
|
|
313
|
-
def
|
314
|
+
def to_hash
|
314
315
|
{ 'operator' => @match,
|
315
|
-
'criteria' => @criteria.map { |c| c.
|
316
|
+
'criteria' => @criteria.map { |c| c.to_hash } }
|
316
317
|
end
|
318
|
+
alias_method :to_map, :to_hash
|
317
319
|
|
318
320
|
# Convert this object into the format expected by Nexpose.
|
319
321
|
#
|
320
322
|
def to_json
|
321
|
-
JSON.generate(
|
323
|
+
JSON.generate(to_hash)
|
322
324
|
end
|
323
325
|
|
324
326
|
# Generate the payload needed for a POST request for Asset Filter.
|
data/lib/nexpose/report.rb
CHANGED
@@ -222,23 +222,23 @@ module Nexpose
|
|
222
222
|
xml << '</AdhocReportConfig>'
|
223
223
|
end
|
224
224
|
|
225
|
-
include XMLUtils
|
226
|
-
include HTMLUtils
|
227
|
-
|
228
225
|
# Generate a report once using a simple configuration.
|
229
226
|
#
|
230
|
-
# For XML-based reports, only the
|
227
|
+
# For XML-based reports, only the textual report is returned and not any images.
|
231
228
|
#
|
232
229
|
# @param [Connection] connection Nexpose connection.
|
233
230
|
# @param [Fixnum] timeout How long, in seconds, to wait for the report to
|
234
231
|
# generate. Larger reports can take a significant amount of time.
|
232
|
+
# @param [Boolean] raw Whether to bypass response parsing an use the raw
|
233
|
+
# response. If this option is used, error will only be exposed by
|
234
|
+
# examining Connection#response_xml.
|
235
235
|
# @return Report in text format except for PDF, which returns binary data.
|
236
236
|
#
|
237
|
-
def generate(connection, timeout = 300)
|
237
|
+
def generate(connection, timeout = 300, raw = false)
|
238
238
|
xml = %(<ReportAdhocGenerateRequest session-id="#{connection.session_id}">)
|
239
239
|
xml << to_xml
|
240
240
|
xml << '</ReportAdhocGenerateRequest>'
|
241
|
-
response = connection.execute(xml, '1.1', timeout: timeout)
|
241
|
+
response = connection.execute(xml, '1.1', timeout: timeout, raw: raw)
|
242
242
|
if response.success
|
243
243
|
content_type_response = response.raw_response.header['Content-Type']
|
244
244
|
if content_type_response =~ /multipart\/mixed;\s*boundary=([^\s]+)/
|
@@ -254,9 +254,9 @@ module Nexpose
|
|
254
254
|
if /.*base64.*/ =~ part.header.to_s
|
255
255
|
if @format =~ /(?:ht|x)ml/
|
256
256
|
if part.header.to_s =~ %r(text/xml)
|
257
|
-
return
|
257
|
+
return part.content.unpack('m*')[0].to_s
|
258
258
|
elsif part.header.to_s =~ %r(text/html)
|
259
|
-
return
|
259
|
+
return part.content.unpack('m*')[0].to_s
|
260
260
|
end
|
261
261
|
else # text|pdf|csv|rtf
|
262
262
|
return part.content.unpack('m*')[0]
|
data/lib/nexpose/scan.rb
CHANGED
@@ -263,7 +263,7 @@ module Nexpose
|
|
263
263
|
case resp
|
264
264
|
when Net::HTTPSuccess
|
265
265
|
if zip_file
|
266
|
-
File.open(zip_file, 'wb') { |file| file.write(resp.body) }
|
266
|
+
::File.open(zip_file, 'wb') { |file| file.write(resp.body) }
|
267
267
|
else
|
268
268
|
resp.body
|
269
269
|
end
|
@@ -296,7 +296,7 @@ module Nexpose
|
|
296
296
|
data = Rex::MIME::Message.new
|
297
297
|
data.add_part(site_id.to_s, nil, nil, 'form-data; name="siteid"')
|
298
298
|
data.add_part(session_id, nil, nil, 'form-data; name="nexposeCCSessionID"')
|
299
|
-
scan = File.new(zip_file, 'rb')
|
299
|
+
scan = ::File.new(zip_file, 'rb')
|
300
300
|
data.add_part(scan.read, 'application/zip', 'binary',
|
301
301
|
"form-data; name=\"scan\"; filename=\"#{zip_file}\"")
|
302
302
|
|
@@ -21,14 +21,16 @@ module Nexpose
|
|
21
21
|
alias_method :delete_shared_cred, :delete_shared_credential
|
22
22
|
end
|
23
23
|
|
24
|
-
class SharedCredentialSummary
|
24
|
+
class SharedCredentialSummary < Credential
|
25
25
|
|
26
26
|
# Unique ID assigned to this credential by Nexpose.
|
27
27
|
attr_accessor :id
|
28
28
|
# Name to identify this credential.
|
29
29
|
attr_accessor :name
|
30
|
-
# The credential type. See Nexpose::Credential::
|
31
|
-
attr_accessor :
|
30
|
+
# The credential service/type. See Nexpose::Credential::Service.
|
31
|
+
attr_accessor :service
|
32
|
+
alias :type :service
|
33
|
+
alias :type= :service=
|
32
34
|
# Domain or realm.
|
33
35
|
attr_accessor :domain
|
34
36
|
# User name.
|
@@ -168,49 +170,6 @@ module Nexpose
|
|
168
170
|
as_xml.to_s
|
169
171
|
end
|
170
172
|
|
171
|
-
# Test this credential against a target where the credentials should apply.
|
172
|
-
# Only works for a newly created credential. Loading an existing credential
|
173
|
-
# will likely fail.
|
174
|
-
#
|
175
|
-
# @param [Connection] nsc An active connection to the security console.
|
176
|
-
# @param [String] target Target host to check credentials against.
|
177
|
-
# @param [Fixnum] engine_id ID of the engine to use for testing credentials.
|
178
|
-
# Will default to the local engine if none is provided.
|
179
|
-
#
|
180
|
-
def test(nsc, target, engine_id = nil)
|
181
|
-
unless engine_id
|
182
|
-
local_engine = nsc.engines.find { |e| e.name == 'Local scan engine' }
|
183
|
-
engine_id = local_engine.id
|
184
|
-
end
|
185
|
-
|
186
|
-
parameters = _to_param(target, engine_id)
|
187
|
-
xml = AJAX.form_post(nsc, '/ajax/test_admin_credentials.txml', parameters)
|
188
|
-
result = REXML::XPath.first(REXML::Document.new(xml), 'TestAdminCredentialsResult')
|
189
|
-
result.attributes['success'].to_i == 1
|
190
|
-
end
|
191
|
-
|
192
|
-
def _to_param(target, engine_id)
|
193
|
-
port = @port
|
194
|
-
port = Credential::DEFAULT_PORTS[@type] if port.nil?
|
195
|
-
|
196
|
-
{ engineid: engine_id,
|
197
|
-
sc_creds_dev: target,
|
198
|
-
sc_creds_svc: @type,
|
199
|
-
sc_creds_database: @database,
|
200
|
-
sc_creds_domain: @domain,
|
201
|
-
sc_creds_uname: @username,
|
202
|
-
sc_creds_password: @password,
|
203
|
-
sc_creds_pemkey: @pem_key,
|
204
|
-
sc_creds_port: port,
|
205
|
-
sc_creds_privilegeelevationusername: @privilege_username,
|
206
|
-
sc_creds_privilegeelevationpassword: @privilege_password,
|
207
|
-
sc_creds_privilegeelevationtype: @privilege_type,
|
208
|
-
sc_creds_snmpv3authtype: @auth_type,
|
209
|
-
sc_creds_snmpv3privtype: @privacy_type,
|
210
|
-
sc_creds_snmpv3privpassword: @privacy_password,
|
211
|
-
siteid: -1 }
|
212
|
-
end
|
213
|
-
|
214
173
|
def self.parse(xml)
|
215
174
|
rexml = REXML::Document.new(xml)
|
216
175
|
rexml.elements.each('Credential') do |c|
|
data/lib/nexpose/site.rb
CHANGED
@@ -352,7 +352,7 @@ module Nexpose
|
|
352
352
|
'tag' => @description.nil? ? '' : @description,
|
353
353
|
'riskFactor' => @risk_factor,
|
354
354
|
# 'vCenter' => @discovery_connection_id,
|
355
|
-
'searchCriteria' => @criteria.nil? ? { 'operator' => 'AND' } : @criteria.
|
355
|
+
'searchCriteria' => @criteria.nil? ? { 'operator' => 'AND' } : @criteria.to_hash }
|
356
356
|
json = JSON.generate(details)
|
357
357
|
|
358
358
|
response = AJAX.post(nsc, uri, json, AJAX::CONTENT_TYPE::JSON)
|
@@ -494,7 +494,7 @@ module Nexpose
|
|
494
494
|
end
|
495
495
|
|
496
496
|
s.elements.each('Credentials/adminCredentials') do |cred|
|
497
|
-
site.credentials <<
|
497
|
+
site.credentials << SiteCredential.parse(cred)
|
498
498
|
end
|
499
499
|
|
500
500
|
s.elements.each('ScanConfig') do |scan_config|
|
@@ -6,29 +6,9 @@ module Nexpose
|
|
6
6
|
# be passed back as is during a Site Save operation. This object
|
7
7
|
# can only be used to create a new set of credentials.
|
8
8
|
#
|
9
|
-
class Credential
|
9
|
+
class SiteCredential < 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
|
-
'snmpv3' => 161,
|
27
|
-
'ssh' => 22,
|
28
|
-
'ssh-key' => 22,
|
29
|
-
'telnet' => 23,
|
30
|
-
'mysql' => 3306,
|
31
|
-
'db2' => 50000 }
|
32
12
|
|
33
13
|
# Security blob for an existing set of credentials
|
34
14
|
attr_accessor :blob
|
@@ -38,8 +18,6 @@ module Nexpose
|
|
38
18
|
attr_accessor :host
|
39
19
|
# The port on which to use these credentials.
|
40
20
|
attr_accessor :port
|
41
|
-
# The user id or username
|
42
|
-
attr_accessor :userid
|
43
21
|
# The password
|
44
22
|
attr_accessor :password
|
45
23
|
# The realm for these credentials
|
@@ -63,10 +41,18 @@ module Nexpose
|
|
63
41
|
# The privacy/encryption pass phrase to use with SNMP v3 credentials
|
64
42
|
attr_accessor :privacy_password
|
65
43
|
|
44
|
+
# Permission elevation type. See Nexpose::Credential::ElevationType.
|
45
|
+
attr_accessor :privilege_type
|
46
|
+
# The User ID or Username
|
47
|
+
attr_accessor :username
|
48
|
+
alias :userid :username
|
49
|
+
alias :userid= :username=
|
50
|
+
|
51
|
+
|
66
52
|
def self.for_service(service, user, password, realm = nil, host = nil, port = nil)
|
67
53
|
cred = new
|
68
54
|
cred.service = service
|
69
|
-
cred.
|
55
|
+
cred.username = user
|
70
56
|
cred.password = password
|
71
57
|
cred.realm = realm
|
72
58
|
cred.host = host
|
@@ -80,7 +66,7 @@ module Nexpose
|
|
80
66
|
@priv_username = username
|
81
67
|
@priv_password = password
|
82
68
|
end
|
83
|
-
|
69
|
+
|
84
70
|
def add_snmpv3_credentials(auth_type, privacy_type, privacy_password)
|
85
71
|
@auth_type = auth_type
|
86
72
|
@privacy_type = privacy_type
|
@@ -102,9 +88,8 @@ module Nexpose
|
|
102
88
|
|
103
89
|
def as_xml
|
104
90
|
attributes = {}
|
105
|
-
|
106
91
|
attributes['service'] = @service
|
107
|
-
attributes['userid'] = @
|
92
|
+
attributes['userid'] = @username
|
108
93
|
attributes['password'] = @password
|
109
94
|
attributes['realm'] = @realm
|
110
95
|
attributes['host'] = @host
|
@@ -113,7 +98,7 @@ module Nexpose
|
|
113
98
|
attributes['privilegeelevationtype'] = @priv_type if @priv_type
|
114
99
|
attributes['privilegeelevationusername'] = @priv_username if @priv_username
|
115
100
|
attributes['privilegeelevationpassword'] = @priv_password if @priv_password
|
116
|
-
|
101
|
+
|
117
102
|
attributes['snmpv3authtype'] = @auth_type if @auth_type
|
118
103
|
attributes['snmpv3privtype'] = @privacy_type if @privacy_type
|
119
104
|
attributes['snmpv3privpassword'] = @privacy_password if @privacy_password
|
@@ -139,61 +124,6 @@ module Nexpose
|
|
139
124
|
to_xml.hash
|
140
125
|
end
|
141
126
|
|
142
|
-
# Credential type options.
|
143
|
-
#
|
144
|
-
module Type
|
145
|
-
|
146
|
-
# Concurrent Versioning System (CVS)
|
147
|
-
CVS = 'cvs'
|
148
|
-
# File Transfer Protocol (FTP)
|
149
|
-
FTP = 'ftp'
|
150
|
-
# Web Site HTTP Authentication
|
151
|
-
HTTP = 'http'
|
152
|
-
# IBM AS/400
|
153
|
-
AS400 = 'as400'
|
154
|
-
# Lotus Notes/Domino
|
155
|
-
NOTES = 'notes'
|
156
|
-
# Microsoft SQL Server
|
157
|
-
TDS = 'tds'
|
158
|
-
# Sybase SQL Server
|
159
|
-
SYBASE = 'sybase'
|
160
|
-
# Microsoft Windows/Samba (SMB/CIFS)
|
161
|
-
CIFS = 'cifs'
|
162
|
-
# Microsoft Windows/Samba LM/NTLM Hash (SMB/CIFS)
|
163
|
-
CIFSHASH = 'cifshash'
|
164
|
-
# Oracle
|
165
|
-
ORACLE = 'oracle'
|
166
|
-
# Post Office Protocol (POP)
|
167
|
-
POP = 'pop'
|
168
|
-
# PostgreSQL
|
169
|
-
POSTGRESQL = 'postgresql'
|
170
|
-
# Remote Execution
|
171
|
-
REMOTE_EXECUTION = 'remote execution'
|
172
|
-
# Simple Network Management Protocol
|
173
|
-
SNMP = 'snmp'
|
174
|
-
# Simple Network Management Protocol v3
|
175
|
-
SNMPV3 = 'snmpv3'
|
176
|
-
# Secure Shell (SSH)
|
177
|
-
SSH = 'ssh'
|
178
|
-
# Secure Shell (SSH) Public Key
|
179
|
-
SSH_KEY = 'ssh-key'
|
180
|
-
# TELNET
|
181
|
-
TELNET = 'telnet'
|
182
|
-
# MySQL Server
|
183
|
-
MYSQL = 'mysql'
|
184
|
-
# DB2
|
185
|
-
DB2 = 'db2'
|
186
|
-
end
|
187
|
-
|
188
|
-
# Permission Elevation Types
|
189
|
-
#
|
190
|
-
module ElevationType
|
191
|
-
|
192
|
-
NONE = 'NONE'
|
193
|
-
SUDO = 'SUDO'
|
194
|
-
SUDOSU = 'SUDOSU'
|
195
|
-
SU = 'SU'
|
196
|
-
end
|
197
127
|
end
|
198
128
|
|
199
129
|
# Object that represents Header name-value pairs, associated with Web Session Authentication.
|
data/lib/nexpose/tag.rb
CHANGED
@@ -259,7 +259,7 @@ module Nexpose
|
|
259
259
|
'tag_config' => { 'site_ids' => @site_ids,
|
260
260
|
'tag_associated_asset_ids' => @associated_asset_ids,
|
261
261
|
'asset_group_ids' => @asset_group_ids,
|
262
|
-
'search_criteria' => @search_criteria ? @search_criteria.
|
262
|
+
'search_criteria' => @search_criteria ? @search_criteria.to_hash : nil
|
263
263
|
}
|
264
264
|
}
|
265
265
|
if @type == Type::Generic::CUSTOM
|
data/lib/nexpose/util.rb
CHANGED
@@ -6,12 +6,6 @@ module Nexpose
|
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
-
module HTMLUtils
|
10
|
-
def parse_html(html)
|
11
|
-
Nokogiri::HTML(html, nil, 'UTF-8')
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
9
|
module XMLUtils
|
16
10
|
|
17
11
|
def parse_xml(xml)
|
@@ -116,4 +110,22 @@ module Nexpose
|
|
116
110
|
time.to_time.utc.strftime('%Y%m%dT%H%M%S.%LZ')
|
117
111
|
end
|
118
112
|
end
|
113
|
+
|
114
|
+
# Functions for handling attributes as understood by the API.
|
115
|
+
# In particular, the API expects a JSON object with the hash defined as:
|
116
|
+
# { "key": "key-string",
|
117
|
+
# "value": "value-string" }
|
118
|
+
#
|
119
|
+
module Attributes
|
120
|
+
module_function
|
121
|
+
|
122
|
+
# Convert an array of attributes into a hash consumable by the API.
|
123
|
+
#
|
124
|
+
# @param [Array[Hash]] arr Array of attributes to convert.
|
125
|
+
# @return [Array[Hash]] Array formatted as expected by the API.
|
126
|
+
#
|
127
|
+
def to_hash(arr)
|
128
|
+
arr.map(&:flatten).map { |p| { 'key' => p.first.to_s, 'value' => p.last.to_s } }
|
129
|
+
end
|
130
|
+
end
|
119
131
|
end
|
data/lib/nexpose/version.rb
CHANGED
data/nexpose.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'nexpose/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'nexpose'
|
8
|
+
s.version = Nexpose::VERSION
|
9
|
+
s.homepage = 'https://github.com/rapid7/nexpose-client'
|
10
|
+
s.summary = 'Ruby API for Rapid7 Nexpose'
|
11
|
+
s.description = 'This gem provides a Ruby API to the Nexpose vulnerability management product by Rapid7.'
|
12
|
+
s.license = 'BSD'
|
13
|
+
s.authors = ['HD Moore', 'Chris Lee', 'Michael Daines', 'Brandon Turner']
|
14
|
+
s.email = ['hd_moore@rapid7.com', 'christopher_lee@rapid7.com', 'michael_daines@rapid7.com', 'brandon_turner@rapid7.com' ]
|
15
|
+
s.files = Dir['[A-Z]*'] + Dir['lib/**/*']
|
16
|
+
s.require_paths = ['lib']
|
17
|
+
s.extra_rdoc_files = ['README.markdown']
|
18
|
+
s.required_ruby_version = '>= 1.9'
|
19
|
+
s.platform = 'ruby'
|
20
|
+
|
21
|
+
s.add_runtime_dependency('rex', '~> 2.0.5', '>= 2.0.5')
|
22
|
+
|
23
|
+
s.add_development_dependency('bundler', '~> 1.3')
|
24
|
+
end
|
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.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- HD Moore
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2014-12-
|
14
|
+
date: 2014-12-31 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rex
|
@@ -19,40 +19,20 @@ dependencies:
|
|
19
19
|
requirements:
|
20
20
|
- - "~>"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 2.0.
|
22
|
+
version: 2.0.5
|
23
23
|
- - ">="
|
24
24
|
- !ruby/object:Gem::Version
|
25
|
-
version: 2.0.
|
25
|
+
version: 2.0.5
|
26
26
|
type: :runtime
|
27
27
|
prerelease: false
|
28
28
|
version_requirements: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
30
|
- - "~>"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 2.0.
|
32
|
+
version: 2.0.5
|
33
33
|
- - ">="
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: 2.0.
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: nokogiri
|
38
|
-
requirement: !ruby/object:Gem::Requirement
|
39
|
-
requirements:
|
40
|
-
- - "~>"
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: '1.6'
|
43
|
-
- - ">="
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: 1.6.2
|
46
|
-
type: :runtime
|
47
|
-
prerelease: false
|
48
|
-
version_requirements: !ruby/object:Gem::Requirement
|
49
|
-
requirements:
|
50
|
-
- - "~>"
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: '1.6'
|
53
|
-
- - ">="
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version: 1.6.2
|
35
|
+
version: 2.0.5
|
56
36
|
- !ruby/object:Gem::Dependency
|
57
37
|
name: bundler
|
58
38
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,7 +72,7 @@ files:
|
|
92
72
|
- lib/nexpose/common.rb
|
93
73
|
- lib/nexpose/connection.rb
|
94
74
|
- lib/nexpose/console.rb
|
95
|
-
- lib/nexpose/
|
75
|
+
- lib/nexpose/credential.rb
|
96
76
|
- lib/nexpose/dag.rb
|
97
77
|
- lib/nexpose/data_table.rb
|
98
78
|
- lib/nexpose/device.rb
|
@@ -112,10 +92,11 @@ files:
|
|
112
92
|
- lib/nexpose/role.rb
|
113
93
|
- lib/nexpose/scan.rb
|
114
94
|
- lib/nexpose/scan_template.rb
|
115
|
-
- lib/nexpose/
|
95
|
+
- lib/nexpose/shared_credential.rb
|
116
96
|
- lib/nexpose/silo.rb
|
117
97
|
- lib/nexpose/silo_profile.rb
|
118
98
|
- lib/nexpose/site.rb
|
99
|
+
- lib/nexpose/site_credential.rb
|
119
100
|
- lib/nexpose/tag.rb
|
120
101
|
- lib/nexpose/tag/criteria.rb
|
121
102
|
- lib/nexpose/ticket.rb
|
@@ -124,6 +105,7 @@ files:
|
|
124
105
|
- lib/nexpose/version.rb
|
125
106
|
- lib/nexpose/vuln.rb
|
126
107
|
- lib/nexpose/vuln_exception.rb
|
108
|
+
- nexpose.gemspec
|
127
109
|
homepage: https://github.com/rapid7/nexpose-client
|
128
110
|
licenses:
|
129
111
|
- BSD
|
@@ -144,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
126
|
version: '0'
|
145
127
|
requirements: []
|
146
128
|
rubyforge_project:
|
147
|
-
rubygems_version: 2.4.
|
129
|
+
rubygems_version: 2.4.5
|
148
130
|
signing_key:
|
149
131
|
specification_version: 4
|
150
132
|
summary: Ruby API for Rapid7 Nexpose
|