'
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 = '
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,'blue']])
else
pie_data = []
pie_data << ['Low',values[:low].to_i,'green'] if @options[:severity] <= 1 and values[:low].to_i > 0
pie_data << ['Medium',values[:med].to_i,'orange'] if @options[:severity] <= 2 and values[:med].to_i > 0
pie_data << ['High',values[:high].to_i,'red'] if @options[:severity] <= 3 and values[:high].to_i > 0
pie_data << ['Critical',values[:crit].to_i,'purple'] if @options[:severity] <= 4 and values[:crit].to_i > 0
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 += '
Vulnerabilities
'
if @options[:severity] <= 4 and values[:crit].to_i > 0
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 and values[:high].to_i > 0
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 and values[:med].to_i > 0
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 and values[:low].to_i > 0
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 and values[:info].to_i > 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({
credits: {
enabled: false
},
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,
allowDecimals: false,
title: {
text: 'Findings'
}
},
legend: {
backgroundColor: '#FFFFFF',
reversed: true
},
tooltip: {
formatter: function() {
return ''+
this.series.name +': '+ this.y +'';
}
},
plotOptions: {
series: {
stacking: 'normal',
//threshold: 1,
dataLabels: {
enabled: true,
color: '#000000',
x: 0,
align: 'center',
formatter: function() {
if (this.y !=0) {
return this.y;
}
}
},
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({
credits: {
enabled: false
},
chart: {
renderTo: '#{renderto}',
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false
},
title: {
text: '#{title}'
},
tooltip: {
formatter: function() {
return ''+ this.point.name +': '+ Math.round(this.percentage) +' %';
}
},
plotOptions: {
pie: {
size: '60%',
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
color: '#000000',
connectorColor: '#000000',
formatter: function() {
return ''+ this.point.name +': '+ this.y;
},
distance: 20
}
eos
unless 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{name: '" + val[0] + "', y: " + val[1].to_s + ", color: '" + val[2] + "'}"
tmpline += "," unless index == series.length - 1
fp.puts tmpline
end
fp.puts <<-eos
]
}]
});
});
});
eos
end
end
end end