· 7 years ago · Jan 07, 2019, 07:34 PM
1#!/usr/bin/ruby
2#parse-nessus -v1
3#Royce Davis - Straight Cash Homie!
4require 'rubygems'
5require 'ruby-nessus'
6
7#Make sure Command Line Arguments are present
8unless ARGV.length > 0
9 puts "PoC Nessus Parsing script...\r\n"
10 puts "USAGE ./parse-nessus.rb <.nessus-file> <output.html>\r\n\r\n"
11 exit!
12end
13
14#Define the layout of findings
15class Finding
16 #All getter & setter mtehods for the Finding class
17 attr_accessor :plugin_id, :title, :description, :solution, :rating, :hosts, :host_count, :links, :output
18
19 #When a new instance of the Finding class is instantiated
20 #a host object and an event option is passed to the funciton call
21 #The folowing peramaters of the host & event object are used to create the values
22 #of the Finding object
23 def initialize(host, event)
24 @hosts = Array.new
25 @host_count = 1
26 @plugin_id = event.plugin_id
27 @title = event.synopsis
28 @description = event.description
29 @solution = event.solution
30 @rating = event.severity.in_words
31 @host_count = @host_count + 1
32 @links = event.see_also
33 @output = event.output
34 new_host_name = host.name
35 new_host_ip = host.ip
36 if host.name
37 add_host = new_host_name.to_s + "+" + new_host_ip.to_s
38 else
39 add_host = " " + "+" + new_host_ip.to_s
40 end
41 @hosts.push(add_host)
42 end
43end
44
45
46nessus = ARGV[0] #.nessus file/s to parse
47@@report = File.new(ARGV[1], "w+") #Output file for report
48high_findings = Array.new #Array used to store plugin_ids
49@@report_exists = false
50@@report_complete = false
51
52#Simple function to create Finding objects
53#Objects must be created outside the main iteration blocks in order to be stored and referenced properly
54def create_object(host, event)
55 @@finding_object = Finding.new(host, event)
56end
57
58#function used to store findings
59def generate_report(finding_object, output)
60 #create report file for working with
61 html_header = "<html>\r\n" +
62 "<head>\r\n" +
63 "<style type=\"text/css\">\r\n" +
64 "#findings\r\n" +
65 "{\r\n" +
66 " font-family:\"Trebuchet MS\", Arial, Helvetica, sans-serif;\r\n" +
67 " width:800;\r\n" +
68 " border-collapse:collapse;\r\n" +
69 "}\r\n" +
70 "#findings td, #findings th\r\n" +
71 "{\r\n" +
72 " font-size:1em;\r\n" +
73 " border:1px solid #98bf21;\r\n" +
74 " padding:3px 7px 2px 7px;\r\n" +
75 "}\r\n" +
76 "#findings th\r\n" +
77 "{\r\n" +
78 " font-size:1em;\r\n" +
79 " text-align:left;\r\n" +
80 " padding-top:4px;\r\n" +
81 " padding-bottom:3px;\r\n" +
82 " background-color:#A7C942;\r\n" +
83 " color:#ffffff;\r\n" +
84 "}\r\n" +
85 "#findings tr.alt td\r\n" +
86 "{\r\n" +
87 " color:#000000;\r\n" +
88 " background-color:#EAF2D3;\r\n" +
89 "}\r\n" +
90 "</style>\r\n" +
91 "<META http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">" +
92 "</head>\r\n" +
93 "\r\n" +
94 "<body>\r\n" +
95 "<h2>High Risk Findings</h2>\r\n"
96
97 @@report.puts html_header unless @@report_exists
98 @@report_exists = true
99
100 @@report.puts "<table id=\"findings\">\r\n"
101 @@report.puts "<tr><th>#{finding_object.title}</th>\r\n"
102 @@report.puts "<tr class=\"alt\"><td><b><font color=\"red\">#{finding_object.rating}</font></b></td></tr>\r\n"
103 @@report.puts "<tr><td width=\"100%\"><b>Number of hosts:</b> #{finding_object.host_count}<br><br><b>Description:</b><br><p>#{finding_object.description}</p><br><br>"
104 if finding_object.output
105 @@report.puts "<b>Output:</b><br>#{finding_object.output}"
106 end
107 @@report.puts "</td></tr>\r\n"
108 @@report.puts "<tr><td><b>Recommendation:</b><br>#{finding_object.solution}</td></tr>\r\n"
109 #Get links if there are any and write them to the finding.
110 if finding_object.links.length > 0
111 @@report.puts "<tr class=\"alt\"><td><b>Additional resources:</b><br>\r\n"
112 finding_object.links.each do |link|
113 @@report.puts "<font color=\"blue\">#{link}</font><br>"
114 end
115 @@report.puts "</td></tr></table><br>\r\n"
116 else
117 @@report.puts "</td></tr></table><br>\r\n"
118 end
119 @@report.puts html_footer if @@report_complete
120end
121
122#Import the .nessus file/s for parsing
123Nessus::Parse.new(nessus) do |scan|
124
125 #First iterate through all hosts to generate a list of high findings
126 scan.each_host do |host|
127 host.each_event do |event|
128 #Add the plugin_id to the high_findings list if it is not already present
129 if event.severity.high?
130 high_findings.push(event.plugin_id) if !high_findings.include?(event.plugin_id)
131 end
132 end
133 end
134
135 #Next iterate through the list of high findinds and create a Finding object for each plugin_id
136 #this block when finished needs to call another function that build the html output from the findings
137 high_findings.each do |finding|
138 finding_exists = false
139 scan.each_host do |host|
140 host.each_event do |event|
141 #If it's the first time through the loop
142 #Create the finding object
143 if event.plugin_id == finding
144 unless finding_exists
145 create_object(host, event)
146 #specity the finding exists, next iteration will skip this
147 finding_exists = true
148 next
149 end
150 #From this point on simply add to the already existing object
151 @@finding_object.host_count = @@finding_object.host_count + 1
152 new_host_name = host.name
153 new_host_ip = host.ip
154 if host.name
155 add_host = new_host_name.to_s + "+" + new_host_ip.to_s
156 else
157 add_host = " " + "+" + new_host_ip.to_s
158 end
159 #add a value to the objects hosts variable
160 @@finding_object.hosts.push(add_host)
161 end
162 end
163 end
164 generate_report(@@finding_object, @@report)
165 end
166 html_footer = "</table>\r\n" +
167 "</body>\r\n" +
168 "</html>\r\n"
169
170 @@report.puts html_footer
171 @@report.close
172
173end
174#Start parseing Nessus data