nexpose_ticketing 0.3.1 → 0.5.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.
@@ -4,6 +4,25 @@ module NexposeTicketing
4
4
  # for Nexpose.
5
5
  # Copyright:: Copyright (c) 2014 Rapid7, LLC.
6
6
  module Queries
7
+
8
+ # Formats SQL query for riskscore based on user config options.
9
+ #
10
+ # * *Args* :
11
+ # - +riskScore+ - riskscore for assets to match in results of query.
12
+ #
13
+ # * *Returns* :
14
+ # - Returns String - Formatted SQL string for inserting into queries.
15
+ #
16
+ def self.createRiskString(riskScore)
17
+ if riskScore.nil?
18
+ riskString = ""
19
+ else
20
+ riskString = "WHERE fa.riskscore >= #{riskScore}"
21
+ end
22
+ return riskString
23
+ end
24
+
25
+
7
26
  # Gets all the latests scans.
8
27
  # Returns |site.id| |last_scan_id| |finished|
9
28
  def self.last_scans
@@ -12,15 +31,16 @@ module NexposeTicketing
12
31
  JOIN dim_scan dsc ON ds.last_scan_id = dsc.scan_id'
13
32
  end
14
33
 
15
- # Gets all delta vulns for all sites.
34
+
35
+ # Gets all delta vulns for all sites sorted by IP.
16
36
  #
17
37
  # * *Returns* :
18
38
  # -Returns |asset_id| |ip_address| |current_scan| |vulnerability_id||solution_id| |nexpose_id|
19
39
  # |url| |summary| |fix|
20
40
  #
21
- def self.all_new_vulns
41
+ def self.all_new_vulns(options = {})
22
42
  "SELECT DISTINCT on (da.ip_address, davs.solution_id) subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, davs.solution_id, ds.nexpose_id,
23
- ds.url,proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix
43
+ ds.url,proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, fa.riskscore
24
44
  FROM (SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan
25
45
  FROM fact_asset_scan_vulnerability_finding fasv
26
46
  JOIN
@@ -34,8 +54,38 @@ module NexposeTicketing
34
54
  JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
35
55
  JOIN dim_solution ds USING (solution_id)
36
56
  JOIN dim_asset da ON subs.asset_id = da.asset_id
57
+ JOIN fact_asset fa ON fa.asset_id = da.asset_id
58
+ #{createRiskString( options[:riskScore])}
37
59
  ORDER BY da.ip_address, davs.solution_id"
38
- end
60
+ end
61
+
62
+ # Gets all delta vulns for all sites sorted by vuln ID.
63
+ #
64
+ # * *Returns* :
65
+ # -Returns |asset_id| |ip_address| |current_scan| |vulnerability_id||solution_id| |nexpose_id|
66
+ # |url| |summary| |fix|
67
+ #
68
+ def self.all_new_vulns_by_vuln_id(options = {})
69
+ "SELECT DISTINCT on (subs.vulnerability_id, subs.asset_id, davs.solution_id) subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dv.title, davs.solution_id, ds.nexpose_id,
70
+ ds.url,proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, fa.riskscore
71
+ FROM (SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan
72
+ FROM fact_asset_scan_vulnerability_finding fasv
73
+ JOIN
74
+ (
75
+ SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
76
+ FROM dim_asset) s
77
+ ON s.asset_id = fasv.asset_id AND (fasv.scan_id = s.baseline_scan OR fasv.scan_id = s.current_scan)
78
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan, fasv.scan_id
79
+ HAVING NOT baselineComparison(fasv.scan_id, current_scan) = 'Old'
80
+ ) subs
81
+ JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
82
+ JOIN dim_solution ds USING (solution_id)
83
+ JOIN dim_asset da ON subs.asset_id = da.asset_id
84
+ JOIN dim_vulnerability dv ON subs.vulnerability_id = dv.vulnerability_id
85
+ JOIN fact_asset fa ON fa.asset_id = da.asset_id
86
+ #{createRiskString(options[:riskScore])}
87
+ ORDER BY subs.vulnerability_id, subs.asset_id, davs.solution_id"
88
+ end
39
89
 
40
90
  # Gets all new vulnerabilities happening after a reported scan id.
41
91
  #
@@ -46,26 +96,61 @@ module NexposeTicketing
46
96
  # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
47
97
  # |url| |summary| |fix|
48
98
  #
49
- def self.new_vulns_since_scan(reported_scan)
99
+ def self.new_vulns_since_scan(options = {})
50
100
  "SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, davs.solution_id, ds.nexpose_id,
51
- ds.url, proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix
101
+ ds.url, proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, fa.riskscore
52
102
  FROM (SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan
53
103
  FROM fact_asset_scan_vulnerability_finding fasv
54
104
  JOIN
55
105
  (
56
106
  SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
57
107
  FROM dim_asset) s
58
- ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{reported_scan} OR fasv.scan_id = s.current_scan)
108
+ ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
59
109
  GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
60
110
  HAVING baselineComparison(fasv.scan_id, current_scan) = 'New'
61
111
  ) subs
62
112
  JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
63
113
  JOIN dim_solution ds USING (solution_id)
64
114
  JOIN dim_asset da ON subs.asset_id = da.asset_id
65
- AND subs.current_scan > #{reported_scan}
115
+ AND subs.current_scan > #{options[:scan_id]}
116
+ JOIN fact_asset fa ON fa.asset_id = da.asset_id
117
+ #{createRiskString(options[:riskScore])}
66
118
  ORDER BY da.ip_address"
67
119
  end
68
-
120
+
121
+
122
+ # Gets all new vulnerabilities happening after a reported scan id. Sorted by vuln ID.
123
+ #
124
+ # * *Args* :
125
+ # - +reported_scan+ - Last reported scan id.
126
+ #
127
+ # * *Returns* :
128
+ # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
129
+ # |url| |summary| |fix|
130
+ #
131
+ def self.new_vulns_by_vuln_id_since_scan(options = {})
132
+ "SELECT DISTINCT on (subs.vulnerability_id, subs.asset_id, davs.solution_id) subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, davs.solution_id, ds.nexpose_id,
133
+ ds.url, proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, fa.riskscore
134
+ FROM (SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan
135
+ FROM fact_asset_scan_vulnerability_finding fasv
136
+ JOIN
137
+ (
138
+ SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
139
+ FROM dim_asset) s
140
+ ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
141
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
142
+ HAVING baselineComparison(fasv.scan_id, current_scan) = 'New'
143
+ ) subs
144
+ JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
145
+ JOIN dim_solution ds USING (solution_id)
146
+ JOIN dim_asset da ON subs.asset_id = da.asset_id
147
+ AND subs.current_scan > #{options[:scan_id]}
148
+ JOIN fact_asset fa ON fa.asset_id = da.asset_id
149
+ #{createRiskString(options[:riskScore])}
150
+ ORDER BY subs.vulnerability_id, subs.asset_id, davs.solution_id"
151
+ end
152
+
153
+
69
154
  # Gets all old vulnerabilities happening after a reported scan id.
70
155
  #
71
156
  # * *Args* :
@@ -75,26 +160,29 @@ module NexposeTicketing
75
160
  # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
76
161
  # |url| |summary| |fix|
77
162
  #
78
- def self.old_vulns_since_scan(reported_scan)
163
+ def self.old_vulns_since_scan(options = {})
79
164
  "SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dvs.solution_id, ds.nexpose_id, ds.url,
80
- proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison
165
+ proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
81
166
  FROM (
82
167
  SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
83
168
  FROM fact_asset_scan_vulnerability_finding fasv
84
169
  JOIN (
85
170
  SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
86
171
  FROM dim_asset
87
- ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{reported_scan} OR fasv.scan_id = s.current_scan)
172
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
88
173
  GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
89
174
  HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
90
175
  ) subs
91
176
  JOIN dim_vulnerability_solution dvs USING (vulnerability_id)
92
177
  JOIN dim_solution ds USING (solution_id)
93
178
  JOIN dim_asset da ON subs.asset_id = da.asset_id
94
- AND subs.current_scan > #{reported_scan}
179
+ AND subs.current_scan > #{options[:scan_id]}
180
+ JOIN fact_asset fa ON fa.asset_id = da.asset_id
181
+ #{createRiskString(options[:riskScore])}
95
182
  ORDER BY da.ip_address"
96
183
  end
97
-
184
+
185
+
98
186
  # Gets all vulnerabilities happening after a reported scan id. This result set also includes the
99
187
  # baseline comparision ("Old", "New", or "Same") allowing for IP-based ticket updating.
100
188
  #
@@ -105,28 +193,30 @@ module NexposeTicketing
105
193
  # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
106
194
  # |url| |summary| |fix| |comparison|
107
195
  #
108
- def self.all_vulns_since_scan(reported_scan)
196
+ def self.all_vulns_since_scan(options = {})
109
197
  "SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dvs.solution_id, ds.nexpose_id, ds.url,
110
- proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison
198
+ proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
111
199
  FROM (
112
- SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
200
+ SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
113
201
  FROM fact_asset_scan_vulnerability_finding fasv
114
202
  JOIN (
115
203
  SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
116
204
  FROM dim_asset
117
- ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{reported_scan} OR fasv.scan_id = s.current_scan)
205
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
118
206
  GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
119
207
  HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
120
208
  ) subs
121
209
  JOIN dim_vulnerability_solution dvs USING (vulnerability_id)
122
210
  JOIN dim_solution ds USING (solution_id)
123
211
  JOIN dim_asset da ON subs.asset_id = da.asset_id
124
- AND subs.current_scan > #{reported_scan}
212
+ JOIN fact_asset fa ON fa.asset_id = subs.asset_id
213
+ #{createRiskString(options[:riskScore])}
214
+ AND subs.current_scan > #{options[:scan_id]}
125
215
 
126
216
  UNION
127
217
 
128
218
  SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, davs.solution_id, ds.nexpose_id, ds.url,
129
- proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison
219
+ proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
130
220
  FROM
131
221
  (
132
222
  SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
@@ -135,17 +225,155 @@ module NexposeTicketing
135
225
  (
136
226
  SELECT asset_id,lastScan(asset_id) AS current_scan
137
227
  FROM dim_asset
138
- ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{reported_scan} OR fasv.scan_id = s.current_scan)
228
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
139
229
  GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
140
230
  HAVING baselineComparison(fasv.scan_id, current_scan) IN ('Same','New')
141
231
  ) subs
142
232
  JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
143
233
  JOIN dim_solution ds USING (solution_id)
144
234
  JOIN dim_asset da ON subs.asset_id = da.asset_id
145
- AND subs.current_scan > #{reported_scan}
235
+ JOIN fact_asset fa ON fa.asset_id = subs.asset_id
236
+ #{createRiskString(options[:riskScore])}
237
+ AND subs.current_scan > #{options[:scan_id]}
146
238
 
147
239
  ORDER BY ip_address, comparison"
148
240
  end
149
-
241
+
242
+ # Gets all vulnerabilities happening after a reported scan id. Sorted by vuln ID. This result set also includes the
243
+ # baseline comparision ("Old", "New", or "Same") allowing for IP-based ticket updating.
244
+ #
245
+ # * *Args* :
246
+ # - +reported_scan+ - Last reported scan id.
247
+ #
248
+ # * *Returns* :
249
+ # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
250
+ # |url| |summary| |fix| |comparison|
251
+ #
252
+ def self.all_vulns_by_vuln_id_since_scan(options = {})
253
+ "SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dv.title, dvs.solution_id, ds.nexpose_id, ds.url,
254
+ proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
255
+ FROM (
256
+ SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
257
+ FROM fact_asset_scan_vulnerability_finding fasv
258
+ JOIN (
259
+ SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
260
+ FROM dim_asset
261
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
262
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
263
+ HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
264
+ ) subs
265
+ JOIN dim_vulnerability_solution dvs USING (vulnerability_id)
266
+ JOIN dim_solution ds USING (solution_id)
267
+ JOIN dim_asset da ON subs.asset_id = da.asset_id
268
+ JOIN dim_vulnerability dv ON subs.vulnerability_id = dv.vulnerability_id
269
+ JOIN fact_asset fa ON fa.asset_id = subs.asset_id
270
+ #{createRiskString(options[:riskScore])}
271
+ AND subs.current_scan > #{options[:scan_id]}
272
+
273
+ UNION
274
+
275
+ SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dv.title, davs.solution_id, ds.nexpose_id, ds.url,
276
+ proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
277
+ FROM
278
+ (
279
+ SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
280
+ FROM fact_asset_scan_vulnerability_finding fasv
281
+ JOIN
282
+ (
283
+ SELECT asset_id,lastScan(asset_id) AS current_scan
284
+ FROM dim_asset
285
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
286
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
287
+ HAVING baselineComparison(fasv.scan_id, current_scan) IN ('Same','New')
288
+ ) subs
289
+ JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
290
+ JOIN dim_solution ds USING (solution_id)
291
+ JOIN dim_asset da ON subs.asset_id = da.asset_id
292
+ JOIN dim_vulnerability dv ON subs.vulnerability_id = dv.vulnerability_id
293
+ JOIN fact_asset fa ON fa.asset_id = subs.asset_id
294
+ #{createRiskString(options[:riskScore])}
295
+ AND subs.current_scan > #{options[:scan_id]}
296
+
297
+ ORDER BY vulnerability_id, comparison, asset_id, solution_id"
298
+ end
299
+
300
+
301
+ # Gets all IP addresses that have only old vulnerabilities i.e. any open tickets can be closed.
302
+ #
303
+ # * *Args* :
304
+ # - +reported_scan+ - Last reported scan id.
305
+ #
306
+ # * *Returns* :
307
+ # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |comparison|
308
+ #
309
+ def self.old_tickets_by_ip(options = {})
310
+ "SELECT subs.asset_id, subs.ip_address, subs.current_scan, subs.vulnerability_id, subs.comparison
311
+ FROM (
312
+ SELECT fasv.asset_id, s.ip_address, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
313
+ FROM fact_asset_scan_vulnerability_finding fasv
314
+ JOIN (
315
+ SELECT asset_id, ip_address, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
316
+ FROM dim_asset
317
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
318
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.ip_address, s.current_scan
319
+ HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
320
+ ) AS subs
321
+ WHERE subs.ip_address NOT IN (
322
+
323
+ SELECT s.ip_address
324
+ FROM fact_asset_scan_vulnerability_finding fasv
325
+ JOIN
326
+ (
327
+ SELECT asset_id, ip_address, lastScan(asset_id) AS current_scan
328
+ FROM dim_asset
329
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
330
+ GROUP BY s.ip_address, s.current_scan
331
+ HAVING baselineComparison(fasv.scan_id, current_scan) IN ('Same','New')
332
+ )
333
+ AND subs.current_scan > #{options[:scan_id]}
334
+ ORDER BY subs.ip_address"
335
+ end
336
+
337
+
338
+ # Gets all old vulns that have no active IPs i.e. any open tickets in vuln mode ('V') can be closed.
339
+ #
340
+ # * *Args* :
341
+ # - +reported_scan+ - Last reported scan id.
342
+ #
343
+ # * *Returns* :
344
+ # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |comparison|
345
+ #
346
+ def self.old_tickets_by_vuln_id(options = {})
347
+ "SELECT subs.vulnerability_id, subs.asset_id, subs.ip_address, subs.current_scan, subs.comparison
348
+ FROM (
349
+ SELECT fasv.asset_id, s.ip_address, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison, fa.riskscore
350
+ FROM fact_asset_scan_vulnerability_finding fasv
351
+ JOIN (
352
+ SELECT asset_id, ip_address, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
353
+ FROM dim_asset
354
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
355
+ JOIN fact_asset fa ON fa.asset_id = fasv.asset_id
356
+ #{createRiskString(options[:riskScore])}
357
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.ip_address, s.current_scan, fa.riskscore
358
+ HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
359
+ ) AS subs
360
+ WHERE subs.vulnerability_id NOT IN (
361
+
362
+ SELECT fasv.vulnerability_id
363
+ FROM fact_asset_scan_vulnerability_finding fasv
364
+ JOIN
365
+ (
366
+ SELECT da.asset_id, da.ip_address, lastScan(da.asset_id) AS current_scan, fa.riskscore
367
+ FROM dim_asset da
368
+ JOIN fact_asset fa ON fa.asset_id = da.asset_id
369
+ #{createRiskString(options[:riskScore])}
370
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
371
+ GROUP BY fasv.vulnerability_id, s.ip_address, s.current_scan
372
+ HAVING baselineComparison(fasv.scan_id, current_scan) IN ('Same','New')
373
+
374
+ )
375
+ AND subs.current_scan > #{options[:scan_id]}
376
+ ORDER BY subs.vulnerability_id"
377
+ end
150
378
  end
151
379
  end
@@ -71,7 +71,7 @@ module NexposeTicketing
71
71
  trimmed_csv = []
72
72
  trimmed_csv << report_output.lines.first
73
73
  csv_output.each do |row|
74
- if sites.include? row.to_s[0]
74
+ if sites.include? row[0].to_s
75
75
  trimmed_csv << row
76
76
  end
77
77
  end
@@ -118,18 +118,34 @@ module NexposeTicketing
118
118
  if site_override.nil?
119
119
  sites = Array(options[:sites])
120
120
  else
121
- sites = site_override
121
+ sites = Array(site_override)
122
122
  end
123
123
  report_config = @report_helper.generate_sql_report_config()
124
124
  severity = options[:severity].nil? ? 0 : options[:severity]
125
125
  report_config.add_filter('version', '1.2.0')
126
- report_config.add_filter('query', Queries.all_new_vulns)
127
- unless sites.empty?
126
+ if options[:ticket_mode] == 'V'
127
+ report_config.add_filter('query', Queries.all_new_vulns_by_vuln_id(options))
128
+ else
129
+ report_config.add_filter('query', Queries.all_new_vulns(options))
130
+ end
131
+ unless sites.nil? || sites.empty?
128
132
  Array(sites).each do |site_id|
129
133
  report_config.add_filter('site', site_id)
130
134
  end
131
135
  end
132
136
  report_config.add_filter('vuln-severity', severity)
137
+
138
+ vuln_filter_cats = createVulnerabilityFilter(options)
139
+ vuln_filer_tags = createTagFilters(options)
140
+
141
+ if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
142
+ report_config.add_filter('vuln-categories', vuln_filter_cats)
143
+ end
144
+
145
+ if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
146
+ vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
147
+ end
148
+
133
149
  @report_helper.save_generate_cleanup_report_config(report_config)
134
150
  end
135
151
 
@@ -149,9 +165,25 @@ module NexposeTicketing
149
165
  fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
150
166
  severity = site_options[:severity].nil? ? 0 : site_options[:severity]
151
167
  report_config.add_filter('version', '1.2.0')
152
- report_config.add_filter('query', Queries.new_vulns_since_scan(reported_scan_id))
168
+ if site_options[:ticket_mode] == 'V'
169
+ report_config.add_filter('query', Queries.new_vulns_by_vuln_id_since_scan(site_options))
170
+ else
171
+ report_config.add_filter('query', Queries.new_vulns_since_scan(site_options))
172
+ end
153
173
  report_config.add_filter('site', site)
154
174
  report_config.add_filter('vuln-severity', severity)
175
+
176
+ vuln_filter_cats = createVulnerabilityFilter(site_options)
177
+ vuln_filer_tags = createTagFilters(site_options)
178
+
179
+ if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
180
+ report_config.add_filter('vuln-categories', vuln_filter_cats)
181
+ end
182
+
183
+ if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
184
+ vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
185
+ end
186
+
155
187
  @report_helper.save_generate_cleanup_report_config(report_config)
156
188
  end
157
189
 
@@ -171,12 +203,63 @@ module NexposeTicketing
171
203
  fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
172
204
  severity = site_options[:severity].nil? ? 0 : site_options[:severity]
173
205
  report_config.add_filter('version', '1.2.0')
174
- report_config.add_filter('query', Queries.old_vulns_since_scan(reported_scan_id))
206
+ report_config.add_filter('query', Queries.old_vulns_since_scan(site_options))
175
207
  report_config.add_filter('site', site)
176
208
  report_config.add_filter('vuln-severity', severity)
209
+
210
+ vuln_filter_cats = createVulnerabilityFilter(site_options)
211
+ vuln_filer_tags = createTagFilters(site_options)
212
+
213
+ if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
214
+ report_config.add_filter('vuln-categories', vuln_filter_cats)
215
+ end
216
+
217
+ if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
218
+ vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
219
+ end
220
+
177
221
  @report_helper.save_generate_cleanup_report_config(report_config)
178
222
  end
179
-
223
+
224
+ # Gets information on possible tickets to close based on only having old vulns/IPs and no new/same ones.
225
+ # Based on IP address (for 'I' mode) or vuln ID ('V' mode).
226
+ #
227
+ # * *Args* :
228
+ # - +site_options+ - A Hash with site(s), reported_scan_id and severity level.
229
+ #
230
+ # * *Returns* :
231
+ # - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |comparison|
232
+ #
233
+ def tickets_to_close(site_options = {})
234
+ report_config = @report_helper.generate_sql_report_config()
235
+ site = site_options[:site_id]
236
+ reported_scan_id = site_options[:scan_id]
237
+ fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
238
+ severity = site_options[:severity].nil? ? 0 : site_options[:severity]
239
+ report_config.add_filter('version', '1.2.0')
240
+ if site_options[:ticket_mode] == 'V'
241
+ report_config.add_filter('query', Queries.old_tickets_by_vuln_id(site_options))
242
+ else
243
+ report_config.add_filter('query', Queries.old_tickets_by_ip(site_options))
244
+ end
245
+ report_config.add_filter('site', site)
246
+ report_config.add_filter('vuln-severity', severity)
247
+
248
+ vuln_filter_cats = createVulnerabilityFilter(site_options)
249
+ vuln_filer_tags = createTagFilters(site_options)
250
+
251
+ if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
252
+ report_config.add_filter('vuln-categories', vuln_filter_cats)
253
+ end
254
+
255
+ if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
256
+ vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
257
+ end
258
+
259
+ @report_helper.save_generate_cleanup_report_config(report_config)
260
+ end
261
+
262
+
180
263
  # Gets all vulns from base scan reported_scan_id and the newest / latest scan from a site. This is
181
264
  # used for IP-based issue updating. Includes the baseline comparision value ('Old','New', or 'Same').
182
265
  #
@@ -194,10 +277,70 @@ module NexposeTicketing
194
277
  fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
195
278
  severity = site_options[:severity].nil? ? 0 : site_options[:severity]
196
279
  report_config.add_filter('version', '1.2.0')
197
- report_config.add_filter('query', Queries.all_vulns_since_scan(reported_scan_id))
280
+ if site_options[:ticket_mode] == 'V'
281
+ report_config.add_filter('query', Queries.all_vulns_by_vuln_id_since_scan(site_options))
282
+ else
283
+ report_config.add_filter('query', Queries.all_vulns_since_scan(site_options))
284
+ end
198
285
  report_config.add_filter('site', site)
199
286
  report_config.add_filter('vuln-severity', severity)
287
+
288
+ vuln_filter_cats = createVulnerabilityFilter(site_options)
289
+ vuln_filer_tags = createTagFilters(site_options)
290
+
291
+ if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
292
+ report_config.add_filter('vuln-categories', vuln_filter_cats)
293
+ end
294
+
295
+ if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
296
+ vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
297
+ end
298
+
200
299
  @report_helper.save_generate_cleanup_report_config(report_config)
201
300
  end
301
+
302
+
303
+ # Parses user-configured vulnerability filter categories and returns aforementioned categories in a
304
+ # format used by the Nexpose::AdhocReportConfig class.
305
+ #
306
+ # * *Args* :
307
+ # - +site_options+ - A Hash with site(s), reported_scan_id and severity level.
308
+ #
309
+ # * *Returns* :
310
+ # - Returns String @vulnerability_categories
311
+ #
312
+ def createVulnerabilityFilter(options = {})
313
+ @vulnerability_categories = nil
314
+ if options.has_key?(:vulnerabilityCategories)
315
+ if not options[:vulnerabilityCategories].nil? and not options[:vulnerabilityCategories].empty?
316
+ @vulnerability_categories = options[:vulnerabilityCategories].strip.split(',').map {|category| "include:#{category}"}.join(',')
317
+ end
318
+ end
319
+ @vulnerability_categories
320
+ end
321
+
322
+ # Parses user-configured tags and returns aforementioned tags in an array containing
323
+ # strings in the format used by the Nexpose::AdhocReportConfig class.
324
+ #
325
+ # * *Args* :
326
+ # - +site_options+ - A Hash with site(s), reported_scan_id and severity level.
327
+ #
328
+ # * *Returns* :
329
+ # - Returns Array @definedTags
330
+ #
331
+ def createTagFilters(options = {})
332
+ @defined_tags = nil
333
+ if options.has_key?(:tags)
334
+ if not options[:tags].nil? and not options[:tags].empty?
335
+ ## Split the tags into an array
336
+ tag_strings = options[:tags].strip.split(',')
337
+
338
+ ## Grab the tag info for the ones we are looking for (if the exist in Nexpose).
339
+ @defined_tags = @nsc.list_tags.select {|nexposeTag| tag_strings.include?(nexposeTag.name)}
340
+ end
341
+ end
342
+ @defined_tags
343
+ end
344
+
202
345
  end
203
346
  end