Class: Prenus::Input::Nessusin

Inherits:
Object
  • Object
show all
Defined in:
lib/input/nessusin.rb

Class Method Summary collapse

Class Method Details

.import_nessus_files(options) ⇒ Object

This class method is used to convert a single (or collection) of .nessus (v2) files into 2 different hashes. events and hosts

Examples:

hosts, events = Prenus::Input::Nessusin.import_nessus_files(options)

Returns:

  • hosts - a hash of hashes

    {<hostid> => {:ip => <ip>, :hostname => <hostname>, :os => <os>, :info => <number of informational findings>,
                  :low => <number of low findings>, :med => <number of medium findings>,
                  :high => <number of high findings>, :crit => <number of critical findings>,
                  :total => <total number of findings>, :total_excl_info => <total number of findings excluding informational findings>}}
    

    events - a hash of hashes

    {<nessus_id> => {:family => <vuln family>, :severity => <severity>, :plugin_name => <plugin name>,
                     :synopsis => <synopsis>, :description => <description>, :solution => <solution>, :see_also => <array of solutions>,
                     :cvss_base_score => <CVSS base score>, :cve => <CVE ID>, :cvss_vector => <CVSS vector>,
                     :ports => {<port string>, :hosts => {<hostid>, :result => <result>}}}
    


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/input/nessusin.rb', line 27

def self.import_nessus_files(options)
	hosts = {}  #initialise the output hosts hash
	events = {} #initialise the output events hash

	hostid = 0  #initialise the unique hostid

	#take the options[:input] parameter as a search parameter for input files, we don't check if these are .nessus files or anything
	#Dir.glob(options[:input]) do |nessus_file|
	options[:input].each do |nessus_file|

		Nessus::Parse.new(nessus_file) do |scan| #use the awesome ruby-nessus gem

			# in the scan file, iterate over each host
			scan.each_host do |host|
				ip = host.ip || "" #grap the IP
				next if ip == ""   #I've found sometimes if it doesn't have an IP it means its not scanned for whatever reasons .. like a printer
								   # I next here because I've found it easier to just ignore those which weren't scanned

				# Lets check if we want to skip an IP for .. whatever reason
				unless options[:skip].nil?
					next if options[:skip].include?(ip.to_s)
				end

				hostname = host.hostname || "" #grab the hostname
				os = host.os || "" #grab the os
				os = os.gsub(/\n/,"/") # sometimes the OS is split over multiple lines - mange them together .. mange mange

				# Lets check if there's an override array in the config
				unless options[:override].nil?
					# Check for this IP address, as this is the primary key we use for overriding
					ovr = options[:override].detect{|x|x['ip'] == ip.to_s}
					unless ovr.nil?
						os = ovr['os'] unless ovr['os'].nil? # Override the OS
						hostname = ovr['hostname'] unless ovr['hostname'].nil? # Override the hostname
					end
				end

				info = host.informational_severity_count || 0 #grab the number of informational findings
				low = host.low_severity_count || 0 #grab the number of low findings
				med = host.medium_severity_count || 0 #grab the number of medium findings
				high = host.high_severity_count || 0 #grab the number of high findings
				crit = host.critical_severity_count || 0 #grab the number of critical findings

				targethostid = hostid #For the moment

				# Check to see if we already have the host (based on IP, Hostname and OS)
				if hosts.select {|key,f| f[:os].to_s == os and f[:ip].to_s == ip and f[:hostname].to_s == hostname}.count == 0
					# Okay, we don't have this host yet

					# add the host into the hosts hash
					hosts[hostid] = {:ip => ip, :hostname => hostname, :os => os, :info => info, :low => low, :med => med, :high => high, :crit => crit, :total => info+low+med+high+crit, :total_excl_info => low+med+high+crit}
					hostid += 1 # We only increase because we've added a new host
				else
					# We do have this host, lets grab the host id
					hosts.select {|key,f| f[:os].to_s == os and f[:ip].to_s == ip and f[:hostname] == hostname}.each {|k,v| targethostid = k}

					# Lets now check who has the greatest number of findings, and then we'll use that one going forward
					if hosts[targethostid][:total].to_i < (info + low + med + high) #therefore the older, previously detected host had more - update the counters
						hosts[targethostid][:info] = info
						hosts[targethostid][:low] = low
						hosts[targethostid][:med] = med
						hosts[targethostid][:high] = high
						hosts[targethostid][:crit] = crit
						hosts[targethostid][:total] = info + low + med + high + crit
						hosts[targethostid][:total_excl_info] = low + med + high + crit
					end
				end

				# Now lets iterate through each of the findings in this particular host
				host.each_event do |event|

					# If the events hash already has this event, lets just add this targethostid to it's hosts array within the ports hash
					if events.has_key?(event.id)

						#Lets check the ports hash
						if events[event.id][:ports].has_key?(event.port.to_s)

							# We'll only add the hostid if the host's not already in the array
							events[event.id][:ports][event.port.to_s][:hosts][targethostid] = event.output unless events[event.id][:ports][event.port.to_s][:hosts].include?(targethostid)

						#Lets add this new port to this hash	
						else
							events[event.id][:ports][event.port.to_s] = {:hosts => { targethostid => event.output}}
						end

					# okay, this event doesn't exist, lets add it to the events hash
					else
						events[event.id] = {
							#:hosts => [hostid],									#start the hosts array
							:family => event.family || "",						#vuln family
							:severity => event.severity || "",					#severity
							:plugin_name => event.plugin_name || "", 			#plugin name
							:synopsis => event.synopsis || "",					#synopsis
							:description => event.description || "",			#description
							:solution => event.solution || "",					#solution
							:see_also => event.see_also || "",					#see also array
							:cvss_base_score => event.cvss_base_score || "",	#CVSS base score
							:cve => event.cve || "",							#CVE
							:cvss_vector => event.cvss_vector || "",			#CVSS vector
							#:port => event.port.to_s || ""						#port
							:ports => {}
						}
						events[event.id][:ports][event.port.to_s] = {:hosts => {targethostid => event.output}}
					end
				end
			end
		end
	end

	#sort the events by severity crit, high, med, low, info
	events = events.sort_by{ |k,v| v[:severity]}.reverse

	#return the hosts and the events hashes
	return hosts, events
end