nexpose 0.0.98 → 0.1.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.
- data/README.markdown +17 -7
- data/Rakefile +17 -22
- data/lib/README.md +5 -0
- data/lib/nexpose.rb +104 -130
- data/lib/nexpose/api_request.rb +133 -144
- data/lib/nexpose/common.rb +138 -0
- data/lib/nexpose/connection.rb +117 -106
- data/lib/nexpose/creds.rb +292 -279
- data/lib/nexpose/error.rb +21 -21
- data/lib/nexpose/manage.rb +83 -0
- data/lib/nexpose/misc.rb +85 -122
- data/lib/nexpose/report.rb +783 -603
- data/lib/nexpose/role.rb +27 -0
- data/lib/nexpose/scan.rb +264 -285
- data/lib/nexpose/scan_engine.rb +344 -350
- data/lib/nexpose/silo.rb +348 -347
- data/lib/nexpose/site.rb +826 -898
- data/lib/nexpose/ticket.rb +108 -108
- data/lib/nexpose/user.rb +223 -221
- data/lib/nexpose/util.rb +36 -36
- data/lib/nexpose/vuln.rb +510 -520
- metadata +37 -23
- data/README +0 -0
- data/nexpose.gemspec +0 -20
data/lib/nexpose/role.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Nexpose
|
2
|
+
|
3
|
+
module NexposeAPI
|
4
|
+
include XMLUtils
|
5
|
+
|
6
|
+
# Returns a summary list of all roles.
|
7
|
+
def role_listing
|
8
|
+
xml = make_xml('RoleListingRequest')
|
9
|
+
r = execute(xml, '1.2')
|
10
|
+
if r.success
|
11
|
+
res = []
|
12
|
+
r.res.elements.each('RoleListingResponse/RoleSummary') do |summary|
|
13
|
+
res << {
|
14
|
+
:id => summary.attributes['id'],
|
15
|
+
:name => summary.attributes['name'],
|
16
|
+
:full_name => summary.attributes['full-name'],
|
17
|
+
:description => summary.attributes['description'],
|
18
|
+
:enabled => summary.attributes['enabled'],
|
19
|
+
:scope => summary.attributes['scope']
|
20
|
+
}
|
21
|
+
end
|
22
|
+
res
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
data/lib/nexpose/scan.rb
CHANGED
@@ -1,285 +1,264 @@
|
|
1
|
-
module Nexpose
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
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
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
# === Description
|
266
|
-
# Object that holds an event that triggers the start of a scan.
|
267
|
-
#
|
268
|
-
class ScanTrigger
|
269
|
-
# Type of Trigger (AutoUpdate)
|
270
|
-
attr_reader :type
|
271
|
-
# Enable or disable this scan trigger
|
272
|
-
attr_reader :enabled
|
273
|
-
# Sets the trigger to start an incremental scan or a full scan
|
274
|
-
attr_reader :incremental
|
275
|
-
|
276
|
-
def initialize(type, incremental, enabled = 1)
|
277
|
-
|
278
|
-
@type = type
|
279
|
-
@incremental = incremental
|
280
|
-
@enabled = enabled
|
281
|
-
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
end
|
1
|
+
module Nexpose
|
2
|
+
module NexposeAPI
|
3
|
+
include XMLUtils
|
4
|
+
|
5
|
+
# Stop a running or paused scan.
|
6
|
+
#
|
7
|
+
# @param [Fixnum] scan_id ID of the scan to stop.
|
8
|
+
# @param [Fixnum] wait_sec Number of seconds to wait for status to be updated. Default: 0
|
9
|
+
def scan_stop(scan_id, wait_sec = 0)
|
10
|
+
r = execute(make_xml('ScanStopRequest', {'scan-id' => scan_id}))
|
11
|
+
if r.success
|
12
|
+
so_far = 0
|
13
|
+
while so_far < wait_sec
|
14
|
+
status = scan_status(scan_id)
|
15
|
+
return status if status == 'stopped'
|
16
|
+
sleep 5
|
17
|
+
so_far += 5
|
18
|
+
end
|
19
|
+
end
|
20
|
+
r.success
|
21
|
+
end
|
22
|
+
|
23
|
+
def scan_status(param)
|
24
|
+
r = execute(make_xml('ScanStatusRequest', {'scan-id' => param}))
|
25
|
+
r.success ? r.attributes['status'] : nil
|
26
|
+
end
|
27
|
+
|
28
|
+
#----------------------------------------------------------------
|
29
|
+
# Resumes a scan.
|
30
|
+
#
|
31
|
+
# @param scan_id The scan ID.
|
32
|
+
# @return Success(0|1) if it exists or null.
|
33
|
+
#----------------------------------------------------------------
|
34
|
+
def scan_resume(scan_id)
|
35
|
+
r = execute(make_xml('ScanResumeRequest', {'scan-id' => scan_id}))
|
36
|
+
r.success ? r.attributes['success'] : nil
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
#----------------------------------------------------------------
|
41
|
+
# Pauses a scan.
|
42
|
+
#
|
43
|
+
# @param scan_id The scan ID.
|
44
|
+
# @return Success(0|1) if it exists or null.
|
45
|
+
#----------------------------------------------------------------
|
46
|
+
def scan_pause(scan_id)
|
47
|
+
r = execute(make_xml('ScanPauseRequest',{ 'scan-id' => scan_id}))
|
48
|
+
r.success ? r.attributes['success'] : nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def scan_activity
|
52
|
+
r = execute(make_xml('ScanActivityRequest', {}))
|
53
|
+
if (r.success)
|
54
|
+
res = []
|
55
|
+
r.res.elements.each("//ScanSummary") do |scan|
|
56
|
+
res << {
|
57
|
+
:scan_id => scan.attributes['scan-id'].to_i,
|
58
|
+
:site_id => scan.attributes['site-id'].to_i,
|
59
|
+
:engine_id => scan.attributes['engine-id'].to_i,
|
60
|
+
:status => scan.attributes['status'].to_s,
|
61
|
+
:start_time => Date.parse(scan.attributes['startTime'].to_s).to_time
|
62
|
+
}
|
63
|
+
end
|
64
|
+
res
|
65
|
+
else
|
66
|
+
false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def scan_statistics(param)
|
71
|
+
r = execute(make_xml('ScanStatisticsRequest', {'scan-id' => param}))
|
72
|
+
if (r.success)
|
73
|
+
res = {}
|
74
|
+
r.res.elements.each("//ScanSummary/nodes") do |node|
|
75
|
+
res[:nodes] = {}
|
76
|
+
node.attributes.keys.each do |k|
|
77
|
+
res[:nodes][k] = node.attributes[k].to_i
|
78
|
+
end
|
79
|
+
end
|
80
|
+
r.res.elements.each("//ScanSummary/tasks") do |task|
|
81
|
+
res[:task] = {}
|
82
|
+
task.attributes.keys.each do |k|
|
83
|
+
res[:task][k] = task.attributes[k].to_i
|
84
|
+
end
|
85
|
+
end
|
86
|
+
r.res.elements.each("//ScanSummary/vulnerabilities") do |vuln|
|
87
|
+
res[:vulns] ||= {}
|
88
|
+
k = vuln.attributes['status'] + (vuln.attributes['severity'] ? ("-" + vuln.attributes['severity']) : '')
|
89
|
+
res[:vulns][k] = vuln.attributes['count'].to_i
|
90
|
+
end
|
91
|
+
r.res.elements.each("//ScanSummary") do |summ|
|
92
|
+
res[:summary] = {}
|
93
|
+
summ.attributes.keys.each do |k|
|
94
|
+
res[:summary][k] = summ.attributes[k]
|
95
|
+
if (res[:summary][k] =~ /^\d+$/)
|
96
|
+
res[:summary][k] = res[:summary][k].to_i
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
r.res.elements.each("//ScanSummary/message") do |message|
|
101
|
+
res[:message] = message.text
|
102
|
+
end
|
103
|
+
res
|
104
|
+
else
|
105
|
+
false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# === Description
|
111
|
+
# Object that represents a summary of a scan.
|
112
|
+
#
|
113
|
+
class ScanSummary
|
114
|
+
# The Scan ID of the Scan
|
115
|
+
attr_reader :scan_id
|
116
|
+
# The Engine ID used to perform the scan
|
117
|
+
attr_reader :engine_id
|
118
|
+
# TODO: add description
|
119
|
+
attr_reader :name
|
120
|
+
# The scan start time
|
121
|
+
attr_reader :startTime
|
122
|
+
# The scan finish time
|
123
|
+
attr_reader :endTime
|
124
|
+
# The scan status (running|finished|stopped|error| dispatched|paused|aborted|uknown)
|
125
|
+
attr_reader :status
|
126
|
+
# The number of pending tasks
|
127
|
+
attr_reader :tasks_pending
|
128
|
+
# The number of active tasks
|
129
|
+
attr_reader :tasks_active
|
130
|
+
# The number of completed tasks
|
131
|
+
attr_reader :tasks_completed
|
132
|
+
# The number of "live" nodes
|
133
|
+
attr_reader :nodes_live
|
134
|
+
# The number of "dead" nodes
|
135
|
+
attr_reader :nodes_dead
|
136
|
+
# The number of filtered nodes
|
137
|
+
attr_reader :nodes_filtered
|
138
|
+
# The number of unresolved nodes
|
139
|
+
attr_reader :nodes_unresolved
|
140
|
+
# The number of "other" nodes
|
141
|
+
attr_reader :nodes_other
|
142
|
+
# Confirmed vulnerabilities found (indexed by severity)
|
143
|
+
# Associative array, indexed by severity
|
144
|
+
attr_reader :vuln_exploit
|
145
|
+
# Unconfirmed vulnerabilities found (indexed by severity)
|
146
|
+
# Associative array, indexed by severity
|
147
|
+
attr_reader :vuln_version
|
148
|
+
# Not vulnerable checks run (confirmed)
|
149
|
+
attr_reader :not_vuln_exploit
|
150
|
+
# Not vulnerable checks run (unconfirmed)
|
151
|
+
attr_reader :not_vuln_version
|
152
|
+
# Vulnerability check errors
|
153
|
+
attr_reader :vuln_error
|
154
|
+
# Vulnerability checks disabled
|
155
|
+
attr_reader :vuln_disabled
|
156
|
+
# Vulnerability checks other
|
157
|
+
attr_reader :vuln_other
|
158
|
+
|
159
|
+
# Constructor
|
160
|
+
# ScanSummary(can_id, $engine_id, $name, tartTime, $endTime, tatus)
|
161
|
+
def initialize(scan_id, engine_id, name, startTime, endTime, status)
|
162
|
+
|
163
|
+
@scan_id = scan_id
|
164
|
+
@engine_id = engine_id
|
165
|
+
@name = name
|
166
|
+
@startTime = startTime
|
167
|
+
@endTime = endTime
|
168
|
+
@status = status
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
# TODO
|
175
|
+
# === Description
|
176
|
+
# Object that represents the overview statistics for a particular scan.
|
177
|
+
#
|
178
|
+
# === Examples
|
179
|
+
#
|
180
|
+
# # Create a new Nexpose Connection on the default port and Login
|
181
|
+
# nsc = Connection.new("10.1.40.10","nxadmin","password")
|
182
|
+
# nsc.login()
|
183
|
+
#
|
184
|
+
# # Get a Site (Site ID = 12) from the NSC
|
185
|
+
# site = new Site(nsc,12)
|
186
|
+
#
|
187
|
+
# # Start a Scan of this site and pause for 1 minute
|
188
|
+
# scan1 = site.scanSite()
|
189
|
+
# sleep(60)
|
190
|
+
#
|
191
|
+
# # Get the Scan Statistics for this scan
|
192
|
+
# scanStatistics = new ScanStatistics(nsc,scan1["scan_id"])
|
193
|
+
#
|
194
|
+
# # Print out number of confirmed vulnerabilities with a 10 severity
|
195
|
+
# puts scanStatistics.scansummary.vuln_exploit[10]
|
196
|
+
#
|
197
|
+
# # Print out the number of pending tasks left in the scan
|
198
|
+
# puts scanStatistics.scan_summary.tasks_pending
|
199
|
+
#
|
200
|
+
class ScanStatistics
|
201
|
+
# true if an error condition exists; false otherwise
|
202
|
+
attr_reader :error
|
203
|
+
# Error message string
|
204
|
+
attr_reader :error_msg
|
205
|
+
# The last XML request sent by this object
|
206
|
+
attr_reader :request_xml
|
207
|
+
# The last XML response received by this object
|
208
|
+
attr_reader :reseponse_xml
|
209
|
+
# The Scan ID
|
210
|
+
attr_reader :scan_id
|
211
|
+
# The ScanSummary of the scan
|
212
|
+
attr_reader :scan_summary
|
213
|
+
# The NSC Connection associated with this object
|
214
|
+
attr_reader :connection
|
215
|
+
|
216
|
+
# Vulnerability checks other
|
217
|
+
attr_reader :vuln_other
|
218
|
+
|
219
|
+
def initialize(connection, scan_id)
|
220
|
+
@error = false
|
221
|
+
@connection = connection
|
222
|
+
@scan_id = scan_id
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# TODO add engineID
|
227
|
+
# === Description
|
228
|
+
# Object that represents the scanning configuration for a Site.
|
229
|
+
#
|
230
|
+
class ScanConfig
|
231
|
+
|
232
|
+
def self.parse(xml)
|
233
|
+
config = ScanConfig.new(xml.attributes['configID'],
|
234
|
+
xml.attributes['name'],
|
235
|
+
xml.attributes['templateID'],
|
236
|
+
xml.attributes['configVersion'],
|
237
|
+
xml.attributes['engineID'])
|
238
|
+
xml.elements.each('Schedules/Schedule') do |sched|
|
239
|
+
schedule = Schedule.new(sched.attributes['type'],
|
240
|
+
sched.attributes['interval'],
|
241
|
+
sched.attributes['start'],
|
242
|
+
sched.attributes['enabled'])
|
243
|
+
config.addSchedule(schedule)
|
244
|
+
end
|
245
|
+
config
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# TODO: review
|
250
|
+
# <scanFilter scanStop='0' scanFailed='0' scanStart='1'/>
|
251
|
+
# === Description
|
252
|
+
#
|
253
|
+
class ScanFilter
|
254
|
+
attr_reader :scanStop
|
255
|
+
attr_reader :scanFailed
|
256
|
+
attr_reader :scanStart
|
257
|
+
|
258
|
+
def initialize(scan_stop, scan_failed, scan_start)
|
259
|
+
@scanStop = scan_stop
|
260
|
+
@scanFailed = scan_failed
|
261
|
+
@scanStart = scan_start
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|