nexpose 0.9.3 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +91 -0
- data/README.markdown +1 -1
- data/lib/nexpose.rb +3 -1
- data/lib/nexpose/asset.rb +276 -0
- data/lib/nexpose/common.rb +40 -1
- data/lib/nexpose/external.rb +205 -0
- data/lib/nexpose/shared_credential.rb +1 -1
- data/lib/nexpose/site.rb +8 -3
- data/lib/nexpose/version.rb +1 -1
- data/lib/nexpose/vuln.rb +46 -5
- data/lib/nexpose/vuln_def.rb +174 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65b6a8c8e5b9a22b4554cad85898b6e54a4f9c87
|
4
|
+
data.tar.gz: 4f75da07def218ce18d31559225d7598ceb07828
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7dff42cc42cc00d08077832ecb896db3fa13b12ae97c2fe2e93b3165d8a0e5597c0ae56d4dd83a00b60dcd3a4083dfd04dc6f80eab9765437b6afc6df6d5e760
|
7
|
+
data.tar.gz: b6564635a8abf0ee9a3231809e938c2b9d189099ad96360a36b59ac690e7e171803caf819235a3b2d0a875fd40a2b520c59497fe3effb6d226f1f55330fea42b
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# Contributing to nexpose-client
|
2
|
+
|
3
|
+
The users and maintainers of nexpose-client would greatly appreciate any contributions
|
4
|
+
you can make to the project. These contributions typically come in the form of
|
5
|
+
filed bugs/issues or pull requests (PRs). These contributions routinely result
|
6
|
+
in new versions of the [nexpose-client
|
7
|
+
gem](https://rubygems.org/gems/nexpose-client) and the
|
8
|
+
[nexpose-client release](https://github.com/rapid7/nexpose-client/releases) to be released. The
|
9
|
+
process for each is outlined below.
|
10
|
+
|
11
|
+
## Contributing Issues / Bug Reports
|
12
|
+
|
13
|
+
If you encounter any bugs or problems with nexpose-client, please file them
|
14
|
+
[here](https://github.com/rapid7/nexpose-client/issues/new), providing as much detail as
|
15
|
+
possible. If the bug is straight-forward enough and you understand the fix for
|
16
|
+
the bug well enough, you may take the simpler, less-paperwork route and simply
|
17
|
+
file a PR with the fix and the necessary details.
|
18
|
+
|
19
|
+
## Contributing Code
|
20
|
+
|
21
|
+
nexpose-client uses a model nearly identical to that of
|
22
|
+
[Metasploit](https://github.com/rapid7/metasploit-framework) as outlined
|
23
|
+
[here](https://github.com/rapid7/metasploit-framework/wiki/Setting-Up-a-Metasploit-Development-Environment),
|
24
|
+
at least from a ```git``` perspective. If you've been through that process
|
25
|
+
(or, even better, you've been through it many times with many people), you can
|
26
|
+
do exactly what you did for Metasploit but with nexpose-client and ignore the rest of
|
27
|
+
this document.
|
28
|
+
|
29
|
+
On the other hand, if you haven't, read on!
|
30
|
+
|
31
|
+
### Fork and Clone
|
32
|
+
|
33
|
+
Generally, this should only need to be done once, or if you need to start over.
|
34
|
+
|
35
|
+
1. Fork nexpose-client: Visit https://github.com/rapid7/nexpose-client and click Fork,
|
36
|
+
selecting your github account if prompted
|
37
|
+
2. Clone ```git@github.com:<your-github-username>/nexpose-client.git```, replacing
|
38
|
+
```<your-github-username>``` with, you guessed it, your Github username.
|
39
|
+
3. Add the master nexpose-client repository as your upstream:
|
40
|
+
```
|
41
|
+
git remote add upstream git://github.com/rapid7/nexpose-client.git
|
42
|
+
git fetch --all
|
43
|
+
```
|
44
|
+
|
45
|
+
### Branch and Improve
|
46
|
+
|
47
|
+
If you have a contribution to make, first create a branch to contain your
|
48
|
+
work. The name is yours to choose, however generally it should roughly
|
49
|
+
describe what you are doing. In this example, and from here on out, the
|
50
|
+
branch will be wow, but you should change this.
|
51
|
+
|
52
|
+
```
|
53
|
+
git fetch --all
|
54
|
+
git checkout master
|
55
|
+
git rebase upstream/master
|
56
|
+
git checkout -b wow
|
57
|
+
```
|
58
|
+
|
59
|
+
Now, make your changes, committing as necessary, using useful commit messages:
|
60
|
+
|
61
|
+
```
|
62
|
+
vim CONTRIBUTING.md
|
63
|
+
git add CONTRIBUTING.md
|
64
|
+
git commit -m "Adds a document on how to contribute to nexpose-client." -a
|
65
|
+
```
|
66
|
+
|
67
|
+
Please note that changes to [lib/nexpose/version.rb](https://github.com/rapid7/nexpose-client/blob/master/lib/nexpose/version.rb) in PRs are almost never necessary.
|
68
|
+
|
69
|
+
Now push your changes to your fork:
|
70
|
+
|
71
|
+
```
|
72
|
+
git push origin wow
|
73
|
+
```
|
74
|
+
|
75
|
+
Finally, submit the PR. Navigate to ```https://github.com/<your-github-username>/nexpose-client/compare/wow```, fill in the details, and submit.
|
76
|
+
|
77
|
+
## Releasing New Versions
|
78
|
+
|
79
|
+
Typically this process is reserved for contributors with push permissions to
|
80
|
+
nexpose-client:
|
81
|
+
|
82
|
+
### Release New Gem
|
83
|
+
|
84
|
+
1. Get an account on [Rubygems](https://rubygems.org)
|
85
|
+
2. Contact one of the nexpose-client project contributors and have them add you to the nexpose-client gem
|
86
|
+
3. Edit [lib/nexpose/version.rb](https://github.com/rapid7/nexpose-client/blob/master/lib/nexpose/version.rb) and increment ```VERSION```. Commit and push to origin/upstream master.
|
87
|
+
4. Run ```rake release```
|
88
|
+
|
89
|
+
### Github Release
|
90
|
+
|
91
|
+
Some users may prefer to consume nexpose-client in a manner other than using git itself. For that reason, Github offers [Releases](https://github.com/blog/1547-release-your-software). Whenever a new version of the software is to be released, be kind and also create a new [Release](https://github.com/rapid7/nexpose-client/releases), using a versioning scheme identical to that used for the gem.
|
data/README.markdown
CHANGED
@@ -11,7 +11,7 @@ This gem is heavily used for internal, automated testing of the Nexpose product.
|
|
11
11
|
|
12
12
|
## Contributions
|
13
13
|
|
14
|
-
We welcome contributions to this package.
|
14
|
+
We welcome contributions to this package. Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
|
15
15
|
|
16
16
|
Our coding standards include:
|
17
17
|
|
data/lib/nexpose.rb
CHANGED
@@ -50,7 +50,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
50
50
|
require 'date'
|
51
51
|
require 'time'
|
52
52
|
require 'rexml/document'
|
53
|
-
require 'nokogiri'
|
54
53
|
require 'net/https'
|
55
54
|
require 'net/http'
|
56
55
|
require 'uri'
|
@@ -64,6 +63,7 @@ require 'nexpose/alert'
|
|
64
63
|
require 'nexpose/ajax'
|
65
64
|
require 'nexpose/api'
|
66
65
|
require 'nexpose/api_request'
|
66
|
+
require 'nexpose/asset'
|
67
67
|
require 'nexpose/common'
|
68
68
|
require 'nexpose/console'
|
69
69
|
require 'nexpose/credential'
|
@@ -74,6 +74,7 @@ require 'nexpose/device'
|
|
74
74
|
require 'nexpose/discovery'
|
75
75
|
require 'nexpose/discovery/filter'
|
76
76
|
require 'nexpose/engine'
|
77
|
+
require 'nexpose/external'
|
77
78
|
require 'nexpose/filter'
|
78
79
|
require 'nexpose/global_settings'
|
79
80
|
require 'nexpose/group'
|
@@ -94,6 +95,7 @@ require 'nexpose/tag/criteria'
|
|
94
95
|
require 'nexpose/ticket'
|
95
96
|
require 'nexpose/user'
|
96
97
|
require 'nexpose/vuln'
|
98
|
+
require 'nexpose/vuln_def'
|
97
99
|
require 'nexpose/vuln_exception'
|
98
100
|
require 'nexpose/connection'
|
99
101
|
require 'nexpose/maint'
|
@@ -0,0 +1,276 @@
|
|
1
|
+
module Nexpose
|
2
|
+
# Asset object as return from the 2.1 API.
|
3
|
+
#
|
4
|
+
class Asset < APIObject
|
5
|
+
# Unique identifier of the asset on the Nexpose console.
|
6
|
+
attr_reader :id
|
7
|
+
# Primary IP address of the asset.
|
8
|
+
attr_reader :ip
|
9
|
+
# MAC address of the asset.
|
10
|
+
attr_reader :mac
|
11
|
+
# Known host names found for the asset.
|
12
|
+
attr_reader :host_names
|
13
|
+
# Operating system name.
|
14
|
+
attr_reader :os_name
|
15
|
+
# The CPE for the asset's operating system.
|
16
|
+
attr_reader :os_cpe
|
17
|
+
# The host type of the asset. One of: GUEST, HYPERVISOR, PHYSICAL, MOBILE.
|
18
|
+
attr_reader :host_type
|
19
|
+
|
20
|
+
# Assessment summary of the asset, including most recent scan info. [Lazy]
|
21
|
+
attr_reader :assessment
|
22
|
+
# Service endpoints enumerated on the asset. [Lazy]
|
23
|
+
attr_reader :services
|
24
|
+
# Software enumerated on the asset. [Lazy]
|
25
|
+
attr_reader :software
|
26
|
+
# Vulnerabilities detected on the asset. [Lazy]
|
27
|
+
attr_reader :vulnerabilities
|
28
|
+
# Vulnerability instances detected on the asset. [Lazy]
|
29
|
+
attr_reader :vulnerability_instances
|
30
|
+
# Vulnerability exploits to which this asset is susceptible. [Lazy]
|
31
|
+
attr_reader :exploits
|
32
|
+
# Malware kits to which this asset is susceptible. [Lazy]
|
33
|
+
attr_reader :malware_kits
|
34
|
+
|
35
|
+
# User accounts enumerated on the asset. [Lazy]
|
36
|
+
attr_reader :user_accounts
|
37
|
+
# Group accounts enumerated on the asset. [Lazy]
|
38
|
+
attr_reader :group_accounts
|
39
|
+
# Files and directories that have been enumerated on the asset. [Lazy]
|
40
|
+
attr_reader :files
|
41
|
+
|
42
|
+
def initialize
|
43
|
+
@addresses = []
|
44
|
+
@host_names = []
|
45
|
+
end
|
46
|
+
|
47
|
+
# Load an asset from the provided console.
|
48
|
+
#
|
49
|
+
# @param [Connection] nsc Active connection to a Nexpose console.
|
50
|
+
# @param [String] id Unique identifier of an asset.
|
51
|
+
# @return [Asset] The requested asset, if found.
|
52
|
+
#
|
53
|
+
def self.load(nsc, id)
|
54
|
+
uri = "/api/2.1/assets/#{id}"
|
55
|
+
resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON)
|
56
|
+
hash = JSON.parse(resp, symbolize_names: true)
|
57
|
+
new.object_from_hash(nsc, hash)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Software found on an asset.
|
62
|
+
#
|
63
|
+
class Software < APIObject
|
64
|
+
# The software product name.
|
65
|
+
attr_reader :product
|
66
|
+
# The version of software detected.
|
67
|
+
attr_reader :version
|
68
|
+
# Name of the vendor publishing the software.
|
69
|
+
attr_reader :vendor
|
70
|
+
# The family of software.
|
71
|
+
attr_reader :family
|
72
|
+
# Type of software.
|
73
|
+
attr_reader :type
|
74
|
+
end
|
75
|
+
|
76
|
+
# A service endpoint on an asset.
|
77
|
+
#
|
78
|
+
class Service < APIObject
|
79
|
+
# Name of the service. [Optional]
|
80
|
+
attr_reader :name
|
81
|
+
# Port on which the service is running.
|
82
|
+
attr_reader :port
|
83
|
+
# Protocol used to communicate to the port. @see Service::Protocol.
|
84
|
+
attr_reader :protocol
|
85
|
+
|
86
|
+
def initialize(port = 0, protocol = Protocol::RAW, name = nil)
|
87
|
+
@port, @protocol, @name = port, protocol, name
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_h
|
91
|
+
{ name: name,
|
92
|
+
port: port,
|
93
|
+
protocol: protocol }
|
94
|
+
end
|
95
|
+
|
96
|
+
def <=>(other)
|
97
|
+
c = port <=> other.port
|
98
|
+
return c unless c == 0
|
99
|
+
c = protocol <=> other.protocol
|
100
|
+
return c unless c == 0
|
101
|
+
name <=> other.name
|
102
|
+
end
|
103
|
+
|
104
|
+
def ==(other)
|
105
|
+
eql?(other)
|
106
|
+
end
|
107
|
+
|
108
|
+
def eql?(other)
|
109
|
+
port.eql?(other.port) && protocol.eql?(other.protocol) && name.eql?(other.name)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Valid protocol values for a service endpoint.
|
113
|
+
module Protocol
|
114
|
+
# Internet Protocol
|
115
|
+
IP = 'IP'
|
116
|
+
# Internet Control Message Protocol
|
117
|
+
ICMP = 'ICMP'
|
118
|
+
# Internet Group Management Protocol
|
119
|
+
IGMP = 'IGMP'
|
120
|
+
# Gateway-to-Gateway Protocol
|
121
|
+
GGP = 'GGP'
|
122
|
+
# Transmission Control Protocol
|
123
|
+
TCP = 'TCP'
|
124
|
+
# PARC Universal Protocol
|
125
|
+
PUP = 'PUP'
|
126
|
+
# User Datagram Protocol
|
127
|
+
UDP = 'UDP'
|
128
|
+
# Internet Datagram Protocol
|
129
|
+
IDP = 'IDP'
|
130
|
+
# Encapsulating Security Payload
|
131
|
+
ESP = 'ESP'
|
132
|
+
# Network Disk Protocol
|
133
|
+
ND = 'ND'
|
134
|
+
# Raw Packet (or unknown)
|
135
|
+
RAW = 'RAW'
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# User accounts on an asset.
|
140
|
+
#
|
141
|
+
class UserAccount < APIObject
|
142
|
+
# User account name.
|
143
|
+
attr_reader :name
|
144
|
+
# Unique identifier of the user as determined by the asset (not Nexpose).
|
145
|
+
attr_reader :id
|
146
|
+
# Full name of the user.
|
147
|
+
attr_reader :full_name
|
148
|
+
# Account attributes.
|
149
|
+
attr_reader :attributes
|
150
|
+
|
151
|
+
def initialize(name = nil, id = 0, full_name = nil, attributes = [])
|
152
|
+
@id, @name, @full_name, @attributes = id, name, full_name, attributes
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_h
|
156
|
+
{ name: name,
|
157
|
+
id: id,
|
158
|
+
full_name: full_name,
|
159
|
+
attributes: Attributes.to_hash(attributes) }
|
160
|
+
end
|
161
|
+
|
162
|
+
def <=>(other)
|
163
|
+
c = name <=> other.name
|
164
|
+
return c unless c == 0
|
165
|
+
c = id <=> other.id
|
166
|
+
return c unless c == 0
|
167
|
+
c = full_name <=> other.full_name
|
168
|
+
return c unless c == 0
|
169
|
+
attributes <=> other.attributes
|
170
|
+
end
|
171
|
+
|
172
|
+
def ==(other)
|
173
|
+
eql?(other)
|
174
|
+
end
|
175
|
+
|
176
|
+
def eql?(other)
|
177
|
+
name.eql?(other.name) && id.eql?(other.id) && full_name.eql?(other.full_name) && attributes.eql?(other.attributes)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Group accounts on an asset.
|
182
|
+
#
|
183
|
+
class GroupAccount < APIObject
|
184
|
+
# Group account name.
|
185
|
+
attr_reader :name
|
186
|
+
# Unique identifier of the group as determined by the asset (not Nexpose).
|
187
|
+
attr_reader :id
|
188
|
+
# Group attributes.
|
189
|
+
attr_reader :attributes
|
190
|
+
|
191
|
+
def initialize(name = nil, id = 0, attributes = [])
|
192
|
+
@name = name
|
193
|
+
@id = id
|
194
|
+
@attributes = attributes
|
195
|
+
end
|
196
|
+
|
197
|
+
def to_h
|
198
|
+
{ name: name,
|
199
|
+
id: id,
|
200
|
+
attributes: Attributes.to_hash(attributes) }
|
201
|
+
end
|
202
|
+
|
203
|
+
def <=>(other)
|
204
|
+
c = name <=> other.name
|
205
|
+
return c unless c == 0
|
206
|
+
c = id <=> other.id
|
207
|
+
return c unless c == 0
|
208
|
+
attributes <=> other.attributes
|
209
|
+
end
|
210
|
+
|
211
|
+
def ==(other)
|
212
|
+
eql?(other)
|
213
|
+
end
|
214
|
+
|
215
|
+
def eql?(other)
|
216
|
+
name.eql?(other.name) && id.eql?(other.id) && attributes.eql?(other.attributes)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# File or directory on an asset.
|
221
|
+
#
|
222
|
+
class File < APIObject
|
223
|
+
# Name of the file.
|
224
|
+
attr_reader :name
|
225
|
+
# Size of the file.
|
226
|
+
attr_reader :size
|
227
|
+
# File attributes.
|
228
|
+
attr_reader :attributes
|
229
|
+
# Whether the file is a directory.
|
230
|
+
attr_reader :directory
|
231
|
+
|
232
|
+
def initialize(name = nil, size = 0, directory = false, attributes = [])
|
233
|
+
@name, @size, @directory, @attributes = name, size, directory, attributes
|
234
|
+
end
|
235
|
+
|
236
|
+
def directory?
|
237
|
+
directory
|
238
|
+
end
|
239
|
+
|
240
|
+
def to_h
|
241
|
+
{ name: name,
|
242
|
+
size: size,
|
243
|
+
directory: directory,
|
244
|
+
attributes: Attributes.to_hash(attributes) }
|
245
|
+
end
|
246
|
+
|
247
|
+
def <=>(other)
|
248
|
+
c = name <=> other.name
|
249
|
+
return c unless c == 0
|
250
|
+
c = size <=> other.size
|
251
|
+
return c unless c == 0
|
252
|
+
c = directory <=> other.directory
|
253
|
+
return c unless c == 0
|
254
|
+
attributes <=> other.attributes
|
255
|
+
end
|
256
|
+
|
257
|
+
def ==(other)
|
258
|
+
eql?(other)
|
259
|
+
end
|
260
|
+
|
261
|
+
def eql?(other)
|
262
|
+
name.eql?(other.name) && size.eql?(other.size) && directory.eql?(other.directory) && attributes.eql?(other.attributes)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# Assessment statistics for an asset.
|
267
|
+
#
|
268
|
+
class Assessment < APIObject
|
269
|
+
# The date an asset was last scanned.
|
270
|
+
attr_reader :last_scan_date
|
271
|
+
# The ID of the scan which last assessed the asset.
|
272
|
+
attr_reader :last_scan_id
|
273
|
+
# The current risk score of the asset.
|
274
|
+
attr_reader :risk_score
|
275
|
+
end
|
276
|
+
end
|
data/lib/nexpose/common.rb
CHANGED
@@ -110,6 +110,18 @@ module Nexpose
|
|
110
110
|
attr_accessor :incremental
|
111
111
|
attr_accessor :repeater_type
|
112
112
|
|
113
|
+
# Extended attributes added with the new scheduler implementation
|
114
|
+
attr_accessor :is_extended
|
115
|
+
attr_accessor :hour
|
116
|
+
attr_accessor :minute
|
117
|
+
attr_accessor :date
|
118
|
+
attr_accessor :day
|
119
|
+
attr_accessor :occurrence
|
120
|
+
attr_accessor :start_month
|
121
|
+
attr_accessor :timezone
|
122
|
+
attr_accessor :next_run_time
|
123
|
+
attr_accessor :template
|
124
|
+
|
113
125
|
def initialize(type, interval, start, enabled = true)
|
114
126
|
@type = type
|
115
127
|
@interval = interval
|
@@ -117,16 +129,33 @@ module Nexpose
|
|
117
129
|
@enabled = enabled
|
118
130
|
end
|
119
131
|
|
132
|
+
def self.from_hash(hash)
|
133
|
+
schedule = new(hash[:type], hash[:interval], hash[:start])
|
134
|
+
hash.each do |k, v|
|
135
|
+
schedule.instance_variable_set("@#{k}", v)
|
136
|
+
end
|
137
|
+
schedule
|
138
|
+
end
|
139
|
+
|
120
140
|
def as_xml
|
121
141
|
xml = REXML::Element.new('Schedule')
|
122
142
|
xml.attributes['enabled'] = @enabled ? 1 : 0
|
123
143
|
xml.attributes['type'] = @type
|
124
144
|
xml.attributes['interval'] = @interval
|
125
|
-
xml.attributes['start'] = @start
|
145
|
+
xml.attributes['start'] = @start if @start
|
126
146
|
xml.attributes['maxDuration'] = @max_duration if @max_duration
|
127
147
|
xml.attributes['notValidAfter'] = @not_valid_after if @not_valid_after
|
128
148
|
xml.attributes['incremental'] = @incremental ? 1 : 0 if @incremental
|
129
149
|
xml.attributes['repeaterType'] = @repeater_type if @repeater_type
|
150
|
+
xml.attributes['is_extended'] = @is_extended if @is_extended
|
151
|
+
xml.attributes['hour'] = @hour if @hour
|
152
|
+
xml.attributes['minute'] = @minute if @minute
|
153
|
+
xml.attributes['date'] = @date if @date
|
154
|
+
xml.attributes['day'] = @day if @day
|
155
|
+
xml.attributes['occurrence'] = @occurrence if @occurrence
|
156
|
+
xml.attributes['start_month'] = @start_month if @start_month
|
157
|
+
xml.attributes['timezone'] = @timezone if @timezone
|
158
|
+
xml.attributes['template'] = @template if @template
|
130
159
|
xml
|
131
160
|
end
|
132
161
|
|
@@ -145,6 +174,16 @@ module Nexpose
|
|
145
174
|
schedule.not_valid_after = xml.attributes['notValidAfter'] if xml.attributes['notValidAfter']
|
146
175
|
schedule.incremental = (xml.attributes['incremental'] && xml.attributes['incremental'] == '1')
|
147
176
|
schedule.repeater_type = xml.attributes['repeaterType'] if xml.attributes['repeaterType']
|
177
|
+
schedule.is_extended = xml.attributes['is_extended'] if xml.attributes['is_extended']
|
178
|
+
schedule.hour = xml.attributes['hour'] if xml.attributes['hour']
|
179
|
+
schedule.minute = xml.attributes['minute'] if xml.attributes['minute']
|
180
|
+
schedule.date = xml.attributes['date'] if xml.attributes['date']
|
181
|
+
schedule.day = xml.attributes['day'] if xml.attributes['day']
|
182
|
+
schedule.occurrence = xml.attributes['occurrence'] if xml.attributes['occurrence']
|
183
|
+
schedule.start_month = xml.attributes['start_month'] if xml.attributes['start_month']
|
184
|
+
schedule.timezone = xml.attributes['timezone'] if xml.attributes['timezone']
|
185
|
+
schedule.next_run_time = xml.attributes['next_run_time'] if xml.attributes['next_run_time']
|
186
|
+
schedule.template = xml.attributes['template'] if xml.attributes['template']
|
148
187
|
schedule
|
149
188
|
end
|
150
189
|
|
@@ -0,0 +1,205 @@
|
|
1
|
+
module Nexpose
|
2
|
+
class Connection
|
3
|
+
# Import external assets into a Nexpose console.
|
4
|
+
#
|
5
|
+
# This method will synchronously import a collection of assets into the
|
6
|
+
# console. Each call to this method will be treated as a single event.
|
7
|
+
#
|
8
|
+
# This method should only be used against "static" sites, i.e., those not
|
9
|
+
# tied to a dynamic population service like vSphere, AWS, etc.
|
10
|
+
#
|
11
|
+
# If a paused scan exists on the site at the time of import, the newly
|
12
|
+
# imported assets will not be included in the scan when it resumes.
|
13
|
+
#
|
14
|
+
# @param [Fixnum] site_id Existing site to import assets into.
|
15
|
+
# @param [Array[External::Asset]] assets External assets to import.
|
16
|
+
# @return [Array[ImportResult]] collection of import results.
|
17
|
+
#
|
18
|
+
def import_assets(site_id, assets)
|
19
|
+
json = JSON.generate(Array(assets).map(&:to_h))
|
20
|
+
import_assets_from_json(site_id, json)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Import external assets into a Nexpose console.
|
24
|
+
#
|
25
|
+
# @param [Fixnum] site_id Existing site to import assets into.
|
26
|
+
# @param [String] json JSON representation of assets to import.
|
27
|
+
# @return [Array[ImportResult]] collection of import results.
|
28
|
+
#
|
29
|
+
def import_assets_from_json(site_id, json)
|
30
|
+
uri = "/api/2.1/sites/#{site_id}/assets"
|
31
|
+
# Wait up to 5 minutes for a response.
|
32
|
+
resp = AJAX.post(self, uri, json, AJAX::CONTENT_TYPE::JSON, 300)
|
33
|
+
arr = JSON.parse(resp, symbolize_names: true)
|
34
|
+
arr.map { |e| External::ImportResult.new.object_from_hash(self, e) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Namespace for functionality around importing external assets into Nexpose.
|
39
|
+
#
|
40
|
+
module External
|
41
|
+
# Object for importing assets from external sources into a Nexpose console.
|
42
|
+
# This exists primarily as a convenience for marshalling the data into the
|
43
|
+
# proper JSON format.
|
44
|
+
#
|
45
|
+
# In order to successfully import an asset, it must contain at least one
|
46
|
+
# scannable identifier: IP address, fully qualified domain name, or NetBIOS
|
47
|
+
# name. This ensures that once an asset is imported to the console, it can
|
48
|
+
# be scanned.
|
49
|
+
#
|
50
|
+
# Besides a scannable identifier, all other fields are optional.
|
51
|
+
#
|
52
|
+
class Asset
|
53
|
+
# IPv4 or IPv6 that is the primary identifier of the asset.
|
54
|
+
attr_accessor :ip
|
55
|
+
# A fully qualified domain name of the asset.
|
56
|
+
attr_accessor :fqdn
|
57
|
+
# A NetBIOS name of the asset.
|
58
|
+
attr_accessor :net_bios
|
59
|
+
# The MAC address of the asset.
|
60
|
+
attr_accessor :mac
|
61
|
+
# The host type of the asset. One of: GUEST, HYPERVISOR, PHYSICAL, MOBILE.
|
62
|
+
attr_accessor :host_type
|
63
|
+
# A list of alternate identifiers of the asset. This can include additional
|
64
|
+
# IP addresses and host names.
|
65
|
+
attr_accessor :aliases
|
66
|
+
# The date the asset was scanned. If left blank, the current time will be
|
67
|
+
# used by the console. Use the ISO 8601 basic date-time format.
|
68
|
+
# For example: 20141211T100614.526Z
|
69
|
+
attr_accessor :scan_date
|
70
|
+
# The CPE for the operating system on the asset.
|
71
|
+
attr_accessor :os
|
72
|
+
# A list of CPEs identifying software installed on the asset.
|
73
|
+
attr_accessor :software
|
74
|
+
# A list of service endpoints on the asset.
|
75
|
+
attr_accessor :services
|
76
|
+
# A list of user accounts on the asset.
|
77
|
+
attr_accessor :users
|
78
|
+
# A list of group accounts on the asset.
|
79
|
+
attr_accessor :groups
|
80
|
+
# Files and directories on the asset.
|
81
|
+
attr_accessor :files
|
82
|
+
# A list of key-value attributes associated with the asset.
|
83
|
+
attr_accessor :attributes
|
84
|
+
# Asset-level vulnerabilities.
|
85
|
+
attr_accessor :vulnerabilities
|
86
|
+
|
87
|
+
def initialize
|
88
|
+
@aliases = []
|
89
|
+
@software = []
|
90
|
+
@services = []
|
91
|
+
@attributes = []
|
92
|
+
@users = []
|
93
|
+
@groups = []
|
94
|
+
@files = []
|
95
|
+
@vulnerabilities = []
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_json
|
99
|
+
JSON.generate(to_h)
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_h
|
103
|
+
{ ip: ip,
|
104
|
+
fqdn: fqdn,
|
105
|
+
net_bios: net_bios,
|
106
|
+
mac: mac,
|
107
|
+
host_type: host_type,
|
108
|
+
aliases: aliases,
|
109
|
+
scan_date: scan_date,
|
110
|
+
os: os,
|
111
|
+
software: software,
|
112
|
+
services: services.map(&:to_h),
|
113
|
+
users: users.map(&:to_h),
|
114
|
+
groups: groups.map(&:to_h),
|
115
|
+
files: files.map(&:to_h),
|
116
|
+
vulnerabilities: vulnerabilities.map(&:to_h),
|
117
|
+
attributes: Attributes.to_hash(attributes) }
|
118
|
+
end
|
119
|
+
|
120
|
+
# Valid host types for an asset.
|
121
|
+
module HostType
|
122
|
+
GUEST = 'GUEST'
|
123
|
+
HYPERVISOR = 'HYPERVISOR'
|
124
|
+
PHYSICAL = 'PHYSICAL'
|
125
|
+
MOBILE = 'MOBILE'
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# A service endpoint on an asset.
|
130
|
+
#
|
131
|
+
class Service
|
132
|
+
# Name of the service. [Optional]
|
133
|
+
attr_accessor :name
|
134
|
+
# Port on which the service is running.
|
135
|
+
attr_accessor :port
|
136
|
+
# Protocol used to communicate to the port. @see Service::Protocol.
|
137
|
+
attr_accessor :protocol
|
138
|
+
# Vulnerabilities specific to this service endpoint.
|
139
|
+
attr_accessor :vulnerabilities
|
140
|
+
|
141
|
+
def initialize(port, protocol = Protocol::RAW, name = nil)
|
142
|
+
@port, @protocol, @name = port, protocol, name
|
143
|
+
@vulnerabilities = []
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_h
|
147
|
+
{ name: name,
|
148
|
+
port: port,
|
149
|
+
protocol: protocol,
|
150
|
+
vulnerabilities: vulnerabilities.map(&:to_h) }
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Vulnerability check object for importing vulnerabilities into Nexpose.
|
155
|
+
#
|
156
|
+
class VulnerabilityCheck
|
157
|
+
# Unique identifier of a vulnerability in Nexpose.
|
158
|
+
attr_accessor :vuln_id
|
159
|
+
# Status of the vulnerability. @see VulnerabilityCheck::Status
|
160
|
+
attr_accessor :status
|
161
|
+
# Unique identifier of a vulnerability instance, typically used for spider
|
162
|
+
# vulns or when multiple instances of a vuln exist on the same service.
|
163
|
+
attr_accessor :key
|
164
|
+
# Explanation of what proves that an asset or service is vulnerable.
|
165
|
+
attr_accessor :proof
|
166
|
+
|
167
|
+
def initialize(vuln_id, status = Status::EXPLOITED, proof = nil, key = nil)
|
168
|
+
@vuln_id, @status, @proof, @key = vuln_id, status, proof, key
|
169
|
+
end
|
170
|
+
|
171
|
+
def to_h
|
172
|
+
{ vuln_id: vuln_id,
|
173
|
+
status: status,
|
174
|
+
key: key,
|
175
|
+
proof: proof }
|
176
|
+
end
|
177
|
+
|
178
|
+
# Valid vulnerability status for import into Nexpose.
|
179
|
+
module Status
|
180
|
+
# Vulnerability verified by exploit.
|
181
|
+
EXPLOITED = 'vulnerable-exploited'
|
182
|
+
# Vulnerable because the service or software version is associated with
|
183
|
+
# a known vulnerability.
|
184
|
+
VERSION = 'vulnerable-version'
|
185
|
+
# A potential vulnerability.
|
186
|
+
POTENTIAL = 'potential'
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# Result object returned from an import_assets call, used to correlate the
|
191
|
+
# supplied scannable identifier with the resulting asset ID or any error
|
192
|
+
# messages from a problematic import.
|
193
|
+
#
|
194
|
+
class ImportResult < APIObject
|
195
|
+
# IP or hostname provided during import.
|
196
|
+
attr_reader :name
|
197
|
+
# Resulting asset ID of the created asset, if any.
|
198
|
+
attr_reader :asset_id
|
199
|
+
# The asset created by the import. [Lazy]
|
200
|
+
attr_reader :asset
|
201
|
+
# Any error messages associated with the import of the asset.
|
202
|
+
attr_reader :error_message
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -127,7 +127,7 @@ module Nexpose
|
|
127
127
|
desc = xml.add_element('Description').add_text(@description)
|
128
128
|
|
129
129
|
services = xml.add_element('Services')
|
130
|
-
service = services.add_element('Service').add_attribute('type', @
|
130
|
+
service = services.add_element('Service').add_attribute('type', @service)
|
131
131
|
|
132
132
|
(account = xml.add_element('Account')).add_attribute('type', 'nexpose')
|
133
133
|
account.add_element('Field', { 'name' => 'database' }).add_text(@database)
|
data/lib/nexpose/site.rb
CHANGED
@@ -257,9 +257,14 @@ module Nexpose
|
|
257
257
|
# @param [Fixnum] id Site ID of an existing site.
|
258
258
|
# @return [Site] Site configuration loaded from a Nexpose console.
|
259
259
|
#
|
260
|
-
def self.load(connection, id)
|
261
|
-
|
262
|
-
|
260
|
+
def self.load(connection, id, is_extended = false)
|
261
|
+
if is_extended
|
262
|
+
r = APIRequest.execute(connection.url,
|
263
|
+
%(<SiteConfigRequest session-id="#{connection.session_id}" site-id="#{id}" is_extended="true"/>))
|
264
|
+
else
|
265
|
+
r = APIRequest.execute(connection.url,
|
266
|
+
%(<SiteConfigRequest session-id="#{connection.session_id}" site-id="#{id}"/>))
|
267
|
+
end
|
263
268
|
site = parse(r.res)
|
264
269
|
site.load_dynamic_attributes(connection) if site.dynamic?
|
265
270
|
site
|
data/lib/nexpose/version.rb
CHANGED
data/lib/nexpose/vuln.rb
CHANGED
@@ -45,12 +45,11 @@ module Nexpose
|
|
45
45
|
#
|
46
46
|
# @return [Array[String]] Array of currently valid check types.
|
47
47
|
#
|
48
|
-
def
|
49
|
-
data = DataTable._get_dyn_table(self, '/
|
48
|
+
def vuln_types
|
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
|
-
|
53
|
-
alias_method :vuln_types, :list_vuln_types
|
52
|
+
alias_method :list_vuln_types, :vuln_types
|
54
53
|
|
55
54
|
# Retrieve details for a vulnerability.
|
56
55
|
#
|
@@ -92,7 +91,7 @@ module Nexpose
|
|
92
91
|
# Nexpose between the provided dates.
|
93
92
|
#
|
94
93
|
def find_vulns_by_date(from, to = nil)
|
95
|
-
uri = "/
|
94
|
+
uri = "/data/vulnerability/synopsis/dyntable.xml?addedMin=#{from}"
|
96
95
|
uri += "&addedMax=#{to}" if to
|
97
96
|
DataTable._get_dyn_table(self, uri).map { |v| VulnSynopsis.new(v) }
|
98
97
|
end
|
@@ -285,4 +284,46 @@ module Nexpose
|
|
285
284
|
@malware = hash['MalwareSource'] == 'true'
|
286
285
|
end
|
287
286
|
end
|
287
|
+
|
288
|
+
# A vulnerability discovered on an asset.
|
289
|
+
#
|
290
|
+
class Vulnerability < APIObject
|
291
|
+
# Unique identifier of the vulnerability.
|
292
|
+
attr_reader :id
|
293
|
+
# Vulnerability title.
|
294
|
+
attr_reader :title
|
295
|
+
# Full vulnerability definition. [Lazy]
|
296
|
+
attr_reader :vulnerability_definition
|
297
|
+
end
|
298
|
+
|
299
|
+
# An instance of a vulnerability discovered on an asset.
|
300
|
+
#
|
301
|
+
class VulnerabilityInstance < APIObject
|
302
|
+
# ID of the asset where the vulnerability instance was detected.
|
303
|
+
attr_reader :asset_id
|
304
|
+
# IP Address of the asset where the vulnerability instance was detected.
|
305
|
+
attr_reader :asset_ip_address
|
306
|
+
# ID of the scan where the vulnerability instance was detected.
|
307
|
+
attr_reader :scan_id
|
308
|
+
# The ID (natural key) of the vulnerability.
|
309
|
+
attr_reader :vulnerability_id
|
310
|
+
# The time at which the vulnerability test was performed.
|
311
|
+
attr_reader :date
|
312
|
+
# The vulnerable status of the vulnerability.
|
313
|
+
attr_reader :status
|
314
|
+
# The proof which explains why the vulnerability is present on the asset.
|
315
|
+
# The value is often HTML-formatted text.
|
316
|
+
attr_reader :proof
|
317
|
+
# Key that can distinguish the instances of the same type on the system.
|
318
|
+
# For spider vulnerabilities, this is typically the relative URI where the
|
319
|
+
# vuln was discovered.
|
320
|
+
attr_reader :key
|
321
|
+
# The service that the vulnerability test was performed against.
|
322
|
+
attr_reader :service
|
323
|
+
# The port on which the service was running if the vulnerability was found
|
324
|
+
# through a network service, -1 if not defined.
|
325
|
+
attr_reader :port
|
326
|
+
# Protocol the service was providing on which the vulnerability was found.
|
327
|
+
attr_reader :protocol
|
328
|
+
end
|
288
329
|
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
module Nexpose
|
2
|
+
class Connection
|
3
|
+
# Retrieve all vulnerability definitions currently in a Nexpose console.
|
4
|
+
#
|
5
|
+
# Note, this can easily take 30 seconds to complete and will load over
|
6
|
+
# 55,000 vulnerability definitions.
|
7
|
+
#
|
8
|
+
# @return [Array[VulnerabilityDefinition]] Collection of vulnerability definitions.
|
9
|
+
#
|
10
|
+
def all_vulns
|
11
|
+
uri = '/api/2.0/vulnerability_definitions'
|
12
|
+
resp = AJAX.get(self, uri, AJAX::CONTENT_TYPE::JSON, per_page: 2_147_483_647)
|
13
|
+
json = JSON.parse(resp, symbolize_names: true)
|
14
|
+
json[:resources].map { |e| VulnerabilityDefinition.new.object_from_hash(self, e) }
|
15
|
+
end
|
16
|
+
|
17
|
+
# Search for any vulnerability definitions which refer to a given CVE.
|
18
|
+
#
|
19
|
+
# @param [String] cve A valid CVE.
|
20
|
+
# @return [Array[VulnerabilityDefinition]] A list of vuln definitions which check the CVE.
|
21
|
+
#
|
22
|
+
def find_vulns_by_cve(cve)
|
23
|
+
uri = '/api/2.0/vulnerability_definitions'
|
24
|
+
resp = AJAX.get(self, uri, AJAX::CONTENT_TYPE::JSON, cve: cve)
|
25
|
+
json = JSON.parse(resp, symbolize_names: true)
|
26
|
+
json[:resources].map { |e| VulnerabilityDefinition.new.object_from_hash(self, e) }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Search for any vulnerability definitions which refer to a given reference
|
30
|
+
# ID.
|
31
|
+
#
|
32
|
+
# Examples:
|
33
|
+
# find_vulns_by_ref('oval', 'OVAL10476')
|
34
|
+
# find_vulns_by_ref('bid', 35067)
|
35
|
+
# find_vulns_by_ref('secunia', 35188)
|
36
|
+
#
|
37
|
+
# @param [String] source External vulnerability reference source.
|
38
|
+
# @param [String] id Unique vulnerability reference ID.
|
39
|
+
# @return [Array[VulnerabilityDefinition]] A list of vuln definitions which
|
40
|
+
# check the vulnerability.
|
41
|
+
#
|
42
|
+
def find_vulns_by_ref(source, id)
|
43
|
+
uri = '/api/2.0/vulnerability_definitions'
|
44
|
+
resp = AJAX.get(self,
|
45
|
+
uri,
|
46
|
+
AJAX::CONTENT_TYPE::JSON,
|
47
|
+
source: source, id: id)
|
48
|
+
json = JSON.parse(resp, symbolize_names: true)
|
49
|
+
json[:resources].map { |e| VulnerabilityDefinition.new.object_from_hash(self, e) }
|
50
|
+
end
|
51
|
+
|
52
|
+
# Search for any vulnerability definitions which refer to a given title.
|
53
|
+
#
|
54
|
+
# Note: This method will return a maximum of 500 results. If the search
|
55
|
+
# yields a high number of results, consider add more specific words to
|
56
|
+
# the title.
|
57
|
+
#
|
58
|
+
# @param [String] title A (partial) title to search for.
|
59
|
+
# @param [Boolean] all_words Whether to include all words from the search
|
60
|
+
# phrase in the search.
|
61
|
+
# @return [Array[VulnerabilityDefinition]] A list of vuln definitions with titles matching
|
62
|
+
# the provided value.
|
63
|
+
#
|
64
|
+
def find_vulns_by_title(title, all_words = true)
|
65
|
+
uri = '/api/2.0/vulnerability_definitions'
|
66
|
+
params = { title: title, all_words: all_words }
|
67
|
+
resp = AJAX.get(self, uri, AJAX::CONTENT_TYPE::JSON, params)
|
68
|
+
json = JSON.parse(resp, symbolize_names: true)
|
69
|
+
json[:resources].map { |e| VulnerabilityDefinition.new.object_from_hash(self, e) }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Vulnerability definition object. Represents a known vulnerability on a given
|
74
|
+
# Nexpose console.
|
75
|
+
#
|
76
|
+
class VulnerabilityDefinition < APIObject
|
77
|
+
# Unique identifier of a vulnerability definition.
|
78
|
+
attr_reader :id
|
79
|
+
# Vulnerability title.
|
80
|
+
attr_reader :title
|
81
|
+
# Vulnerability description, usually formated in HTML.
|
82
|
+
attr_reader :description
|
83
|
+
# The CVEs for the vulnerability.
|
84
|
+
attr_reader :cves
|
85
|
+
# Date the vulnerability was publicized by the third-party, vendor, or another
|
86
|
+
# authoring source.
|
87
|
+
attr_reader :date_published
|
88
|
+
# Date the vulnerability was first checked by Nexpose.
|
89
|
+
attr_reader :date_added
|
90
|
+
# Severity category. One of: Critical, Severe, Moderate.
|
91
|
+
attr_reader :severity
|
92
|
+
# Severity score, in the range of 0.0 to 10.0.
|
93
|
+
attr_reader :severity_score
|
94
|
+
# Risk score associated with vulnerability.
|
95
|
+
attr_reader :riskscore
|
96
|
+
|
97
|
+
# Whether the presence of the vulnerability can cause PCI failure.
|
98
|
+
# One of: Pass, Fail.
|
99
|
+
attr_reader :pci_status
|
100
|
+
# PCI severity score of the vulnerability, measured on a scale of 1 to 5.
|
101
|
+
attr_reader :pci_severity_score
|
102
|
+
|
103
|
+
# CVSS score of the vulnerability. Value between 0.0 and 10.0.
|
104
|
+
attr_reader :cvss_score
|
105
|
+
# Full CVSS vector in CVSS Version 2.0 notation.
|
106
|
+
attr_reader :cvss_vector
|
107
|
+
# Base score for the exploitability of a vulnerability that is used to compute
|
108
|
+
# the overall CVSS score.
|
109
|
+
attr_reader :cvss_exploit_score
|
110
|
+
# Base score for the impact of a vulnerability that is used to compute the
|
111
|
+
# overall CVSS score.
|
112
|
+
attr_reader :cvss_impact_score
|
113
|
+
|
114
|
+
# Whether the vulnerability is classified as a denial-of-service vuln.
|
115
|
+
attr_reader :denial_of_service
|
116
|
+
|
117
|
+
# Load a vulnerability definition from the provided console.
|
118
|
+
#
|
119
|
+
# @param [Connection] nsc Active connection to a Nexpose console.
|
120
|
+
# @param [String] id Unique identifier of a vulnerability definition.
|
121
|
+
# @return [VulnerabilityDefinition] The requested vulnerability definition, if found.
|
122
|
+
#
|
123
|
+
def self.load(nsc, id)
|
124
|
+
uri = "/api/2.0/vulnerability_definitions/#{id}"
|
125
|
+
resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON)
|
126
|
+
hash = JSON.parse(resp, symbolize_names: true)
|
127
|
+
new.object_from_hash(nsc, hash)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Known malware kits that can target a vulnerability.
|
132
|
+
#
|
133
|
+
class MalwareKit < APIObject
|
134
|
+
# Internal Nexpose identifier of the malware kit.
|
135
|
+
attr_reader :id
|
136
|
+
# Malware kit name.
|
137
|
+
attr_reader :name
|
138
|
+
# Malware kit description, if available.
|
139
|
+
attr_reader :description
|
140
|
+
# Popularity of the malware kit, which identifies how common or accessible
|
141
|
+
# it is. Values include: rare, uncommon, common, popular, occasional.
|
142
|
+
attr_reader :popularity
|
143
|
+
end
|
144
|
+
|
145
|
+
# Known exploits of a vulnerability.
|
146
|
+
#
|
147
|
+
class Exploit < APIObject
|
148
|
+
# Internal Nexpose identifier of the exploit.
|
149
|
+
attr_reader :id
|
150
|
+
# Exploit title.
|
151
|
+
attr_reader :title
|
152
|
+
# A description of the exploit, if available.
|
153
|
+
attr_reader :description
|
154
|
+
# Skill level required to use the exploit. One of: Expert, Intermediate,
|
155
|
+
# Novice.
|
156
|
+
attr_reader :skill_level
|
157
|
+
# Source which defined and published the exploit, such as Metasploit or
|
158
|
+
# Exploit Database.
|
159
|
+
attr_reader :source
|
160
|
+
# Reference key used by the publishing source to identify the exploit.
|
161
|
+
attr_reader :source_key
|
162
|
+
end
|
163
|
+
|
164
|
+
# External vulnerability reference.
|
165
|
+
#
|
166
|
+
class Reference < APIObject
|
167
|
+
# Internal Nexpose identifier of the reference.
|
168
|
+
attr_reader :id
|
169
|
+
# Reference value, such as the full CVE identifier.
|
170
|
+
attr_reader :reference
|
171
|
+
# Reference source, such as CVE, MS, RedHat, etc.
|
172
|
+
attr_reader :source
|
173
|
+
end
|
174
|
+
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.9.
|
4
|
+
version: 0.9.4
|
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: 2015-01-
|
14
|
+
date: 2015-01-28 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rex
|
@@ -59,6 +59,7 @@ extensions: []
|
|
59
59
|
extra_rdoc_files:
|
60
60
|
- README.markdown
|
61
61
|
files:
|
62
|
+
- CONTRIBUTING.md
|
62
63
|
- COPYING
|
63
64
|
- Gemfile
|
64
65
|
- README.markdown
|
@@ -69,6 +70,7 @@ files:
|
|
69
70
|
- lib/nexpose/alert.rb
|
70
71
|
- lib/nexpose/api.rb
|
71
72
|
- lib/nexpose/api_request.rb
|
73
|
+
- lib/nexpose/asset.rb
|
72
74
|
- lib/nexpose/common.rb
|
73
75
|
- lib/nexpose/connection.rb
|
74
76
|
- lib/nexpose/console.rb
|
@@ -80,6 +82,7 @@ files:
|
|
80
82
|
- lib/nexpose/discovery/filter.rb
|
81
83
|
- lib/nexpose/engine.rb
|
82
84
|
- lib/nexpose/error.rb
|
85
|
+
- lib/nexpose/external.rb
|
83
86
|
- lib/nexpose/filter.rb
|
84
87
|
- lib/nexpose/global_settings.rb
|
85
88
|
- lib/nexpose/group.rb
|
@@ -104,6 +107,7 @@ files:
|
|
104
107
|
- lib/nexpose/util.rb
|
105
108
|
- lib/nexpose/version.rb
|
106
109
|
- lib/nexpose/vuln.rb
|
110
|
+
- lib/nexpose/vuln_def.rb
|
107
111
|
- lib/nexpose/vuln_exception.rb
|
108
112
|
- nexpose.gemspec
|
109
113
|
homepage: https://github.com/rapid7/nexpose-client
|