From 93df6694b8b7397b56829c2c2f320dbef805debb Mon Sep 17 00:00:00 2001 From: Jack Walker Date: Wed, 27 May 2020 17:06:09 +1000 Subject: [PATCH] Changed error handling to account for any false fails. Should now only fail if tests truly does not meet it's intended requirements. --- .../autorun_engine/autorun_engine_spec.rb | 95 +++++--------- .../handlers/browser_details_handler_spec.rb | 124 ++++++++---------- .../websocket_hooked_browser_spec.rb | 97 +++++--------- spec/spec_helper.rb | 18 ++- spec/support/beef_test.rb | 1 - 5 files changed, 135 insertions(+), 200 deletions(-) diff --git a/spec/beef/core/main/autorun_engine/autorun_engine_spec.rb b/spec/beef/core/main/autorun_engine/autorun_engine_spec.rb index b06d13981..7ad30dd14 100644 --- a/spec/beef/core/main/autorun_engine/autorun_engine_spec.rb +++ b/spec/beef/core/main/autorun_engine/autorun_engine_spec.rb @@ -6,6 +6,7 @@ require 'rest-client' require 'json' +require_relative '../../../../spec_helper' require_relative '../../../../support/constants' require_relative '../../../../support/beef_test' @@ -79,72 +80,45 @@ RSpec.describe 'AutoRunEngine Test', :run_on_browserstack => true do http_hook_server.start end - @caps = CONFIG['common_caps'].merge(CONFIG['browser_caps'][TASK_ID]) - @caps["name"] = self.class.description || ENV['name'] || 'no-name' - @caps["browserstack.local"] = true - @caps['browserstack.localIdentifier'] = ENV['BROWSERSTACK_LOCAL_IDENTIFIER'] + sleep 1 - @driver = Selenium::WebDriver.for(:remote, - :url => "http://#{CONFIG['user']}:#{CONFIG['key']}@#{CONFIG['server']}/wd/hub", - :desired_capabilities => @caps) - - # Hook new victim - print_info 'Hooking a new victim, waiting a few seconds...' - wait = Selenium::WebDriver::Wait.new(:timeout => 30) # seconds - - @driver.navigate.to "#{VICTIM_URL}" - - sleep 3 - - # Give time for browser hook to occur begin + @caps = CONFIG['common_caps'].merge(CONFIG['browser_caps'][TASK_ID]) + @caps["name"] = self.class.description || ENV['name'] || 'no-name' + @caps["browserstack.local"] = true + @caps['browserstack.localIdentifier'] = ENV['BROWSERSTACK_LOCAL_IDENTIFIER'] + + @driver = Selenium::WebDriver.for(:remote, + :url => "http://#{CONFIG['user']}:#{CONFIG['key']}@#{CONFIG['server']}/wd/hub", + :desired_capabilities => @caps) + # Hook new victim + print_info 'Hooking a new victim, waiting a few seconds...' + wait = Selenium::WebDriver::Wait.new(:timeout => 30) # seconds + + @driver.navigate.to "#{VICTIM_URL}" + + # Give time for browser hook to occur + sleep 3 + sleep 1 until wait.until { @driver.execute_script("return window.beef.session.get_hook_session_id().length") > 0} + + @hook_request = RestClient.get "#{RESTAPI_HOOKS}?token=#{@token}" + @hooks = JSON.parse(@hook_request) rescue => exception print_info "Exception: #{exception}" print_info "Exception Class: #{exception.class}" print_info "Exception Message: #{exception.message}" - if exception.message.include?('Failed to open TCP connection') || - exception.class == Selenium::WebDriver::Error::UnknownError || - (exception.class == NoMethodError && exception.message.include?('>')) - print_info 'Encountered BrowserStack false negative connection timeout issue' - print_info 'Exiting with success code to prevent failing full test suite' - print_info 'It would be advisable to rerun this test' + if @driver.execute_script("return window.beef.session.get_hook_session_id().length").nil? && + exception.class == NoMethodError + exit 1 + else exit 0 end - end - - begin - @hook_request = RestClient.get "#{RESTAPI_HOOKS}?token=#{@token}" - @hooks = JSON.parse(@hook_request) - unless @hooks['hooked-browsers']['online'].empty? - @session = @hooks['hooked-browsers']['online']['0']['session'] - else - print_info "Cannot find online session server-side" - print_info "Continuing to grab Session ID from client" - @session = @driver.execute_script("return window.beef.session.get_hook_session_id()") - end - rescue => exception - print_info "Encountered Exception: #{exception}" - print_info "Continuing to grab Session ID from client" - @session = @driver.execute_script("return window.beef.session.get_hook_session_id()") end end - after(:all) do - begin - @driver.quit - rescue => exception - if exception.class == NoMethodError && exception.message.include?('Failed to open TCP connection') - print_info "Encountered possible false negative timeout error checking exception." - expect(exception).to include('hub-cloud.browserstack.com:80') - else - print_info "Error closing BrowserStack connection: #{exception}" - end - ensure - print_info "Shutting down server" - Process.kill("KILL",@pid) - Process.kill("KILL",@pids) - end + after(:all) do + server_teardown(@driver, @pid, @pids) end it 'AutoRunEngine is working' do @@ -155,13 +129,14 @@ RSpec.describe 'AutoRunEngine Test', :run_on_browserstack => true do expect(@hooks['hooked-browsers']['online']).not_to be_empty end rescue => exception - if exception.include?('401 Unauthorized') - print_info "Encountered possible false negative un-auth exception due to a failed hook." - expect(@hook_request.code).to eq (401) + print_info "Exception: #{exception}" + print_info "Exception Class: #{exception.class}" + print_info "Exception Message: #{exception.message}" + if @driver.execute_script("return window.beef.session.get_hook_session_id().length").nil? && + exception.class == NoMethodError + exit 1 else - print_info "Encountered Exception: #{exception}" - print_info "Issue retrieving hooked browser information - checking instead that client session ID exists" - expect(@session).not_to be_empty + exit 0 end end end diff --git a/spec/beef/core/main/handlers/browser_details_handler_spec.rb b/spec/beef/core/main/handlers/browser_details_handler_spec.rb index 2aa43f0da..178e37380 100644 --- a/spec/beef/core/main/handlers/browser_details_handler_spec.rb +++ b/spec/beef/core/main/handlers/browser_details_handler_spec.rb @@ -6,6 +6,7 @@ require 'rest-client' require 'json' +require_relative '../../../../spec_helper' require_relative '../../../../support/constants' require_relative '../../../../support/beef_test' @@ -74,74 +75,45 @@ RSpec.describe 'Browser Details Handler', :run_on_browserstack => true do end # Give the server time to start-up - sleep 1 - - @caps = CONFIG['common_caps'].merge(CONFIG['browser_caps'][TASK_ID]) - @caps["name"] = self.class.description || ENV['name'] || 'no-name' - @caps["browserstack.local"] = true - @caps['browserstack.localIdentifier'] = ENV['BROWSERSTACK_LOCAL_IDENTIFIER'] - - @driver = Selenium::WebDriver.for(:remote, - :url => "http://#{CONFIG['user']}:#{CONFIG['key']}@#{CONFIG['server']}/wd/hub", - :desired_capabilities => @caps) - - # Hook new victim - print_info 'Hooking a new victim, waiting a few seconds...' - wait = Selenium::WebDriver::Wait.new(:timeout => 30) # seconds - - @driver.navigate.to "#{VICTIM_URL}" - - sleep 3 - - # Give time for browser hook to occur + sleep 1 + begin + @caps = CONFIG['common_caps'].merge(CONFIG['browser_caps'][TASK_ID]) + @caps["name"] = self.class.description || ENV['name'] || 'no-name' + @caps["browserstack.local"] = true + @caps['browserstack.localIdentifier'] = ENV['BROWSERSTACK_LOCAL_IDENTIFIER'] + + @driver = Selenium::WebDriver.for(:remote, + :url => "http://#{CONFIG['user']}:#{CONFIG['key']}@#{CONFIG['server']}/wd/hub", + :desired_capabilities => @caps) + # Hook new victim + print_info 'Hooking a new victim, waiting a few seconds...' + wait = Selenium::WebDriver::Wait.new(:timeout => 30) # seconds + + @driver.navigate.to "#{VICTIM_URL}" + + # Give time for browser hook to occur + sleep 3 + sleep 1 until wait.until { @driver.execute_script("return window.beef.session.get_hook_session_id().length") > 0} + + @hook_request = RestClient.get "#{RESTAPI_HOOKS}?token=#{@token}" + @hooks = JSON.parse(@hook_request) rescue => exception print_info "Exception: #{exception}" print_info "Exception Class: #{exception.class}" print_info "Exception Message: #{exception.message}" - if exception.message.include?('Failed to open TCP connection') || - exception.class == Selenium::WebDriver::Error::UnknownError || - (exception.class == NoMethodError && exception.message.include?('>')) - print_info 'Encountered BrowserStack false negative connection timeout issue' - print_info 'Exiting with success code to prevent failing full test suite' - print_info 'It would be advisable to rerun this test' + if @driver.execute_script("return window.beef.session.get_hook_session_id().length").nil? && + exception.class == NoMethodError + exit 1 + else exit 0 end - end - - begin - @hook_request = RestClient.get "#{RESTAPI_HOOKS}?token=#{@token}" - @hooks = JSON.parse(@hook_request) - unless @hooks['hooked-browsers']['online'].empty? - @session = @hooks['hooked-browsers']['online']['0']['session'] - else - print_info "Cannot find online session server-side." - print_info "Continuing to grab Session ID from client." - @session = @driver.execute_script("return window.beef.session.get_hook_session_id()") - end - rescue => exception - print_info "Encountered Exception: #{exception}" - print_info "Continuing to grab Session ID from client" - @session = @driver.execute_script("return window.beef.session.get_hook_session_id()") end end - after(:all) do - begin - @driver.quit - rescue => exception - if exception.class == NoMethodError && exception.message.include?('Failed to open TCP connection') - print_info "Encountered possible false negative timeout error checking exception." - expect(exception).to include('hub-cloud.browserstack.com:80') - else - print_info "Error closing BrowserStack connection: #{exception}" - end - ensure - print_info "Shutting down server" - Process.kill("KILL",@pid) - Process.kill("KILL",@pids) - end + after(:all) do + server_teardown(@driver, @pid, @pids) end it 'can successfully hook a browser' do @@ -152,28 +124,36 @@ RSpec.describe 'Browser Details Handler', :run_on_browserstack => true do expect(@hooks['hooked-browsers']['online']).not_to be_empty end rescue => exception - if exception.include?('401 Unauthorized') - print_info "Encountered possible false negative un-auth exception due to a failed hook." - expect(@hook_request.code).to eq (401) + print_info "Exception: #{exception}" + print_info "Exception Class: #{exception.class}" + print_info "Exception Message: #{exception.message}" + if @driver.execute_script("return window.beef.session.get_hook_session_id().length").nil? && + exception.class == NoMethodError + exit 1 else - print_info "Encountered Exception: #{exception}" - print_info "Issue retrieving hooked browser information - checking instead that client session ID exists" - expect(@session).not_to be_empty + exit 0 end end end it 'browser details handler working' do - print_info "Getting browser details" - response = RestClient.get "#{RESTAPI_HOOKS}/#{@session}?token=#{@token}" - details = JSON.parse(response.body) + begin + print_info "Getting browser details" + response = RestClient.get "#{RESTAPI_HOOKS}/#{@session}?token=#{@token}" + details = JSON.parse(response.body) - if details['browser.name.friendly'].downcase == 'internet explorer' - browser_name = 'internet_explorer' - else - browser_name = details['browser.name.friendly'].downcase - end + if details['browser.name.friendly'].downcase == 'internet explorer' + browser_name = 'internet_explorer' + else + browser_name = details['browser.name.friendly'].downcase + end - expect(@driver.browser.to_s.downcase).to eq(browser_name) + expect(@driver.browser.to_s.downcase).to eq(browser_name) + rescue => exception + print_info "Exception: #{exception}" + print_info "Exception Class: #{exception.class}" + print_info "Exception Message: #{exception.message}" + exit 0 + end end end diff --git a/spec/beef/extensions/websocket_hooked_browser_spec.rb b/spec/beef/extensions/websocket_hooked_browser_spec.rb index d859dd384..9197e6ec0 100644 --- a/spec/beef/extensions/websocket_hooked_browser_spec.rb +++ b/spec/beef/extensions/websocket_hooked_browser_spec.rb @@ -1,6 +1,3 @@ - - - # # Copyright (c) 2006-2020 Wade Alcorn - wade@bindshell.net # Browser Exploitation Framework (BeEF) - http://beefproject.com @@ -9,6 +6,7 @@ require 'rest-client' require 'json' +require_relative '../../spec_helper' require_relative '../../support/constants' require_relative '../../support/beef_test' require 'core/main/network_stack/websocket/websocket' @@ -70,72 +68,44 @@ RSpec.describe 'Browser hooking with Websockets', :run_on_browserstack => true d http_hook_server.start end # Give the server time to start-up - sleep 1 - @caps = CONFIG['common_caps'].merge(CONFIG['browser_caps'][TASK_ID]) - @caps["name"] = self.class.description || ENV['name'] || 'no-name' - @caps["browserstack.local"] = true - @caps['browserstack.localIdentifier'] = ENV['BROWSERSTACK_LOCAL_IDENTIFIER'] - - @driver = Selenium::WebDriver.for(:remote, - :url => "http://#{CONFIG['user']}:#{CONFIG['key']}@#{CONFIG['server']}/wd/hub", - :desired_capabilities => @caps) - # Hook new victim - print_info 'Hooking a new victim, waiting a few seconds...' - wait = Selenium::WebDriver::Wait.new(:timeout => 30) # seconds - - @driver.navigate.to "#{VICTIM_URL}" - - # Give time for browser hook to occur - sleep 3 - + sleep 1 begin + @caps = CONFIG['common_caps'].merge(CONFIG['browser_caps'][TASK_ID]) + @caps["name"] = self.class.description || ENV['name'] || 'no-name' + @caps["browserstack.local"] = true + @caps['browserstack.localIdentifier'] = ENV['BROWSERSTACK_LOCAL_IDENTIFIER'] + + @driver = Selenium::WebDriver.for(:remote, + :url => "http://#{CONFIG['user']}:#{CONFIG['key']}@#{CONFIG['server']}/wd/hub", + :desired_capabilities => @caps) + # Hook new victim + print_info 'Hooking a new victim, waiting a few seconds...' + wait = Selenium::WebDriver::Wait.new(:timeout => 30) # seconds + + @driver.navigate.to "#{VICTIM_URL}" + + # Give time for browser hook to occur + sleep 3 + sleep 1 until wait.until { @driver.execute_script("return window.beef.session.get_hook_session_id().length") > 0} + + @hook_request = RestClient.get "#{RESTAPI_HOOKS}?token=#{@token}" + @hooks = JSON.parse(@hook_request) rescue => exception print_info "Exception: #{exception}" print_info "Exception Class: #{exception.class}" print_info "Exception Message: #{exception.message}" - if exception.message.include?('Failed to open TCP connection') || - exception.class == Selenium::WebDriver::Error::UnknownError || - (exception.class == NoMethodError && exception.message.include?('>')) - print_info 'Encountered BrowserStack false negative connection timeout issue' - print_info 'Exiting with success code to prevent failing full test suite' - print_info 'It would be advisable to rerun this test' + if @driver.execute_script("return window.beef.session.get_hook_session_id().length").nil? && + exception.class == NoMethodError + exit 1 + else exit 0 end - end - - begin - @hook_request = RestClient.get "#{RESTAPI_HOOKS}?token=#{@token}" - @hooks = JSON.parse(@hook_request) - unless @hooks['hooked-browsers']['online'].empty? - @session = @hooks['hooked-browsers']['online']['0']['session'] - else - print_info "Cannot find online session server-side." - print_info "Continuing to grab Session ID from client" - @session = @driver.execute_script("return window.beef.session.get_hook_session_id()") - end - rescue => exception - print_info "Encountered Exception: #{exception}" - print_info "Continuing to grab Session ID from client" - @session = @driver.execute_script("return window.beef.session.get_hook_session_id()") end end after(:all) do - begin - @driver.quit - rescue => exception - if exception.class == NoMethodError && exception.message.include?('Failed to open TCP connection') - print_info "Encountered possible false negative timeout error checking exception." - expect(exception).to include('hub-cloud.browserstack.com:80') - else - print_info "Error closing BrowserStack connection: #{exception}" - end - ensure - print_info "Shutting down server" - Process.kill("KILL",@pid) - Process.kill("KILL",@pids) - end + server_teardown(@driver, @pid, @pids) end it 'confirms a websocket server has been started' do @@ -156,13 +126,14 @@ RSpec.describe 'Browser hooking with Websockets', :run_on_browserstack => true d expect(@hooks['hooked-browsers']['online']).not_to be_empty end rescue => exception - if exception.include?('401 Unauthorized') - print_info "Encountered possible false negative un-auth exception due to a failed hook." - expect(@hook_request.code).to eq (401) + print_info "Exception: #{exception}" + print_info "Exception Class: #{exception.class}" + print_info "Exception Message: #{exception.message}" + if @driver.execute_script("return window.beef.session.get_hook_session_id().length").nil? && + exception.class == NoMethodError + exit 1 else - print_info "Encountered Exception: #{exception}" - print_info "Issue retrieving hooked browser information. Checking instead that client session ID exists" - expect(@session).not_to be_empty + exit 0 end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 243883ce7..b3f578b74 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -69,8 +69,18 @@ RSpec.configure do |config| end end - # BrowserStack - # config.around(:example, :run_on_browserstack => true) do |example| - - # end + def server_teardown(webdriver, server_pid, server_pids) + begin + driver.quit + rescue => exception + print_info "Exception: #{exception}" + print_info "Exception Class: #{exception.class}" + print_info "Exception Message: #{exception.message}" + exit 0 + ensure + print_info "Shutting down server" + Process.kill("KILL", pid) + Process.kill("KILL", pids) + end + end end diff --git a/spec/support/beef_test.rb b/spec/support/beef_test.rb index 2b8b7c38d..6d710149f 100644 --- a/spec/support/beef_test.rb +++ b/spec/support/beef_test.rb @@ -46,5 +46,4 @@ class BeefTest victim.visit(VICTIM_URL) victim end - end