# frozen_string_literal: true require 'nokogiri' require 'time' require 'base64' module PWN module Plugins # This plugin is used for interacting w/ OpenVAS using OMP (OpenVAS Management Protocol). module OpenVAS # Supported Method Parameters:: # task_xml_resp = PWN::Plugins::OpenVAS.get_task_id( # task_name: 'required task name to start', # username: 'required username', # password: 'optional password (will prompt if nil)' # ) public_class_method def self.get_task_id(opts = {}) task_name = opts[:task_name].to_s.scrub username = opts[:username].to_s.scrub password = if opts[:password].nil? PWN::Plugins::AuthenticationHelper.mask_password else opts[:password].to_s.scrub end get_tasks_xml_resp = Nokogiri::XML( `sudo runuser -u _gvm -- /usr/bin/gvm-cli \ --gmp-username '#{username}' \ --gmp-password '#{password}' \ socket \ --xml="" ` ) get_tasks_xml_resp.xpath( "/get_tasks_response/task[name/text()='#{task_name}']" ) rescue StandardError => e raise e end # Supported Method Parameters:: # start_task_xml_resp = PWN::Plugins::OpenVAS.start_task( # task_name: 'required task name to start', # username: 'required username', # password: 'optional password (will prompt if nil)' # ) public_class_method def self.start_task(opts = {}) task_name = opts[:task_name].to_s.scrub username = opts[:username].to_s.scrub password = if opts[:password].nil? PWN::Plugins::AuthenticationHelper.mask_password else opts[:password].to_s.scrub end task_id = get_task_id( task_name: task_name, username: username, password: password ).xpath('@id').text Nokogiri::XML( `sudo runuser -u _gvm -- /usr/bin/gvm-cli \ --gmp-username '#{username}' \ --gmp-password '#{password}' \ socket \ --xml="" ` ) rescue StandardError => e raise e end # Supported Method Parameters:: # task_status = PWN::Plugins::OpenVAS.get_task_status( # task_name: 'required task name to start', # username: 'required username', # password: 'optional password (will prompt if nil)' # ) public_class_method def self.get_task_status(opts = {}) task_name = opts[:task_name].to_s.scrub username = opts[:username].to_s.scrub password = if opts[:password].nil? PWN::Plugins::AuthenticationHelper.mask_password else opts[:password].to_s.scrub end get_task_id( task_name: task_name, username: username, password: password ).xpath('status').text rescue StandardError => e raise e end # Supported Method Parameters:: # last_report_id = PWN::Plugins::OpenVAS.last_report_id( # task_name: 'required task name to start', # username: 'required username', # password: 'optional password (will prompt if nil)' # ) public_class_method def self.last_report_id(opts = {}) task_name = opts[:task_name].to_s.scrub username = opts[:username].to_s.scrub password = if opts[:password].nil? PWN::Plugins::AuthenticationHelper.mask_password else opts[:password].to_s.scrub end task_id = get_task_id( task_name: task_name, username: username, password: password ).xpath('@id').text report_xml_resp = Nokogiri::XML( `sudo runuser -u _gvm -- /usr/bin/gvm-cli \ --gmp-username '#{username}' \ --gmp-password '#{password}' \ socket \ --xml="" ` ) report_xml_resp.xpath( "/get_reports_response/report/task[@id='#{task_id}']" ).last.parent.xpath( '@id' ).text rescue StandardError => e raise e end # Supported Method Parameters:: # PWN::Plugins::OpenVAS.save_report( # report_type: 'required report type (csv|itg|pdf|txt|xml)', # report_id: 'required report id to save', # report_dir: 'required directory to save report', # username: 'required username', # password: 'optional password (will prompt if nil)', # report_filter: 'optional - results filter (Default: "apply_overrides=0 levels=hml rows=1000 min_qod=70 first=1 sort-reverse=severity") # ) public_class_method def self.save_report(opts = {}) report_type = opts[:report_type].to_s.scrub report_id = opts[:report_id].to_s.scrub report_dir = opts[:report_dir].to_s.scrub raise "#{report_dir} Does Not Exist." unless Dir.exist?( report_dir ) username = opts[:username].to_s.scrub password = if opts[:password].nil? PWN::Plugins::AuthenticationHelper.mask_password else opts[:password].to_s.scrub end report_filter = opts[:report_filter] report_filter ||= 'apply_overrides=0 levels=hml rows=1000 min_qod=70 first=1 sort-reverse=severity' case report_type.to_sym when :csv report_type_name = 'CSV Results' when :itg report_type_name = 'ITG' when :pdf report_type_name = 'PDF' when :txt report_type_name = 'TXT' when :xml report_type_name = 'XML' else raise "Report Type: \"#{report_type}\" not supported." end report_formats_xml_resp = Nokogiri::XML( `sudo runuser -u _gvm -- /usr/bin/gvm-cli \ --gmp-username '#{username}' \ --gmp-password '#{password}' \ socket \ --xml="" ` ) rpt_fmt_xml_resp_by_name = report_formats_xml_resp.xpath( "/get_report_formats_response/report_format[name/text()='#{report_type_name}']" ) format_id = rpt_fmt_xml_resp_by_name.xpath('@id').text # Generate Report report_xml_resp = Nokogiri::XML( `sudo runuser -u _gvm -- /usr/bin/gvm-cli \ --gmp-username '#{username}' \ --gmp-password '#{password}' \ socket \ --xml="" ` ) # timestamp = Time.parse( # report_xml_resp.xpath('//modification_time') # ).localtime.strftime( # '%Y-%m-%d-%H-%M-%S%z' # ) base64_report = report_xml_resp.xpath( '//report/text()' ).text # File.open("#{report_dir}/openvas_results-#{timestamp}.#{report_type}", 'w') do |f| File.open("#{report_dir}/openvas_results.#{report_type}", 'w') do |f| f.puts Base64.strict_decode64(base64_report) end rescue StandardError => e raise e end # Supported Method Parameters:: # report_types = PWN::Plugins::OpenVAS.get_report_types( # username: 'required username', # password: 'optional password (will prompt if nil)' # ) public_class_method def self.get_report_types(opts = {}) username = opts[:username].to_s.scrub password = if opts[:password].nil? PWN::Plugins::AuthenticationHelper.mask_password else opts[:password].to_s.scrub end report_types = %i[ csv itg pdf txt xml ] rescue StandardError => e raise e end # Author(s):: 0day Inc. public_class_method def self.authors "AUTHOR(S): 0day Inc. " end # Display Usage for this Module public_class_method def self.help puts "USAGE: task_xml_resp = #{self}.get_task_id( task_name: 'required task name to start', username: 'required username', password: 'optional password (will prompt if nil)' ) start_task_xml_resp = #{self}.start_task( task_name: 'required task name to start', username: 'required username', password: 'optional password (will prompt if nil)' ) task_status = #{self}.get_task_status( task_name: 'required task name to start', username: 'required username', password: 'optional password (will prompt if nil)' ) last_report_id = #{self}.last_report_id( task_name: 'required task name to start', username: 'required username', password: 'optional password (will prompt if nil)' ) #{self}.save_report( report_type: 'required report type (csv|itg|pdf|txt|xml)', report_id: 'required report id to save', report_dir: 'required directory to save report', username: 'required username', password: 'optional password (will prompt if nil)', report_filter: 'optional - results filter (Default: \"apply_overrides=0 levels=hml rows=1000 min_qod=70 first=1 sort-reverse=severity\") ) report_types = #{self}.get_report_types( username: 'required username', password: 'optional password (will prompt if nil)' ) #{self}.authors " end end end end