123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- #
- # This plugin provides integration with beSECURE. Written by Noam Rathaus.
- #
- # Distributed under MIT license:
- # http://www.opensource.org/licenses/mit-license.php
- #
- # Version 10.5.17
- require 'base64'
- require 'zlib'
- require 'tempfile'
- require 'pathname'
- module Msf
- class Plugin::BeSECURE < Msf::Plugin
- class BeSECURECommandDispatcher
- include Msf::Ui::Console::CommandDispatcher
- def name
- 'beSECURE'
- end
- def commands
- {
- 'besecure_help' => 'Displays help',
- 'besecure_version' => 'Display the version of the beSECURE server',
- 'besecure_apikey' => 'Set the beSECURE API Key',
- 'besecure_hostname' => 'Set the beSECURE Hostname',
- 'besecure_debug' => 'Enable/Disable debugging',
- 'besecure_ssl_verify' => 'Enable/Disable SSL verification',
- 'besecure_report_list' => 'Display list of reports',
- 'besecure_report_download' => 'Save a report to disk',
- 'besecure_report_import' => 'Import report specified by ID into framework'
- }
- end
- def cmd_besecure_help
- print_status('besecure_help Display this help')
- print_status('besecure_debug Enable/Disable debugging')
- print_status('besecure_version Display the version of the beSECURE server')
- print_status('besecure_apikey Set the beSECURE API Key')
- print_status('besecure_ssl_verify Set whether to verify or not SSL')
- print_status('besecure_hostname Set the beSECURE Hostname')
- print_status
- print_status('REPORTS')
- print_status('=======')
- print_status('besecure_report_list Lists reports')
- print_status('besecure_report_download Downloads an beSECURE report specified by ID')
- print_status('besecure_report_import Import report specified by ID into framework')
- end
- # Verify the database is connected and usable
- def database?
- if !(framework.db && framework.db.usable)
- return false
- else
- return true
- end
- end
- # Verify correct number of arguments and verify -h was not given. Return
- # true if correct number of arguments and help was not requested.
- def args?(args, min = 1, max = nil)
- if !max then max = min end
- if ((args.length < min) || (args.length > max) || (args[0] == '-h'))
- return false
- end
- return true
- end
- #--------------------------
- # Basic Functions
- #--------------------------
- def cmd_besecure_hostname(*args)
- if args?(args)
- @hostname = args[0]
- print_good(@hostname)
- else
- print_status('Usage:')
- print_status('besecure_hostname string')
- end
- end
- def cmd_besecure_apikey(*args)
- if args?(args)
- @apikey = args[0]
- print_good(@apikey)
- else
- print_status('Usage:')
- print_status('besecure_apikey string')
- end
- end
- def cmd_besecure_ssl_verify(*args)
- if args?(args)
- @ssl_verify = args[0]
- if (@ssl_verify != 'yes') && (@ssl_verify != 'no')
- @ssl_verify = 'yes'
- end
- print_good(@ssl_verify)
- else
- print_status('Usage:')
- print_status("besecure_ssl_verify 'yes'/'no' (default is yes)")
- end
- end
- def cmd_besecure_debug(*args)
- if args?(args)
- @debug = args[0].to_i
- print_good(@debug)
- else
- print_status('Usage:')
- print_status('besecure_debug integer')
- end
- end
- def cmd_besecure_version
- req = Net::HTTP::Post.new('/json.cgi', { 'Host' => @hostname })
- req.set_form_data({ 'apikey' => @apikey, 'primary' => 'interface' })
- if @debug
- print_status(req.body)
- end
- http = Net::HTTP.new(@hostname, 443)
- if @debug
- http.set_debug_output($stdout) # Logger.new("foo.log") works too
- end
- http.use_ssl = true
- if @ssl_verify == 'no'
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
- end
- res = http.start { |h| h.request(req) }
- unless res
- print_error("#{@hostname} - Connection timed out")
- return ''
- end
- body = ''
- begin
- body = JSON.parse(res.body)
- rescue JSON::ParserError
- print_error("#{@hostname} - Unable to parse the response")
- return ''
- end
- if body['error']
- print_error("#{@hostname} - An error occurred:")
- print_error(body)
- return ''
- end
- print_good(body['version'])
- end
- #--------------------------
- # Report Functions
- #--------------------------
- def cmd_besecure_report_list(*_args)
- tbl = Rex::Text::Table.new(
- 'Columns' => ['ID', 'Name', 'Hosts']
- )
- if @hostname.empty?
- print_error('Missing host value')
- return ''
- end
- req = Net::HTTP::Post.new('/json.cgi', { 'Host' => @hostname })
- req.set_form_data({ 'apikey' => @apikey, 'primary' => 'admin', 'secondary' => 'networks', 'action' => 'returnnetworks', 'search_limit' => 10000 })
- if @debug
- print_status(req.body)
- end
- http = Net::HTTP.new(@hostname, 443)
- if @debug
- http.set_debug_output($stdout) # Logger.new("foo.log") works too
- end
- http.use_ssl = true
- if @ssl_verify == 'no'
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
- end
- res = http.start { |h| h.request(req) }
- unless res
- print_error("#{@hostname} - Connection timed out")
- return ''
- end
- body = ''
- begin
- body = JSON.parse(res.body)
- rescue JSON::ParserError
- print_error("#{@hostname} - Unable to parse the response")
- return ''
- end
- if body['error']
- print_error("#{@hostname} - An error occurred:")
- print_error(body)
- return ''
- end
- data = body['data']
- data.each do |item|
- tbl << [ item['ID'], item['Name'], item['PrettyRange']]
- end
- # print_good(body)
- print_good('beSECURE list of reports')
- print_line
- print_line tbl.to_s
- print_line
- end
- def cmd_besecure_report_download(*args)
- if args?(args, 4)
- req = Net::HTTP::Post.new('/json.cgi', { 'Host' => @hostname })
- format_file = args[1]
- req.set_form_data({ 'apikey' => @apikey, 'primary' => 'vulnerabilities', 'secondary' => 'report', 'action' => 'getreport', 'network' => args[0], 'format' => format_file })
- http = Net::HTTP.new(@hostname, 443)
- if @debug
- http.set_debug_output($stdout) # Logger.new("foo.log") works too
- end
- http.use_ssl = true
- if @ssl_verify == 'no'
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
- end
- res = http.start { |h| h.request(req) }
- unless res
- print_error("#{@hostname} - Connection timed out")
- return ''
- end
- body = ''
- begin
- body = JSON.parse(res.body)
- rescue JSON::ParserError
- print_error("#{@hostname} - Unable to parse the response")
- return ''
- end
- if body['error']
- print_error("#{@hostname} - An error occurred:")
- print_error(body)
- return ''
- end
- decompressed = ''
- if format_file != 'json'
- compressed_base64 = body['compresseddata']
- compressed = Base64.decode64(compressed_base64)
- decompressed = Zlib::Inflate.inflate(compressed)
- else
- decompressed = body
- end
- if @debug
- print_status(decompressed)
- end
- ::FileUtils.mkdir_p(args[2])
- name = ::File.join(args[2], args[3])
- print_status("Saving report to #{name}")
- output = ::File.new(name, 'w')
- output.puts(decompressed)
- output.close
- ###
- # Return the report
- return decompressed
- else
- print_status('Usage: besecure_report_download <network_id> <format_name> <path> <report_name>')
- end
- return ''
- end
- def cmd_besecure_report_import(*args)
- if args?(args, 2)
- if !database?
- print_error('Database not ready')
- return ''
- end
- tempfile = Tempfile.new('results')
- res = cmd_besecure_report_download(args[0], 'nbe', File.dirname(tempfile) + '/', File.basename(tempfile))
- if res.empty?
- print_error('An empty report has been received')
- return ''
- end
- print_status('Importing report to database.')
- framework.db.import_file({ filename: tempfile })
- tempfile.unlink
- else
- print_status('Usage: besecure_report_import <network_id> <format_name>')
- print_status('Only the NBE and XML formats are supported for importing.')
- end
- end
- end
- #------------------------------
- # Plugin initialization
- #------------------------------
- def initialize(framework, opts)
- super
- add_console_dispatcher(BeSECURECommandDispatcher)
- print_status('Welcome to beSECURE integration by Noam Rathaus.')
- print_status
- print_status('beSECURE integration requires a database connection. Once the ')
- print_status('database is ready, connect to the beSECURE server using besecure_connect.')
- print_status('For additional commands use besecure_help.')
- print_status
- @debug = nil
- end
- def cleanup
- remove_console_dispatcher('beSECURE')
- end
- def name
- 'beSECURE'
- end
- def desc
- 'Integrates with the beSECURE - open source vulnerability management'
- end
- end
- end
|