diff --git a/config.yaml b/config.yaml index e21cc52f0..9bd40c4ff 100644 --- a/config.yaml +++ b/config.yaml @@ -57,7 +57,6 @@ beef: # Hook hook_file: "/hook.js" hook_session_name: "BEEFHOOK" - session_cookie_name: "BEEFSESSION" # Allow one or multiple origins to access the RESTful API using CORS # For multiple origins use: "http://browserhacker.com, http://domain2.com" diff --git a/core/bootstrap.rb b/core/bootstrap.rb index b5df5bbec..051612715 100644 --- a/core/bootstrap.rb +++ b/core/bootstrap.rb @@ -29,9 +29,6 @@ require 'core/main/network_stack/handlers/raw' require 'core/main/network_stack/assethandler' require 'core/main/network_stack/api' -# @note Include the distributed engine -require 'core/main/distributed_engine/models/rules' - # @note Include the autorun engine require 'core/main/autorun_engine/models/rule' require 'core/main/autorun_engine/models/execution' diff --git a/core/core.rb b/core/core.rb index dc5d49db8..a28c81b84 100644 --- a/core/core.rb +++ b/core/core.rb @@ -22,7 +22,6 @@ require 'core/main/models/browserdetails' # @note Include the constants require 'core/main/constants/browsers' require 'core/main/constants/commandmodule' -require 'core/main/constants/distributedengine' require 'core/main/constants/os' require 'core/main/constants/hardware' diff --git a/core/main/constants/distributedengine.rb b/core/main/constants/distributedengine.rb deleted file mode 100644 index d02c3fa02..000000000 --- a/core/main/constants/distributedengine.rb +++ /dev/null @@ -1,21 +0,0 @@ -# -# Copyright (c) 2006-2019 Wade Alcorn - wade@bindshell.net -# Browser Exploitation Framework (BeEF) - http://beefproject.com -# See the file 'doc/COPYING' for copying permission -# - -module BeEF -module Core -module Constants - - # @note The distributed engine codes - module DistributedEngine - - REQUESTER = 1 - PORTSCANNER = 2 - - end - -end -end -end diff --git a/core/main/distributed_engine/models/rules.rb b/core/main/distributed_engine/models/rules.rb deleted file mode 100644 index 1d720fdf6..000000000 --- a/core/main/distributed_engine/models/rules.rb +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (c) 2006-2019 Wade Alcorn - wade@bindshell.net -# Browser Exploitation Framework (BeEF) - http://beefproject.com -# See the file 'doc/COPYING' for copying permission -# - -module BeEF -module Core -module DistributedEngine -module Models - - # @note Table stores the rules for the Distributed Engine. - class Rules - - include DataMapper::Resource - - storage_names[:default] = 'extension_distributedengine_rules' - - property :id, Serial - property :data, Text - property :enabled, Boolean - - end - -end -end -end -end diff --git a/core/main/rest/handlers/hookedbrowsers.rb b/core/main/rest/handlers/hookedbrowsers.rb index e53250164..b4b72fe85 100644 --- a/core/main/rest/handlers/hookedbrowsers.rb +++ b/core/main/rest/handlers/hookedbrowsers.rb @@ -20,13 +20,6 @@ module BeEF 'Expires' => '0' end - # - # @note Return a can of Leffe to the thirsty Bovine Security Team member. AthCon2012 joke /antisnatchor/ - # - #get "/to/a/pub" - # "BeER please" - #end - # # @note Get online and offline hooked browsers details (like name, version, os, ip, port, ...) # @@ -158,7 +151,8 @@ module BeEF BeEF::Core::Models::BrowserDetails.new(:session_id => hb.session, :detail_key => 'OsVersion', :detail_value => os_version).save BeEF::Core::Models::BrowserDetails.new(:session_id => hb.session, :detail_key => 'Arch', :detail_value => arch).save - #TODO if there where any ARE rules defined for this hooked browser, after updating OS/arch, force a retrigger of the rule. + # TODO if there where any ARE rules defined for this hooked browser, + # after updating OS/arch, force a retrigger of the rule. {'success' => true}.to_json end @@ -176,19 +170,24 @@ module BeEF details = BeEF::Core::Models::BrowserDetails { - 'id' => hb.id, - 'session' => hb.session, - 'name' => details.get(hb.session, 'BrowserName'), - 'version' => details.get(hb.session, 'BrowserVersion'), - 'os' => details.get(hb.session, 'OsName'), - 'os_version' => details.get(hb.session, 'OsVersion'), - 'platform' => details.get(hb.session, 'BrowserPlatform'), - 'ip' => hb.ip, - 'domain' => details.get(hb.session, 'HostName'), - 'port' => hb.port.to_s, - 'page_uri' => details.get(hb.session, 'PageURI'), - 'firstseen' => hb.firstseen, - 'lastseen' => hb.lastseen, + 'id' => hb.id, + 'session' => hb.session, + 'name' => details.get(hb.session, 'BrowserName'), + 'version' => details.get(hb.session, 'BrowserVersion'), + 'os' => details.get(hb.session, 'OsName'), + 'os_version' => details.get(hb.session, 'OsVersion'), + 'platform' => details.get(hb.session, 'BrowserPlatform'), + 'hardware' => details.get(hb.session, 'Hardware'), + 'ip' => hb.ip, + 'domain' => details.get(hb.session, 'HostName'), + 'port' => hb.port.to_s, + 'page_uri' => details.get(hb.session, 'PageURI'), + 'firstseen' => hb.firstseen, + 'lastseen' => hb.lastseen, + 'date_stamp' => details.get(hb.session, 'DateStamp'), + 'city' => details.get(hb.session, 'LocationCity'), + 'country' => details.get(hb.session, 'LocationCountry'), + 'country_code' => details.get(hb.session, 'LocationCountryIsoCode'), } end diff --git a/core/main/router/router.rb b/core/main/router/router.rb index 0298b1f49..9bce57523 100644 --- a/core/main/router/router.rb +++ b/core/main/router/router.rb @@ -104,24 +104,26 @@ module BeEF headers "Server" => "nginx", "Content-Type" => "text/html" else - print_error "You have an error in beef.http.web_server_imitation.type! Supported values are: apache, iis, nginx." + headers "Server" => '', + "Content-Type" => "text/html" + print_error "You have an error in beef.http.web_server_imitation.type!" + print_more "Supported values are: apache, iis, nginx." end end - # @note If CORS is enabled, expose the appropriate headers - # this apparently duplicate code is needed to reply to preflight OPTIONS requests, which need to respond with a 200 - # and be able to handle requests with a JSON content-type - if request.request_method == 'OPTIONS' && config.get("beef.http.restful_api.allow_cors") - allowed_domains = config.get("beef.http.restful_api.cors_allowed_domains") - headers "Access-Control-Allow-Origin" => allowed_domains, - "Access-Control-Allow-Methods" => "POST, GET", - "Access-Control-Allow-Headers" => "Content-Type" - halt 200 - end - # @note If CORS is enabled, expose the appropriate headers if config.get("beef.http.restful_api.allow_cors") allowed_domains = config.get("beef.http.restful_api.cors_allowed_domains") + + # Responses to preflight OPTIONS requests need to respond with hTTP 200 + # and be able to handle requests with a JSON content-type + if request.request_method == 'OPTIONS' + headers "Access-Control-Allow-Origin" => allowed_domains, + "Access-Control-Allow-Methods" => "POST, GET", + "Access-Control-Allow-Headers" => "Content-Type" + halt 200 + end + headers "Access-Control-Allow-Origin" => allowed_domains, "Access-Control-Allow-Methods" => "POST, GET" end diff --git a/extensions/admin_ui/api/command.rb b/extensions/admin_ui/api/command.rb deleted file mode 100644 index 4b6926a4f..000000000 --- a/extensions/admin_ui/api/command.rb +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright (c) 2006-2019 Wade Alcorn - wade@bindshell.net -# Browser Exploitation Framework (BeEF) - http://beefproject.com -# See the file 'doc/COPYING' for copying permission -# -module BeEF -module Extension -module AdminUI -module API - - module CommandExtension - - extend BeEF::API::Command - - include BeEF::Core::Constants::Browsers - include BeEF::Core::Constants::CommandModule - - # - # Get the browser detail from the database. - # - def get_browser_detail(key) - bd = BeEF::Core::Models::BrowserDetails - (print_error "@session_id is invalid";return) if not BeEF::Filters.is_valid_hook_session_id?(@session_id) - bd.get(@session_id, key) - end - end - -end -end -end -end diff --git a/extensions/admin_ui/api/handler.rb b/extensions/admin_ui/api/handler.rb index a319c4c78..64bea0d18 100644 --- a/extensions/admin_ui/api/handler.rb +++ b/extensions/admin_ui/api/handler.rb @@ -36,16 +36,47 @@ module API end def self.build_javascript_ui(beef_server) - auth_js_file = File.read(File.dirname(__FILE__)+'/../media/javascript/ui/authentication.js') + "\n\n" - js_files = "" - #NOTE: order counts! make sure you know what you're doing if you add files - esapi = %w(esapi/Class.create.js esapi/jquery-3.3.1.min.js esapi/jquery-encoder-0.1.0.js) - ux = %w(ui/common/beef_common.js ux/PagingStore.js ux/StatusBar.js ux/TabCloseMenu.js) - panel = %w(ui/panel/common.js ui/panel/DistributedEngine.js ui/panel/PanelStatusBar.js ui/panel/tabs/ZombieTabDetails.js ui/panel/tabs/ZombieTabLogs.js ui/panel/tabs/ZombieTabCommands.js ui/panel/tabs/ZombieTabRider.js ui/panel/tabs/ZombieTabXssRays.js wterm/wterm.jquery.js ui/panel/tabs/ZombieTabIpec.js ui/panel/tabs/ZombieTabAutorun.js ui/panel/PanelViewer.js ui/panel/LogsDataGrid.js ui/panel/ZombieDataGrid.js ui/panel/MainPanel.js ui/panel/ZombieTab.js ui/panel/ZombieTabs.js ui/panel/zombiesTreeList.js ui/panel/ZombiesMgr.js ui/panel/tabs/ZombieTabNetwork.js ui/panel/tabs/ZombieTabRTC.js ui/panel/Logout.js ui/panel/WelcomeTab.js ui/panel/ModuleSearching.js) + esapi = %w( + esapi/Class.create.js + esapi/jquery-3.3.1.min.js + esapi/jquery-encoder-0.1.0.js) + + ux = %w( + ui/common/beef_common.js + ux/PagingStore.js + ux/StatusBar.js + ux/TabCloseMenu.js) + + panel = %w( + ui/panel/common.js + ui/panel/PanelStatusBar.js + ui/panel/tabs/ZombieTabDetails.js + ui/panel/tabs/ZombieTabLogs.js + ui/panel/tabs/ZombieTabCommands.js + ui/panel/tabs/ZombieTabRider.js + ui/panel/tabs/ZombieTabXssRays.js + vis.js/vis.min.js + wterm/wterm.jquery.js + ui/panel/tabs/ZombieTabIpec.js + ui/panel/tabs/ZombieTabAutorun.js + ui/panel/PanelViewer.js + ui/panel/LogsDataGrid.js + ui/panel/ZombieDataGrid.js + ui/panel/MainPanel.js + ui/panel/ZombieTab.js + ui/panel/ZombieTabs.js + ui/panel/zombiesTreeList.js + ui/panel/ZombiesMgr.js + ui/panel/tabs/ZombieTabNetwork.js + ui/panel/tabs/ZombieTabRTC.js + ui/panel/Logout.js + ui/panel/WelcomeTab.js + ui/panel/ModuleSearching.js) global_js = esapi + ux + panel + js_files = '' global_js.each do |file| js_files << File.read(File.dirname(__FILE__)+'/../media/javascript/'+file) + "\n\n" end @@ -61,11 +92,11 @@ module API # process all JavaScript files, evaluating them with Erubis web_ui_all = self.evaluate_and_minify(js_files, params, 'web_ui_all') + auth_js_file = File.read(File.dirname(__FILE__)+'/../media/javascript/ui/authentication.js') + "\n\n" web_ui_auth = self.evaluate_and_minify(auth_js_file, params, 'web_ui_auth') beef_server.mount("#{bp}/web_ui_all.js", Rack::File.new(web_ui_all)) beef_server.mount("#{bp}/web_ui_auth.js", Rack::File.new(web_ui_auth)) - end # @@ -84,22 +115,16 @@ module API beef_server.mount("#{bp}/#{mod_name}", BeEF::Extension::AdminUI::Handlers::UI.new(mod_name)) end - # registers the http controllers used by BeEF extensions (requester, proxy, xssrays, etc..) - Dir["#{$root_dir}/extensions/**/controllers/*.rb"].each do |http_module| - require http_module - mod_name = File.basename http_module, '.rb' - beef_server.mount("#{bp}/#{mod_name}", BeEF::Extension::AdminUI::Handlers::UI.new(mod_name)) - end - # mount the folder were we store static files (javascript, css, images, audio) for the admin ui media_dir = File.dirname(__FILE__)+'/../media/' beef_server.mount("#{bp}/media", Rack::File.new(media_dir)) - # mount the favicon file, if we're not imitating a web server. + # If we're not imitating a web server, mount the favicon to /favicon.ico if !config.get("beef.http.web_server_imitation.enable") BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind( - "/extensions/admin_ui/media#{config.get("beef.extension.admin_ui.favicon_dir")}/#{config.get("beef.extension.admin_ui.favicon_file_name")}", - '/favicon.ico', 'ico') + "/extensions/admin_ui/media/images/#{config.get("beef.extension.admin_ui.favicon_file_name")}", + '/favicon.ico', + 'ico') end self.build_javascript_ui beef_server diff --git a/extensions/admin_ui/classes/httpcontroller.rb b/extensions/admin_ui/classes/httpcontroller.rb index f2d7026bd..e0a01423c 100644 --- a/extensions/admin_ui/classes/httpcontroller.rb +++ b/extensions/admin_ui/classes/httpcontroller.rb @@ -60,7 +60,7 @@ module AdminUI path = request.path_info (print_error "path is invalid";return) if not BeEF::Filters.is_valid_path_info?(path) function = @paths[path] || @paths[path + '/'] # check hash for '' and '/' - (print_error "path does not exist";return) if function.nil? + (print_error "[Admin UI] Path does not exist: #{path}";return) if function.nil? # call the relevant mapped function function.call @@ -86,17 +86,17 @@ module AdminUI # Constructs a html script tag (from media/javascript directory) def script_tag(filename) - "" + "" end # Constructs a html script tag (from media/javascript-min directory) def script_tag_min(filename) - "" + "" end # Constructs a html stylesheet tag def stylesheet_tag(filename) - "" + "" end # Constructs a hidden html nonce tag diff --git a/extensions/admin_ui/classes/session.rb b/extensions/admin_ui/classes/session.rb index 9ebbee06d..76702a59a 100644 --- a/extensions/admin_ui/classes/session.rb +++ b/extensions/admin_ui/classes/session.rb @@ -90,7 +90,6 @@ class Session # Check if a session valid # def valid_session?(request) - # check if a valid session exists return false if @id.nil? return false if @ip.nil? @@ -99,7 +98,7 @@ class Session return false if not @ip.to_s.eql? request.ip # get session cookie name from config - session_cookie_name = BeEF::Core::Configuration.instance.get('beef.http.session_cookie_name') + session_cookie_name = BeEF::Core::Configuration.instance.get('beef.extension.admin_ui.session_cookie_name') # check session id matches request.cookies.each{|cookie| @@ -110,9 +109,7 @@ class Session # not a valid session false end - -end - +end end end end diff --git a/extensions/admin_ui/config.yaml b/extensions/admin_ui/config.yaml index 52131c44c..bc9a7a94d 100644 --- a/extensions/admin_ui/config.yaml +++ b/extensions/admin_ui/config.yaml @@ -9,13 +9,13 @@ beef: name: 'Admin UI' enable: false - # Admin UI base path - base_path: "/ui" - - # Favicon - favicon_file_name: "favicon.ico" - favicon_dir: "/images" - + # Authentication and authorisation + session_cookie_name: "BEEFSESSION" login_fail_delay: 1 - play_sound_on_new_zombie: false + + # Admin UI + base_path: "/ui" + favicon_file_name: "favicon.ico" + play_sound_on_new_zombie: false + panel_update_interval: 10 # seconds diff --git a/extensions/admin_ui/constants/agents.rb b/extensions/admin_ui/constants/agents.rb deleted file mode 100644 index 4f74a5afd..000000000 --- a/extensions/admin_ui/constants/agents.rb +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright (c) 2006-2019 Wade Alcorn - wade@bindshell.net -# Browser Exploitation Framework (BeEF) - http://beefproject.com -# See the file 'doc/COPYING' for copying permission -# -module BeEF -module Extension -module AdminUI -module Constants - - # The User Agent strings for browser detection - module Agents - - AGENT_UNKNOWN_IMG = 'unknown.png' - AGENT_FIREFOX_UA_STR = 'Firefox' - AGENT_FIREFOX_IMG = 'firefox.png' - AGENT_MOZILLA_UA_STR = 'Mozilla' - AGENT_MOZILLA_IMG = 'mozilla.png' - AGENT_IE_UA_STR = 'MSIE' - AGENT_IE_IMG = 'msie.png' - AGENT_EDGE_UA_STR = 'Edge' - AGENT_EDGE_IMG = 'edge.png' - AGENT_EPIPHANY_UA_STR = 'Epiphany' - AGENT_EPIPHANY_IMG = 'epiphany.png' - AGENT_SAFARI_UA_STR = 'Safari' - AGENT_SAFARI_IMG = 'safari.png' - AGENT_KONQ_UA_STR = 'Konqueror' - AGENT_KONQ_IMG = 'konqueror.png' - AGENT_CHROME_UA_STR = 'Chrome' - AGENT_CHROME_IMG = 'chrome.png' - AGENT_OPERA_UA_STR = 'Opera' - AGENT_OPERA_IMG = 'opera.ico' - AGENT_MIDORI_UA_STR = 'Midori' - AGENT_MIDORI_IMG = 'midori.png' - AGENT_ODYSSEY_UA_STR = 'Odyssey Web Browser' - AGENT_ODYSSEY_IMG = 'odyssey.png' - AGENT_BRAVE_UA_STR = 'brave' - AGENT_BRAVE_IMG = 'brave.png' - - end - -end -end -end -end diff --git a/extensions/admin_ui/controllers/authentication/authentication.rb b/extensions/admin_ui/controllers/authentication/authentication.rb index 573456dff..281dc1565 100644 --- a/extensions/admin_ui/controllers/authentication/authentication.rb +++ b/extensions/admin_ui/controllers/authentication/authentication.rb @@ -70,7 +70,7 @@ class Authentication < BeEF::Extension::AdminUI::HttpController @session.set_logged_in(ua_ip) # create session cookie - session_cookie_name = config.get('beef.http.session_cookie_name') # get session cookie name + session_cookie_name = config.get('beef.extension.admin_ui.session_cookie_name') # get session cookie name Rack::Utils.set_cookie_header!(@headers, session_cookie_name, {:value => @session.get_id, :path => "/", :httponly => true}) BeEF::Core::Logger.instance.register('Authentication', "User with ip #{@request.ip} has successfully authenticated in the application.") @@ -94,7 +94,7 @@ class Authentication < BeEF::Extension::AdminUI::HttpController # clean up UA and expire the session cookie config = BeEF::Core::Configuration.instance - session_cookie_name = config.get('beef.http.session_cookie_name') # get session cookie name + session_cookie_name = config.get('beef.extension.admin_ui.session_cookie_name') # get session cookie name Rack::Utils.set_cookie_header!(@headers, session_cookie_name, {:value => "", :path => "/", :httponly => true, expires: Time.now}) BeEF::Core::Logger.instance.register('Authentication', "User with ip #{@request.ip} has successfully logged out.") diff --git a/extensions/admin_ui/controllers/panel/index.html b/extensions/admin_ui/controllers/panel/index.html index 1d7b8baa6..8aac18ed8 100644 --- a/extensions/admin_ui/controllers/panel/index.html +++ b/extensions/admin_ui/controllers/panel/index.html @@ -12,7 +12,6 @@ <%= script_tag 'ext-base.js' %> <%= script_tag 'ext-all.js' %> - <%= script_tag 'vis.js/vis.min.js' %> <%= script_tag_min 'web_ui_all.js' %> <%= stylesheet_tag 'wterm.css' %> <%= stylesheet_tag 'ext-all.css' %> @@ -20,7 +19,7 @@ - <%= nonce_tag %> + <%= nonce_tag %>