risu 1.4.9 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/Gemfile.ci +18 -0
  2. data/LICENSE +3 -3
  3. data/NEWS.markdown +45 -0
  4. data/README.markdown +10 -2
  5. data/Rakefile +15 -5
  6. data/TODO.markdown +45 -19
  7. data/lib/risu.rb +2 -1
  8. data/lib/risu/base/schema.rb +3 -4
  9. data/lib/risu/base/template_base.rb +11 -11
  10. data/lib/risu/cli/application.rb +23 -15
  11. data/lib/risu/exceptions.rb +1 -3
  12. data/lib/risu/models/host.rb +1 -1
  13. data/lib/risu/models/item.rb +90 -18
  14. data/lib/risu/models/plugin.rb +2 -2
  15. data/lib/risu/models/reference.rb +93 -0
  16. data/lib/risu/parsers/nessus/nessus_sax_listener.rb +28 -30
  17. data/lib/risu/renderers.rb +6 -0
  18. data/lib/risu/renderers/nilrenderer.rb +25 -0
  19. data/lib/risu/templates/assets.rb +5 -2
  20. data/lib/risu/templates/cover_sheet.rb +1 -1
  21. data/lib/risu/templates/exec_summary.rb +19 -4
  22. data/lib/risu/templates/executive_summary.rb +20 -5
  23. data/lib/risu/templates/finding_statistics.rb +1 -1
  24. data/lib/risu/templates/findings_host.rb +27 -8
  25. data/lib/risu/templates/findings_summary.rb +14 -1
  26. data/lib/risu/templates/findings_summary_with_pluginid.rb +1 -1
  27. data/lib/risu/templates/graphs.rb +5 -1
  28. data/lib/risu/templates/host_summary.rb +8 -4
  29. data/lib/risu/templates/ms_patch_summary.rb +1 -1
  30. data/lib/risu/templates/ms_update_summary.rb +1 -1
  31. data/lib/risu/templates/notable.rb +1 -2
  32. data/lib/risu/templates/notable_detailed.rb +8 -8
  33. data/lib/risu/templates/pci_compliance.rb +1 -1
  34. data/lib/risu/templates/stig_findings_summary.rb +135 -0
  35. data/lib/risu/templates/technical_findings.rb +5 -17
  36. data/lib/risu/templates/template.rb +1 -1
  37. data/risu.gemspec +1 -2
  38. metadata +43 -28
@@ -0,0 +1,6 @@
1
+ module Risu
2
+ module Renderers
3
+ end
4
+ end
5
+
6
+ require 'risu/renderers/nilrenderer'
@@ -0,0 +1,25 @@
1
+ module Risu
2
+ module Renderers
3
+ class NilRenderer
4
+
5
+ #
6
+ #
7
+ def text text, *args
8
+ true
9
+ end
10
+
11
+ #
12
+ #
13
+ def font_size x
14
+ true
15
+ end
16
+
17
+ #
18
+ #
19
+ def start_new_page
20
+ true
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -1,6 +1,6 @@
1
1
  module Risu
2
- module Modules
3
- class Assests < Risu::Base::TemplateBase
2
+ module Templates
3
+ class Assets < Risu::Base::TemplateBase
4
4
 
5
5
  #
6
6
  #
@@ -14,9 +14,12 @@ module Risu
14
14
  }
15
15
  end
16
16
 
17
+ #undef :render if method_defined? :render
17
18
  #
18
19
  #
19
20
  def render(output)
21
+ output.font_size 10
22
+
20
23
  output.text Report.classification.upcase, :align => :center
21
24
  output.text "\n"
22
25
 
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class CoverSheet < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class ExecSummary < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -40,13 +40,27 @@ module Risu
40
40
 
41
41
  output.text "A total of #{Host.count} hosts were found and scanned for vulnerabities.\n\n"
42
42
 
43
- output.text "There were #{Item.risks.count} vulnerabilities found during this scan. Of these, #{Item.high_risks.count} were high vulnerabilities, #{Item.medium_risks.count} were medium vulnerabilities, #{Item.low_risks.count} were low vulnerabilities and #{Item.info_risks.count} were information findings.\n\n"
43
+ output.text "There were #{Item.risks.count} vulnerabilities found during this scan. Of these, #{Item.critical_risks.count} were critical vulnerabilities,#{Item.high_risks.count} were high vulnerabilities, #{Item.medium_risks.count} were medium vulnerabilities, #{Item.low_risks.count} were low vulnerabilities and #{Item.info_risks.count} were information findings.\n\n"
44
44
 
45
45
  output.text "Scan Statistics", :style => :bold
46
46
  output.text "\n"
47
47
 
48
- output.table([["Number of hosts","Number of risks","High Risks", "Medium Risks", "Low Risks", "Info Risks"],
49
- [Host.count, Item.risks.count, Item.high_risks.count, Item.medium_risks.count, Item.low_risks.count, Item.info_risks.count]],
48
+ output.table([[
49
+ "Number of hosts",
50
+ "Number of risks",
51
+ "Critical Risks",
52
+ "High Risks",
53
+ "Medium Risks",
54
+ "Low Risks",
55
+ "Info Risks"],
56
+ [
57
+ Host.count,
58
+ Item.risks.count,
59
+ Item.critical_risks.count,
60
+ Item.high_risks.count,
61
+ Item.medium_risks.count,
62
+ Item.low_risks.count,
63
+ Item.info_risks.count]],
50
64
  :cell_style => { :padding =>12 }, :width => output.bounds.width)
51
65
  output.text "\n\n\n"
52
66
 
@@ -72,6 +86,7 @@ module Risu
72
86
  cury = output.y
73
87
  #move_down 550
74
88
  output.image Host.windows_os_graph, :width => 250, :at => [output.bounds.left, cury]
89
+ output.image Item.stigs_severity_graph, :width => 250, :at => [output.bounds.right - 250, cury]
75
90
  end
76
91
  end
77
92
  end
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class ExecutiveSummaryDetailed < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -9,7 +9,7 @@ module Risu
9
9
  {
10
10
  :name => "exec_summary_detailed",
11
11
  :author => "Ed Davison <EDavison@getmns.com>",
12
- :version => "0.0.2",
12
+ :version => "0.0.3",
13
13
  :description => "Generates a detailed executive summary report"
14
14
  }
15
15
  end
@@ -61,8 +61,22 @@ module Risu
61
61
  output.text "Scan Statistics", :style => :bold
62
62
  output.text "\n"
63
63
 
64
- headers = ["Number of hosts","Number of risks","High Risks", "Medium Risks", "Low Risks", "Info Risks"]
65
- data = [[Host.count, Item.risks.count, Item.high_risks.count, Item.medium_risks.count, Item.low_risks.count, Item.info_risks.count]]
64
+ headers = [
65
+ "Number of hosts",
66
+ "Number of risks",
67
+ "Critical Risks",
68
+ "High Risks",
69
+ "Medium Risks",
70
+ "Low Risks",
71
+ "Info Risks"]
72
+ data = [[
73
+ Host.count,
74
+ Item.risks.count,
75
+ Item.critical_risks.count,
76
+ Item.high_risks.count,
77
+ Item.medium_risks.count,
78
+ Item.low_risks.count,
79
+ Item.info_risks.count]]
66
80
 
67
81
  output.table([headers] + data, :header => true, :row_colors => ['ffffff', 'f0f0f0']) do
68
82
  row(0).style(:font_style => :bold, :background_color => 'cccccc')
@@ -77,12 +91,13 @@ module Risu
77
91
  output.text "There were #{Item.risks.count} risks found during this scan. Of these, #{Item.high_risks.count} were High risk vulnerabilities. High risk vulnerabilities require immediate attention to handle as they are relatively easy for attackers to exploit frequently resulting in full access to affected systems. There were #{Item.medium_risks.count} findings which were Medium risk. High risk vulnerabilities are harder to exploit and may not result in full control of the affected system and should be addressed rapidly and with priority. There were #{Item.low_risks.count} findings which were Low risk vulnerabilities. These risks usually let attackers gain information about your network making it easier for launching more advanced attacks and should be handled in a timely manner. And #{Item.info_risks.count} findings which were information findings.\n"
78
92
  output.text "\n"
79
93
 
94
+ crit_host_count = Item.where(:severity => 4).group(:host_id).all.count
80
95
  high_host_count = Item.where(:severity => 3).group(:host_id).all.count
81
96
  medium_host_count = Item.where(:severity => 2).group(:host_id).all.count
82
97
  low_host_count = Item.where(:severity => 1).group(:host_id).all.count
83
98
  info_host_count = Item.where(:severity => 0).group(:host_id).all.count
84
99
 
85
- output.text "There were #{high_host_count} hosts with High risk vulnerabilities, #{medium_host_count} hosts with Medium risk vulnerabilities, #{low_host_count} hosts with Low risk vulnerabilities and #{info_host_count} hosts with information findings."
100
+ output.text "There were #{crit_host_count} hosts with Critical risk vulnerabilities, #{high_host_count} hosts with High risk vulnerabilities, #{medium_host_count} hosts with Medium risk vulnerabilities, #{low_host_count} hosts with Low risk vulnerabilities and #{info_host_count} hosts with information findings."
86
101
  output.text "\n"
87
102
 
88
103
  output.text "The following output.table shows the top 5 vulnerabilities that were found. These are the most important vulnerabilities to address as they represent a sizeable footprint for an attacker to exploit in an attempt to compromise.\n"
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class FindingStatistics < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class FindingsHost < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -9,7 +9,7 @@ module Risu
9
9
  {
10
10
  :name => "findings_host",
11
11
  :author => "hammackj",
12
- :version => "0.0.1",
12
+ :version => "0.0.2",
13
13
  :description => "Generates a findings report by host"
14
14
  }
15
15
  end
@@ -17,12 +17,14 @@ module Risu
17
17
  #
18
18
  #
19
19
  def render(output)
20
+ output.font_size 10
21
+
20
22
  output.text Report.classification.upcase, :align => :center
21
23
  output.text "\n"
22
24
 
23
25
  output.font_size(22) { output.text Report.title, :align => :center }
24
26
  output.font_size(18) {
25
- output.text "Findings Summary Report", :align => :center
27
+ output.text "Findings Summary by Host Report", :align => :center
26
28
  output.text "\n"
27
29
  output.text "This report was prepared by\n#{Report.author}", :align => :center
28
30
  }
@@ -31,13 +33,30 @@ module Risu
31
33
 
32
34
  Host.sorted.each do |host|
33
35
  if host.items.high_risks_unique_sorted.all.size > 0 or host.items.medium_risks_unique_sorted.all.size > 0
34
- output.font_size(20) {
35
- output.text "#{host.ip} - #{host.fqdn}", :style => :bold
36
- }
36
+ output.font_size(16) do
37
+
38
+ host_string = "#{host.ip}"
39
+ host_string << " (#{host.fqdn})" if host.fqdn != nil
40
+
41
+ output.text "#{host_string}", :style => :bold
42
+ end
43
+ end
44
+
45
+ if host.items.critical_risks_unique_sorted.all.size > 0
46
+ output.font_size(12) do
47
+ output.fill_color "551A8B"
48
+ output.text "Critical Findings", :style => :bold
49
+ output.fill_color "000000"
50
+ end
51
+
52
+ host.items.high_risks_unique_sorted.each do |item|
53
+ name = Plugin.find_by_id(item.plugin_id).plugin_name
54
+ output.text "#{name}"
55
+ end
37
56
  end
38
57
 
39
58
  if host.items.high_risks_unique_sorted.all.size > 0
40
- output.font_size(18) {
59
+ output.font_size(12) {
41
60
  output.fill_color "FF0000"
42
61
  output.text "High Findings", :style => :bold
43
62
  output.fill_color "000000"
@@ -50,7 +69,7 @@ module Risu
50
69
  end
51
70
 
52
71
  if host.items.medium_risks_unique_sorted.all.size > 0
53
- output.font_size(18) {
72
+ output.font_size(12) {
54
73
  output.fill_color "FF8040"
55
74
  output.text "Medium Findings", :style => :bold
56
75
  output.fill_color "000000"
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class FindingsSummary < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -32,6 +32,19 @@ module Risu
32
32
 
33
33
  output.text "\n\n\n"
34
34
 
35
+ output.font_size(20) do
36
+ output.fill_color "551A8B"
37
+ output.text "Critical Findings", :style => :bold
38
+ output.fill_color "000000"
39
+ end
40
+
41
+ Item.critical_risks_unique_sorted.each do |item|
42
+ name = Plugin.find_by_id(item.plugin_id).plugin_name
43
+ count = Item.where(:plugin_id => item.plugin_id).count
44
+
45
+ output.text "#{count} - #{name}"
46
+ end
47
+
35
48
  output.font_size(20) do
36
49
  output.fill_color "FF0000"
37
50
  output.text "High Findings", :style => :bold
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class FindingsSummaryWithPluginID < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class Graphs < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -54,6 +54,10 @@ module Risu
54
54
  output.start_new_page
55
55
 
56
56
  output.image Host.windows_os_graph, :width => 500, :height => 375, :position => :center
57
+
58
+ output.start_new_page
59
+
60
+ output.image Item.stigs_severity_graph, :width => 500, :height => 375, :position => :center
57
61
  end
58
62
  end
59
63
  end
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class HostSummary < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -9,7 +9,7 @@ module Risu
9
9
  {
10
10
  :name => "host_summary",
11
11
  :author => "hammackj",
12
- :version => "0.0.1",
12
+ :version => "0.0.2",
13
13
  :description => "Generates a Host Summary Report"
14
14
  }
15
15
  end
@@ -31,13 +31,14 @@ module Risu
31
31
 
32
32
  results = Array.new
33
33
 
34
- headers = ["Hostname", "Total", "High", "Medium", "Low", "Info"]
35
- header_widths = {0 => 137, 1 => 75, 2 => 75, 3 => 75, 4 => 75, 5 => 75}
34
+ headers = ["Hostname", "Total", "Critical", "High", "Medium", "Low", "Info"]
35
+ header_widths = {0 => 140, 1 => 62, 2 => 62, 3 => 62, 4 => 62, 5 => 62, 6 => 62}
36
36
 
37
37
  Host.sorted.each do |host|
38
38
  row = Array.new
39
39
 
40
40
  total = Item.risks.where(:host_id => host.id).count
41
+ crit = Item.critical_risks.where(:host_id => host.id).count
41
42
  high = Item.high_risks.where(:host_id => host.id).count
42
43
  medium = Item.medium_risks.where(:host_id => host.id).count
43
44
  low = Item.low_risks.where(:host_id => host.id).count
@@ -45,6 +46,7 @@ module Risu
45
46
 
46
47
  row.push(host.name)
47
48
  row.push(total)
49
+ row.push(crit)
48
50
  row.push(high)
49
51
  row.push(medium)
50
52
  row.push(low)
@@ -57,6 +59,8 @@ module Risu
57
59
  row(0).style(:font_style => :bold, :background_color => 'D0D0D0')
58
60
  cells.borders = [:top, :bottom, :left, :right]
59
61
  end
62
+
63
+ output.number_pages "<page> of <total>", :at => [output.bounds.right - 75, 0], :width => 150, :page_filter => :all
60
64
  end
61
65
  end
62
66
  end
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class MSPatchSummary < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class MSUpdateSummary < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class Top10 < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -42,4 +42,3 @@ module Risu
42
42
  end
43
43
  end
44
44
  end
45
-
@@ -1,6 +1,6 @@
1
1
  module Risu
2
- module Modules
3
- class Top10Detailed < Risu::Base::TemplateBase
2
+ module Templates
3
+ class NotableDetailed < Risu::Base::TemplateBase
4
4
 
5
5
  #
6
6
  #
@@ -9,7 +9,7 @@ module Risu
9
9
  {
10
10
  :name => "notable_detailed",
11
11
  :author => "hammackj",
12
- :version => "0.0.3",
12
+ :version => "0.0.4",
13
13
  :description => "Notable Vulnerabilities Detailed"
14
14
  }
15
15
  end
@@ -20,15 +20,15 @@ module Risu
20
20
  output.text Report.classification.upcase, :align => :center
21
21
  output.text "\n"
22
22
 
23
- output.font_size(22) {
23
+ output.font_size(22) do
24
24
  output.text Report.title, :align => :center
25
- }
25
+ end
26
26
 
27
- output.font_size(18) {
27
+ output.font_size(18) do
28
28
  output.text "Notable Vulnerabilities", :align => :center
29
29
  output.text "\n"
30
30
  output.text "This report was prepared by\n#{Report.author}", :align => :center
31
- }
31
+ end
32
32
 
33
33
  output.text "\n\n\n"
34
34
 
@@ -41,7 +41,7 @@ module Risu
41
41
  data = Item.top_10_sorted_raw
42
42
 
43
43
  unique_risks = Array.new
44
- unique_risks << Hash[:title => "High Findings", :color => "FF0000", :values => Item.top_10_sorted_raw[0..9]]
44
+ unique_risks << Hash[:title => "Notable Findings", :color => "9B30FF", :values => Item.top_10_sorted_raw[0..9]]
45
45
  counter = 1
46
46
 
47
47
  unique_risks.each do |h|
@@ -1,5 +1,5 @@
1
1
  module Risu
2
- module Modules
2
+ module Templates
3
3
  class PCICompliance < Risu::Base::TemplateBase
4
4
 
5
5
  #
@@ -0,0 +1,135 @@
1
+ module Risu
2
+ module Templates
3
+ class StigFindingsSummary < Risu::Base::TemplateBase
4
+
5
+ # Initializes the template loading metadata
6
+ #
7
+ def initialize ()
8
+ @template_info =
9
+ {
10
+ :name => "stig_findings_summary",
11
+ :author => "hammackj",
12
+ :version => "0.0.1",
13
+ :description => "DISA Stig findings summary report"
14
+ }
15
+
16
+ @output = nil
17
+ end
18
+
19
+ #
20
+ #
21
+ def header
22
+ @output.text Report.classification.upcase, :align => :center
23
+ @output.text "\n"
24
+
25
+ @output.font_size(22) do
26
+ @output.text Report.title, :align => :center
27
+ end
28
+
29
+ @output.font_size(18) do
30
+ @output.text "Stig Findings Summary", :align => :center
31
+ @output.text "\n"
32
+ @output.text "This report was prepared by\n#{Report.author}", :align => :center
33
+ end
34
+
35
+ @output.text "\n\n\n"
36
+ end
37
+
38
+ # Creates a list of hosts from an list of Items
39
+ #
40
+ # @param items
41
+ def host_list_from_plugin_id(plugin_id)
42
+ Host.where('id IN (:hosts)', :hosts => Item.where(:plugin_id => plugin_id).select(:host_id).select('host_id AS id'))
43
+ end
44
+
45
+ def host_list_text(hosts)
46
+ host_string = ""
47
+ hosts.all.each do |host|
48
+ host_string << "#{host.ip}"
49
+ host_string << " (#{host.netbios})" if host.netbios
50
+ host_string << ", "
51
+ end
52
+
53
+ return host_string.chomp!(", ")
54
+ end
55
+
56
+ # Generates stig finding text for
57
+ #
58
+ # @param categeory I/II/III for each stig severity
59
+ def stig_findings_text(categeory="I")
60
+ if categeory != "I" || categeory != "II" || categeory != "III"
61
+ return
62
+ end
63
+
64
+ stigs = Item.stig_findings(categeory).group(:plugin_id)
65
+
66
+ stigs.each do |stig|
67
+ @output.text "#{stig.plugin_name}", :size => 16
68
+ hosts = host_list_from_plugin_id(stig.plugin_id)
69
+ hosts_string = host_list_text(hosts)
70
+
71
+ if hosts.count > 1
72
+ @output.text "<b>Hosts</b>: #{hosts_string}", :inline_format => true
73
+ else
74
+ @output.text "<b>Host</b>: #{hosts_string}", :inline_format => true
75
+ end
76
+
77
+ @output.text "<b>Risk</b>: #{stig.plugin.risk_factor}", :inline_format => true
78
+ @output.text "<b>CVE Reference</b>: #{ref_string(stig.plugin.references.cve)}", :inline_format => true
79
+ @output.text "<b>IAVA Reference</b>: #{ref_string(stig.plugin.references.iava)}", :inline_format => true
80
+
81
+ if stig.plugin.description != nil
82
+ @output.text "\nDescription:", :style => :bold
83
+ @output.text stig.plugin.description
84
+ end
85
+
86
+ @output.text "\n"
87
+ end
88
+ end
89
+
90
+ #
91
+ #
92
+ def ref_string ref
93
+ return "" if ref == nil
94
+
95
+ ref_string = ""
96
+ ref.each do |r|
97
+ ref_string << r.value + ", "
98
+ end
99
+
100
+ ref_string.chomp!(", ")
101
+ end
102
+
103
+ # Called during the rendering process
104
+ #
105
+ def render(output)
106
+ @output = output
107
+
108
+ @output.font_size 10
109
+
110
+ header
111
+
112
+ if Item.stig_findings("I").count > 0
113
+ @output.text "<color rgb='551A8B'>Category I Findings</color>", :size => 18, :style => :bold, :inline_format => true
114
+ stig_findings_text("I")
115
+ end
116
+
117
+ if Item.stig_findings("II").count > 0
118
+ @output.start_new_page
119
+ @output.text "<color rgb='FF0000'>Category II Findings</color>", :size => 18, :style => :bold, :inline_format => true
120
+ stig_findings_text("II")
121
+ end
122
+
123
+ if Item.stig_findings("III").count > 0
124
+ @output.start_new_page
125
+ @output.text "<color rgb='FF8040'>Category III Findings</color>", :size => 18, :style => :bold, :inline_format => true
126
+ stig_findings_text("III")
127
+ end
128
+
129
+ @output.number_pages "<page> of <total>", :at => [@output.bounds.right - 75, 0], :width => 150, :page_filter => :all
130
+
131
+ end
132
+ end
133
+ end
134
+ end
135
+