'
body += ''
body_text(f,body)
close_all(f)
end
end
#
# Generates the various vuln_*.html files, outputting them to the nominated output directory
# @see @options[:output]
#
# @return
# Returns nothing
#
# @example
# print_vulns
#
def print_vulns
@events.each do |id,values|
next if values[:severity].to_i < @options[:severity].to_i
File.open(@options[:output] + "/vuln_" + id.to_s + ".html", 'w') do |f|
html_header(f,id.to_s)
close_html_header(f)
body = '
Nessus ID: ' + id.to_s + '
Name: ' + values[:plugin_name] + '
Severity: ' + values[:severity].to_s + '
Family: ' + values[:family] + '
Ports: '
impacted_hosts = []
values[:ports].each_with_index {|(k,v),index|
body += k.to_s
v[:hosts].each do |h,w|
impacted_hosts << h
end
body += ", " unless index == values[:ports].length - 1
}
body += '
Synopsis:
' + values[:synopsis] + '
Description:
' + values[:description] + '
Solution:
' + values[:solution] + '
See Also:
'
values[:see_also].each do |val|
val.split("\n").each do |val2|
body += '
' + val2 + ''
end
end
body +='
CVE: ' + values[:cve].to_s + '
CVSS Base Score: ' + values[:cvss_base_score].to_s + '
CVSS Vector: ' + values[:cvss_vector].to_s + '
'
body += '
Hosts
'
body += '
Host IP | Hostname | OS | Port | Result |
'
impacted_hosts.uniq.each do |host|
values[:ports].each{|k,v|
v[:hosts].each do |h,w|
if h == host
body += '' + @hosts[host][:ip] + ' | ' + @hosts[host][:hostname] + ' | ' + @hosts[host][:os] + ' | '
body += '' + k.to_s + ' | ' + w.to_s.gsub(/<\/?[^>]*>/, "").gsub("\n"," \n") + " |
\n"
end
end
}
end
body += '
'
body += ''
body_text(f,body)
close_all(f)
end
end
end
#
# Generates the various host_*.html files, outputting them to the nominated output directory
# @see @options[:output]
#
# @return
# Returns nothing
#
# @example
# print_hosts
#
def print_hosts
@hosts.each do |id,values|
File.open(@options[:output] + "/host_" + id.to_s + ".html", 'w') do |f|
html_header(f,values[:ip])
if values[:total_excl_info] == 0
pie_js(f,"pie_graph","Criticality Breakdown","Criticality Breakdown",[['Informational ONLY',values[:info].to_i]])
else
pie_data = []
pie_data << ['Low',values[:low].to_i] if @options[:severity] <= 1
pie_data << ['Medium',values[:med].to_i] if @options[:severity] <= 2
pie_data << ['High',values[:high].to_i] if @options[:severity] <= 3
pie_data << ['Critical',values[:crit].to_i] if @options[:severity] <= 4
pie_js(f,"pie_graph","Criticality Breakdown","Criticality Breakdown",pie_data,"document.location.href = '#' + event.point.name;")
end
close_html_header(f)
body = '
HomeHostname: ' + values[:hostname] + '
IP: ' + values[:ip] + '
OS: ' + values[:os] + '
'
body += '
Overview
'
body += '
'
body += '
'
body += '
Vulns
'
if @options[:severity] <= 4
body += '
Critical
'
body += '
Nessus ID | Name | Synopsis | Result | Family | Port |
'
@events.sort_by{|k,v| v[:port].to_s}.each do |vuln_id,vuln_data|
vuln_data[:ports].each {|k,v|
v[:hosts].each do |h,v2|
if h == id and vuln_data[:severity] == 4
body += '' + vuln_id.to_s + ' | ' + vuln_data[:plugin_name] + ' | ' + vuln_data[:synopsis] + ' | ' + v2.to_s.gsub(/<\/?[^>]*>/, "").gsub("\n"," ") + ' | ' + vuln_data[:family] + ' | ' + k.to_s + ' |
'
end
end
}
end
body += '
'
end
if @options[:severity] <= 3
body += '
High
'
body += '
Nessus ID | Name | Synopsis | Result | Family | Port |
'
@events.sort_by{|k,v| v[:port].to_s}.each do |vuln_id,vuln_data|
vuln_data[:ports].each {|k,v|
v[:hosts].each do |h,v2|
if h == id and vuln_data[:severity] == 3
body += '' + vuln_id.to_s + ' | ' + vuln_data[:plugin_name] + ' | ' + vuln_data[:synopsis] + ' | ' + v2.to_s.gsub(/<\/?[^>]*>/, "").gsub("\n"," ") + ' | ' + vuln_data[:family] + ' | ' + k.to_s + ' |
'
end
end
}
end
body += '
'
end
if @options[:severity] <= 2
body += '
Medium
'
body += '
Nessus ID | Name | Synopsis | Result | Family | Port |
'
@events.sort_by{|k,v| v[:port].to_s}.each do |vuln_id,vuln_data|
vuln_data[:ports].each {|k,v|
v[:hosts].each do |h,v2|
if h == id and vuln_data[:severity] == 2
body += '' + vuln_id.to_s + ' | ' + vuln_data[:plugin_name] + ' | ' + vuln_data[:synopsis] + ' | ' + v2.to_s.gsub(/<\/?[^>]*>/, "").gsub("\n"," ") + ' | ' + vuln_data[:family] + ' | ' + k.to_s + ' |
'
end
end
}
end
body += '
'
end
if @options[:severity] <= 1
body += '
Low
'
body += '
Nessus ID | Name | Synopsis | Result | Family | Port |
'
@events.sort_by{|k,v| v[:port].to_s}.each do |vuln_id,vuln_data|
vuln_data[:ports].each {|k,v|
v[:hosts].each do |h,v2|
if h == id and vuln_data[:severity] == 1
body += '' + vuln_id.to_s + ' | ' + vuln_data[:plugin_name] + ' | ' + vuln_data[:synopsis] + ' | ' + v2.to_s.gsub(/<\/?[^>]*>/, "").gsub("\n"," ") + ' | ' + vuln_data[:family] + ' | ' + k.to_s + ' |
'
end
end
}
end
body += '
'
end
if @options[:severity] <= 0
body += '
'
end
body += ""
body += '
'
body_text(f,body)
close_all(f)
end
end
end
#
# Prints the universal HTML header into the nominated output file
#
# @return
# Returns nothing
#
# @input
# fp - the file pointer (which should be opened already by the calling method) which this method prints its output into
# title - the title field which is printed as the HTML title
#
# @example
# File.open(@options[:output] + "/file.html", 'w') do |f|
# html_header(f,"Title")
# end
#
def html_header(fp,title)
fp.puts <<-eos
#{title}
eos
end
#
# Prints out miscellanrous HTML text into the nominated output file
#
# @return
# Returns nothing
#
# @input
# fp - the file pointer (which should be opened already by the calling method) which this method prints its output into
# text - the text to print out to the output file
#
# @example
# File.open(@options[:output] + "/file.html",'w') do |f|
# tmpline = "Sometext
"
# tmpline += "Some more text here
"
# body_text(f,tmpline)
# end
#
def body_text(fp,text)
fp.puts text
end
#
# Closes out the HTML of the page in the nominated output file
#
# @return
# Returns nothing
#
# @input
# fp - the file pointer (which should be opened already by the calling method) which this method prints its output into
#
# @example
# @see html_header's @example
#
def close_all(fp)
fp.puts <<-eos
eos
end
#
# Prints the Highcharts javascript for a bar graph into the nominated output file
#
# @return
# Returns nothing
#
# @input
# fp - the file pointer (which should be opened already by the calling method) which this method prints its output into
# renderto - the highchart renderTo parameter (which is then referenced in the html's div id)
# title - the highchart's title
# data - a hash of hosts data @see Nessusin#import_nessus_files
#
# @example
# File.open(@options[:output] + "/file.html",'w') do |f|
# bar_js(f,"bargraph1","Some title",{0 => {:hostname => 'hostname',:ip => 'ip'}})
#
# body_text(f,"
")
# end
#
def bar_js(fp,renderto,title,data)
fp.puts <<-eos
$(function () {
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: '#{renderto}',
type: 'bar'
},
title: {
text: '#{title}'
},
xAxis: {
categories: [
eos
data.each_with_index do |entry,index|
tmpline = "'"
if entry[1][:hostname] == ""
tmpline += entry[1][:ip]
else
tmpline += entry[1][:hostname] + " (" + entry[1][:ip] + ")"
end
tmpline += "'"
tmpline += "," unless index == data.length - 1
fp.puts tmpline
end
fp.puts <<-eos
]
},
yAxis: {
min: 0,
title: {
text: 'Findings'
}
},
legend: {
backgroundColor: '#FFFFFF',
reversed: true
},
tooltip: {
formatter: function() {
return ''+
this.series.name +': '+ this.y +'';
}
},
plotOptions: {
series: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: '#000000',
x: 0,
align: 'center'
},
events: {
click: function(event) {
//alert(target_lookup[event.point.category])
document.location.href = 'host_' + target_lookup[event.point.category] + '.html#' + event.currentTarget.name;
//console.log(event)
}
}
}
},
series: [
eos
if @options[:severity] <= 4
fp.puts "{name: 'Critical',"
fp.puts "color: 'purple',"
tmpline = "data: ["
data.each_with_index do |entry,index|
tmpline += entry[1][:crit].to_s
tmpline += "," unless index == data.length - 1
end
tmpline += "]"
fp.puts tmpline
fp.puts "}"
end
if @options[:severity] <= 3
fp.puts ",{name: 'High',"
fp.puts "color: 'red',"
tmpline = "data: ["
data.each_with_index do |entry,index|
tmpline += entry[1][:high].to_s
tmpline += "," unless index == data.length - 1
end
tmpline += "]"
fp.puts tmpline
fp.puts "}"
end
if @options[:severity] <= 2
fp.puts ",{name: 'Medium',"
fp.puts "color: 'orange',"
tmpline = "data: ["
data.each_with_index do |entry,index|
tmpline += entry[1][:med].to_s
tmpline += "," unless index == data.length - 1
end
tmpline += "]"
fp.puts tmpline
fp.puts "}"
end
if @options[:severity] <= 1
fp.puts ",{name: 'Low',"
fp.puts "color: 'green',"
tmpline = "data: ["
data.each_with_index do |entry,index|
tmpline += entry[1][:low].to_s
tmpline += "," unless index == data.length - 1
end
tmpline += "]"
fp.puts tmpline
fp.puts "}"
end
fp.puts <<-eos
]
});
});
});
eos
end
#
# Prints the Highcharts javascript for a pie graph into the nominated output file
#
# @return
# Returns nothing
#
# @input
# fp - the file pointer (which should be opened already by the calling method) which this method prints its output into
# renderto - the highchart renderTo parameter (which is then referenced in the html's div id)
# title - the highchart's title
# seriesname - the highchart's series name
# series - an array of array's with pie piece names and values
# clickfunction - an optional string which is then used as the click event for a pie piece
#
# @example
# File.open(@options[:output] + "/file.html",'w') do |f|
# pie_js(f,"pie_graph","Vuln Breakdown","Vuln Breakdown",[['Low',2],['Medium',5],['High',3]],"document.location.href = 'vuln_overview.html#' + event.point.name;")
#
# body_text(f,"
")
# end
#
def pie_js(fp,renderto,title,seriesname,series,clickfunction = nil)
fp.puts <<-eos
$(function () {
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: '#{renderto}',
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false
},
title: {
text: '#{title}'
},
tooltip: {
formatter: function() {
return ''+ this.point.name +': '+ this.percentage +' %';
}
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
color: '#000000',
connectorColor: '#000000',
formatter: function() {
return ''+ this.point.name +': '+ this.y;
}
}
eos
if not clickfunction.nil?
fp.puts ',events: { click: function(event) { ' + clickfunction + '} }'
end
fp.puts <<-eos
}
},
series: [{
type: 'pie',
name: '#{seriesname}',
data: [
eos
series.each_with_index do |val,index|
tmpline = "\t\t\t['" + val[0] + "'," + val[1].to_s + "]"
tmpline += "," unless index == series.length - 1
fp.puts tmpline
end
fp.puts <<-eos
]
}]
});
});
});
eos
end
end
end end