hammackj/risu

View on GitHub
lib/risu/base/post_process_base.rb

Summary

Maintainability
B
6 hrs
Test Coverage
# Copyright (c) 2010-2020 Jacob Hammack.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.


module Risu
    module Base

        #
        class PostProcessBase
            @possible_postprocesses = Array.new

            class << self
                attr_reader :possible_postprocesses
            end

            #
            attr_accessor :info

            #
            def self.inherited child
                possible_postprocesses << child
            end

            def == other

                if self.info == nil || self.info[:plugin_id] == nil
                    false
                elsif other == nil || other.info == nil || other.info[:plugin_id] == nil
                    false
                else
                    self.info[:plugin_id] == other.info[:plugin_id]
                end
            end

            def <=> other
                if self.info[:plugin_id] < other.info[:plugin_id]
                    -1
                elsif self.info[:plugin_id] > other.info[:plugin_id]
                    1
                else
                    0
                end
            end

            # Create a plugin based on a combination of all plugins
            # to be rolled up.
            def create_plugin

                plugin = Plugin.find_by_id(@info[:plugin_id])

                if plugin == nil
                    plugin = Plugin.new
                end

                # Populate items from post process module
                plugin.id = @info[:plugin_id]
                plugin.plugin_name = @info[:plugin_name]
                plugin.description = @info[:description]
                plugin.plugin_version = @info[:version]
                plugin.plugin_publication_date = @info[:publication_date]
                plugin.plugin_modification_date = @info[:modification_date]

                # Boiler plate for all roll up plugins
                plugin.family_name = "Risu Rollup Plugins"
                plugin.synopsis = "Software often has vulnerabilities that are corrected in newer versions. It was determined that an older version of the software is installed on this system."
                plugin.solution = "If possible, update to the latest version of the software."
                plugin.plugin_type = "Rollup"
                plugin.rollup = true
                plugin.compliance = false

                # Find oldest vuln date.
                begin
                    p = Plugin.where(:id => @info[:plugin_ids]).where.not(:vuln_publication_date => nil).order(:vuln_publication_date).first
                    unless p.nil?
                        plugin.vuln_publication_date = p.vuln_publication_date
                    end
                end

                begin
                    p = Plugin.where(:id => @info[:plugin_ids]).where.not(:cvss_base_score => nil).order(:cvss_base_score).last
                    unless p.nil?
                        plugin.cvss_base_score = p.cvss_base_score
                        plugin.cvss_vector = p.cvss_vector
                    end
                end

                begin
                    p = Plugin.where(:id => @info[:plugin_ids]).where.not(:cvss_temporal_score => nil).order(:cvss_temporal_score).last
                    unless p.nil?
                        plugin.cvss_temporal_score = p.cvss_temporal_score
                        plugin.cvss_temporal_vector = p.cvss_temporal_vector
                    end
                end

                if Plugin.where(:id => @info[:plugin_ids], :exploit_available => true).count > 0
                    plugin.exploit_available = true
                end

                if Plugin.where(:id => @info[:plugin_ids], :exploit_framework_core => "true").count > 0
                    plugin.exploit_framework_core = true
                end

                if Plugin.where(:id => @info[:plugin_ids], :exploit_framework_metasploit => "true").count > 0
                    plugin.exploit_framework_metasploit = true
                end

                if Plugin.where(:id => @info[:plugin_ids], :exploit_framework_canvas => "true").count > 0
                    plugin.exploit_framework_canvas = true
                end

                if Plugin.where(:id => @info[:plugin_ids], :exploit_framework_exploithub => "true").count > 0
                    plugin.exploit_framework_exploithub = true
                end

                if Plugin.where(:id => @info[:plugin_ids], :exploit_framework_d2_elliot => "true").count > 0
                    plugin.exploit_framework_d2_elliot = true
                end

                if Plugin.where(:id => @info[:plugin_ids], :in_the_news => true).count > 0
                    plugin.in_the_news = true
                end

                if Plugin.where(:id => @info[:plugin_ids], :exploited_by_malware => "true").count > 0
                    plugin.exploited_by_malware = true
                end

                ["Critical", "High", "Medium", "Low", "Info"].each do |risk|
                    if Plugin.where(:id => @info[:plugin_ids], :risk_factor => risk).size > 0
                        plugin.risk_factor = risk
                        break
                    end
                end

                begin
                    p = Plugin.where(:id => @info[:plugin_ids]).where.not(:stig_severity => nil).order(:stig_severity).first
                    unless p.nil?
                        plugin.stig_severity = p.stig_severity
                    end
                end

                # Broken
                #plugin.references << References.where(:plugin_id => @info[:plugin_ids], :reference_name => "cve")

                plugin.save
            end

            #
            def create_item host_id, severity
                item = Item.new

                    item.host_id = host_id
                    item.plugin_id = @info[:plugin_id]
                    item.plugin_output = nil
                    item.port = 0
                    item.severity = severity
                    item.plugin_name = @info[:item_name]
                    item.rollup_finding = true

                item.save
            end

            #
            def has_findings
                Item.where(:plugin_id => @info[:plugin_ids]).count > 0
            end

            def has_host_findings(host_id)
                Item.where(:plugin_id => @info[:plugin_ids]).where(:host_id => host_id).count > 0
            end

            #
            def calculate_severity current_severity, severity
                if severity > current_severity
                    return severity
                else
                    return current_severity
                end
            end

            #
            def run
                if !has_findings()
                    return
                end

                # If this is a "roll up" post-process, create a plugin
                if Plugin.where(:id => @info[:plugin_ids]).count > 0
                    create_plugin()
                end

                finding_severity = 0

                Host.all.each do |host|
                    if !has_host_findings(host.id)
                        next
                    end

                    # Downgrade Nessus findings to -1, to replace with rollup
                    @info[:plugin_ids].each do |plugin_id|
                        Item.where(:plugin_id => plugin_id).each do |item|

                            severity = item.severity
                            item.real_severity = severity
                            item.severity = -1
                            item.save

                            finding_severity = calculate_severity(finding_severity, severity)
                        end
                    end

                    create_item(host.id, finding_severity)
                end
            end
        end
    end
end