From 67892d46a8786a76240d159d750e905bb09e1d99 Mon Sep 17 00:00:00 2001 From: bcoles Date: Tue, 15 Mar 2022 15:30:01 +1100 Subject: [PATCH] Admin UI: Treat URL route mount failures as fatal (#2349) --- extensions/admin_ui/api/handler.rb | 96 ++++++++++++++++++------------ 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/extensions/admin_ui/api/handler.rb b/extensions/admin_ui/api/handler.rb index 21d3038e6..fd07c06ec 100644 --- a/extensions/admin_ui/api/handler.rb +++ b/extensions/admin_ui/api/handler.rb @@ -15,38 +15,46 @@ module BeEF BeEF::API::Registrar.instance.register(BeEF::Extension::AdminUI::API::Handler, BeEF::API::Server, 'mount_handler') - def self.evaluate_and_minify(content, params, name) - erubis = Erubis::FastEruby.new(content) - evaluated = erubis.evaluate(params) - - print_debug "[AdminUI] Minifying #{name} (#{evaluated.size} bytes)" + def self.evaluate_and_minify(content, params) begin - opts = { - output: { - comments: :none - }, - compress: { - dead_code: true - }, - harmony: true - } - minified = Uglifier.compile(evaluated, opts) - print_debug "[AdminUI] Minified #{name} (#{minified.size} bytes)" - rescue StandardError - print_error "[AdminUI] Error: Could not minify JavaScript file: #{name}" - print_more "[AdminUI] Ensure nodejs is installed and `node' is in `$PATH` !" - minified = evaluated + erubis = Erubis::FastEruby.new(content) + evaluated = erubis.evaluate(params) + rescue => e + print_error("[Admin UI] Evaluating with Eruby failed: #{e.message}") + return end - write_to = File.new("#{File.dirname(__FILE__)}/../media/javascript-min/#{name}.js", 'w+') - File.write(write_to, minified) - File.path write_to - rescue StandardError => e - print_error "[AdminUI] Error: #{e.message}" - print_error e.backtrace + print_debug "[AdminUI] Minifying JavaScript (#{evaluated.size} bytes)" + + opts = { + output: { + comments: :none + }, + compress: { + dead_code: true + }, + harmony: true + } + + begin + minified = Uglifier.compile(evaluated, opts) + rescue StandardError => e + print_warning "[AdminUI] Error: Could not minify '#{name}' JavaScript file: #{e.message}" + print_more "[AdminUI] Ensure nodejs is installed and `node' is in `$PATH` !" + return evaluated + end + + print_debug "[AdminUI] Minified #{evaluated.size} bytes to #{minified.size} bytes" + + return minified end - def self.build_javascript_ui(beef_server) + def self.write_minified_js(name, content) + temp_file = File.new("#{File.dirname(__FILE__)}/../media/javascript-min/#{File.basename(name)}.js", 'w+') + File.write(temp_file, content) + end + + def self.build_javascript_ui # NOTE: order counts! make sure you know what you're doing if you add files esapi = %w[ esapi/Class.create.js @@ -90,9 +98,9 @@ module BeEF global_js = esapi + ux + panel - js_files = '' - global_js.each do |file| - js_files << ("#{File.read("#{File.dirname(__FILE__)}/../media/javascript/#{file}")}\n\n") + admin_ui_js = '' + global_js.each do |file_name| + admin_ui_js << ("#{File.binread("#{File.dirname(__FILE__)}/../media/javascript/#{file_name}")}\n\n") end config = BeEF::Core::Configuration.instance @@ -106,12 +114,21 @@ module BeEF # process all JavaScript files, evaluating them with Erubis print_debug '[AdminUI] Initializing admin panel ...' - web_ui_all = 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 = 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)) + web_ui_all = evaluate_and_minify(admin_ui_js, params) + unless web_ui_all + raise StandardError, "[AdminUI] evaluate_and_minify JavaScript failed: web_ui_all JavaScript is empty" + end + write_minified_js('web_ui_all.js', web_ui_all) + + auth_js_file = "#{File.binread("#{File.dirname(__FILE__)}/../media/javascript/ui/authentication.js")}\n\n" + web_ui_auth = evaluate_and_minify(auth_js_file, params) + unless web_ui_auth + raise StandardError, "[AdminUI] evaluate_and_minify JavaScript failed: web_ui_auth JavaScript is empty" + end + write_minified_js('web_ui_auth.js', web_ui_auth) + rescue => e + raise StandardError, "Building Admin UI JavaScript failed: #{e.message}" end # @@ -130,11 +147,12 @@ module BeEF 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 + # mount the media folder where 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)) # If we're not imitating a web server, mount the favicon to /favicon.ico + # NOTE: this appears to be broken unless config.get('beef.http.web_server_imitation.enable') BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind( "/extensions/admin_ui/media/images/#{config.get('beef.extension.admin_ui.favicon_file_name')}", @@ -143,7 +161,11 @@ module BeEF ) end - build_javascript_ui beef_server + build_javascript_ui + rescue => e + print_error("[Admin UI] Could not mount URL route handlers: #{e.message}") + print_more(e.backtrace) + exit(1) end end end