risu 1.7.2 → 1.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/NEWS.markdown +10 -0
- data/lib/risu.rb +1 -1
- data/lib/risu/base/schema.rb +1 -1
- data/lib/risu/base/shares_template_helper.rb +1 -1
- data/lib/risu/base/template_helper.rb +29 -22
- data/lib/risu/parsers/nessus/nessus_sax_listener.rb +337 -294
- data/lib/risu/parsers/nexpose/simple_nexpose.rb +7 -7
- data/lib/risu/templates/technical_findings.rb +53 -95
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3976d26d2c92a443ccbc3a367a78f452e1bf959e
|
4
|
+
data.tar.gz: 0d8c53e2188555be31370de88051c3b033ab5e25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdee561ba2e2d97d7c07cc211b469c51fabc303c7ceaa673fb92aaa8141d52fa53c9a6c28054002ba8a548d1d6e1e9787bb1c44ce49fc4bf5836ea6cb31fb05a
|
7
|
+
data.tar.gz: baed03ceb606c9034731555abe4857552a61e97453a5dbd15ed6b72cef40a3a33f1fd5e4c03aa61ddc23b8f604a3985e6c3f35c4cff0fed649e5d737be011cef
|
data/NEWS.markdown
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
# 1.7.3 (January 8, 2015)
|
4
|
+
- Parser Optimizations by [@bluehavana]
|
5
|
+
- Renamed Attachment.type to Attachment.ttype, due to a rails naming issue
|
6
|
+
- Added SAX Parser tests for Attachments
|
7
|
+
- Rewrote the technical_findings template
|
8
|
+
- Template Helper
|
9
|
+
- Added title method
|
10
|
+
- Added definition method
|
11
|
+
- Fixed various bugs
|
12
|
+
|
3
13
|
# 1.7.2 (January 5, 2015)
|
4
14
|
- Updated Copyrights / etc
|
5
15
|
- Added VMware ESXi Post Processing
|
data/lib/risu.rb
CHANGED
data/lib/risu/base/schema.rb
CHANGED
@@ -144,7 +144,7 @@ module Risu
|
|
144
144
|
heading1 "Poor Security Practice" if poor_count > 0
|
145
145
|
|
146
146
|
#Anon ftp/smb + clear text
|
147
|
-
@output.text anon_ftp_text + anon_smb_text + anonymous_access_text if anon_ftp_count >
|
147
|
+
@output.text anon_ftp_text + anon_smb_text + anonymous_access_text if anon_ftp_count > 0 || anon_smb_count > 0
|
148
148
|
@output.text "\n"
|
149
149
|
@output.text "\n"
|
150
150
|
end
|
@@ -73,45 +73,52 @@ module Risu
|
|
73
73
|
@output.text text, options
|
74
74
|
end
|
75
75
|
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
@output.text
|
76
|
+
def title(text, size=18, color='#000000')
|
77
|
+
@output.font_size(size) do
|
78
|
+
@output.fill_color color.gsub('#', '')
|
79
|
+
@output.text text, :style => :bold
|
80
|
+
@output.fill_color "000000"
|
80
81
|
end
|
82
|
+
|
83
|
+
@output.text "\n"
|
81
84
|
end
|
82
85
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
@output.text
|
86
|
+
def definition term, text, options = {}
|
87
|
+
if text != nil
|
88
|
+
@output.text "\n#{term}", :style => :bold
|
89
|
+
@output.text text, options
|
87
90
|
end
|
88
91
|
end
|
89
92
|
|
90
93
|
#
|
91
|
-
def
|
92
|
-
|
93
|
-
@output.text title, :style => :bold
|
94
|
-
end
|
94
|
+
def heading1 title_text
|
95
|
+
title title_text, 24
|
95
96
|
end
|
96
97
|
|
97
98
|
#
|
98
|
-
def
|
99
|
-
|
100
|
-
@output.text title, :style => :bold
|
101
|
-
end
|
99
|
+
def heading2 title_text
|
100
|
+
title title_text, 18
|
102
101
|
end
|
103
102
|
|
104
103
|
#
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
104
|
+
def heading3 title_text
|
105
|
+
title title_text, 14
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
def heading4 title_text
|
110
|
+
title title_text, 12
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
def heading5 title_text
|
115
|
+
title title_text, 10
|
109
116
|
end
|
110
117
|
|
111
118
|
#
|
112
|
-
def heading6
|
119
|
+
def heading6 title_text
|
113
120
|
@output.font_size(8) do
|
114
|
-
@output.text
|
121
|
+
@output.text title_text, :style => :bold
|
115
122
|
end
|
116
123
|
end
|
117
124
|
|
@@ -24,6 +24,8 @@
|
|
24
24
|
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
25
25
|
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
26
|
|
27
|
+
require 'set'
|
28
|
+
|
27
29
|
ActiveRecord::Migration.verbose = false
|
28
30
|
|
29
31
|
module Risu
|
@@ -34,64 +36,125 @@ module Risu
|
|
34
36
|
class NessusSaxListener
|
35
37
|
include LibXML::XML::SaxParser::Callbacks
|
36
38
|
|
37
|
-
#
|
39
|
+
# An array of valid reference element names
|
40
|
+
VALID_REFERENCES = Set.new(%w[
|
41
|
+
cpe bid see_also xref cve iava msft
|
42
|
+
osvdb cert edb-id rhsa secunia suse dsa
|
43
|
+
owasp cwe iavb iavt cisco-sa ics-alert
|
44
|
+
cisco-bug-id cisco-sr cert-vu vmsa apple-sa
|
45
|
+
icsa cert-cc msvr usn hp glsa freebsd
|
46
|
+
])
|
47
|
+
|
48
|
+
# An array of valid host properties
|
49
|
+
VALID_HOST_PROPERTIES = Set.new(%w[
|
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
|
+
pcidss:insecure_http_methods LastUnauthenticatedResults LastAuthenticatedResults cpe-0 cpe-1
|
59
|
+
cpe-2 cpe-3 Credentialed_Scan policy-used UnsupportedProduct:microsoft:windows_xp::sp2
|
60
|
+
UnsupportedProduct:microsoft:windows_xp UnsupportedProduct:microsoft:windows_2000 UnsupportedProduct
|
61
|
+
])
|
62
|
+
|
63
|
+
# An array of all valid elements expected during parsing
|
64
|
+
VALID_ELEMENTS = VALID_REFERENCES \
|
65
|
+
+ Set.new(%w[ReportItem plugin_version risk_factor
|
66
|
+
description cvss_base_score solution item plugin_output tag synopsis plugin_modification_date
|
67
|
+
FamilyName FamilyItem Status vuln_publication_date ReportHost HostProperties preferenceName
|
68
|
+
preferenceValues preferenceType fullName pluginId pluginName selectedValue selectedValue
|
69
|
+
name value preference plugin_publication_date cvss_vector patch_publication_date
|
70
|
+
NessusClientData_v2 Policy PluginName ServerPreferences policyComments policyName PluginItem
|
71
|
+
Report Family Preferences PluginsPreferences FamilySelection IndividualPluginSelection PluginId
|
72
|
+
pci-dss-compliance exploitability_ease cvss_temporal_vector exploit_framework_core cvss_temporal_score
|
73
|
+
exploit_available metasploit_name exploit_framework_canvas canvas_package exploit_framework_metasploit
|
74
|
+
plugin_type exploithub_sku exploit_framework_exploithub stig_severity plugin_name fname always_run
|
75
|
+
cm:compliance-info cm:compliance-actual-value cm:compliance-check-id cm:compliance-policy-value
|
76
|
+
cm:compliance-audit-file cm:compliance-check-name cm:compliance-result cm:compliance-output policyOwner
|
77
|
+
visibility script_version attachment policy_comments d2_elliot_name exploit_framework_d2_elliot
|
78
|
+
exploited_by_malware compliance
|
79
|
+
])
|
80
|
+
|
81
|
+
# TODO: documentation. These are never used in the class
|
82
|
+
VALID_HOST_PROPERTIES_REGEX = [
|
83
|
+
"patch-summary-cve-num", "patch-summary-cves", "patch-summary-txt", "cpe-\d+", "KB\d+"
|
84
|
+
]
|
85
|
+
|
86
|
+
# Map of host properties to symbols for use with ActiveRecord
|
87
|
+
# interfaces
|
88
|
+
#
|
89
|
+
# These are the more commonly used host properties,
|
90
|
+
# mapping them here to store in the host table
|
91
|
+
HOST_PROPERTIES_MAPPING = {
|
92
|
+
"HOST_END" => :end,
|
93
|
+
"mac-address" => :mac,
|
94
|
+
"HOST_START" => :start,
|
95
|
+
"operating-system" => :os,
|
96
|
+
"host-ip" => :ip,
|
97
|
+
"host-fqdn" => :fqdn,
|
98
|
+
"netbios-name" => :netbios
|
99
|
+
}
|
100
|
+
|
101
|
+
# Used to map element names to private methods so
|
102
|
+
# that the methods can be called when the parser
|
103
|
+
# encounters the opening of an element.
|
104
|
+
#
|
105
|
+
# {"ElementName" => :start_method_to_be_called}
|
106
|
+
#
|
107
|
+
# @example call #start_policy for a "Policy" element
|
108
|
+
# element = "Policy"
|
109
|
+
# send(DYNAMIC_START_METHOD_NAMES[element], element, attributes)
|
110
|
+
#
|
111
|
+
# @param element [String] the element name starting to be parsed
|
112
|
+
# @param attributes [Array<Hash{Sring=>String}>] the array of
|
113
|
+
# key value pairs for the element that is starting to be parsed
|
114
|
+
DYNAMIC_START_METHOD_NAMES = {
|
115
|
+
"Policy" => :start_policy,
|
116
|
+
"preference" => :start_preference,
|
117
|
+
"item" => :start_item,
|
118
|
+
"FamilyItem" => :start_family_item,
|
119
|
+
"PluginItem" => :start_plugin_item,
|
120
|
+
"Report" => :start_report,
|
121
|
+
"ReportHost" => :start_report_host,
|
122
|
+
"tag" => :start_tag,
|
123
|
+
"ReportItem" => :start_report_item,
|
124
|
+
"attachment" => :start_attachment
|
125
|
+
}
|
126
|
+
|
127
|
+
# @see DYNAMIC_START_MEHTOD_NAMES
|
128
|
+
#
|
129
|
+
# @note only one argument for the methods
|
130
|
+
#
|
131
|
+
# @example call #end_policy_name for a "policyName" element
|
132
|
+
# element = "policyName"
|
133
|
+
# send(DYNAMIC_END_METHOD_NAMES[element], element)
|
134
|
+
#
|
135
|
+
# @param element [String] the name of the element ending
|
136
|
+
DYNAMIC_END_METHOD_NAMES = {
|
137
|
+
"policyName" => :end_policy_name,
|
138
|
+
"policyComments" => :end_policy_comments,
|
139
|
+
"policy_comments" => :end_policy_comments,
|
140
|
+
"policyOwner" => :end_policy_owner,
|
141
|
+
"visibility" => :end_visibility,
|
142
|
+
"preference" => :end_preference,
|
143
|
+
"item" => :end_item,
|
144
|
+
"FamilyItem" => :end_family_item,
|
145
|
+
"PluginItem" => :end_plugin_item,
|
146
|
+
"tag" => :end_tag,
|
147
|
+
"ReportItem" => :end_report_item,
|
148
|
+
"attachment" => :end_attachment
|
149
|
+
}
|
150
|
+
|
151
|
+
private_constant :DYNAMIC_END_METHOD_NAMES, :DYNAMIC_START_METHOD_NAMES,
|
152
|
+
:HOST_PROPERTIES_MAPPING, :VALID_HOST_PROPERTIES_REGEX, :VALID_HOST_PROPERTIES,
|
153
|
+
:VALID_ELEMENTS, :VALID_REFERENCES
|
154
|
+
|
155
|
+
# vals tracks state for elements encountered during parsing
|
38
156
|
def initialize
|
39
157
|
@vals = Hash.new
|
40
|
-
|
41
|
-
@valid_references = Array[
|
42
|
-
"cpe", "bid", "see_also", "xref", "cve", "iava", "msft",
|
43
|
-
"osvdb", "cert", "edb-id", "rhsa", "secunia", "suse", "dsa",
|
44
|
-
"owasp", "cwe", "iavb", "iavt", "cisco-sa", "ics-alert",
|
45
|
-
"cisco-bug-id", "cisco-sr", "cert-vu", "vmsa", "apple-sa",
|
46
|
-
"icsa", "cert-cc", "msvr", "usn", "hp", "glsa", "freebsd"
|
47
|
-
]
|
48
|
-
|
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", "operating-system-unsupported", "patch-summary-total-cves",
|
58
|
-
"pcidss:insecure_http_methods", "LastUnauthenticatedResults", "LastAuthenticatedResults", "cpe-0", "cpe-1",
|
59
|
-
"cpe-2", "cpe-3", "Credentialed_Scan", "policy-used", "UnsupportedProduct:microsoft:windows_xp::sp2",
|
60
|
-
"UnsupportedProduct:microsoft:windows_xp", "UnsupportedProduct:microsoft:windows_2000", "UnsupportedProduct"
|
61
|
-
]
|
62
|
-
|
63
|
-
@valid_host_properties_regex = Array[
|
64
|
-
"patch-summary-cve-num", "patch-summary-cves", "patch-summary-txt", "cpe-\d+", "KB\d+"
|
65
|
-
]
|
66
|
-
|
67
|
-
@valid_elements = Array["ReportItem", "plugin_version", "risk_factor",
|
68
|
-
"description", "cvss_base_score", "solution", "item", "plugin_output", "tag", "synopsis", "plugin_modification_date",
|
69
|
-
"FamilyName", "FamilyItem", "Status", "vuln_publication_date", "ReportHost", "HostProperties", "preferenceName",
|
70
|
-
"preferenceValues", "preferenceType", "fullName", "pluginId", "pluginName", "selectedValue", "selectedValue",
|
71
|
-
"name", "value", "preference", "plugin_publication_date", "cvss_vector", "patch_publication_date",
|
72
|
-
"NessusClientData_v2", "Policy", "PluginName", "ServerPreferences", "policyComments", "policyName", "PluginItem",
|
73
|
-
"Report", "Family", "Preferences", "PluginsPreferences", "FamilySelection", "IndividualPluginSelection", "PluginId",
|
74
|
-
"pci-dss-compliance", "exploitability_ease", "cvss_temporal_vector", "exploit_framework_core", "cvss_temporal_score",
|
75
|
-
"exploit_available", "metasploit_name", "exploit_framework_canvas", "canvas_package", "exploit_framework_metasploit",
|
76
|
-
"plugin_type", "exploithub_sku", "exploit_framework_exploithub", "stig_severity", "plugin_name", "fname", "always_run",
|
77
|
-
"cm:compliance-info", "cm:compliance-actual-value", "cm:compliance-check-id", "cm:compliance-policy-value",
|
78
|
-
"cm:compliance-audit-file", "cm:compliance-check-name", "cm:compliance-result", "cm:compliance-output", "policyOwner",
|
79
|
-
"visibility", "script_version", "attachment", "policy_comments", "d2_elliot_name", "exploit_framework_d2_elliot",
|
80
|
-
"exploited_by_malware", "compliance"
|
81
|
-
]
|
82
|
-
|
83
|
-
@valid_elements = @valid_elements + @valid_references
|
84
|
-
|
85
|
-
# These are the more commonly used host properties, mapping them here to store in the host table
|
86
|
-
@host_properties_mapping = {
|
87
|
-
"HOST_END" => :end,
|
88
|
-
"mac-address" => :mac,
|
89
|
-
"HOST_START" => :start,
|
90
|
-
"operating-system" => :os,
|
91
|
-
"host-ip" => :ip,
|
92
|
-
"host-fqdn" => :fqdn,
|
93
|
-
"netbios-name" => :netbios
|
94
|
-
}
|
95
158
|
end
|
96
159
|
|
97
160
|
# Callback for when the start of a XML element is reached
|
@@ -102,95 +165,14 @@ module Risu
|
|
102
165
|
@tag = element
|
103
166
|
@vals[@tag] = ""
|
104
167
|
|
105
|
-
if
|
168
|
+
if !VALID_ELEMENTS.include?(element)
|
106
169
|
puts "New XML element detected: #{element}. Please report this at #{Risu::GITHUB}/issues/new or via email to #{Risu::EMAIL}"
|
107
170
|
end
|
108
171
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
when "preference"
|
114
|
-
@sp = @policy.server_preferences.create
|
115
|
-
@sp.save
|
116
|
-
when "item"
|
117
|
-
@item = @policy.plugins_preferences.create
|
118
|
-
@item.save
|
119
|
-
when "FamilyItem"
|
120
|
-
@family = @policy.family_selections.create
|
121
|
-
@family.save
|
122
|
-
when "PluginItem"
|
123
|
-
@plugin_selection = @policy.individual_plugin_selections.create
|
124
|
-
@plugin_selection.save
|
125
|
-
when "Report"
|
126
|
-
@report = @policy.reports.create
|
127
|
-
@report.name = attributes["name"]
|
128
|
-
@report.save
|
129
|
-
when "ReportHost"
|
130
|
-
@rh = @report.hosts.create
|
131
|
-
@rh.name = attributes["name"]
|
132
|
-
@rh.save
|
133
|
-
when "tag"
|
134
|
-
@attr = nil
|
135
|
-
@hp = @rh.host_properties.create
|
136
|
-
|
137
|
-
if attributes["name"] =~ /[M|m][S|s]\d{2,}-\d{2,}/
|
138
|
-
@attr = if attributes["name"] =~ /[M|m][S|s]\d{2,}-\d{2,}/
|
139
|
-
attributes["name"]
|
140
|
-
else
|
141
|
-
nil
|
142
|
-
end
|
143
|
-
#Ugly as fuck. Really this needs to be rewritten. Fuck.
|
144
|
-
elsif attributes['name'] =~ /patch-summary-cve-num/ ||
|
145
|
-
attributes['name'] =~ /patch-summary-cves/ ||
|
146
|
-
attributes['name'] =~ /patch-summary-txt/ ||
|
147
|
-
attributes['name'] =~ /cpe-\d+/ ||
|
148
|
-
attributes['name'] =~ /KB\d+/
|
149
|
-
@attr = if attributes["name"] =~ /patch-summary-cve-num/ ||
|
150
|
-
attributes['name'] =~ /patch-summary-cves/ ||
|
151
|
-
attributes['name'] =~ /patch-summary-txt/ ||
|
152
|
-
attributes['name'] =~ /cpe-\d+/ ||
|
153
|
-
attributes['name'] =~ /KB\d+/
|
154
|
-
attributes["name"]
|
155
|
-
else
|
156
|
-
nil
|
157
|
-
end
|
158
|
-
else
|
159
|
-
@attr = if @valid_host_properties.include?(attributes["name"])
|
160
|
-
attributes["name"]
|
161
|
-
else
|
162
|
-
nil
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
# implicit nil check?
|
167
|
-
if attributes["name"] !~ /(netstat-(?:established|listen)-(?:tcp|udp)\d+-\d+)/ && attributes["name"] !~ /traceroute-hop-\d+/
|
168
|
-
puts "New HostProperties attribute: #{attributes["name"]}. Please report this at #{Risu::GITHUB}/issues/new or via email to #{Risu::EMAIL}\n" if @attr.nil?
|
169
|
-
end
|
170
|
-
when "ReportItem"
|
171
|
-
@vals = Hash.new # have to clear this out or everything has the same references
|
172
|
-
@ri = @rh.items.create
|
173
|
-
if attributes["pluginID"] == "0"
|
174
|
-
@plugin = Risu::Models::Plugin.find_or_create_by(:id => 1)
|
175
|
-
else
|
176
|
-
@plugin = Risu::Models::Plugin.find_or_create_by(:id => attributes["pluginID"])
|
177
|
-
end
|
178
|
-
|
179
|
-
@ri.port = attributes["port"]
|
180
|
-
@ri.svc_name = attributes["svc_name"]
|
181
|
-
@ri.protocol = attributes["protocol"]
|
182
|
-
@ri.severity = attributes["severity"]
|
183
|
-
|
184
|
-
@ri.plugin_id = @plugin.id
|
185
|
-
@plugin.plugin_name = attributes["pluginName"]
|
186
|
-
@plugin.family_name = attributes["pluginFamily"]
|
187
|
-
@plugin.save
|
188
|
-
@ri.save
|
189
|
-
when "attachment"
|
190
|
-
@attachment = @ri.attachments.create
|
191
|
-
@attachment.name = attributes['name']
|
192
|
-
@attachment.type = attributes['type']
|
193
|
-
@attachment.save
|
172
|
+
if DYNAMIC_START_METHOD_NAMES.key?(element)
|
173
|
+
# Dynamic dispatch to private instance "policyComments"methods in the const hash
|
174
|
+
# DYNAMIC_START_METHOD_NAMES where {"element" => :start_element}
|
175
|
+
send(DYNAMIC_START_METHOD_NAMES[element], element, attributes)
|
194
176
|
end
|
195
177
|
end
|
196
178
|
|
@@ -210,160 +192,221 @@ module Risu
|
|
210
192
|
# @param element
|
211
193
|
def on_end_element(element)
|
212
194
|
@tag = nil
|
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
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
}
|
279
|
-
|
280
|
-
@family.save
|
281
|
-
when "PluginItem"
|
282
|
-
@plugin_selection.attributes = {
|
283
|
-
:plugin_id => @vals["PluginId"],
|
284
|
-
:plugin_name => @vals["PluginName"],
|
285
|
-
:family => @vals["Family"],
|
286
|
-
:status => @vals["Status"]
|
287
|
-
}
|
288
|
-
|
289
|
-
@plugin_selection.save
|
290
|
-
when "tag"
|
291
|
-
if @attr =~ /[M|m][S|s]\d{2}-\d{2,}/
|
292
|
-
@patch = @rh.patches.create
|
293
|
-
@patch.name = @attr
|
294
|
-
@patch.value = @vals['tag']
|
295
|
-
@patch.save
|
296
|
-
else
|
297
|
-
@rh.attributes = {@host_properties_mapping[@attr] => @vals["tag"].gsub("\n", ",") } if @host_properties_mapping.keys.include?(@attr)
|
298
|
-
@rh.save
|
299
|
-
|
300
|
-
@hp.name = @attr
|
301
|
-
@hp.value = @vals['tag']
|
302
|
-
@hp.save
|
303
|
-
|
304
|
-
end if @attr != nil
|
305
|
-
#We cannot handle the references in the same block as the rest of the ReportItem tag because
|
306
|
-
#there tends to be more than of the different types of reference per ReportItem, this causes issue for a sax
|
307
|
-
#parser. To solve this we do the references before the final plugin data, Valid references must be added
|
308
|
-
#the @valid_reference array at the top to be parsed.
|
309
|
-
# *@valid_reference, does a 'when' on each element of the @valid_references array, pure magic
|
310
|
-
when *@valid_references
|
311
|
-
@ref = @plugin.references.create
|
312
|
-
@ref.reference_name = element
|
313
|
-
@ref.value = @vals["#{element}"]
|
314
|
-
@ref.save
|
315
|
-
when "ReportItem"
|
316
|
-
@ri.plugin_output = @vals["plugin_output"]
|
317
|
-
@ri.plugin_name = @vals["plugin_name"]
|
318
|
-
@ri.cm_compliance_info = @vals["cm:compliance-info"]
|
319
|
-
@ri.cm_compliance_actual_value = @vals["cm:compliance-actual-value"]
|
320
|
-
@ri.cm_compliance_check_id = @vals["cm:compliance-check-id"]
|
321
|
-
@ri.cm_compliance_policy_value= @vals["cm:compliance-policy-value"]
|
322
|
-
@ri.cm_compliance_audit_file = @vals["cm:compliance-audit-file"]
|
323
|
-
@ri.cm_compliance_check_name = @vals["cm:compliance-check-name"]
|
324
|
-
@ri.cm_compliance_result = @vals["cm:compliance-result"]
|
325
|
-
@ri.cm_compliance_output = @vals["cm:compliance-output"]
|
326
|
-
|
327
|
-
@ri.save
|
328
|
-
|
329
|
-
@plugin.attributes = {
|
330
|
-
:solution => @vals["solution"],
|
331
|
-
:risk_factor => @vals["risk_factor"],
|
332
|
-
:description => @vals["description"],
|
333
|
-
:plugin_publication_date => @vals["plugin_publication_date"],
|
334
|
-
:plugin_modification_date => @vals["plugin_modification_date"],
|
335
|
-
:synopsis => @vals["synopsis"],
|
336
|
-
:plugin_type => @vals["plugin_type"],
|
337
|
-
:cvss_vector => @vals["cvss_vector"],
|
338
|
-
:cvss_base_score => @vals["cvss_base_score"].to_f,
|
339
|
-
:vuln_publication_date => @vals["vuln_publication_date"],
|
340
|
-
:plugin_version => @vals["plugin_version"],
|
341
|
-
:cvss_temporal_score => @vals["cvss_temporal_score"],
|
342
|
-
:cvss_temporal_vector => @vals["cvss_temporal_vector"],
|
343
|
-
:exploitability_ease => @vals["exploitability_ease"],
|
344
|
-
:exploit_framework_core => @vals["exploit_framework_core"],
|
345
|
-
:exploit_available => @vals["exploit_available"],
|
346
|
-
:exploit_framework_metasploit => @vals["exploit_framework_metasploit"],
|
347
|
-
:metasploit_name => @vals["metasploit_name"],
|
348
|
-
:exploit_framework_canvas => @vals["exploit_framework_canvas"],
|
349
|
-
:canvas_package => @vals["canvas_package"],
|
350
|
-
:exploit_framework_exploithub => @vals["exploit_framework_exploithub"],
|
351
|
-
:exploithub_sku => @vals["exploithub_sku"],
|
352
|
-
:stig_severity => @vals["stig_severity"],
|
353
|
-
:fname => @vals["fname"],
|
354
|
-
:always_run => @vals["always_run"],
|
355
|
-
:script_version => @vals["script_version"],
|
356
|
-
:exploited_by_malware => @vals["exploited_by_malware"],
|
357
|
-
:compliance => @vals["compliance"]
|
358
|
-
}
|
359
|
-
@plugin.save
|
360
|
-
when "attachment"
|
361
|
-
@attachment.attributes = {
|
362
|
-
:ahash => @vals['attachment']
|
363
|
-
}
|
364
|
-
@attachment.save
|
195
|
+
|
196
|
+
if DYNAMIC_END_METHOD_NAMES.key?(element)
|
197
|
+
# Dynamic dispatch to private instance methods in the const hash
|
198
|
+
# DYNAMIC_END_METHOD_NAMES where {"element" => :end_element}
|
199
|
+
send(DYNAMIC_END_METHOD_NAMES[element], element)
|
200
|
+
elsif VALID_REFERENCES.include?(element)
|
201
|
+
end_valid_reference(element)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
private
|
206
|
+
|
207
|
+
# Dynamic dispatch start element methods
|
208
|
+
def start_policy(_element, _attributes)
|
209
|
+
@policy = Risu::Models::Policy.create
|
210
|
+
end
|
211
|
+
|
212
|
+
def start_preference(_element, _attributes)
|
213
|
+
@sp = @policy.server_preferences.create
|
214
|
+
end
|
215
|
+
|
216
|
+
def start_item(_element, _attributes)
|
217
|
+
@item = @policy.plugins_preferences.create
|
218
|
+
end
|
219
|
+
|
220
|
+
def start_family_item(_element, _attributes)
|
221
|
+
@family = @policy.family_selections.create
|
222
|
+
end
|
223
|
+
|
224
|
+
def start_plugin_item(_element, _attributes)
|
225
|
+
@plugin_selection = @policy.individual_plugin_selections.create
|
226
|
+
end
|
227
|
+
|
228
|
+
def start_report(_element, attributes)
|
229
|
+
@report = @policy.reports.create(:name => attributes["name"])
|
230
|
+
end
|
231
|
+
|
232
|
+
def start_report_host(_element, attributes)
|
233
|
+
@rh = @report.hosts.create(:name => attributes["name"])
|
234
|
+
end
|
235
|
+
|
236
|
+
def start_tag(_, attributes)
|
237
|
+
@attr = nil
|
238
|
+
@hp = @rh.host_properties.create
|
239
|
+
|
240
|
+
if attributes["name"] =~ /[M|m][S|s]\d{2,}-\d{2,}/
|
241
|
+
@attr = attributes["name"]
|
242
|
+
#Ugly as fuck. Really this needs to be rewritten. Fuck.
|
243
|
+
elsif attributes['name'] =~ /
|
244
|
+
(?:patch-summary-cve-num)
|
245
|
+
| (?:patch-summary-cves)
|
246
|
+
| (?:patch-summary-txt)
|
247
|
+
| (?:cpe-\d+)
|
248
|
+
| (?:KB\d+)
|
249
|
+
/x
|
250
|
+
@attr = attributes["name"]
|
251
|
+
elsif VALID_HOST_PROPERTIES.include?(attributes["name"])
|
252
|
+
@attr = attributes["name"]
|
253
|
+
end
|
254
|
+
|
255
|
+
# implicit nil check?
|
256
|
+
if attributes["name"] !~ /(netstat-(?:established|listen)-(?:tcp|udp)\d+-\d+)/ \
|
257
|
+
&& attributes["name"] !~ /traceroute-hop-\d+/ \
|
258
|
+
&& @attr.nil?
|
259
|
+
puts "New HostProperties attribute: #{attributes["name"]}. Please report this at #{Risu::GITHUB}/issues/new or via email to #{Risu::EMAIL}\n"
|
365
260
|
end
|
366
261
|
end
|
262
|
+
|
263
|
+
def start_report_item(_element, attributes)
|
264
|
+
@vals = Hash.new # have to clear this out or everything has the same references
|
265
|
+
|
266
|
+
if attributes["pluginID"] == "0"
|
267
|
+
@plugin = Risu::Models::Plugin.find_or_create_by(:id => 1)
|
268
|
+
else
|
269
|
+
@plugin = Risu::Models::Plugin.find_or_create_by(:id => attributes["pluginID"]) do |plugin|
|
270
|
+
plugin.plugin_name = attributes["pluginName"]
|
271
|
+
plugin.family_name = attributes["pluginFamily"]
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
@ri = @rh.items.create(:port => attributes["port"],
|
276
|
+
:svc_name => attributes["svc_name"],
|
277
|
+
:protocol => attributes["protocol"],
|
278
|
+
:severity => attributes["severity"],
|
279
|
+
:plugin_id => @plugin.id)
|
280
|
+
|
281
|
+
@plugin.save
|
282
|
+
end
|
283
|
+
|
284
|
+
def start_attachment(_element, attributes)
|
285
|
+
@attachment = @ri.attachments.create(:name => attributes['name'], :ttype => attributes['type'])
|
286
|
+
end
|
287
|
+
|
288
|
+
# Dynamic dispatch end element methods
|
289
|
+
def end_policy_name(_)
|
290
|
+
@policy.update(:name => @vals["policyName"])
|
291
|
+
end
|
292
|
+
|
293
|
+
def end_policy_comments(element)
|
294
|
+
return unless element == "policyComments" || element == "policy_comments"
|
295
|
+
@policy.update(:comments => @vals[element])
|
296
|
+
end
|
297
|
+
|
298
|
+
def end_policy_owner(_)
|
299
|
+
@policy.update(:owner => @vals["policyOwner"])
|
300
|
+
end
|
301
|
+
|
302
|
+
def end_visibility(_)
|
303
|
+
@policy.update(:visibility => @vals["visibility"])
|
304
|
+
end
|
305
|
+
|
306
|
+
def end_preference(_)
|
307
|
+
@sp.update(:name => @vals["name"], :value => @vals["value"])
|
308
|
+
end
|
309
|
+
|
310
|
+
# This takes a really long time, there is about 34,000 pluginIDs in this
|
311
|
+
# field and it takes about 36 minutes to parse just this info =\
|
312
|
+
# lets pre-populate the plugins table with the known plugin_id's
|
313
|
+
#
|
314
|
+
# if @vals["name"] == "plugin_set"
|
315
|
+
# @all_plugins = @vals["value"].split(";")
|
316
|
+
#
|
317
|
+
# @all_plugins.each { |p|
|
318
|
+
# @plug = Plugin.find_or_create_by_id(p)
|
319
|
+
# @plug.save
|
320
|
+
# }
|
321
|
+
# end
|
322
|
+
def end_item(_)
|
323
|
+
@item.update(:plugin_name => @vals["pluginName"],
|
324
|
+
:plugin_id => @vals["pluginId"], :fullname => @vals["fullName"],
|
325
|
+
:preference_name => @vals["preferenceName"],
|
326
|
+
:preference_type => @vals["preferenceType"],
|
327
|
+
:preference_values => @vals["preferenceValues"],
|
328
|
+
:selected_values => @vals["selectedValue"])
|
329
|
+
end
|
330
|
+
|
331
|
+
def end_family_item(_)
|
332
|
+
@family.update( :family_name => @vals["FamilyName"],
|
333
|
+
:status => @vals["Status"])
|
334
|
+
end
|
335
|
+
|
336
|
+
def end_plugin_item(_)
|
337
|
+
@plugin_selection.update(:plugin_id => @vals["PluginId"],
|
338
|
+
:plugin_name => @vals["PluginName"],
|
339
|
+
:family => @vals["Family"], :status => @vals["Status"])
|
340
|
+
end
|
341
|
+
|
342
|
+
def end_tag(_)
|
343
|
+
return if @attr.nil?
|
344
|
+
|
345
|
+
if @attr =~ /[M|m][S|s]\d{2}-\d{2,}/
|
346
|
+
@patch = @rh.patches.create(:name => @attr, :value => @vals['tag'])
|
347
|
+
else
|
348
|
+
if HOST_PROPERTIES_MAPPING.key?(@attr)
|
349
|
+
@rh.update(HOST_PROPERTIES_MAPPING[@attr] => @vals["tag"].gsub("\n", ","))
|
350
|
+
end
|
351
|
+
|
352
|
+
@hp.update(:name => @attr, :value => @vals['tag'])
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
#We cannot handle the references in the same block as the rest of the ReportItem tag because
|
357
|
+
#there tends to be more than of the different types of reference per ReportItem, this causes issue for a sax
|
358
|
+
#parser. To solve this we do the references before the final plugin data, Valid references must be added
|
359
|
+
#the VALID_REFERENCE set at the top to be parsed.
|
360
|
+
def end_valid_reference(element)
|
361
|
+
@ref = @plugin.references.create(:reference_name => element,
|
362
|
+
:value => @vals["#{element}"])
|
363
|
+
end
|
364
|
+
|
365
|
+
def end_report_item(_)
|
366
|
+
@ri.update(:plugin_output => @vals["plugin_output"],
|
367
|
+
:plugin_name => @vals["plugin_name"],
|
368
|
+
:cm_compliance_info => @vals["cm:compliance-info"],
|
369
|
+
:cm_compliance_actual_value => @vals["cm:compliance-actual-value"],
|
370
|
+
:cm_compliance_check_id => @vals["cm:compliance-check-id"],
|
371
|
+
:cm_compliance_policy_value => @vals["cm:compliance-policy-value"],
|
372
|
+
:cm_compliance_audit_file => @vals["cm:compliance-audit-file"],
|
373
|
+
:cm_compliance_check_name => @vals["cm:compliance-check-name"],
|
374
|
+
:cm_compliance_result => @vals["cm:compliance-result"],
|
375
|
+
:cm_compliance_output => @vals["cm:compliance-output"])
|
376
|
+
|
377
|
+
@plugin.update(:solution => @vals["solution"],
|
378
|
+
:risk_factor => @vals["risk_factor"],
|
379
|
+
:description => @vals["description"],
|
380
|
+
:plugin_publication_date => @vals["plugin_publication_date"],
|
381
|
+
:plugin_modification_date => @vals["plugin_modification_date"],
|
382
|
+
:synopsis => @vals["synopsis"],
|
383
|
+
:plugin_type => @vals["plugin_type"],
|
384
|
+
:cvss_vector => @vals["cvss_vector"],
|
385
|
+
:cvss_base_score => @vals["cvss_base_score"].to_f,
|
386
|
+
:vuln_publication_date => @vals["vuln_publication_date"],
|
387
|
+
:plugin_version => @vals["plugin_version"],
|
388
|
+
:cvss_temporal_score => @vals["cvss_temporal_score"],
|
389
|
+
:cvss_temporal_vector => @vals["cvss_temporal_vector"],
|
390
|
+
:exploitability_ease => @vals["exploitability_ease"],
|
391
|
+
:exploit_framework_core => @vals["exploit_framework_core"],
|
392
|
+
:exploit_available => @vals["exploit_available"],
|
393
|
+
:exploit_framework_metasploit => @vals["exploit_framework_metasploit"],
|
394
|
+
:metasploit_name => @vals["metasploit_name"],
|
395
|
+
:exploit_framework_canvas => @vals["exploit_framework_canvas"],
|
396
|
+
:canvas_package => @vals["canvas_package"],
|
397
|
+
:exploit_framework_exploithub => @vals["exploit_framework_exploithub"],
|
398
|
+
:exploithub_sku => @vals["exploithub_sku"],
|
399
|
+
:stig_severity => @vals["stig_severity"],
|
400
|
+
:fname => @vals["fname"],
|
401
|
+
:always_run => @vals["always_run"],
|
402
|
+
:script_version => @vals["script_version"],
|
403
|
+
:exploited_by_malware => @vals["exploited_by_malware"],
|
404
|
+
:compliance => @vals["compliance"])
|
405
|
+
end
|
406
|
+
|
407
|
+
def end_attachment(_)
|
408
|
+
@attachment.update(:ahash => @vals['attachment'])
|
409
|
+
end
|
367
410
|
end
|
368
411
|
end
|
369
412
|
end
|
@@ -34,12 +34,7 @@ module Risu
|
|
34
34
|
class SimpleNexpose
|
35
35
|
include LibXML::XML::SaxParser::Callbacks
|
36
36
|
|
37
|
-
|
38
|
-
#
|
39
|
-
def initialize
|
40
|
-
@vals = Hash.new
|
41
|
-
|
42
|
-
@valid_fingerprints = {
|
37
|
+
VALID_FINGERPRINTS = {
|
43
38
|
"description" => :os,
|
44
39
|
"vendor" => nil,
|
45
40
|
"family" => nil,
|
@@ -49,6 +44,11 @@ module Risu
|
|
49
44
|
"architecture" => nil
|
50
45
|
}
|
51
46
|
|
47
|
+
# @todo comment
|
48
|
+
#
|
49
|
+
def initialize
|
50
|
+
@vals = Hash.new
|
51
|
+
|
52
52
|
@report = Report.create
|
53
53
|
end
|
54
54
|
|
@@ -93,7 +93,7 @@ module Risu
|
|
93
93
|
@in_device = false
|
94
94
|
when "description"
|
95
95
|
if @in_device && @in_fingerprint
|
96
|
-
@rh.attributes = {
|
96
|
+
@rh.attributes = { VALID_FINGERPRINTS[element] => @vals[element].gsub("\n", ",") } if VALID_FINGERPRINTS.key?(element)
|
97
97
|
@rh.save
|
98
98
|
end
|
99
99
|
when "fingerprint"
|
@@ -34,117 +34,75 @@ module Risu
|
|
34
34
|
{
|
35
35
|
:name => "technical_findings",
|
36
36
|
:author => "hammackj",
|
37
|
-
:version => "0.0.
|
37
|
+
:version => "0.0.9",
|
38
38
|
:renderer => "PDF",
|
39
39
|
:description => "Generates a Technical Findings Report"
|
40
40
|
}
|
41
41
|
end
|
42
42
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
43
|
+
def print_technical_findings(risks, text, color, last=false)
|
44
|
+
if risks.length > 0
|
45
|
+
title text, 18, color
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
text "\n\n\n"
|
47
|
+
risks.each do |f|
|
48
|
+
hosts = Item.where(:plugin_id => f.plugin_id).group(:host_id)
|
49
|
+
plugin = Plugin.find_by_id(f.plugin_id)
|
52
50
|
|
53
|
-
|
54
|
-
unique_risks << Hash[:title => "Critical Findings", :color => Risu::GRAPH_COLORS[0], :values => Item.critical_risks_unique] if Item.critical_risks_unique.to_a.size != 0
|
55
|
-
unique_risks << Hash[:title => "High Findings", :color => Risu::GRAPH_COLORS[1], :values => Item.high_risks_unique] if Item.high_risks_unique.to_a.size != 0
|
51
|
+
references = Reference.where(:plugin_id => plugin.id).group(:value).order(:reference_name)
|
56
52
|
|
57
|
-
|
58
|
-
|
53
|
+
output.font_size(16) do
|
54
|
+
text "#{plugin.plugin_name}\n"
|
55
|
+
end
|
59
56
|
|
60
|
-
|
61
|
-
|
57
|
+
if hosts.length > 1
|
58
|
+
text "Hosts", :style => :bold
|
59
|
+
else
|
60
|
+
text "Host", :style => :bold
|
61
|
+
end
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
63
|
+
hostlist = Array.new
|
64
|
+
hosts.each do |host|
|
65
|
+
ho = Host.find_by_id(host.host_id)
|
66
|
+
host_string = "#{ho.name}"
|
67
|
+
host_string << " (#{ho.fqdn})" if ho.fqdn != nil
|
68
|
+
hostlist << host_string
|
67
69
|
end
|
68
70
|
|
69
|
-
text
|
71
|
+
text hostlist.join(', ')
|
70
72
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
text "Hosts", :style => :bold
|
84
|
-
else
|
85
|
-
text "Host", :style => :bold
|
86
|
-
end
|
87
|
-
|
88
|
-
hostlist = Array.new
|
89
|
-
hosts.each do |host|
|
90
|
-
ho = Host.find_by_id(host.host_id)
|
91
|
-
#if h.id != blacklist_host_id.first.id
|
92
|
-
host_string = "#{ho.name}"
|
93
|
-
host_string << " (#{ho.fqdn})" if ho.fqdn != nil
|
94
|
-
hostlist << host_string
|
95
|
-
#end
|
96
|
-
end
|
97
|
-
|
98
|
-
text hostlist.join(', ')
|
99
|
-
|
100
|
-
if f.plugin_output != nil
|
101
|
-
text "\nPlugin output", :style => :bold
|
102
|
-
text f.plugin_output
|
103
|
-
end
|
104
|
-
|
105
|
-
if plugin.description != nil
|
106
|
-
text "\nDescription", :style => :bold
|
107
|
-
text plugin.description.gsub(/[ ]{2,}/, " "), :inline_format => true
|
108
|
-
end
|
109
|
-
|
110
|
-
if plugin.synopsis != nil
|
111
|
-
text "\nSynopsis", :style => :bold
|
112
|
-
text plugin.synopsis
|
113
|
-
end
|
114
|
-
|
115
|
-
if plugin.cvss_base_score != nil
|
116
|
-
text "\nCVSS Base Score", :style => :bold
|
117
|
-
text plugin.cvss_base_score
|
118
|
-
end
|
119
|
-
|
120
|
-
if plugin.exploit_available != nil
|
121
|
-
text "\nExploit Available", :style => :bold
|
122
|
-
|
123
|
-
if plugin.exploit_available == "true"
|
124
|
-
text "Yes"
|
125
|
-
else
|
126
|
-
text "No"
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
if plugin.solution != nil
|
131
|
-
text "\nSolution", :style => :bold
|
132
|
-
text plugin.solution
|
133
|
-
end
|
134
|
-
|
135
|
-
if references.size != 0
|
136
|
-
text "\nReferences", :style => :bold
|
137
|
-
text plugin.references.reference_string, :inline_format => true
|
138
|
-
plugin_url = "http://www.tenablesecurity.com/plugins/index.php?view=single&id=#{plugin.id}"
|
139
|
-
text "<b>nessus_plugin</b>: #{plugin_url}", :inline_format => true, :link => plugin_url
|
140
|
-
end
|
141
|
-
|
142
|
-
text "\n"
|
143
|
-
end
|
73
|
+
definition "Plugin output", f.plugin_output
|
74
|
+
definition "Description", plugin.description.gsub(/[ ]{2,}/, " ") if plugin.description != nil
|
75
|
+
definition "Synopsis", plugin.synopsis
|
76
|
+
definition "CVSS Base Score", plugin.cvss_base_score
|
77
|
+
definition "Exploit Available", (plugin.exploit_available == "true") ? "Yes" : "No"
|
78
|
+
definition "Solution", plugin.solution
|
79
|
+
definition "References", plugin.references.reference_string, :inline_format => true
|
80
|
+
|
81
|
+
plugin_url = "http://www.tenablesecurity.com/plugins/index.php?view=single&id=#{plugin.id}"
|
82
|
+
definition "Nessus Plugin", plugin_url, :inline_format => true, :link => plugin_url
|
83
|
+
|
84
|
+
text "\n"
|
144
85
|
end
|
145
86
|
|
146
|
-
output.start_new_page if
|
87
|
+
@output.start_new_page if last == false
|
147
88
|
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def render(output)
|
92
|
+
text Report.classification.upcase, :align => :center
|
93
|
+
text "\n"
|
94
|
+
|
95
|
+
report_title Report.title
|
96
|
+
report_subtitle "Technical Findings"
|
97
|
+
report_author "This report was prepared by\n#{Report.author}"
|
98
|
+
text "\n\n\n"
|
99
|
+
|
100
|
+
# If you uncomment the med/low change the true in high to false for a new page after it
|
101
|
+
|
102
|
+
print_technical_findings(Item.critical_risks_unique, "Critical Findings", Risu::GRAPH_COLORS[0]) if Item.critical_risks_unique.to_a.size != 0
|
103
|
+
print_technical_findings(Item.high_risks_unique, "High Findings", Risu::GRAPH_COLORS[1], true) if Item.high_risks_unique.to_a.size != 0
|
104
|
+
#print_technical_findings(Item.medium_risks_unique, "Medium Findings", Risu::GRAPH_COLORS[2]) if Item.medium_risks_unique.to_a.size != 0
|
105
|
+
#print_technical_findings(Item.low_risks_unique, "Low Findings", Risu::GRAPH_COLORS[3], true) if Item.low_risks_unique.to_a.size != 0
|
148
106
|
|
149
107
|
output.number_pages "<page> of <total>", :at => [output.bounds.right - 75, 0], :width => 150, :page_filter => :all
|
150
108
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: risu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.7.
|
4
|
+
version: 1.7.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jacob Hammack
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: simplecov
|