Changed Dns::Server to use RubyDNS 0.7.x API.
At this point, it is just a prototype that resolves any request to 1.1.1.1.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -11,34 +11,41 @@ module BeEF
|
||||
module NameserverHandler
|
||||
|
||||
BeEF::API::Registrar.instance.register(
|
||||
BeEF::Extension::Dns::API::NameserverHandler,
|
||||
BeEF::API::Server,
|
||||
'pre_http_start'
|
||||
BeEF::Extension::Dns::API::NameserverHandler,
|
||||
BeEF::API::Server,
|
||||
'pre_http_start'
|
||||
)
|
||||
|
||||
BeEF::API::Registrar.instance.register(
|
||||
BeEF::Extension::Dns::API::NameserverHandler,
|
||||
BeEF::API::Server,
|
||||
'mount_handler'
|
||||
BeEF::Extension::Dns::API::NameserverHandler,
|
||||
BeEF::API::Server,
|
||||
'mount_handler'
|
||||
)
|
||||
|
||||
# Begins main DNS server run-loop at BeEF startup
|
||||
# Starts the DNS nameserver at BeEF startup.
|
||||
#
|
||||
# @param http_hook_server [BeEF::Core::Server] HTTP server instance
|
||||
def self.pre_http_start(http_hook_server)
|
||||
dns_config = BeEF::Core::Configuration.instance.get('beef.extension.dns')
|
||||
dns = BeEF::Extension::Dns::Server.instance
|
||||
|
||||
protocol = dns_config['protocol'].to_sym
|
||||
address = dns_config['address']
|
||||
port = dns_config['port']
|
||||
interfaces = [[protocol, address, port]]
|
||||
|
||||
dns = BeEF::Extension::Dns::Server.instance
|
||||
dns.run_server(address, port)
|
||||
Thread.new { EventMachine.next_tick { dns.run(:listen => interfaces) } }
|
||||
|
||||
print_info "DNS Server: #{address}:#{port}"
|
||||
print_info "DNS Server: #{address}:#{port} (#{protocol})"
|
||||
|
||||
# @todo Upstream servers are not yet supported. Uncomment this section when they are.
|
||||
=begin
|
||||
servers = []
|
||||
|
||||
unless dns_config['upstream'].nil?
|
||||
dns_config['upstream'].each do |server|
|
||||
if server[1].nil? or server[2].nil?
|
||||
next
|
||||
end
|
||||
next if server[1].nil? or server[2].nil?
|
||||
|
||||
if server[0] == 'tcp'
|
||||
servers << ['tcp', server[1], server[2]]
|
||||
elsif server[0] == 'udp'
|
||||
@@ -46,20 +53,27 @@ module BeEF
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if servers.empty?
|
||||
servers << ['tcp', '8.8.8.8', 53]
|
||||
servers << ['udp', '8.8.8.8', 53]
|
||||
end
|
||||
|
||||
upstream_servers = ''
|
||||
servers.each do |server|
|
||||
upstream_servers << "Upstream server: #{server[1]}:#{server[2]} (#{server[0]})\n"
|
||||
upstream_servers << "Upstream Server: #{server[1]}:#{server[2]} (#{server[0]})\n"
|
||||
end
|
||||
|
||||
print_more upstream_servers
|
||||
=end
|
||||
end
|
||||
|
||||
# Mounts handler for processing RESTful API calls
|
||||
# Mounts the handler for processing DNS RESTful API requests.
|
||||
#
|
||||
# @param beef_server [BeEF::Core::Server] HTTP server instance
|
||||
def self.mount_handler(beef_server)
|
||||
beef_server.mount('/api/dns', BeEF::Extension::Dns::DnsRest.new)
|
||||
# @todo Uncomment when RESTful API is DNS 2.0 compliant.
|
||||
#beef_server.mount('/api/dns', BeEF::Extension::Dns::DnsRest.new)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -7,156 +7,30 @@ module BeEF
|
||||
module Extension
|
||||
module Dns
|
||||
|
||||
# This class is responsible for providing a DNS nameserver that can be dynamically
|
||||
# configured by other modules and extensions. It is particularly useful for
|
||||
# performing DNS spoofing, hijacking, tunneling, etc.
|
||||
#
|
||||
# Only a single instance will exist during runtime (known as the "singleton pattern").
|
||||
# This makes it easier to coordinate actions across the various BeEF systems.
|
||||
class Server
|
||||
# @todo Add option for configuring upstream servers.
|
||||
|
||||
# Provides the core DNS nameserver functionality. The nameserver handles incoming requests
|
||||
# using a rule-based system. A list of user-defined rules is used to match against incoming
|
||||
# DNS requests. These rules generate a response that is either a resource record or a
|
||||
# failure code.
|
||||
class Server < RubyDNS::Server
|
||||
|
||||
include Singleton
|
||||
|
||||
attr_reader :address, :port
|
||||
|
||||
# @!method self.instance
|
||||
# Returns the singleton instance. Use this in place of {#initialize}.
|
||||
|
||||
# @note This method cannot be invoked! Use {.instance} instead.
|
||||
# @see ::instance
|
||||
def initialize
|
||||
super()
|
||||
@lock = Mutex.new
|
||||
@server = nil
|
||||
end
|
||||
|
||||
def set_server(server)
|
||||
@server = server
|
||||
end
|
||||
|
||||
def get_server
|
||||
@server
|
||||
end
|
||||
|
||||
# Starts the main DNS server run-loop in a new thread.
|
||||
# Entry point for processing incoming DNS requests. Attempts to find a matching rule and
|
||||
# sends back its associated response.
|
||||
#
|
||||
# @param address [String] interface address server should run on
|
||||
# @param port [Integer] desired server port number
|
||||
def run_server(address = '0.0.0.0', port = 5300)
|
||||
@address = address
|
||||
@port = port
|
||||
Thread.new do
|
||||
sleep(2)
|
||||
|
||||
# antisnatchor: RubyDNS is already implemented with EventMachine
|
||||
run_server_block(@address, @port)
|
||||
end
|
||||
end
|
||||
|
||||
# Adds a new DNS rule or "resource record". Does nothing if rule is already present.
|
||||
#
|
||||
# @example Adds an A record for foobar.com with the value 1.2.3.4
|
||||
#
|
||||
# dns = BeEF::Extension::Dns::Server.instance
|
||||
#
|
||||
# id = dns.add_rule('foobar.com', Resolv::DNS::Resource::IN::A) do |transaction|
|
||||
# transaction.respond!('1.2.3.4')
|
||||
# end
|
||||
#
|
||||
# @param pattern [String, Regexp] query pattern to recognize
|
||||
# @param type [Resolv::DNS::Resource::IN] resource record type (e.g. A, CNAME, NS, etc.)
|
||||
#
|
||||
# @note When parameter 'pattern' is a literal Regexp object, it must NOT be passed
|
||||
# using the /.../ literal syntax. Instead use either %r{...} or Regexp::new.
|
||||
# This does not apply if 'pattern' is a variable.
|
||||
#
|
||||
# @yield callback to invoke when pattern is matched
|
||||
# @yieldparam transaction [RubyDNS::Transaction] details of query question and response
|
||||
#
|
||||
# @return [String] unique 7-digit hex identifier for use with {#remove_rule}
|
||||
#
|
||||
# @see #remove_rule
|
||||
# @see http://rubydoc.info/gems/rubydns/RubyDNS/Transaction
|
||||
def add_rule(pattern, type, &block)
|
||||
@lock.synchronize { @server.match(pattern, type, block) }
|
||||
end
|
||||
|
||||
# Removes the given DNS rule. Any future queries for it will be passed through.
|
||||
#
|
||||
# @param id [Integer] id returned from {#add_rule}
|
||||
#
|
||||
# @return [Boolean] true on success, false on failure
|
||||
#
|
||||
# @see #add_rule
|
||||
def remove_rule(id)
|
||||
@lock.synchronize { @server.remove_rule(id) }
|
||||
end
|
||||
|
||||
# Retrieves a specific rule given its id
|
||||
#
|
||||
# @param id [Integer] unique identifier for rule
|
||||
#
|
||||
# @return [Hash] hash representation of rule
|
||||
def get_rule(id)
|
||||
@lock.synchronize { @server.get_rule(id) }
|
||||
end
|
||||
|
||||
# Returns an AoH representing the entire current DNS ruleset.
|
||||
#
|
||||
# Each element is a hash with the following keys:
|
||||
#
|
||||
# * <code>:id</code>
|
||||
# * <code>:pattern</code>
|
||||
# * <code>:type</code>
|
||||
# * <code>:response</code>
|
||||
#
|
||||
# @return [Array<Hash>] DNS ruleset (empty if no rules are currently loaded)
|
||||
def get_ruleset
|
||||
@lock.synchronize { @server.get_ruleset }
|
||||
end
|
||||
|
||||
# Clears the entire DNS ruleset.
|
||||
#
|
||||
# Requests made after doing so will be passed through to the root nameservers.
|
||||
#
|
||||
# @return [Boolean] true on success, false on failure
|
||||
def remove_ruleset
|
||||
@lock.synchronize { @server.remove_ruleset }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Common code needed by {#run_server} to start DNS server.
|
||||
#
|
||||
# @param address [String] interface address server should run on
|
||||
# @param port [Integer] desired server port number
|
||||
def run_server_block(address, port)
|
||||
RubyDNS.run_server(:listen => [[:udp, address, port]]) do
|
||||
# Pass unmatched queries upstream to root nameservers
|
||||
dns_config = BeEF::Core::Configuration.instance.get('beef.extension.dns')
|
||||
unless dns_config['upstream'].nil?
|
||||
dns_config['upstream'].each do |server|
|
||||
if server[1].nil? or server[2].nil?
|
||||
print_error "Invalid server '#{server[1]}:#{server[2]}' specified for upstream DNS server."
|
||||
next
|
||||
elsif server[0] == 'tcp'
|
||||
servers << [:tcp, server[1], server[2]]
|
||||
elsif server[0] == 'udp'
|
||||
servers << [:udp, server[1], server[2]]
|
||||
else
|
||||
print_error "Invalid protocol '#{server[0]}' specified for upstream DNS server."
|
||||
end
|
||||
end
|
||||
end
|
||||
if servers.empty?
|
||||
print_debug "No upstream DNS servers specified. Using '8.8.8.8'"
|
||||
servers << [:tcp, '8.8.8.8', 53]
|
||||
servers << [:udp, '8.8.8.8', 53]
|
||||
end
|
||||
otherwise do |transaction|
|
||||
transaction.passthrough!(
|
||||
RubyDNS::Resolver.new servers
|
||||
)
|
||||
end
|
||||
# @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
|
||||
transaction.respond!('1.1.1.1')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2013 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -18,9 +18,9 @@ module BeEF
|
||||
end
|
||||
end
|
||||
|
||||
#TODO antisnatchor: uncomment this when code will be stable
|
||||
#require 'extensions/dns/api'
|
||||
#require 'extensions/dns/dns'
|
||||
#require 'extensions/dns/model'
|
||||
require 'extensions/dns/api'
|
||||
require 'extensions/dns/dns'
|
||||
require 'extensions/dns/logger'
|
||||
require 'extensions/dns/model'
|
||||
# @todo Uncomment when RESTful API is DNS 2.0 compliant.
|
||||
#require 'extensions/dns/rest/dns'
|
||||
#require 'extensions/dns/ruby'
|
||||
|
||||
Reference in New Issue
Block a user