risu 1.6.2 → 1.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.ci +1 -3
- data/NEWS.markdown +36 -4
- data/README.markdown +2 -2
- data/Rakefile +0 -1
- data/bin/risu +0 -1
- data/lib/risu.rb +2 -1
- data/lib/risu/base/schema.rb +34 -16
- data/lib/risu/base/template_manager.rb +2 -0
- data/lib/risu/cli/application.rb +48 -19
- data/lib/risu/models.rb +1 -0
- data/lib/risu/models/attachment.rb +36 -0
- data/lib/risu/models/host.rb +49 -49
- data/lib/risu/models/item.rb +25 -24
- data/lib/risu/models/plugin.rb +4 -4
- data/lib/risu/models/policy.rb +4 -4
- data/lib/risu/models/report.rb +1 -1
- data/lib/risu/parsers.rb +1 -0
- data/lib/risu/parsers/nessus/nessus_sax_listener.rb +54 -20
- data/lib/risu/parsers/nessus/postprocess.rb +36 -0
- data/lib/risu/parsers/nessus/postprocess/java.rb +234 -0
- data/lib/risu/parsers/nessus/postprocess/risk_score.rb +101 -0
- data/lib/risu/templates/executive_summary_detailed.rb +14 -7
- data/lib/risu/templates/findings_host.rb +5 -5
- data/lib/risu/templates/malicious_process_detection.rb +137 -0
- data/lib/risu/templates/technical_findings.rb +4 -4
- data/risu.gemspec +1 -2
- metadata +10 -5
data/lib/risu/models/item.rb
CHANGED
@@ -32,6 +32,7 @@ module Risu
|
|
32
32
|
class Item < ActiveRecord::Base
|
33
33
|
belongs_to :host
|
34
34
|
belongs_to :plugin
|
35
|
+
has_many :attachments
|
35
36
|
|
36
37
|
class << self
|
37
38
|
|
@@ -109,7 +110,7 @@ module Risu
|
|
109
110
|
#
|
110
111
|
# @return [ActiveRecord::Relation] with the query results
|
111
112
|
def medium_risks_unique
|
112
|
-
where(:severity => 2).joins(:plugin).order(
|
113
|
+
where(:severity => 2).joins(:plugin).order("plugins.cvss_base_score").group(:plugin_id)
|
113
114
|
end
|
114
115
|
|
115
116
|
# Queries for all the unique medium findings and sorts them by count
|
@@ -123,7 +124,7 @@ module Risu
|
|
123
124
|
#
|
124
125
|
# @return [ActiveRecord::Relation] with the query results
|
125
126
|
def low_risks_unique
|
126
|
-
where(:severity => 1).joins(:plugin).order(
|
127
|
+
where(:severity => 1).joins(:plugin).order("plugins.cvss_base_score").group(:plugin_id)
|
127
128
|
end
|
128
129
|
|
129
130
|
# Queries for all the unique low findings and sorts them by count
|
@@ -137,7 +138,8 @@ module Risu
|
|
137
138
|
#
|
138
139
|
# @return [ActiveRecord::Relation] with the query results
|
139
140
|
def info_risks_unique
|
140
|
-
where(:severity => 0).joins(:plugin).order(:cvss_base_score).group(:plugin_id)
|
141
|
+
#where(:severity => 0).joins(:plugin).order(:cvss_base_score).group(:plugin_id)
|
142
|
+
where(:severity => 0).joins(:plugin).order("plugins.cvss_base_score").group(:plugin_id)
|
141
143
|
end
|
142
144
|
|
143
145
|
# Queries for all the unique info findings and sorts them by count
|
@@ -229,7 +231,7 @@ module Risu
|
|
229
231
|
# @return [StringIO] Object containing the generated PNG image
|
230
232
|
def risks_by_service_graph(limit=10)
|
231
233
|
g = Gruff::Pie.new(GRAPH_WIDTH)
|
232
|
-
g.title = sprintf "Top %d Services By Vulnerability", Item.risks_by_service(limit).
|
234
|
+
g.title = sprintf "Top %d Services By Vulnerability", Item.risks_by_service(limit).to_a.count
|
233
235
|
g.sort = false
|
234
236
|
g.marker_count = 1
|
235
237
|
g.theme = {
|
@@ -237,8 +239,8 @@ module Risu
|
|
237
239
|
:background_colors => %w(white white)
|
238
240
|
}
|
239
241
|
|
240
|
-
Item.risks_by_service(limit).
|
241
|
-
g.data(service.svc_name, Item.
|
242
|
+
Item.risks_by_service(limit).to_a.each do |service|
|
243
|
+
g.data(service.svc_name, Item.all.where(:svc_name => service.svc_name).count)
|
242
244
|
end
|
243
245
|
|
244
246
|
StringIO.new(g.to_blob)
|
@@ -270,19 +272,19 @@ module Risu
|
|
270
272
|
high = Item.high_risks.count
|
271
273
|
medium = Item.medium_risks.count
|
272
274
|
low = Item.low_risks.count
|
273
|
-
info = Item.info_risks.count
|
275
|
+
#info = Item.info_risks.count
|
274
276
|
|
275
277
|
if crit == nil then crit = 0 end
|
276
278
|
if high == nil then high = 0 end
|
277
279
|
if medium == nil then medium = 0 end
|
278
280
|
if low == nil then low = 0 end
|
279
|
-
if info == nil then info = 0 end
|
281
|
+
#if info == nil then info = 0 end
|
280
282
|
|
281
283
|
g.data("Critical", crit, "purple")
|
282
284
|
g.data("High", high, "red")
|
283
285
|
g.data("Medium", medium, "orange")
|
284
286
|
g.data("Low", low, "yellow")
|
285
|
-
g.data("Informational", info, "blue")
|
287
|
+
#g.data("Informational", info, "blue")
|
286
288
|
|
287
289
|
StringIO.new(g.to_blob)
|
288
290
|
end
|
@@ -324,22 +326,13 @@ module Risu
|
|
324
326
|
StringIO.new(g.to_blob)
|
325
327
|
end
|
326
328
|
|
329
|
+
# Calculates a vulnerable host percent based on Critical and High findings
|
330
|
+
# (unique_vuln_crit_high_count / host_count) * 100
|
327
331
|
#
|
328
|
-
# @
|
329
|
-
#
|
332
|
+
# @return [FixNum] Percentage of vulnerable hosts
|
330
333
|
def calculate_vulnerable_host_percent
|
331
|
-
|
332
|
-
|
333
|
-
(Item.critical_risks.all + Item.high_risks.all).each do |item|
|
334
|
-
ip = Host.find_by_id(item.host_id).name
|
335
|
-
if hosts_with_critical[ip] == nil
|
336
|
-
hosts_with_critical[ip] = 1
|
337
|
-
end
|
338
|
-
|
339
|
-
hosts_with_critical[ip] = hosts_with_critical[ip] + 1
|
340
|
-
end
|
341
|
-
|
342
|
-
host_percent = (hosts_with_critical.count.to_f / Host.all.count.to_f) * 100
|
334
|
+
unique_hosts_with_critical_and_high = Host.unique_hosts_with_critical.count + Host.unique_hosts_with_high.count
|
335
|
+
host_percent = (unique_hosts_with_critical_and_high.to_f / Host.count.to_f) * 100
|
343
336
|
end
|
344
337
|
|
345
338
|
#
|
@@ -417,11 +410,19 @@ module Risu
|
|
417
410
|
return graph_text
|
418
411
|
end
|
419
412
|
|
413
|
+
def risk_percent_rounded_text
|
414
|
+
"#{calculate_vulnerable_host_percent().round}%"
|
415
|
+
end
|
416
|
+
|
420
417
|
#
|
421
418
|
# @todo comment
|
422
419
|
#
|
423
420
|
def notable_order_by_cvss_raw
|
424
|
-
|
421
|
+
|
422
|
+
#MIGHT NOT BE CORRECT @TODO
|
423
|
+
|
424
|
+
#return Item.joins(:plugin).where(:severity => 4).order("plugins.cvss_base_score").count(:all, :group => :plugin_id)
|
425
|
+
return Item.joins(:plugin).where(:severity => 4).order("plugins.cvss_base_score").group(:plugin_id).distinct.count
|
425
426
|
end
|
426
427
|
|
427
428
|
#
|
data/lib/risu/models/plugin.rb
CHANGED
@@ -21,8 +21,8 @@
|
|
21
21
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
22
22
|
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
23
23
|
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
24
|
-
#OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
25
|
-
#OF THE POSSIBILITY OF SUCH DAMAGE.
|
24
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
25
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
26
|
|
27
27
|
module Risu
|
28
28
|
module Models
|
@@ -92,7 +92,7 @@ module Risu
|
|
92
92
|
# @return Filename of the created graph
|
93
93
|
def top_by_count_graph(limit=10)
|
94
94
|
g = Gruff::Bar.new(GRAPH_WIDTH)
|
95
|
-
g.title = sprintf "Top %d Critical Findings By Plugin", Item.risks_by_plugin(limit).
|
95
|
+
g.title = sprintf "Top %d Critical Findings By Plugin", Item.risks_by_plugin(limit).to_a.count
|
96
96
|
g.sort = false
|
97
97
|
g.marker_count = 1
|
98
98
|
g.theme = {
|
@@ -100,7 +100,7 @@ module Risu
|
|
100
100
|
:background_colors => %w(white white)
|
101
101
|
}
|
102
102
|
|
103
|
-
Item.risks_by_plugin(limit).
|
103
|
+
Item.risks_by_plugin(limit).to_a.each do |plugin|
|
104
104
|
plugin_name = Plugin.find_by_id(plugin.plugin_id).plugin_name
|
105
105
|
|
106
106
|
#We need to filter the names a little to make everything look nice on the graph
|
data/lib/risu/models/policy.rb
CHANGED
@@ -30,10 +30,10 @@ module Risu
|
|
30
30
|
# Policy Model
|
31
31
|
#
|
32
32
|
class Policy < ActiveRecord::Base
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
has_many :family_selections
|
34
|
+
has_many :individual_plugin_selections
|
35
|
+
has_many :reports
|
36
|
+
has_many :plugins_preferences
|
37
37
|
has_many :server_preferences
|
38
38
|
end
|
39
39
|
end
|
data/lib/risu/models/report.rb
CHANGED
@@ -48,7 +48,7 @@ module Risu
|
|
48
48
|
# @todo comment this
|
49
49
|
#
|
50
50
|
def scanner_nessus_ratings_text
|
51
|
-
text = "The vulnerability scanner used by #{Report.company} rates the findings as follows: High, Medium, Low and Informational. High findings represents a security hole, initially this is the highest rating a risk can get. These generally represent vulnerabilities that can lead to full system compromise due to missing security patches. High findings should be re-mediated first as they generally leave the network wide open. Medium findings are considered a security warning; these are not as severe as high but should be evaluated on a risk-by-risk basis. These are typically configuration errors that can lead to information disclosures such as usernames, passwords, and configuration settings. Low findings are identified as security notes; these provide information the scanner discovered during the scanning process. The information includes items such as hostname, domain name, and MAC address. Open Port findings represent the open ports on each system that the scanner found during the scan process. These should be evaluated against firewall settings to test the firewall configurations.\n\n"
|
51
|
+
text = "The vulnerability scanner used by #{Report.company} rates the findings as follows: Critical, High, Medium, Low and Informational. High findings represents a security hole, initially this is the highest rating a risk can get. These generally represent vulnerabilities that can lead to full system compromise due to missing security patches. High findings should be re-mediated first as they generally leave the network wide open. Medium findings are considered a security warning; these are not as severe as high but should be evaluated on a risk-by-risk basis. These are typically configuration errors that can lead to information disclosures such as usernames, passwords, and configuration settings. Low findings are identified as security notes; these provide information the scanner discovered during the scanning process. The information includes items such as hostname, domain name, and MAC address. Open Port findings represent the open ports on each system that the scanner found during the scan process. These should be evaluated against firewall settings to test the firewall configurations.\n\n"
|
52
52
|
text << "After the scanner is complete, the scanner evaluates each finding and bases it on the Common Vulnerability Scoring System (CVSS) score assigned to each finding. Any findings with a CVSS base score of 10 are upgraded to a Critical finding. These represent vulnerabilities that are trivial to gain administrator access to the system, with little to no effort. For more information on the CVSS scoring system please visit: http://nvd.nist.gov/cvss.cfm.\n\n"
|
53
53
|
|
54
54
|
return text
|
data/lib/risu/parsers.rb
CHANGED
@@ -42,19 +42,23 @@ module Risu
|
|
42
42
|
"cpe", "bid", "see_also", "xref", "cve", "iava", "msft",
|
43
43
|
"osvdb", "cert", "edb-id", "rhsa", "secunia", "suse", "dsa",
|
44
44
|
"owasp", "cwe", "iavb", "iavt", "cisco-sa", "ics-alert",
|
45
|
-
"cisco-bug-id", "cisco-sr", "cert-vu", "vmsa", "apple-sa",
|
45
|
+
"cisco-bug-id", "cisco-sr", "cert-vu", "vmsa", "apple-sa",
|
46
46
|
"icsa", "cert-cc", "msvr", "usn"
|
47
47
|
]
|
48
48
|
|
49
49
|
@valid_host_properties = Array[
|
50
|
-
"HOST_END", "mac-address", "HOST_START", "operating-system", "host-ip", "host-fqdn", "netbios-name",
|
51
|
-
"local-checks-proto", "smb-login-used", "ssh-auth-meth", "ssh-login-used", "pci-dss-compliance",
|
52
|
-
"pci-dss-compliance:", "system-type", "bios-uuid", "pcidss:compliance:failed", "pcidss:compliance:passed",
|
53
|
-
"pcidss:deprecated_ssl", "pcidss:expired_ssl_certificate", "pcidss:high_risk_flaw", "pcidss:medium_risk_flaw",
|
54
|
-
"pcidss:reachable_db", "pcidss:www:xss", "pcidss:directory_browsing", "pcidss:known_credentials",
|
55
|
-
"pcidss:compromised_host:worm", "pcidss:obsolete_operating_system", "pcidss:dns_zone_transfer",
|
56
|
-
"pcidss:unprotected_mssql_db", "pcidss:obsolete_software", "pcidss:www:sql_injection", "pcidss:backup_files",
|
57
|
-
"traceroute-hop-0", "traceroute-hop-1", "traceroute-hop-2"
|
50
|
+
"HOST_END", "mac-address", "HOST_START", "operating-system", "host-ip", "host-fqdn", "netbios-name",
|
51
|
+
"local-checks-proto", "smb-login-used", "ssh-auth-meth", "ssh-login-used", "pci-dss-compliance",
|
52
|
+
"pci-dss-compliance:", "system-type", "bios-uuid", "pcidss:compliance:failed", "pcidss:compliance:passed",
|
53
|
+
"pcidss:deprecated_ssl", "pcidss:expired_ssl_certificate", "pcidss:high_risk_flaw", "pcidss:medium_risk_flaw",
|
54
|
+
"pcidss:reachable_db", "pcidss:www:xss", "pcidss:directory_browsing", "pcidss:known_credentials",
|
55
|
+
"pcidss:compromised_host:worm", "pcidss:obsolete_operating_system", "pcidss:dns_zone_transfer",
|
56
|
+
"pcidss:unprotected_mssql_db", "pcidss:obsolete_software", "pcidss:www:sql_injection", "pcidss:backup_files",
|
57
|
+
"traceroute-hop-0", "traceroute-hop-1", "traceroute-hop-2", "operating-system-unsupported", "patch-summary-total-cves"
|
58
|
+
]
|
59
|
+
|
60
|
+
@valid_host_properties_regex = Array[
|
61
|
+
"patch-summary-cve-num", "patch-summary-cves", "patch-summary-txt"
|
58
62
|
]
|
59
63
|
|
60
64
|
@valid_elements = Array["ReportItem", "plugin_version", "risk_factor",
|
@@ -69,7 +73,7 @@ module Risu
|
|
69
73
|
"plugin_type", "exploithub_sku", "exploit_framework_exploithub", "stig_severity", "plugin_name", "fname", "always_run",
|
70
74
|
"cm:compliance-info", "cm:compliance-actual-value", "cm:compliance-check-id", "cm:compliance-policy-value",
|
71
75
|
"cm:compliance-audit-file", "cm:compliance-check-name", "cm:compliance-result", "cm:compliance-output", "policyOwner",
|
72
|
-
"visibility"
|
76
|
+
"visibility", "script_version", "attachment", "policy_comments", "d2_elliot_name", "exploit_framework_d2_elliot"
|
73
77
|
]
|
74
78
|
|
75
79
|
@valid_elements = @valid_elements + @valid_references
|
@@ -95,7 +99,7 @@ module Risu
|
|
95
99
|
@vals[@tag] = ""
|
96
100
|
|
97
101
|
if !@valid_elements.include?(element)
|
98
|
-
puts "New XML element detected: #{element}. Please report this to #{Risu::EMAIL}"
|
102
|
+
puts "New XML element detected: #{element}. Please report this at https://github.com/arxopia/risu/issues/new or via email to #{Risu::EMAIL}"
|
99
103
|
end
|
100
104
|
|
101
105
|
case element
|
@@ -128,10 +132,21 @@ module Risu
|
|
128
132
|
|
129
133
|
if attributes["name"] =~ /[M|m][S|s]\d{2,}-\d{2,}/
|
130
134
|
@attr = if attributes["name"] =~ /[M|m][S|s]\d{2,}-\d{2,}/
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
+
attributes["name"]
|
136
|
+
else
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
#Ugly as fuck.
|
140
|
+
elsif attributes['name'] =~ /patch-summary-cve-num/ ||
|
141
|
+
attributes['name'] =~ /patch-summary-cves/ ||
|
142
|
+
attributes['name'] =~ /patch-summary-txt/
|
143
|
+
@attr = if attributes["name"] =~ /patch-summary-cve-num/ ||
|
144
|
+
attributes['name'] =~ /patch-summary-cves/ ||
|
145
|
+
attributes['name'] =~ /patch-summary-txt/
|
146
|
+
attributes["name"]
|
147
|
+
else
|
148
|
+
nil
|
149
|
+
end
|
135
150
|
else
|
136
151
|
@attr = if @valid_host_properties.include?(attributes["name"])
|
137
152
|
attributes["name"]
|
@@ -140,17 +155,19 @@ module Risu
|
|
140
155
|
end
|
141
156
|
end
|
142
157
|
|
143
|
-
|
158
|
+
# implicit nil check?
|
159
|
+
if attributes["name"] !~ /(netstat-(?:established|listen)-(?:tcp|udp)\d+-\d+)/ &&
|
160
|
+
attributes["name"] !~ /traceroute-hop-\d+/
|
144
161
|
#puts attributes["name"]
|
145
|
-
puts "New HostProperties attribute: #{attributes["name"]}. Please report this to #{Risu::EMAIL}\n" if @attr.nil?
|
162
|
+
puts "New HostProperties attribute: #{attributes["name"]}. Please report this at https://github.com/arxopia/risu/issues/new or via email to #{Risu::EMAIL}\n" if @attr.nil?
|
146
163
|
end
|
147
164
|
when "ReportItem"
|
148
165
|
@vals = Hash.new # have to clear this out or everything has the same references
|
149
166
|
@ri = @rh.items.create
|
150
167
|
if attributes["pluginID"] == "0"
|
151
|
-
@plugin = Risu::Models::Plugin.
|
168
|
+
@plugin = Risu::Models::Plugin.find_or_create_by(:id => 1)
|
152
169
|
else
|
153
|
-
@plugin = Risu::Models::Plugin.
|
170
|
+
@plugin = Risu::Models::Plugin.find_or_create_by(:id => attributes["pluginID"])
|
154
171
|
end
|
155
172
|
|
156
173
|
@ri.port = attributes["port"]
|
@@ -163,6 +180,11 @@ module Risu
|
|
163
180
|
@plugin.family_name = attributes["pluginFamily"]
|
164
181
|
@plugin.save
|
165
182
|
@ri.save
|
183
|
+
when "attachment"
|
184
|
+
@attachment = @ri.attachments.create
|
185
|
+
@attachment.name = attributes['name']
|
186
|
+
@attachment.type = attributes['type']
|
187
|
+
@attachment.save
|
166
188
|
end
|
167
189
|
end
|
168
190
|
|
@@ -195,6 +217,12 @@ module Risu
|
|
195
217
|
}
|
196
218
|
@policy.save
|
197
219
|
|
220
|
+
when "policy_comments"
|
221
|
+
@policy.attributes = {
|
222
|
+
:comments => @vals["policy_comments"]
|
223
|
+
}
|
224
|
+
@policy.save
|
225
|
+
|
198
226
|
when "policyOwner"
|
199
227
|
@policy.attributes = {
|
200
228
|
:owner => @vals["policyOwner"]
|
@@ -317,9 +345,15 @@ module Risu
|
|
317
345
|
:exploithub_sku => @vals["exploithub_sku"],
|
318
346
|
:stig_severity => @vals["stig_severity"],
|
319
347
|
:fname => @vals["fname"],
|
320
|
-
:always_run => @vals["always_run"]
|
348
|
+
:always_run => @vals["always_run"],
|
349
|
+
:script_version => @vals["script_version"]
|
321
350
|
}
|
322
351
|
@plugin.save
|
352
|
+
when "attachment"
|
353
|
+
@attachment.attributes = {
|
354
|
+
:ahash => @vals['attachment']
|
355
|
+
}
|
356
|
+
@attachment.save
|
323
357
|
end
|
324
358
|
end
|
325
359
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright (c) 2010-2013 Arxopia LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# * Redistributions of source code must retain the above copyright
|
8
|
+
# notice, this list of conditions and the following disclaimer.
|
9
|
+
# * Redistributions in binary form must reproduce the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer in the
|
11
|
+
# documentation and/or other materials provided with the distribution.
|
12
|
+
# * Neither the name of the Arxopia LLC nor the names of its contributors
|
13
|
+
# may be used to endorse or promote products derived from this software
|
14
|
+
# without specific prior written permission.
|
15
|
+
#
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
# DISCLAIMED. IN NO EVENT SHALL ARXOPIA LLC BE LIABLE FOR ANY DIRECT, INDIRECT,
|
20
|
+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
21
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
22
|
+
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
23
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
24
|
+
#OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
25
|
+
#OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
|
+
|
27
|
+
module Risu
|
28
|
+
module Nessus
|
29
|
+
module PostProcess
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'risu/parsers/nessus/postprocess/java'
|
36
|
+
require 'risu/parsers/nessus/postprocess/risk_score'
|
@@ -0,0 +1,234 @@
|
|
1
|
+
# Copyright (c) 2010-2013 Arxopia LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# * Redistributions of source code must retain the above copyright
|
8
|
+
# notice, this list of conditions and the following disclaimer.
|
9
|
+
# * Redistributions in binary form must reproduce the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer in the
|
11
|
+
# documentation and/or other materials provided with the distribution.
|
12
|
+
# * Neither the name of the Arxopia LLC nor the names of its contributors
|
13
|
+
# may be used to endorse or promote products derived from this software
|
14
|
+
# without specific prior written permission.
|
15
|
+
#
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
# DISCLAIMED. IN NO EVENT SHALL ARXOPIA LLC BE LIABLE FOR ANY DIRECT, INDIRECT,
|
20
|
+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
21
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
22
|
+
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
23
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
24
|
+
#OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
25
|
+
#OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
|
+
|
27
|
+
module Risu
|
28
|
+
module Parsers
|
29
|
+
module Nessus
|
30
|
+
module PostProcess
|
31
|
+
class Java
|
32
|
+
|
33
|
+
#
|
34
|
+
def initialize
|
35
|
+
@java_plugins = [
|
36
|
+
66932,
|
37
|
+
65995, # Needs ver
|
38
|
+
56959, # Needs ver
|
39
|
+
59462, # Needs ver
|
40
|
+
62593, # Needs ver
|
41
|
+
45544,
|
42
|
+
45379, # Oracle Java SE Multiple Vulnerabilities (March 2010 CPU)
|
43
|
+
65050, # Oracle Java JDK/JRE 6 < Update 43 Remote Code Execution (Windows)
|
44
|
+
63521,
|
45
|
+
65052,
|
46
|
+
49996,
|
47
|
+
52002,
|
48
|
+
54997,
|
49
|
+
55958, # Oracle Java JRE Unsupported Version Detection
|
50
|
+
56566,
|
51
|
+
57290,
|
52
|
+
57959,
|
53
|
+
64454,
|
54
|
+
64790
|
55
|
+
]
|
56
|
+
end
|
57
|
+
|
58
|
+
#NOTE:
|
59
|
+
#looks like its working
|
60
|
+
def newest_java_plugin
|
61
|
+
newest = DateTime.new(0001, 01, 01)
|
62
|
+
newest_plugin = nil
|
63
|
+
|
64
|
+
@java_plugins.each do |id|
|
65
|
+
plugin = Plugin.find_by_id(id)
|
66
|
+
|
67
|
+
if plugin == nil || plugin.plugin_modification_date == nil
|
68
|
+
next
|
69
|
+
end
|
70
|
+
|
71
|
+
if plugin.plugin_modification_date >= newest
|
72
|
+
newest = plugin.plugin_modification_date if plugin.plugin_modification_date != nil
|
73
|
+
newest_plugin = plugin
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
return newest_plugin
|
78
|
+
end
|
79
|
+
|
80
|
+
# Creates a rollup plugin based on the newest java plugin
|
81
|
+
#
|
82
|
+
def create_plugin
|
83
|
+
|
84
|
+
plugin = Plugin.find_by_id(-99999)
|
85
|
+
|
86
|
+
newest_plugin = newest_java_plugin()
|
87
|
+
|
88
|
+
if newest_plugin == nil
|
89
|
+
return
|
90
|
+
end
|
91
|
+
|
92
|
+
if plugin == nil
|
93
|
+
plugin = Plugin.new
|
94
|
+
end
|
95
|
+
|
96
|
+
plugin.id = -99999
|
97
|
+
plugin.plugin_name = "Upgrade to the latest Oracle Java SE"
|
98
|
+
plugin.family_name = "Risu Rollup Plugins"
|
99
|
+
plugin.description = newest_plugin.description || ""
|
100
|
+
plugin.plugin_version = newest_plugin.plugin_version || ""
|
101
|
+
plugin.plugin_publication_date = newest_plugin.plugin_publication_date
|
102
|
+
plugin.plugin_modification_date = newest_plugin.plugin_modification_date
|
103
|
+
plugin.vuln_publication_date = newest_plugin.vuln_publication_date
|
104
|
+
plugin.cvss_vector = newest_plugin.cvss_vector || ""
|
105
|
+
plugin.cvss_base_score = newest_plugin.cvss_base_score
|
106
|
+
plugin.cvss_temporal_score = newest_plugin.cvss_temporal_score
|
107
|
+
plugin.cvss_temporal_vector = newest_plugin.cvss_temporal_vector
|
108
|
+
plugin.risk_factor = newest_plugin.risk_factor
|
109
|
+
plugin.solution = newest_plugin.solution
|
110
|
+
plugin.synopsis = newest_plugin.synopsis
|
111
|
+
plugin.plugin_type = "Rollup"
|
112
|
+
plugin.rollup = true
|
113
|
+
|
114
|
+
plugin.save
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
def create_item(host_id, severity)
|
119
|
+
item = Item.new
|
120
|
+
|
121
|
+
item.host_id = host_id
|
122
|
+
item.plugin_id = -99999
|
123
|
+
item.plugin_output = nil
|
124
|
+
item.port = 0
|
125
|
+
item.severity = severity
|
126
|
+
item.plugin_name = "Upgrade to the latest Oracle Java SE"
|
127
|
+
|
128
|
+
item.save
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
def has_java_findings
|
133
|
+
@java_plugins.each do |plugin_id|
|
134
|
+
if Item.where(:plugin_id => plugin_id)
|
135
|
+
return true
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
return false
|
140
|
+
end
|
141
|
+
|
142
|
+
def has_host_java_findings (host_id)
|
143
|
+
@java_plugins.each do |plugin_id|
|
144
|
+
if Item.where(:plugin_id => plugin_id).where(:host_id => host_id).count >= 1
|
145
|
+
return true
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
return false
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
def calculate_severity current_severity, severity
|
154
|
+
#record highest severity for all of the rolled up
|
155
|
+
if severity == 4
|
156
|
+
return 4
|
157
|
+
elsif severity == 3 && current_severity != 4
|
158
|
+
return 3
|
159
|
+
elsif severity == 2 && current_severity != 4 && current_severity != 3
|
160
|
+
return 2
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
#
|
165
|
+
def run
|
166
|
+
if !has_java_findings()
|
167
|
+
return
|
168
|
+
end
|
169
|
+
|
170
|
+
#Create the dummy plugin
|
171
|
+
create_plugin()
|
172
|
+
|
173
|
+
Host.all.each do |host|
|
174
|
+
if !has_host_java_findings(host.id)
|
175
|
+
next
|
176
|
+
end
|
177
|
+
|
178
|
+
finding_severity = 0
|
179
|
+
|
180
|
+
@java_plugins.each do |plugin_id|
|
181
|
+
Item.where(:plugin_id => plugin_id).each do |item|
|
182
|
+
severity = item.severity
|
183
|
+
item.real_severity = severity
|
184
|
+
item.severity = -1
|
185
|
+
item.save
|
186
|
+
|
187
|
+
finding_severity = calculate_severity(finding_severity, severity)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
create_item(host.id, finding_severity)
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
# @host_list = Hash.new
|
196
|
+
|
197
|
+
# #Set all plugins
|
198
|
+
# @java_plugins.each do |plugin_id|
|
199
|
+
# @current_severity = "None"
|
200
|
+
|
201
|
+
# Item.where(:plugin_id => plugin_id).each do |item|
|
202
|
+
# severity = item.severity
|
203
|
+
# item.real_severity = severity
|
204
|
+
# item.severity = -1
|
205
|
+
# item.save
|
206
|
+
|
207
|
+
# #record highest severity for all of the rolled up
|
208
|
+
# if severity == 4
|
209
|
+
# @current_severity = 4
|
210
|
+
# elsif severity == 3 && @current_severity != 4
|
211
|
+
# @current_severity = 3
|
212
|
+
# elsif severity == 2 && @current_severity != 4 && @current_severity != 3
|
213
|
+
# @current_severity = 2
|
214
|
+
# end
|
215
|
+
|
216
|
+
# @host_list[item.host_id] = @current_severity
|
217
|
+
|
218
|
+
# end
|
219
|
+
# end
|
220
|
+
|
221
|
+
# #Create the rollup plugin
|
222
|
+
# create_plugin()
|
223
|
+
|
224
|
+
# #Create 1 finding for each host, flagged with the highest severity for that host
|
225
|
+
# @host_list.keys.each do |host_id|
|
226
|
+
# create_item(host_id, @host_list[host_id])
|
227
|
+
# end
|
228
|
+
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|