# frozen_string_literal: true require 'json' module PWN module Plugins # This plugin is used for interacting w/ BeEF's REST API using # the 'rest' browser type of PWN::Plugins::TransparentBrowser. module BeEF @@logger = PWN::Plugins::PWNLogger.create # Supported Method Parameters:: # beef_obj = PWN::Plugins::BeEF.login( # beef_ip: 'required - host/ip of BeEF Server', # beef_port: 'optional - port of BeEF server (defaults to 3000)', # username: 'required - username', # password: 'optional - password (will prompt if nil)' # ) public_class_method def self.login(opts = {}) beef_ip = opts[:beef_ip] beef_port = if opts[:beef_port] opts[:beef_port].to_i else 3000 end username = opts[:username].to_s.scrub base_beef_api_uri = "http://#{beef_ip}:#{beef_port}/api".to_s.scrub password = if opts[:password].nil? PWN::Plugins::AuthenticationHelper.mask_password else opts[:password].to_s.scrub end auth_payload = {} auth_payload[:username] = username auth_payload[:password] = password @@logger.info("Logging into BeEF REST API: #{beef_ip}") browser_obj = PWN::Plugins::TransparentBrowser.open(browser_type: :rest) rest_client = browser_obj[:browser]::Request response = rest_client.execute( method: :post, url: "#{base_beef_api_uri}/admin/login", payload: auth_payload.to_json ) # Return array containing the post-authenticated BeEF REST API token json_response = JSON.parse(response) beef_success = json_response['success'] api_token = json_response['token'] beef_obj = {} beef_obj[:beef_ip] = beef_ip beef_obj[:beef_port] = beef_port beef_obj[:beef_success] = beef_success beef_obj[:api_token] = api_token beef_obj[:raw_response] = response beef_obj rescue StandardError => e raise e end # Supported Method Parameters:: # beef_rest_call( # beef_obj: 'required beef_obj returned from #login method', # http_method: 'optional HTTP method (defaults to GET) # rest_call: 'required rest call to make per the schema', # http_body: 'optional HTTP body sent in HTTP methods that support it e.g. POST' # ) private_class_method def self.beef_rest_call(opts = {}) beef_obj = opts[:beef_obj] http_method = if opts[:http_method].nil? :get else opts[:http_method].to_s.scrub.to_sym end rest_call = opts[:rest_call].to_s.scrub http_body = opts[:http_body].to_s.scrub beef_success = beef_obj[:beef_success].to_s.scrub beef_ip = beef_obj[:beef_ip].to_s.scrub beef_port = beef_obj[:beef_port].to_i base_beef_api_uri = "http://#{beef_ip}:#{beef_port}/api".to_s.scrub api_token = beef_obj[:api_token] browser_obj = PWN::Plugins::TransparentBrowser.open(browser_type: :rest) rest_client = browser_obj[:browser]::Request case http_method when :get response = rest_client.execute( method: :get, url: "#{base_beef_api_uri}/#{rest_call}", headers: { content_type: 'application/json; charset=UTF-8', params: { token: api_token } } ) when :post response = rest_client.execute( method: :post, url: "#{base_beef_api_uri}/#{rest_call}", headers: { content_type: 'application/json; charset=UTF-8' }, payload: http_body ) else raise @@logger.error("Unsupported HTTP Method #{http_method} for #{self} Plugin") end rescue StandardError => e raise e end # Supported Method Parameters:: # hooks = PWN::Plugins::BeEF.hooks( # beef_obj: 'required beef_obj returned from #login method' # ) public_class_method def self.hooks(opts = {}) beef_obj = opts[:beef_obj] @@logger.info('Retrieving BeEF Hooks...') response = beef_rest_call( beef_obj: beef_obj, rest_call: 'hooks' ) JSON.parse(response) rescue StandardError => e raise e end # Supported Method Parameters:: # hooked_browser_info = PWN::Plugins::BeEF.hooked_browser_info( # beef_obj: 'required beef_obj returned from #login method', # browser_session: 'required - browser session id returned from #hooks method' # ) public_class_method def self.hooked_browser_info(opts = {}) beef_obj = opts[:beef_obj] browser_session = opts[:browser_session].to_s.scrub @@logger.info('Retrieving Browser Info...') response = beef_rest_call( beef_obj: beef_obj, rest_call: "hooks/#{browser_session}" ) JSON.parse(response) rescue StandardError => e raise e end # Supported Method Parameters:: # logs = PWN::Plugins::BeEF.logs( # beef_obj: 'required beef_obj returned from #login method' # ) public_class_method def self.logs(opts = {}) beef_obj = opts[:beef_obj] @@logger.info('Retrieving BeEF Logs...') response = beef_rest_call( beef_obj: beef_obj, rest_call: 'logs' ) JSON.parse(response) rescue StandardError => e raise e end # Supported Method Parameters:: # hooked_browser_logs = PWN::Plugins::BeEF.hooked_browser_logs( # beef_obj: 'required beef_obj returned from #login method', # browser_session: 'required - browser session id returned from #hooks method' # ) public_class_method def self.hooked_browser_logs(opts = {}) beef_obj = opts[:beef_obj] browser_session = opts[:browser_session].to_s.scrub @@logger.info('Retrieving Browser Logs...') response = beef_rest_call( beef_obj: beef_obj, rest_call: "logs/#{browser_session}" ) JSON.parse(response) rescue StandardError => e raise e end # Supported Method Parameters:: # modules = PWN::Plugins::BeEF.modules( # beef_obj: 'required beef_obj returned from #login method' # ) public_class_method def self.modules(opts = {}) beef_obj = opts[:beef_obj] @@logger.info('Retrieving BeEF Modules...') response = beef_rest_call( beef_obj: beef_obj, rest_call: 'modules' ) JSON.parse(response) rescue StandardError => e raise e end # Supported Method Parameters:: # module_info = PWN::Plugins::BeEF.module_info( # beef_obj: 'required beef_obj returned from #login method', # module_id: 'required - module id returned from #modules method' # ) public_class_method def self.module_info(opts = {}) beef_obj = opts[:beef_obj] module_id = opts[:module_id].to_i @@logger.info('Retrieving Module Info...') response = beef_rest_call( beef_obj: beef_obj, rest_call: "modules/#{module_id}" ) JSON.parse(response) rescue StandardError => e raise e end # Supported Method Parameters:: # PWN::Plugins::BeEF.logout( # beef_obj: 'required beef_obj returned from #login method' # ) public_class_method def self.logout(opts = {}) beef_obj = opts[:beef_obj] @@logger.info('Logging out...') beef_obj = nil 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: beef_obj = #{self}.login( beef_ip: 'required host/ip of Nexpose Console (server)', beef_port: 'optional - port of BeEF server (defaults to 3000)', username: 'required username', password: 'optional password (will prompt if nil)' ) hooks = #{self}.hooks( beef_obj: 'required beef_obj returned from #login method' ) hooked_browser_info = #{self}.hooked_browser_info( beef_obj: 'required beef_obj returned from #login method', browser_session: 'required - browser session id returned from #hooks method' ) logs = #{self}.logs( beef_obj: 'required beef_obj returned from #login method' ) hooked_browser_logs = #{self}.hooked_browser_logs( beef_obj: 'required beef_obj returned from #login method', browser_session: 'required - browser session id returned from #hooks method' ) modules = #{self}.modules( beef_obj: 'required beef_obj returned from #login method' ) module_info = #{self}.module_info( beef_obj: 'required beef_obj returned from #login method', module_id: 'required - module id returned from #modules method' ) beef_obj = #{self}.logout( beef_obj: 'required beef_obj returned from #login method' ) #{self}.authors " end end end end