diff --git a/VERSION b/VERSION index 644b60f8b..63fecfb58 100644 --- a/VERSION +++ b/VERSION @@ -4,4 +4,4 @@ # See the file 'doc/COPYING' for copying permission # -0.4.5.0-alpha +0.4.5.1-alpha diff --git a/beef b/beef index 2aa781350..30f446051 100755 --- a/beef +++ b/beef @@ -58,6 +58,11 @@ unless BeEF::Core::Console::CommandLine.parse[:ws_port].empty? config.set('beef.http.websocket.port', BeEF::Core::Console::CommandLine.parse[:ws_port]) end +# @note Check if interactive was specified from the command line, therefore override the extension to enable +if BeEF::Core::Console::CommandLine.parse[:interactive] == true + config.set('beef.extension.console.shell.enable',true) +end + # @note Prints BeEF welcome message BeEF::Core::Console::Banners.print_welcome_msg diff --git a/config.yaml b/config.yaml index 42cc103d7..05dbb3982 100644 --- a/config.yaml +++ b/config.yaml @@ -6,34 +6,49 @@ # BeEF Configuration file beef: - version: '0.4.5.0-alpha' + version: '0.4.5.1-alpha' # More verbose messages (server-side) debug: false # More verbose messages (client-side) client_debug: false + # Used for generating secure tokens + crypto_default_value_length: 80 + # Interface / IP restrictions restrictions: - # subnet of browser ip addresses that can hook to the framework + # subnet of IP addresses that can hook to the framework permitted_hooking_subnet: "0.0.0.0/0" - # subnet of browser ip addresses that can connect to the UI - # permitted_ui_subnet: "127.0.0.1/32" + # subnet of IP addresses that can connect to the admin UI + #permitted_ui_subnet: "127.0.0.1/32" permitted_ui_subnet: "0.0.0.0/0" + # HTTP server http: debug: false #Thin::Logging.debug, very verbose. Prints also full exception stack trace. host: "0.0.0.0" port: "3000" - # Decrease this setting up to 1000 if you want more responsiveness when sending modules and retrieving results. - # It's not advised to decrease it with tons of hooked browsers (more than 50), - # because it might impact performance. Also, enable WebSockets is generally better. + + # Decrease this setting to 1,000 (ms) if you want more responsiveness + # when sending modules and retrieving results. + # NOTE: A poll timeout of less than 5,000 (ms) might impact performance + # when hooking lots of browsers (50+). + # Enabling WebSockets is generally better (beef.websocket.enable) xhr_poll_timeout: 5000 - # if running behind a nat set the public ip address here - #public: "" - #public_port: "" # port setting is experimental + + # Reverse Proxy / NAT + # If BeEF is running behind a reverse proxy or NAT + # set the public hostname and port here + #public: "" # public hostname/IP address + #public_port: "" # experimental + # DNS dns_host: "localhost" dns_port: 53 + + # Web Admin user interface URI web_ui_basepath: "/ui" + + # Hook hook_file: "/hook.js" hook_session_name: "BEEFHOOK" session_cookie_name: "BEEFSESSION" @@ -46,16 +61,18 @@ beef: # Prefer WebSockets over XHR-polling when possible. websocket: - enable: false - secure: true # use 'WebSocketSecure' works only on HTTPS domains and with HTTPS support enabled in BeEF - port: 61985 # WS: good success rate through proxies - secure_port: 61986 # WSSecure - ws_poll_timeout: 1000 # poll BeEF every second + enable: false + port: 61985 # WS: good success rate through proxies + # Use encrypted 'WebSocketSecure' + # NOTE: works only on HTTPS domains and with HTTPS support enabled in BeEF + secure: true + secure_port: 61986 # WSSecure + ws_poll_timeout: 1000 # poll BeEF every second # Imitate a specified web server (default root page, 404 default error page, 'Server' HTTP response header) web_server_imitation: enable: true - type: "apache" #supported: apache, iis + type: "apache" # Supported: apache, iis, nginx # Experimental HTTPS support for the hook / admin / all other Thin managed web services https: @@ -89,7 +106,8 @@ beef: db_passwd: "beef123" db_encoding: "UTF-8" - # Credentials to authenticate in BeEF. Used by both the RESTful API and the Admin_UI extension + # Credentials to authenticate in BeEF. + # Used by both the RESTful API and the Admin_UI extension credentials: user: "beef" passwd: "beef" @@ -98,17 +116,16 @@ beef: # NOTE: only modules with target type 'working' or 'user_notify' can be run automatically. autorun: enable: true - # set this to FALSE if you don't want to allow auto-run execution for modules with target->user_notify + # set this to TRUE if you want to allow auto-run execution for modules with target->user_notify allow_user_notify: true - crypto_default_value_length: 80 - # IP Geolocation - # Requires MaxMind database - # curl -O http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz + # NOTE: requires MaxMind database: + # curl -O http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz + # gunzip GeoLiteCity.dat.gz && mkdir /opt/GeoIP && mv GeoLiteCity.dat /opt/GeoIP geoip: - enable: false - database: '/opt/GeoIP/GeoLiteCity.dat' + enable: false + database: '/opt/GeoIP/GeoLiteCity.dat' # You may override default extension configuration parameters here extension: diff --git a/core/filters/browser.rb b/core/filters/browser.rb index e73e0e0f7..86818efb9 100644 --- a/core/filters/browser.rb +++ b/core/filters/browser.rb @@ -12,7 +12,7 @@ module Filters def self.is_valid_browsername?(str) return false if not is_non_empty_string?(str) return false if str.length > 2 - return false if has_non_printable_char?(str) + return false if has_non_printable_char?(str) true end @@ -22,7 +22,7 @@ module Filters def self.is_valid_browsertype?(str) return false if not is_non_empty_string?(str) return false if str.length < 10 - return false if str.length > 250 + return false if str.length > 500 #CxF - had to increase this because the Chrome detection JSON String is getting bigger. return false if has_non_printable_char?(str) true end @@ -32,7 +32,7 @@ module Filters # @return [Boolean] If the string has valid Operating System name characters def self.is_valid_osname?(str) return false if not is_non_empty_string?(str) - return false if has_non_printable_char?(str) + return false if has_non_printable_char?(str) return false if str.length < 2 true end @@ -52,7 +52,7 @@ module Filters # @return [Boolean] If the string has valid browser version characters def self.is_valid_browserversion?(str) return false if not is_non_empty_string?(str) - return false if has_non_printable_char?(str) + return false if has_non_printable_char?(str) return true if str.eql? "UNKNOWN" return false if not nums_only?(str) and not is_valid_float?(str) return false if str.length > 10 @@ -64,7 +64,7 @@ module Filters # @return [Boolean] If the string has valid browser / ua string characters def self.is_valid_browserstring?(str) return false if not is_non_empty_string?(str) - return false if has_non_printable_char?(str) + return false if has_non_printable_char?(str) return false if str.length > 300 true end @@ -73,7 +73,7 @@ module Filters # @param [String] str String for testing # @return [Boolean] If the string has valid cookie characters def self.is_valid_cookies?(str) - return false if has_non_printable_char?(str) + return false if has_non_printable_char?(str) return false if str.length > 2000 true end @@ -82,7 +82,7 @@ module Filters # @param [String] str String for testing # @return [Boolean] If the string has valid screen size characters def self.is_valid_screen_size?(str) - return false if has_non_printable_char?(str) + return false if has_non_printable_char?(str) return false if str.length > 200 true end @@ -91,7 +91,7 @@ module Filters # @param [String] str String for testing # @return [Boolean] If the string has valid window size characters def self.is_valid_window_size?(str) - return false if has_non_printable_char?(str) + return false if has_non_printable_char?(str) return false if str.length > 200 true end @@ -114,6 +114,16 @@ module Filters true end + # Verify the CPU type string is valid + # @param [String] str String for testing + # @return [Boolean] If the string has valid CPU type characters + def self.is_valid_cpu?(str) + return false if not is_non_empty_string?(str) + return false if has_non_printable_char?(str) + return false if str.length > 200 + true + end + # Verify the browser_plugins string is valid # @param [String] str String for testing # @return [Boolean] If the string has valid browser plugin characters diff --git a/core/filters/page.rb b/core/filters/page.rb index 15f25ff68..6d6596c3a 100644 --- a/core/filters/page.rb +++ b/core/filters/page.rb @@ -12,7 +12,7 @@ module Filters def self.is_valid_pagetitle?(str) return false if not str.is_a? String return false if has_non_printable_char?(str) - return false if str.length > 50 + return false if str.length > 500 # CxF Increased this because some page titles are MUCH longer true end diff --git a/core/main/client/browser.js b/core/main/client/browser.js index 41331fe18..af4e0a7dd 100644 --- a/core/main/client/browser.js +++ b/core/main/client/browser.js @@ -322,7 +322,15 @@ beef.browser = { * @example: beef.browser.isFF28() */ isFF28: function () { - return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && window.navigator.userAgent.match(/Firefox\/28./) != null; + return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt !== 'function' && window.navigator.userAgent.match(/Firefox\/28./) != null; + }, + + /** + * Returns true if FF29 + * @example: beef.browser.isFF29() + */ + isFF29: function () { + return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && window.navigator.userAgent.match(/Firefox\/29./) != null; }, /** @@ -330,7 +338,7 @@ beef.browser = { * @example: beef.browser.isFF() */ isFF: function () { - return this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10() || this.isFF11() || this.isFF12() || this.isFF13() || this.isFF14() || this.isFF15() || this.isFF16() || this.isFF17() || this.isFF18() || this.isFF19() || this.isFF20() || this.isFF21() || this.isFF22() || this.isFF23() || this.isFF24() || this.isFF25() || this.isFF26() || this.isFF27() || this.isFF28(); + return this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10() || this.isFF11() || this.isFF12() || this.isFF13() || this.isFF14() || this.isFF15() || this.isFF16() || this.isFF17() || this.isFF18() || this.isFF19() || this.isFF20() || this.isFF21() || this.isFF22() || this.isFF23() || this.isFF24() || this.isFF25() || this.isFF26() || this.isFF27() || this.isFF28() || this.isFF29(); }, /** @@ -677,6 +685,14 @@ beef.browser = { return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 31) ? true : false); }, + /** + * Returns true if Chrome for iOS 31. + * @example: beef.browser.isC31iOS() + */ + isC31iOS: function () { + return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 31) ? true : false); + }, + /** * Returns true if Chrome 32. * @example: beef.browser.isC32() @@ -685,6 +701,14 @@ beef.browser = { return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 32) ? true : false); }, + /** + * Returns true if Chrome for iOS 32. + * @example: beef.browser.isC32iOS() + */ + isC32iOS: function () { + return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 32) ? true : false); + }, + /** * Returns true if Chrome 33. * @example: beef.browser.isC33() @@ -694,19 +718,68 @@ beef.browser = { }, /** - * Returns true if Chrome for iOS 31. - * @example: beef.browser.isC31iOS() - */ - isC31iOS: function () { - return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 31) ? true : false); + * Returns true if Chrome for iOS 33. + * @example: beef.browser.isC33iOS() + */ + isC33iOS: function () { + return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 33) ? true : false); }, + /** + * Returns true if Chrome 34. + * @example: beef.browser.isC34() + */ + isC34: function () { + return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 34) ? true : false); + }, + + /** + * Returns true if Chrome for iOS 34. + * @example: beef.browser.isC34iOS() + */ + isC34iOS: function () { + return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 34) ? true : false); + }, + + /** + * Returns true if Chrome 35. + * @example: beef.browser.isC35() + */ + isC35: function () { + return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 35) ? true : false); + }, + + /** + * Returns true if Chrome for iOS 35. + * @example: beef.browser.isC35iOS() + */ + isC35iOS: function () { + return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 35) ? true : false); + }, + + /** + * Returns true if Chrome 36. + * @example: beef.browser.isC36() + */ + isC36: function () { + return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 36) ? true : false); + }, + + /** + * Returns true if Chrome for iOS 36. + * @example: beef.browser.isC36iOS() + */ + isC36iOS: function () { + return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 36) ? true : false); + }, + + /** * Returns true if Chrome. * @example: beef.browser.isC() */ isC: function () { - return this.isC5() || this.isC6() || this.isC7() || this.isC8() || this.isC9() || this.isC10() || this.isC11() || this.isC12() || this.isC13() || this.isC14() || this.isC15() || this.isC16() || this.isC17() || this.isC18() || this.isC19() || this.isC19iOS() || this.isC20() || this.isC20iOS() || this.isC21() || this.isC21iOS() || this.isC22() || this.isC22iOS() || this.isC23() || this.isC23iOS() || this.isC24() || this.isC24iOS() || this.isC25() || this.isC25iOS() || this.isC26() || this.isC26iOS() || this.isC27() || this.isC27iOS() || this.isC28() || this.isC28iOS() || this.isC29() || this.isC29iOS() || this.isC30() || this.isC30iOS() || this.isC31() || this.isC32() || this.isC33() || this.isC31iOS(); + return this.isC5() || this.isC6() || this.isC7() || this.isC8() || this.isC9() || this.isC10() || this.isC11() || this.isC12() || this.isC13() || this.isC14() || this.isC15() || this.isC16() || this.isC17() || this.isC18() || this.isC19() || this.isC19iOS() || this.isC20() || this.isC20iOS() || this.isC21() || this.isC21iOS() || this.isC22() || this.isC22iOS() || this.isC23() || this.isC23iOS() || this.isC24() || this.isC24iOS() || this.isC25() || this.isC25iOS() || this.isC26() || this.isC26iOS() || this.isC27() || this.isC27iOS() || this.isC28() || this.isC28iOS() || this.isC29() || this.isC29iOS() || this.isC30() || this.isC30iOS() || this.isC31() || this.isC31iOS() || this.isC32() || this.isC32iOS() || this.isC33() || this.isC33iOS() || this.isC34() || this.isC34iOS() || this.isC35() || this.isC35iOS() || this.isC36() || this.isC36iOS(); }, /** @@ -805,9 +878,18 @@ beef.browser = { C30: this.isC30(), // Chrome 30 C30iOS: this.isC30iOS(), // Chrome 30 on iOS C31: this.isC31(), // Chrome 31 - C31: this.isC32(), // Chrome 32 - C31: this.isC33(), // Chrome 33 C31iOS: this.isC31iOS(), // Chrome 31 on iOS + C32: this.isC32(), // Chrome 32 + C32iOS: this.isC32iOS(), // Chrome 32 on iOS + C33: this.isC33(), // Chrome 33 + C33iOS: this.isC33iOS(), // Chrome 33 on iOS + C34: this.isC34(), // Chrome 34 + C34iOS: this.isC34iOS(), // Chrome 34 on iOS + C35: this.isC35(), // Chrome 35 + C35iOS: this.isC35iOS(), // Chrome 35 on iOS + C36: this.isC36(), // Chrome 36 + C36iOS: this.isC36iOS(), // Chrome 36 on iOS + C: this.isC(), // Chrome any version FF2: this.isFF2(), // Firefox 2 @@ -837,8 +919,9 @@ beef.browser = { FF24: this.isFF24(), // Firefox 24 FF25: this.isFF25(), // Firefox 25 FF26: this.isFF26(), // Firefox 26 - FF26: this.isFF27(), // Firefox 27 - FF26: this.isFF28(), // Firefox 28 + FF27: this.isFF27(), // Firefox 27 + FF28: this.isFF28(), // Firefox 28 + FF29: this.isFF29(), // Firefox 29 FF: this.isFF(), // Firefox any version IE6: this.isIE6(), // Internet Explorer 6 @@ -1026,19 +1109,51 @@ beef.browser = { if (this.isC31()) { return '31' } - ; - if (this.isC32()) { - return '32' - } - ; - if (this.isC33()) { - return '33' - } - ;// Chrome 31 + ; // Chrome 31 if (this.isC31iOS()) { return '31' } ; // Chrome 31 for iOS + if (this.isC32()) { + return '32' + } + ; // Chrome 32 + if (this.isC32iOS()) { + return '32' + } + ; // Chrome 32 for iOS + if (this.isC33()) { + return '33' + } + ; // Chrome 33 + if (this.isC33iOS()) { + return '33' + } + ; // Chrome 33 for iOS + if (this.isC34()) { + return '34' + } + ; // Chrome 34 + if (this.isC34iOS()) { + return '34' + } + ; // Chrome 34 for iOS + if (this.isC35()) { + return '35' + } + ; // Chrome 35 + if (this.isC35iOS()) { + return '35' + } + ; // Chrome 35 for iOS + if (this.isC36()) { + return '36' + } + ; // Chrome 36 + if (this.isC36iOS()) { + return '36' + } + ; // Chrome 36 for iOS if (this.isFF2()) { return '2' } @@ -1155,6 +1270,10 @@ beef.browser = { return '28' } ; // Firefox 28 + if (this.isFF29()) { + return '29' + } + ; // Firefox 29 if (this.isIE6()) { return '6' @@ -1479,7 +1598,7 @@ beef.browser = { }, /** - * Checks if the Phonegap API is available from the hooked domain. + * Checks if the Phonegap API is available from the hooked origin. * @return: {Boolean} true or false. * * @example: if(beef.browser.hasPhonegap()) { ... } @@ -1871,9 +1990,9 @@ beef.browser = { if (has_session_cookies) details['hasSessionCookies'] = has_session_cookies; if (has_persistent_cookies) details['hasPersistentCookies'] = has_persistent_cookies; } catch (e) { - // the hooked domain is using HttpOnly. EverCookie is persisting the BeEF hook in a different way, + // the hooked origin is using HttpOnly. EverCookie is persisting the BeEF hook in a different way, // and there is no reason to read cookies at this point - details['Cookies'] = "Cookies can't be read. The hooked domain is most probably using HttpOnly."; + details['Cookies'] = "Cookies can't be read. The hooked origin is most probably using HttpOnly."; details['hasSessionCookies'] = "No"; details['hasPersistentCookies'] = "No"; } @@ -2146,10 +2265,9 @@ beef.browser = { if (scope == 'PER_DOMAIN') testUrl = "http://browserspy.dk/connections.php?img=1&random="; else - // The token will be replaced by a different number with each request(different domain). + // The token will be replaced by a different number with each request (different origin). testUrl = "http://.browserspy.dk/connections.php?img=1&random="; - var imagesLoaded = 0; // Number of responding images before timeout. var imagesRequested = 0; // Number of requested images. var testImages = new Array(); // Array of all images. diff --git a/core/main/client/net/cors.js b/core/main/client/net/cors.js index 01cf86008..cf12dcffe 100644 --- a/core/main/client/net/cors.js +++ b/core/main/client/net/cors.js @@ -12,7 +12,7 @@ beef.net.cors = { }, /** - * Make a cross-domain request using CORS + * Make a cross-origin request using CORS * * @param method {String} HTTP verb ('GET', 'POST', 'DELETE', etc.) * @param url {String} url diff --git a/core/main/client/timeout.js b/core/main/client/timeout.js index c766ade42..77719a79a 100644 --- a/core/main/client/timeout.js +++ b/core/main/client/timeout.js @@ -6,7 +6,7 @@ /* Sometimes there are timing issues and looks like beef_init - is not called at all (always in cross-domain situations, + is not called at all (always in cross-origin situations, for example calling the hook with jquery getScript, or sometimes with event handler injections). diff --git a/core/main/client/websocket.js b/core/main/client/websocket.js index 551ce17c8..122e16631 100644 --- a/core/main/client/websocket.js +++ b/core/main/client/websocket.js @@ -20,7 +20,7 @@ beef.websocket = { /** * Initialize the WebSocket client object. - * Note: use WebSocketSecure only if the hooked domain is under https. + * Note: use WebSocketSecure only if the hooked origin is under https. * Mixed-content in WS is quite different from a non-WS context. */ init:function () { diff --git a/core/main/console/commandline.rb b/core/main/console/commandline.rb index f61af94b1..5dadde941 100644 --- a/core/main/console/commandline.rb +++ b/core/main/console/commandline.rb @@ -18,6 +18,7 @@ module BeEF @options[:ext_config] = "" @options[:port] = "" @options[:ws_port] = "" + @options[:interactive] = false @already_parsed = false @@ -54,6 +55,10 @@ module BeEF opts.on('-w', '--wsport WS_PORT', 'Change the default BeEF WebSocket listening port') do |ws_port| @options[:ws_port] = ws_port end + + opts.on('-i', '--interactive', 'Starts with the Console Shell activated') do + @options[:interactive] = true + end end optparse.parse! diff --git a/core/main/handlers/browserdetails.rb b/core/main/handlers/browserdetails.rb index bbc1abde7..03d593d83 100644 --- a/core/main/handlers/browserdetails.rb +++ b/core/main/handlers/browserdetails.rb @@ -288,105 +288,25 @@ module BeEF self.err_msg "Invalid window size returned from the hook browser's initial connection." end - # get and store the yes|no value for VBScriptEnabled - vbscript_enabled = get_param(@data['results'], 'VBScriptEnabled') - if BeEF::Filters.is_valid_yes_no?(vbscript_enabled) - BD.set(session_id, 'VBScriptEnabled', vbscript_enabled) - else - self.err_msg "Invalid value for VBScriptEnabled returned from the hook browser's initial connection." - end - - # get and store the yes|no value for HasFlash - has_flash = get_param(@data['results'], 'HasFlash') - if BeEF::Filters.is_valid_yes_no?(has_flash) - BD.set(session_id, 'HasFlash', has_flash) - else - self.err_msg "Invalid value for HasFlash returned from the hook browser's initial connection." - end - - # get and store the yes|no value for HasPhonegap - has_phonegap = get_param(@data['results'], 'HasPhonegap') - if BeEF::Filters.is_valid_yes_no?(has_phonegap) - BD.set(session_id, 'HasPhonegap', has_phonegap) - else - self.err_msg "Invalid value for HasPhonegap returned from the hook browser's initial connection." - end - - # get and store the yes|no value for HasGoogleGears - has_googlegears = get_param(@data['results'], 'HasGoogleGears') - if BeEF::Filters.is_valid_yes_no?(has_googlegears) - BD.set(session_id, 'HasGoogleGears', has_googlegears) - else - self.err_msg "Invalid value for HasGoogleGears returned from the hook browser's initial connection." - end - - # get and store the yes|no value for HasFoxit - has_foxit = get_param(@data['results'], 'HasFoxit') - if BeEF::Filters.is_valid_yes_no?(has_foxit) - BD.set(session_id, 'HasFoxit', has_foxit) - else - self.err_msg "Invalid value for HasFoxit returned from the hook browser's initial connection." - end - - # get and store the yes|no value for HasWebSocket - has_web_socket = get_param(@data['results'], 'HasWebSocket') - if BeEF::Filters.is_valid_yes_no?(has_web_socket) - BD.set(session_id, 'HasWebSocket', has_web_socket) - else - self.err_msg "Invalid value for HasWebSocket returned from the hook browser's initial connection." - end - - # get and store the yes|no value for HasWebRTC - has_webrtc = get_param(@data['results'], 'HasWebRTC') - if BeEF::Filters.is_valid_yes_no?(has_webrtc) - BD.set(session_id, 'HasWebRTC', has_webrtc) - else - self.err_msg "Invalid value for HasWebRTC returned from the hook browser's initial connection." - end - - # get and store the yes|no value for HasActiveX - has_activex = get_param(@data['results'], 'HasActiveX') - if BeEF::Filters.is_valid_yes_no?(has_activex) - BD.set(session_id, 'HasActiveX', has_activex) - else - self.err_msg "Invalid value for HasActiveX returned from the hook browser's initial connection." - end - - # get and store the yes|no value for HasSilverlight - has_silverlight = get_param(@data['results'], 'HasSilverlight') - if BeEF::Filters.is_valid_yes_no?(has_silverlight) - BD.set(session_id, 'HasSilverlight', has_silverlight) - else - self.err_msg "Invalid value for HasSilverlight returned from the hook browser's initial connection." - end - - # get and store the yes|no value for HasQuickTime - has_quicktime = get_param(@data['results'], 'HasQuickTime') - if BeEF::Filters.is_valid_yes_no?(has_quicktime) - BD.set(session_id, 'HasQuickTime', has_quicktime) - else - self.err_msg "Invalid value for HasQuickTime returned from the hook browser's initial connection." - end - - # get and store the yes|no value for HasRealPlayer - has_realplayer = get_param(@data['results'], 'HasRealPlayer') - if BeEF::Filters.is_valid_yes_no?(has_realplayer) - BD.set(session_id, 'HasRealPlayer', has_realplayer) - else - self.err_msg "Invalid value for HasRealPlayer returned from the hook browser's initial connection." - end - - # get and store the yes|no value for HasWMP - has_wmp = get_param(@data['results'], 'HasWMP') - if BeEF::Filters.is_valid_yes_no?(has_wmp) - BD.set(session_id, 'HasWMP', has_wmp) - else - self.err_msg "Invalid value for HasWMP returned from the hook browser's initial connection." + # get and store the yes|no value for browser components + components = [ + 'VBScriptEnabled', 'HasFlash', 'HasPhonegap', 'HasGoogleGears', + 'HasFoxit', 'HasWebSocket', 'HasWebRTC', 'HasActiveX', + 'HasSilverlight', 'HasQuickTime', 'HasRealPlayer', 'HasWMP', + 'hasSessionCookies', 'hasPersistentCookies' + ] + components.each do |k| + v = get_param(@data['results'], k) + if BeEF::Filters.is_valid_yes_no?(v) + BD.set(session_id, k, v) + else + self.err_msg "Invalid value for #{k} returned from the hook browser's initial connection." + end end # get and store the value for CPU cpu_type = get_param(@data['results'], 'CPU') - if !cpu_type.nil? + if BeEF::Filters.is_valid_cpu?(cpu_type) BD.set(session_id, 'CPU', cpu_type) else self.err_msg "Invalid value for CPU returned from the hook browser's initial connection." @@ -400,22 +320,6 @@ module BeEF self.err_msg "Invalid value for TouchEnabled returned from the hook browser's initial connection." end - # get and store whether the browser has session cookies enabled - has_session_cookies = get_param(@data['results'], 'hasSessionCookies') - if BeEF::Filters.is_valid_yes_no?(has_session_cookies) - BD.set(session_id, 'hasSessionCookies', has_session_cookies) - else - self.err_msg "Invalid value for hasSessionCookies returned from the hook browser's initial connection." - end - - # get and store whether the browser has persistent cookies enabled - has_persistent_cookies = get_param(@data['results'], 'hasPersistentCookies') - if BeEF::Filters.is_valid_yes_no?(has_persistent_cookies) - BD.set(session_id, 'hasPersistentCookies', has_persistent_cookies) - else - self.err_msg "Invalid value for hasPersistentCookies returned from the hook browser's initial connection." - end - # log a few info of newly hooked zombie in the console print_info "New Hooked Browser [id:#{zombie.id}, ip:#{zombie.ip}, type:#{browser_name}-#{browser_version}, os:#{os_name}], hooked domain [#{log_zombie_domain}:#{log_zombie_port.to_s}]" diff --git a/core/main/rest/handlers/server.rb b/core/main/rest/handlers/server.rb index a2d02c6fb..e10a1a210 100644 --- a/core/main/rest/handlers/server.rb +++ b/core/main/rest/handlers/server.rb @@ -35,7 +35,11 @@ module BeEF error 400 end end + + get '/version' do + { 'version' => config.get('beef.version') }.to_json + end end end end -end \ No newline at end of file +end diff --git a/core/main/router/router.rb b/core/main/router/router.rb index d9197c7af..0c851af18 100644 --- a/core/main/router/router.rb +++ b/core/main/router/router.rb @@ -66,6 +66,15 @@ module BeEF "and search for topics titled Web Site Setup, Common Administrative Tasks, and About Custom Error Messages." + "" + "" + when "nginx" + #response body + "\n"+ + "404 Not Found\n" + + "\n" + + "

404 Not Found

\n" + + "
nginx
\n" + + "\n" + + "\n" else "Not Found." end @@ -87,12 +96,15 @@ module BeEF headers "Server" => "Microsoft-IIS/6.0", "X-Powered-By" => "ASP.NET", "Content-Type" => "text/html; charset=UTF-8" + when "nginx" + headers "Server" => "nginx", + "Content-Type" => "text/html" else - print_error "You have and error in beef.http.web_server_imitation.type! Supported values are: apache, iis." + print_error "You have an error in beef.http.web_server_imitation.type! Supported values are: apache, iis, nginx." end end - # @note If CORS are enabled, expose the appropriate headers + # @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") @@ -103,7 +115,7 @@ module BeEF halt 200 end - # @note If CORS are enabled, expose the appropriate headers + # @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") headers "Access-Control-Allow-Origin" => allowed_domains, @@ -255,6 +267,30 @@ module BeEF "" + "" + "" + when "nginx" + "\n" + + "\n" + + "\n" + + "Welcome to nginx!\n" + + "\n" + + "\n" + + "\n" + + "

Welcome to nginx!

\n" + + "

If you see this page, the nginx web server is successfully installed and\n" + + "working. Further configuration is required.

\n\n" + + "

For online documentation and support please refer to\n" + + "nginx.org.
\n" + + "Commercial support is available at\n" + + "nginx.com.

\n\n" + + "

Thank you for using nginx.

\n" + + "\n" + + "\n" else "" end @@ -264,4 +300,4 @@ module BeEF end end end -end \ No newline at end of file +end diff --git a/core/main/server.rb b/core/main/server.rb index f82eb9d7d..6b321d21f 100644 --- a/core/main/server.rb +++ b/core/main/server.rb @@ -109,7 +109,7 @@ module BeEF if @configuration.get('beef.http.https.enable') == true openssl_version = OpenSSL::OPENSSL_VERSION - if openssl_version =~ / 1\.0\.1([a-f])/ + if openssl_version =~ / 1\.0\.1([a-f])? / print_warning "Warning: #{openssl_version} is vulnerable to Heartbleed (CVE-2014-0160)." print_more "Upgrade OpenSSL to version 1.0.1g or newer." end diff --git a/modules/browser/browser_fingerprinting/config.yaml b/modules/browser/browser_fingerprinting/config.yaml index 31b29f98b..27979730e 100644 --- a/modules/browser/browser_fingerprinting/config.yaml +++ b/modules/browser/browser_fingerprinting/config.yaml @@ -8,8 +8,8 @@ beef: browser_fingerprinting: enable: true category: "Browser" - name: "Fingerprint Browser" - description: "This module attempts to fingerprint the browser type and version using URI handlers unique to Safari, Internet Explorer and Mozilla Firefox. This method does not rely on JavaScript objects which may have been modified by the user or browser compatibility mode." + name: "Fingerprint Browser (PoC)" + description: "This module attempts to fingerprint the browser type and version using URI protocol handlers unique to Safari, Internet Explorer and Mozilla Firefox." authors: ["bcoles"] target: working: ["IE", "FF", "S"]