risu 1.4.4 → 1.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/NEWS.markdown +14 -1
- data/README.markdown +23 -41
- data/TODO.markdown +48 -39
- data/lib/risu.rb +4 -9
- data/lib/risu/base.rb +15 -0
- data/lib/risu/base/prawn_templater.rb +37 -0
- data/lib/risu/{schema.rb → base/schema.rb} +34 -15
- data/lib/risu/base/template_base.rb +23 -0
- data/lib/risu/base/template_manager.rb +106 -0
- data/lib/risu/base/templater.rb +37 -0
- data/lib/risu/cli/application.rb +28 -8
- data/lib/risu/models.rb +1 -2
- data/lib/risu/models/host.rb +147 -23
- data/lib/risu/models/item.rb +131 -43
- data/lib/risu/models/plugin.rb +1 -1
- data/lib/risu/models/report.rb +11 -1
- data/lib/risu/models/serverpreference.rb +0 -2
- data/lib/risu/models/servicedescription.rb +10 -0
- data/lib/risu/parsers.rb +2 -3
- data/lib/risu/parsers/nessus/nessus_document.rb +69 -0
- data/lib/risu/parsers/nessus/nessus_sax_listener.rb +278 -0
- data/lib/risu/templates/assets.rb +45 -18
- data/lib/risu/templates/cover_sheet.rb +70 -42
- data/lib/risu/templates/exec_summary.rb +64 -45
- data/lib/risu/templates/executive_summary.rb +185 -161
- data/lib/risu/templates/finding_statistics.rb +44 -17
- data/lib/risu/templates/findings_host.rb +70 -46
- data/lib/risu/templates/findings_summary.rb +78 -54
- data/lib/risu/templates/findings_summary_with_pluginid.rb +80 -54
- data/lib/risu/templates/graphs.rb +46 -19
- data/lib/risu/templates/host_summary.rb +62 -39
- data/lib/risu/templates/ms_patch_summary.rb +59 -35
- data/lib/risu/templates/ms_update_summary.rb +59 -35
- data/lib/risu/templates/pci_compliance.rb +88 -64
- data/lib/risu/templates/technical_findings.rb +132 -106
- data/lib/risu/templates/template.rb +24 -0
- metadata +12 -6
- data/lib/risu/listener.rb +0 -274
- data/lib/risu/nessusdocument.rb +0 -66
- data/lib/risu/prawn_templater.rb +0 -38
@@ -1,33 +1,60 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Risu
|
2
|
+
module Modules
|
3
|
+
class Graphs < Risu::Base::TemplateBase
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
#
|
6
|
+
#
|
7
|
+
def initialize ()
|
8
|
+
@template_info =
|
9
|
+
{
|
10
|
+
:name => "graphs",
|
11
|
+
:author => "hammackj",
|
12
|
+
:version => "0.0.1",
|
13
|
+
:description => "Generates a report with all the graphs in it",
|
14
|
+
:scanner => "Nessus"
|
15
|
+
}
|
16
|
+
end
|
8
17
|
|
9
|
-
|
18
|
+
#
|
19
|
+
#
|
20
|
+
def render(output)
|
21
|
+
output.text Report.classification, :align => :center
|
22
|
+
output.text "\n"
|
10
23
|
|
11
|
-
|
24
|
+
output.font_size(24) do
|
25
|
+
output.text Report.title, :align => :center
|
26
|
+
end
|
12
27
|
|
13
|
-
|
28
|
+
output.font_size(18) do
|
29
|
+
output.text "This report was prepared by\n#{Report.author}", :align => :center
|
30
|
+
end
|
14
31
|
|
15
|
-
|
32
|
+
output.text "\n\n\n"
|
16
33
|
|
17
|
-
|
34
|
+
output.start_new_page
|
18
35
|
|
19
|
-
|
36
|
+
output.image Item.risks_by_severity_graph, :width => 500, :height => 375, :position => :center
|
20
37
|
|
21
|
-
|
38
|
+
output.start_new_page
|
22
39
|
|
23
|
-
|
40
|
+
output.image Item.risks_by_service_graph(10), :width => 500, :height => 375, :position => :center
|
24
41
|
|
25
|
-
|
42
|
+
output.start_new_page
|
26
43
|
|
27
|
-
|
44
|
+
output.image Plugin.top_by_count_graph(10), :width => 500, :height => 375, :position => :center
|
28
45
|
|
29
|
-
|
46
|
+
output.start_new_page
|
30
47
|
|
31
|
-
|
48
|
+
output.image Host.top_vuln_graph(10), :width => 500, :height => 375, :position => :center
|
32
49
|
|
33
|
-
|
50
|
+
output.start_new_page
|
51
|
+
|
52
|
+
output.image Host.other_os_graph, :width => 500, :height => 375, :position => :center
|
53
|
+
|
54
|
+
output.start_new_page
|
55
|
+
|
56
|
+
output.image Host.windows_os_graph, :width => 500, :height => 375, :position => :center
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,40 +1,63 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
1
|
+
module Risu
|
2
|
+
module Modules
|
3
|
+
class HostSummary < Risu::Base::TemplateBase
|
4
|
+
|
5
|
+
#
|
6
|
+
#
|
7
|
+
def initialize ()
|
8
|
+
@template_info =
|
9
|
+
{
|
10
|
+
:name => "host_summary",
|
11
|
+
:author => "hammackj",
|
12
|
+
:version => "0.0.1",
|
13
|
+
:description => "Generates a Host Summary Report"
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
#
|
19
|
+
def render(output)
|
20
|
+
output.text Report.classification, :align => :center
|
21
|
+
output.text "\n"
|
22
|
+
|
23
|
+
output.font_size(22) { output.text Report.title, :align => :center }
|
24
|
+
output.font_size(18) {
|
25
|
+
output.text "Host Summary Report", :align => :center
|
26
|
+
output.text "\n"
|
27
|
+
output.text "This report was prepared by\n#{Report.author}", :align => :center
|
28
|
+
}
|
29
|
+
|
30
|
+
output.text "\n\n\n"
|
31
|
+
|
32
|
+
results = Array.new
|
33
|
+
|
34
|
+
headers = ["Hostname", "Total", "High", "Medium", "Low", "Info"]
|
35
|
+
header_widths = {0 => 137, 1 => 75, 2 => 75, 3 => 75, 4 => 75, 5 => 75}
|
36
|
+
|
37
|
+
Host.sorted.each do |host|
|
38
|
+
row = Array.new
|
39
|
+
|
40
|
+
total = Item.risks.where(:host_id => host.id).count
|
41
|
+
high = Item.high_risks.where(:host_id => host.id).count
|
42
|
+
medium = Item.medium_risks.where(:host_id => host.id).count
|
43
|
+
low = Item.low_risks.where(:host_id => host.id).count
|
44
|
+
info = Item.info_risks.where(:host_id => host.id).count
|
45
|
+
|
46
|
+
row.push(host.name)
|
47
|
+
row.push(total)
|
48
|
+
row.push(high)
|
49
|
+
row.push(medium)
|
50
|
+
row.push(low)
|
51
|
+
row.push(info)
|
52
|
+
|
53
|
+
results.push(row)
|
54
|
+
end
|
55
|
+
|
56
|
+
output.table([headers] + results, :header => true, :column_widths => header_widths, :row_colors => ['ffffff', 'E5E5E5']) do
|
57
|
+
row(0).style(:font_style => :bold, :background_color => 'D0D0D0')
|
58
|
+
cells.borders = [:top, :bottom, :left, :right]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
40
63
|
end
|
@@ -1,37 +1,61 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
1
|
+
module Risu
|
2
|
+
module Modules
|
3
|
+
class MSPatchSummary < Risu::Base::TemplateBase
|
4
|
+
|
5
|
+
#
|
6
|
+
#
|
7
|
+
def initialize ()
|
8
|
+
@template_info =
|
9
|
+
{
|
10
|
+
:name => "ms_patch_summary",
|
11
|
+
:author => "hammackj",
|
12
|
+
:version => "0.0.1",
|
13
|
+
:description => "Generates a Microsoft Patch Summary Report"
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
#
|
19
|
+
def render(output)
|
20
|
+
output.text Report.classification, :align => :center
|
21
|
+
output.text "\n"
|
22
|
+
|
23
|
+
output.font_size(22) { output.text Report.title, :align => :center }
|
24
|
+
output.font_size(18) {
|
25
|
+
output.text "Missing Microsoft Patch Summary", :align => :center
|
26
|
+
output.text "\n"
|
27
|
+
output.text "This report was prepared by\n#{Report.author}", :align => :center
|
28
|
+
}
|
29
|
+
|
30
|
+
output.text "\n\n\n"
|
31
|
+
|
32
|
+
Item.ms_patches.each do |item|
|
33
|
+
host = Host.find_by_id(item.host_id)
|
34
|
+
|
35
|
+
if host == nil
|
36
|
+
next
|
37
|
+
end
|
38
|
+
|
39
|
+
if host.name != nil
|
40
|
+
output.text "Host:", :style => :bold
|
41
|
+
output.text host.name
|
42
|
+
end
|
43
|
+
|
44
|
+
if host.os != nil
|
45
|
+
output.text "OS:", :style => :bold
|
46
|
+
output.text host.os
|
47
|
+
end
|
48
|
+
|
49
|
+
if host.mac != nil
|
50
|
+
output.text "Mac:", :style => :bold
|
51
|
+
output.text host.mac
|
52
|
+
end
|
53
|
+
output.text "\n"
|
54
|
+
output.text item.plugin_output
|
55
|
+
output.text "\n"
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
33
60
|
end
|
34
|
-
text "\n"
|
35
|
-
text item.plugin_output
|
36
|
-
text "\n"
|
37
61
|
end
|
@@ -1,43 +1,67 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Risu
|
2
|
+
module Modules
|
3
|
+
class MSUpdateSummary < Risu::Base::TemplateBase
|
4
|
+
|
5
|
+
#
|
6
|
+
#
|
7
|
+
def initialize ()
|
8
|
+
@template_info =
|
9
|
+
{
|
10
|
+
:name => "ms_update_summary",
|
11
|
+
:author => "hammackj",
|
12
|
+
:version => "0.0.1",
|
13
|
+
:description => "Generates a Microsoft Update Summary Report"
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
#
|
19
|
+
def render(output)
|
20
|
+
output.text Report.classification, :align => :center
|
21
|
+
output.text "\n"
|
3
22
|
|
4
|
-
font_size(22) { text Report.title, :align => :center }
|
5
|
-
font_size(18) {
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
}
|
23
|
+
output.font_size(22) { output.text Report.title, :align => :center }
|
24
|
+
output.font_size(18) {
|
25
|
+
output.text "Microsoft Update Summary", :align => :center
|
26
|
+
output.text "\n"
|
27
|
+
output.text "This report was prepared by\n#{Report.author}", :align => :center
|
28
|
+
}
|
10
29
|
|
11
|
-
text "\n\n\n"
|
30
|
+
output.text "\n\n\n"
|
12
31
|
|
13
|
-
font_size(12)
|
32
|
+
output.font_size(12)
|
14
33
|
|
15
|
-
results = Array.new
|
34
|
+
results = Array.new
|
16
35
|
|
17
|
-
headers = ["Hostname","Operating System", "Windows Update Status"]
|
18
|
-
header_widths = {0 => 108, 1 => 264, 2 => 140}
|
36
|
+
headers = ["Hostname","Operating System", "Windows Update Status"]
|
37
|
+
header_widths = {0 => 108, 1 => 264, 2 => 140}
|
19
38
|
|
20
|
-
Item.ms_update.each do |item|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
if item.plugin_output =~ /'Automatic Updates' are disabled/
|
32
|
-
row.push("Disabled")
|
33
|
-
else
|
34
|
-
row.push("Enabled")
|
35
|
-
end
|
36
|
-
|
37
|
-
results.push(row)
|
38
|
-
end
|
39
|
+
Item.ms_update.each do |item|
|
40
|
+
host = Host.find_by_id(item.host_id)
|
41
|
+
|
42
|
+
if host == nil
|
43
|
+
next
|
44
|
+
end
|
45
|
+
|
46
|
+
row = Array.new
|
47
|
+
row.push(host.name)
|
48
|
+
row.push(host.os)
|
39
49
|
|
40
|
-
|
41
|
-
|
42
|
-
|
50
|
+
if item.plugin_output =~ /'Automatic Updates' are disabled/
|
51
|
+
row.push("Disabled")
|
52
|
+
else
|
53
|
+
row.push("Enabled")
|
54
|
+
end
|
55
|
+
|
56
|
+
results.push(row)
|
57
|
+
end
|
58
|
+
|
59
|
+
output.table([headers] + results, :header => true, :column_widths => header_widths, :row_colors => ['ffffff', '336699']) do
|
60
|
+
row(0).style(:font_style => :bold, :background_color => 'cccccc')
|
61
|
+
cells.borders = [:top, :bottom, :left, :right]
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
43
67
|
end
|
@@ -1,66 +1,90 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
text "
|
22
|
-
|
23
|
-
text
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
1
|
+
module Risu
|
2
|
+
module Modules
|
3
|
+
class PCICompliance < Risu::Base::TemplateBase
|
4
|
+
|
5
|
+
#
|
6
|
+
#
|
7
|
+
def initialize ()
|
8
|
+
@template_info =
|
9
|
+
{
|
10
|
+
:name => "pci_compliance",
|
11
|
+
:author => "hammackj",
|
12
|
+
:version => "0.0.1",
|
13
|
+
:description => "Generates a PCI Compliance Overview Report"
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
#
|
19
|
+
def render(output)
|
20
|
+
output.text Report.classification, :align => :center
|
21
|
+
output.text "\n"
|
22
|
+
|
23
|
+
output.font_size(22) { output.text Report.title, :align => :center }
|
24
|
+
output.font_size(18) {
|
25
|
+
output.text "PCI /DSS Complience Overview", :align => :center
|
26
|
+
output.text "\n"
|
27
|
+
output.text "This report was prepared by\n#{Report.author}", :align => :center
|
28
|
+
}
|
29
|
+
|
30
|
+
output.text "\n\n\n"
|
31
|
+
|
32
|
+
@hosts_count = Host.find(:all, :conditions => ["pci_dss_compliance is not null"]).count
|
33
|
+
@hosts_passed = Host.find(:all, :conditions => ["pci_dss_compliance like 'passed'"])
|
34
|
+
@hosts_failed = Host.find(:all, :conditions => ["pci_dss_compliance like 'failed'"])
|
35
|
+
|
36
|
+
output.font_size(20) {
|
37
|
+
output.text "Summary\n", :style => :bold
|
38
|
+
}
|
39
|
+
|
40
|
+
output.text "Of #{@hosts_count} total hosts, #{@hosts_passed.count} passed and #{@hosts_failed.count} failed."
|
41
|
+
|
42
|
+
output.text "\n\n"
|
43
|
+
|
44
|
+
if @hosts_passed.length > 0
|
45
|
+
output.font_size(20) {
|
46
|
+
output.fill_color "00FF00"
|
47
|
+
output.text "PCI / DSS Compliant Hosts", :style => :bold
|
48
|
+
output.fill_color "000000"
|
49
|
+
}
|
50
|
+
|
51
|
+
output.text "\n"
|
52
|
+
|
53
|
+
@hosts_passed.each do |host|
|
54
|
+
output.text "#{host.ip} / #{host.fqdn} - passed\n"
|
55
|
+
end unless @hosts_passed == nil
|
56
|
+
|
57
|
+
output.start_new_page
|
58
|
+
end
|
59
|
+
|
60
|
+
if @hosts_failed.length > 0
|
61
|
+
output.font_size(20) {
|
62
|
+
output.fill_color "FF0000"
|
63
|
+
output.text "Non PCI / DSS Compliant Hosts", :style => :bold
|
64
|
+
output.fill_color "000000"
|
65
|
+
}
|
66
|
+
|
67
|
+
output.text "\n"
|
68
|
+
|
69
|
+
@hosts_failed.each do |host|
|
70
|
+
host_id = host.id
|
71
|
+
plugin = Plugin.find(:first, :conditions => { :id => 33929 })
|
72
|
+
item = Item.find(:first, :conditions => { :host_id => host_id, :plugin_id => plugin.id })
|
73
|
+
|
74
|
+
output.text "#{host.ip} / #{host.fqdn} - failed\n", :style => :bold
|
75
|
+
output.text "Description:\n", :style => :bold
|
76
|
+
output.text "#{plugin.description}\n"
|
77
|
+
output.text "Plugin Output:\n", :style => :bold
|
78
|
+
output.text "#{item.plugin_output}\n"
|
79
|
+
|
80
|
+
output.text "\n"
|
81
|
+
|
82
|
+
end unless @hosts_failed == nil
|
83
|
+
|
84
|
+
output.start_new_page
|
85
|
+
end
|
40
86
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
text "Non PCI / DSS Compliant Hosts", :style => :bold
|
45
|
-
fill_color "000000"
|
46
|
-
}
|
47
|
-
|
48
|
-
text "\n"
|
49
|
-
|
50
|
-
@hosts_failed.each do |host|
|
51
|
-
host_id = host.id
|
52
|
-
plugin = Plugin.find(:first, :conditions => { :id => 33929 })
|
53
|
-
item = Item.find(:first, :conditions => { :host_id => host_id, :plugin_id => plugin.id })
|
54
|
-
|
55
|
-
text "#{host.ip} / #{host.fqdn} - failed\n", :style => :bold
|
56
|
-
text "Description:\n", :style => :bold
|
57
|
-
text "#{plugin.description}\n"
|
58
|
-
text "Plugin Output:\n", :style => :bold
|
59
|
-
text "#{item.plugin_output}\n"
|
60
|
-
|
61
|
-
text "\n"
|
62
|
-
|
63
|
-
end unless @hosts_failed == nil
|
64
|
-
|
65
|
-
start_new_page
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
66
90
|
end
|