From ec9cf4d460cca4bfec058291bb74c93be8178120 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Sun, 2 Mar 2014 12:56:33 +0000 Subject: [PATCH] Manually merged DNS extension code (pull request 967 from @soh-cah-toa) --- config.yaml | 2 +- extensions/dns/api.rb | 64 +-- extensions/dns/dns.rb | 258 +++++------ extensions/dns/extension.rb | 18 +- extensions/dns/model.rb | 28 +- extensions/dns/rest/dns.rb | 425 +++++++++--------- extensions/dns/ruby/rubydns.rb | 36 +- .../rest/socialengineering.rb | 4 +- .../web_cloner/web_cloner.rb | 22 +- test/integration/tc_dns_rest.rb | 22 +- .../integration/tc_social_engineering_rest.rb | 10 +- test/unit/extensions/tc_dns.rb | 12 +- test/unit/tc_grep.rb | 4 +- test/unit/ts_unit.rb | 4 +- 14 files changed, 457 insertions(+), 452 deletions(-) diff --git a/config.yaml b/config.yaml index 462a135c4..cf58d53f6 100644 --- a/config.yaml +++ b/config.yaml @@ -121,4 +121,4 @@ beef: ipec: enable: true dns: - enable: true + enable: false diff --git a/extensions/dns/api.rb b/extensions/dns/api.rb index b5cf4e65d..d7d0d050c 100644 --- a/extensions/dns/api.rb +++ b/extensions/dns/api.rb @@ -4,45 +4,45 @@ # See the file 'doc/COPYING' for copying permission # module BeEF -module Extension -module Dns -module API + module Extension + module Dns + module API - module NameserverHandler + module NameserverHandler - BeEF::API::Registrar.instance.register( - BeEF::Extension::Dns::API::NameserverHandler, - BeEF::API::Server, - 'pre_http_start' - ) + BeEF::API::Registrar.instance.register( + 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::API::Registrar.instance.register( + BeEF::Extension::Dns::API::NameserverHandler, + BeEF::API::Server, + 'mount_handler' + ) - # Begins main DNS server run-loop at BeEF startup - def self.pre_http_start(http_hook_server) - dns_config = BeEF::Core::Configuration.instance.get('beef.extension.dns') + # Begins main DNS server run-loop at BeEF startup + def self.pre_http_start(http_hook_server) + dns_config = BeEF::Core::Configuration.instance.get('beef.extension.dns') - address = dns_config['address'] - port = dns_config['port'] + address = dns_config['address'] + port = dns_config['port'] - dns = BeEF::Extension::Dns::Server.instance - dns.run_server(address, port) + dns = BeEF::Extension::Dns::Server.instance + dns.run_server(address, port) - print_info "DNS Server: #{address}:#{port}" + print_info "DNS Server: #{address}:#{port}" + end + + # Mounts handler for processing RESTful API calls + def self.mount_handler(beef_server) + beef_server.mount('/api/dns', BeEF::Extension::Dns::DnsRest.new) + end + + end + + end end - - # Mounts handler for processing RESTful API calls - def self.mount_handler(beef_server) - beef_server.mount('/api/dns', BeEF::Extension::Dns::DnsRest.new) - end - end - -end -end -end end diff --git a/extensions/dns/dns.rb b/extensions/dns/dns.rb index 050f5f37e..94c291af8 100644 --- a/extensions/dns/dns.rb +++ b/extensions/dns/dns.rb @@ -4,148 +4,148 @@ # See the file 'doc/COPYING' for copying permission # module BeEF -module Extension -module Dns + 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 + # 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 - include Singleton + include Singleton - attr_reader :address, :port + attr_reader :address, :port - # @!method self.instance - # Returns the singleton instance. Use this in place of {#initialize}. + # @!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 - @lock = Mutex.new - @server = nil - end + # @note This method cannot be invoked! Use {.instance} instead. + # @see ::instance + def initialize + @lock = Mutex.new + @server = nil + end - # Starts the main DNS server run-loop in a new thread. - # - # @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 + # Starts the main DNS server run-loop in a new thread. + # + # @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 - @lock.synchronize do - Thread.new do - # @note Calling #sleep is a quick fix that prevents race conditions - # with WebSockets. A better solution is needed; perhaps a - # global EventMachine mutex. - sleep(1) + @lock.synchronize do + Thread.new do + # @note Calling #sleep is a quick fix that prevents race conditions + # with WebSockets. A better solution is needed; perhaps a + # global EventMachine mutex. + sleep(1) - if EventMachine.reactor_running? - EventMachine.next_tick { run_server_block(@address, @port) } - else - run_server_block(@address, @port) + if EventMachine.reactor_running? + EventMachine.next_tick { run_server_block(@address, @port) } + else + run_server_block(@address, @port) + end + end end end - 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: - # - # * :id - # * :pattern - # * :type - # * :response - # - # @return [Array] 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 - server = self - BeEF::Extension::Dns::Server.instance.instance_eval { @server = server } - - # Pass unmatched queries upstream to root nameservers - otherwise do |transaction| - transaction.passthrough!( - RubyDNS::Resolver.new([[:udp, '8.8.8.8', 53], [:tcp, '8.8.8.8', 53]]) - ) + # 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: + # + # * :id + # * :pattern + # * :type + # * :response + # + # @return [Array] 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 + server = self + BeEF::Extension::Dns::Server.instance.instance_eval { @server = server } + + # Pass unmatched queries upstream to root nameservers + otherwise do |transaction| + transaction.passthrough!( + RubyDNS::Resolver.new([[:udp, '8.8.8.8', 53], [:tcp, '8.8.8.8', 53]]) + ) + end + end + end + end + end - end - -end -end end diff --git a/extensions/dns/extension.rb b/extensions/dns/extension.rb index 702f602f7..ca5ed94d7 100644 --- a/extensions/dns/extension.rb +++ b/extensions/dns/extension.rb @@ -4,18 +4,18 @@ # See the file 'doc/COPYING' for copying permission # module BeEF -module Extension -module Dns + module Extension + module Dns - extend BeEF::API::Extension + extend BeEF::API::Extension - @short_name = 'dns' - @full_name = 'DNS Server' - @description = 'A configurable DNS nameserver for performing DNS spoofing, ' + - 'hijacking, and other related attacks against hooked zombies' + @short_name = 'dns' + @full_name = 'DNS Server' + @description = 'A configurable DNS nameserver for performing DNS spoofing, ' + + 'hijacking, and other related attacks against hooked browsers.' -end -end + end + end end require 'extensions/dns/api' diff --git a/extensions/dns/model.rb b/extensions/dns/model.rb index ee6a4e291..14f5a2310 100644 --- a/extensions/dns/model.rb +++ b/extensions/dns/model.rb @@ -4,24 +4,24 @@ # See the file 'doc/COPYING' for copying permission # module BeEF -module Core -module Models -module Dns + module Core + module Models + module Dns - class Rule + class Rule - include DataMapper::Resource + include DataMapper::Resource - storage_names[:default] = 'extension_dns_rules' + storage_names[:default] = 'extension_dns_rules' - property :id, String, :key => true # Unique identifier - property :pattern, Object # Query pattern - property :type, Object # Resource type - property :block, Text # Associated callback + property :id, String, :key => true # Unique identifier + property :pattern, Object # Query pattern + property :type, Object # Resource type + property :block, Text # Associated callback + end + + end + end end - -end -end -end end diff --git a/extensions/dns/rest/dns.rb b/extensions/dns/rest/dns.rb index 754277df7..3e65d908f 100644 --- a/extensions/dns/rest/dns.rb +++ b/extensions/dns/rest/dns.rb @@ -4,242 +4,243 @@ # See the file 'doc/COPYING' for copying permission # module BeEF -module Extension -module Dns + module Extension + module Dns - # This class handles the routing of RESTful API requests that query BeEF's DNS server - class DnsRest < BeEF::Core::Router::Router + # This class handles the routing of RESTful API requests that query BeEF's DNS server + class DnsRest < BeEF::Core::Router::Router - # Filters out bad requests before performing any routing - before do - config = BeEF::Core::Configuration.instance + # Filters out bad requests before performing any routing + before do + config = BeEF::Core::Configuration.instance - # Require a valid API token from a valid IP address - halt 401 unless params[:token] == config.get('beef.api_token') - halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip) + # Require a valid API token from a valid IP address + halt 401 unless params[:token] == config.get('beef.api_token') + halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip) - headers 'Content-Type' => 'application/json; charset=UTF-8', - 'Pragma' => 'no-cache', - 'Cache-Control' => 'no-cache', - 'Expires' => '0' - end - - # Returns the entire current DNS ruleset - get '/ruleset' do - begin - ruleset = BeEF::Extension::Dns::Server.instance.get_ruleset - count = ruleset.length - - result = {} - result[:count] = count - result[:ruleset] = ruleset - result.to_json - rescue StandardError => e - print_error "Internal error while retrieving DNS ruleset (#{e.message})" - halt 500 - end - end - - # Returns a specific rule given its id - get '/rule/:id' do - begin - id = params[:id] - - unless BeEF::Filters.alphanums_only?(id) - raise InvalidParamError, 'Invalid "id" parameter passed to endpoint /api/dns/rule/:id' + headers 'Content-Type' => 'application/json; charset=UTF-8', + 'Pragma' => 'no-cache', + 'Cache-Control' => 'no-cache', + 'Expires' => '0' end - result = BeEF::Extension::Dns::Server.instance.get_rule(id) - halt 404 if result.length == 0 - - result.to_json - rescue InvalidParamError => e - print_error e.message - halt 400 - rescue StandardError => e - print_error "Internal error while retrieving DNS rule with id #{id} (#{e.message})" - halt 500 - end - end - - # Adds a new DNS rule - post '/rule' do - begin - body = JSON.parse(request.body.read) - - pattern = body['pattern'] - type = body['type'] - response = body['response'] - - # Validate required JSON keys - unless [pattern, type, response].include?(nil) - # Determine whether 'pattern' is a String or Regexp + # Returns the entire current DNS ruleset + get '/ruleset' do begin - pattern_test = eval pattern - pattern = pattern_test if pattern_test.class == Regexp - rescue => e; end + ruleset = BeEF::Extension::Dns::Server.instance.get_ruleset + count = ruleset.length - if response.class == Array - if response.length == 0 - raise InvalidJsonError, 'Empty "reponse" key passed to endpoint /api/dns/rule' + result = {} + result[:count] = count + result[:ruleset] = ruleset + result.to_json + rescue StandardError => e + print_error "Internal error while retrieving DNS ruleset (#{e.message})" + halt 500 + end + end + + # Returns a specific rule given its id + get '/rule/:id' do + begin + id = params[:id] + + unless BeEF::Filters.alphanums_only?(id) + raise InvalidParamError, 'Invalid "id" parameter passed to endpoint /api/dns/rule/:id' + end + + result = BeEF::Extension::Dns::Server.instance.get_rule(id) + halt 404 if result.length == 0 + + result.to_json + rescue InvalidParamError => e + print_error e.message + halt 400 + rescue StandardError => e + print_error "Internal error while retrieving DNS rule with id #{id} (#{e.message})" + halt 500 + end + end + + # Adds a new DNS rule + post '/rule' do + begin + body = JSON.parse(request.body.read) + + pattern = body['pattern'] + type = body['type'] + response = body['response'] + + # Validate required JSON keys + unless [pattern, type, response].include?(nil) + # Determine whether 'pattern' is a String or Regexp + begin + pattern_test = eval pattern + pattern = pattern_test if pattern_test.class == Regexp + rescue => e; end - else - raise InvalidJsonError, 'Non-array "reponse" key passed to endpoint /api/dns/rule' + + if response.class == Array + if response.length == 0 + raise InvalidJsonError, 'Empty "reponse" key passed to endpoint /api/dns/rule' + end + else + raise InvalidJsonError, 'Non-array "reponse" key passed to endpoint /api/dns/rule' + end + + unless BeEF::Filters.is_non_empty_string?(pattern) + raise InvalidJsonError, 'Empty "pattern" key passed to endpoint /api/dns/rule' + end + + unless BeEF::Filters.is_non_empty_string?(type) + raise InvalidJsonError, 'Empty "type" key passed to endpoint /api/dns/rule' + end + + id = '' + + block_src = format_response(type, response) + type_obj = eval "Resolv::DNS::Resource::IN::#{type}" + + # Bypass #add_rule so that 'block_src' can be passed as a String + BeEF::Extension::Dns::Server.instance.instance_eval do + id = @server.match(pattern, type_obj, block_src) + end + + result = {} + result['success'] = true + result['id'] = id + result.to_json + end + rescue InvalidJsonError => e + print_error e.message + halt 400 + rescue StandardError => e + print_error "Internal error while adding DNS rule (#{e.message})" + halt 500 end - - unless BeEF::Filters.is_non_empty_string?(pattern) - raise InvalidJsonError, 'Empty "pattern" key passed to endpoint /api/dns/rule' - end - - unless BeEF::Filters.is_non_empty_string?(type) - raise InvalidJsonError, 'Empty "type" key passed to endpoint /api/dns/rule' - end - - id = '' - - block_src = format_response(type, response) - type_obj = eval "Resolv::DNS::Resource::IN::#{type}" - - # Bypass #add_rule so that 'block_src' can be passed as a String - BeEF::Extension::Dns::Server.instance.instance_eval do - id = @server.match(pattern, type_obj, block_src) - end - - result = {} - result['success'] = true - result['id'] = id - result.to_json - end - rescue InvalidJsonError => e - print_error e.message - halt 400 - rescue StandardError => e - print_error "Internal error while adding DNS rule (#{e.message})" - halt 500 - end - end - - # Removes a rule given its id - delete '/rule/:id' do - begin - id = params[:id] - - unless BeEF::Filters.alphanums_only?(id) - raise InvalidParamError, 'Invalid "id" parameter passed to endpoint /api/dns/rule/:id' end - result = {} - result['success'] = BeEF::Extension::Dns::Server.instance.remove_rule(id) - result.to_json - rescue InvalidParamError => e - print_error e.message - halt 400 - rescue StandardError => e - print_error "Internal error while removing DNS rule with id #{id} (#{e.message})" - halt 500 - end - end + # Removes a rule given its id + delete '/rule/:id' do + begin + id = params[:id] - private + unless BeEF::Filters.alphanums_only?(id) + raise InvalidParamError, 'Invalid "id" parameter passed to endpoint /api/dns/rule/:id' + end - # Generates a formatted string representation of the callback to invoke as a response. - # - # @param [String] type resource record type (e.g. A, CNAME, NS, etc.) - # @param [Array] rdata record data to include in response - # - # @return [String] string representation of response callback - def format_response(type, rdata) - src = 'proc { |t| t.respond!(%s) }' + result = {} + result['success'] = BeEF::Extension::Dns::Server.instance.remove_rule(id) + result.to_json + rescue InvalidParamError => e + print_error e.message + halt 400 + rescue StandardError => e + print_error "Internal error while removing DNS rule with id #{id} (#{e.message})" + halt 500 + end + end - args = case type - when 'A' - data = { :address => rdata[0] } - sprintf "'%
s'", data - when 'AAAA' - data = { :address => rdata[0] } - sprintf "'%
s'", data - when 'CNAME' - data = { :cname => rdata[0] } - sprintf "Resolv::DNS::Name.create('%s')", data - when 'HINFO' - data = { :cpu => rdata[0], :os => rdata[1] } - sprintf "'%s', '%s'", data - when 'MINFO' - data = { :rmailbx => rdata[0], :emailbx => rdata[1] } + private - sprintf "Resolv::DNS::Name.create('%s'), " + - "Resolv::DNS::Name.create('%s')", - data - when 'MX' - data = { :preference => rdata[0], :exchange => rdata[1] } - sprintf "%d, Resolv::DNS::Name.create('%s')", data - when 'NS' - data = { :nsdname => rdata[0] } - sprintf "Resolv::DNS::Name.create('%s')", data - when 'PTR' - data = { :ptrdname => rdata[0] } - sprintf "Resolv::DNS::Name.create('%s')", data - when 'SOA' - data = { - :mname => rdata[0], - :rname => rdata[1], - :serial => rdata[2], - :refresh => rdata[3], - :retry => rdata[4], - :expire => rdata[5], - :minimum => rdata[6] - } + # Generates a formatted string representation of the callback to invoke as a response. + # + # @param [String] type resource record type (e.g. A, CNAME, NS, etc.) + # @param [Array] rdata record data to include in response + # + # @return [String] string representation of response callback + def format_response(type, rdata) + src = 'proc { |t| t.respond!(%s) }' - sprintf "Resolv::DNS::Name.create('%s'), " + - "Resolv::DNS::Name.create('%s'), " + - '%d, ' + - '%d, ' + - '%d, ' + - '%d, ' + - '%d', - data - when 'TXT' - data = { :txtdata => rdata[0] } - sprintf "'%s'", data - when 'WKS' - data = { - :address => rdata[0], - :protocol => rdata[1], - :bitmap => rdata[2] - } + args = case type + when 'A' + data = {:address => rdata[0]} + sprintf "'%
s'", data + when 'AAAA' + data = {:address => rdata[0]} + sprintf "'%
s'", data + when 'CNAME' + data = {:cname => rdata[0]} + sprintf "Resolv::DNS::Name.create('%s')", data + when 'HINFO' + data = {:cpu => rdata[0], :os => rdata[1]} + sprintf "'%s', '%s'", data + when 'MINFO' + data = {:rmailbx => rdata[0], :emailbx => rdata[1]} - sprintf "'%
s', %d, %d", data - else - raise InvalidJsonError, 'Unknown "type" key passed to endpoint /api/dns/rule' - end + sprintf "Resolv::DNS::Name.create('%s'), " + + "Resolv::DNS::Name.create('%s')", + data + when 'MX' + data = {:preference => rdata[0], :exchange => rdata[1]} + sprintf "%d, Resolv::DNS::Name.create('%s')", data + when 'NS' + data = {:nsdname => rdata[0]} + sprintf "Resolv::DNS::Name.create('%s')", data + when 'PTR' + data = {:ptrdname => rdata[0]} + sprintf "Resolv::DNS::Name.create('%s')", data + when 'SOA' + data = { + :mname => rdata[0], + :rname => rdata[1], + :serial => rdata[2], + :refresh => rdata[3], + :retry => rdata[4], + :expire => rdata[5], + :minimum => rdata[6] + } - sprintf(src, args) - end + sprintf "Resolv::DNS::Name.create('%s'), " + + "Resolv::DNS::Name.create('%s'), " + + '%d, ' + + '%d, ' + + '%d, ' + + '%d, ' + + '%d', + data + when 'TXT' + data = {:txtdata => rdata[0]} + sprintf "'%s'", data + when 'WKS' + data = { + :address => rdata[0], + :protocol => rdata[1], + :bitmap => rdata[2] + } - # Raised when invalid JSON input is passed to an /api/dns handler. - class InvalidJsonError < StandardError + sprintf "'%
s', %d, %d", data + else + raise InvalidJsonError, 'Unknown "type" key passed to endpoint /api/dns/rule' + end - DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/dns handler' + sprintf(src, args) + end + + # Raised when invalid JSON input is passed to an /api/dns handler. + class InvalidJsonError < StandardError + + DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/dns handler' + + def initialize(message = nil) + super(message || DEFAULT_MESSAGE) + end + + end + + # Raised when an invalid named parameter is passed to an /api/dns handler. + class InvalidParamError < StandardError + + DEFAULT_MESSAGE = 'Invalid parameter passed to /api/dns handler' + + def initialize(message = nil) + super(message || DEFAULT_MESSAGE) + end + + end - def initialize(message = nil) - super(message || DEFAULT_MESSAGE) end end - - # Raised when an invalid named parameter is passed to an /api/dns handler. - class InvalidParamError < StandardError - - DEFAULT_MESSAGE = 'Invalid parameter passed to /api/dns handler' - - def initialize(message = nil) - super(message || DEFAULT_MESSAGE) - end - - end - end - -end -end end diff --git a/extensions/dns/ruby/rubydns.rb b/extensions/dns/ruby/rubydns.rb index ded90a681..4bf17dc09 100644 --- a/extensions/dns/ruby/rubydns.rb +++ b/extensions/dns/ruby/rubydns.rb @@ -49,7 +49,7 @@ module RubyDNS # Now uses an 'id' parameter to uniquely identify rules def initialize(id, pattern, callback) @id = id - @pattern = pattern + @pattern = pattern @callback = callback end @@ -77,15 +77,17 @@ module RubyDNS begin # Sourcify block (already a string only for RESTful API calls) block_src = case block - when String then block - when Proc then block.to_source + when String then + block + when Proc then + block.to_source end # Break out and return id if rule is already present BeEF::Core::Models::Dns::Rule.each do |rule| if pattern[0] == rule.pattern && - pattern[1] == rule.type && - block_src == rule.block + pattern[1] == rule.type && + block_src == rule.block id = rule.id throw :match @@ -95,23 +97,23 @@ module RubyDNS id = generate_id case block - when String - @rules << Rule.new(id, pattern, eval(block_src)) - when Proc - @rules << Rule.new(id, pattern, block) + when String + @rules << Rule.new(id, pattern, eval(block_src)) + when Proc + @rules << Rule.new(id, pattern, block) end BeEF::Core::Models::Dns::Rule.create( - :id => id, - :pattern => pattern[0].to_s, - :type => pattern[1], - :block => block_src + :id => id, + :pattern => pattern[0].to_s, + :type => pattern[1], + :block => block_src ) rescue Sourcify::CannotHandleCreatedOnTheFlyProcError, - Sourcify::CannotParseEvalCodeError, - Sourcify::MultipleMatchingProcsPerLineError, - Sourcify::NoMatchingProcError, - Sourcify::ParserInternalError + Sourcify::CannotParseEvalCodeError, + Sourcify::MultipleMatchingProcsPerLineError, + Sourcify::NoMatchingProcError, + Sourcify::ParserInternalError @logger.error "Failed to sourcify block for DNS rule '#{id}'" raise diff --git a/extensions/social_engineering/rest/socialengineering.rb b/extensions/social_engineering/rest/socialengineering.rb index e36272014..8edbe4580 100644 --- a/extensions/social_engineering/rest/socialengineering.rb +++ b/extensions/social_engineering/rest/socialengineering.rb @@ -102,14 +102,14 @@ module BeEF halt 401 end - if (link =~ URI::regexp).nil?#invalid URI + if (link =~ URI::regexp).nil? #invalid URI print_error "Invalid link or linktext" halt 401 end recipients = body["recipients"][0] - recipients.each do |email,name| + recipients.each do |email, name| if !/\b[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}\z/.match(email) || name.nil? print_error "Email [#{email}] or name [#{name}] are not valid/null." halt 401 diff --git a/extensions/social_engineering/web_cloner/web_cloner.rb b/extensions/social_engineering/web_cloner/web_cloner.rb index bbd621bd4..d82f9645e 100644 --- a/extensions/social_engineering/web_cloner/web_cloner.rb +++ b/extensions/social_engineering/web_cloner/web_cloner.rb @@ -35,8 +35,9 @@ module BeEF # 2nd request. {"uri":"http://example.com", "mount":"/", "use_existing":"true"} <- serve the example.com_mod file # 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| end + begin #,"--background" + IO.popen(["wget", "#{url}", "-c", "-k", "-O", "#{@cloned_pages_dir + output}", "-U", "#{user_agent}", "--no-check-certificate"], 'r+') do |wget_io| + end success = true rescue => e print_error "Errors executing wget: #{e}" @@ -108,7 +109,7 @@ module BeEF interceptor.set :frameable, frameable interceptor.set :beef_hook, @beef_hook interceptor.set :cloned_page, get_page_content(file_path) - interceptor.set :db_entry, persist_page(url,mount) + interceptor.set :db_entry, persist_page(url, mount) @http_server.mount("#{mount}", interceptor.new) print_info "Mounting cloned page on URL [#{mount}]" @@ -117,7 +118,7 @@ module BeEF # Add a DNS record spoofing the address of the cloned webpage as the BeEF server if dns_spoof dns = BeEF::Extension::Dns::Server.instance - ip = Socket.ip_address_list.detect {|i| !(i.ipv4_loopback? || i.ipv6_loopback?)} + ip = Socket.ip_address_list.detect { |i| !(i.ipv4_loopback? || i.ipv6_loopback?) } domain = url.gsub(%r{^http://}, '') id = dns.add_rule(domain, Resolv::DNS::Resource::IN::A) do |transaction| @@ -137,12 +138,11 @@ module BeEF private # Replace with def add_beef_hook(line) - if line.include?("") - line.gsub!("","\n") - elsif - line.gsub!("","\n") - end - line + if line.include?("") + line.gsub!("", "\n") + elsif line.gsub!("", "\n") + end + line end private @@ -176,7 +176,7 @@ module BeEF end def get_page_content(file_path) - file = File.open(file_path,'r') + file = File.open(file_path, 'r') cloned_page = file.read file.close cloned_page diff --git a/test/integration/tc_dns_rest.rb b/test/integration/tc_dns_rest.rb index b6921ebf5..d5dde1a63 100644 --- a/test/integration/tc_dns_rest.rb +++ b/test/integration/tc_dns_rest.rb @@ -20,7 +20,7 @@ class TC_DnsRest < Test::Unit::TestCase json, @@headers) - result = JSON.parse(response.body) + result = JSON.parse(response.body) @@token = result['token'] $root_dir = '../../' @@ -231,13 +231,13 @@ class TC_DnsRest < Test::Unit::TestCase # Test SOA type rule['type'] = 'SOA' rule['response'] = [ - "ns.#{rule['pattern']}.", - "mail.#{rule['pattern']}.", - 2012031500, - 10800, - 3600, - 604800, - 3600 + "ns.#{rule['pattern']}.", + "mail.#{rule['pattern']}.", + 2012031500, + 10800, + 3600, + 604800, + 3600 ] regex = %r{ @@ -359,8 +359,8 @@ class TC_DnsRest < Test::Unit::TestCase # Adds a new DNS rule def add_rule(params) response = RestClient.post("#{RESTAPI_DNS}/rule?token=#{@@token}", - params.to_json, - @@headers) + params.to_json, + @@headers) check_rest_response(response) end @@ -379,7 +379,7 @@ class TC_DnsRest < Test::Unit::TestCase # Compares output of dig command against regex def check_dns_response(regex, type, pattern) address = @@config.get('beef.extension.dns.address') - port = @@config.get('beef.extension.dns.port') + port = @@config.get('beef.extension.dns.port') dig_output = `dig @#{address} -p #{port} -t #{type} #{pattern}` assert_match(regex, dig_output) diff --git a/test/integration/tc_social_engineering_rest.rb b/test/integration/tc_social_engineering_rest.rb index 9895bb0f3..5a970cdce 100644 --- a/test/integration/tc_social_engineering_rest.rb +++ b/test/integration/tc_social_engineering_rest.rb @@ -22,7 +22,7 @@ class TC_SocialEngineeringRest < Test::Unit::TestCase json, @@headers) - result = JSON.parse(response.body) + result = JSON.parse(response.body) @@token = result['token'] $root_dir = '../../' @@ -51,12 +51,12 @@ class TC_SocialEngineeringRest < Test::Unit::TestCase json = {:url => url, :mount => mount, :dns_spoof => dns_spoof}.to_json response = RestClient.post("#{RESTAPI_SENG}/clone_page?token=#{@@token}", - json, - @@headers) + json, + @@headers) check_response(response) - ip = Socket.ip_address_list.detect {|i| !(i.ipv4_loopback? || i.ipv6_loopback?)} + ip = Socket.ip_address_list.detect { |i| !(i.ipv4_loopback? || i.ipv6_loopback?) } domain = url.gsub(%r{^http://}, '') regex = %r{ @@ -69,7 +69,7 @@ class TC_SocialEngineeringRest < Test::Unit::TestCase # 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') + dns_port = @@config.get('beef.extension.dns.port') dig_output = `dig @#{dns_address} -p #{dns_port} -t A #{domain}` assert_match(regex, dig_output) diff --git a/test/unit/extensions/tc_dns.rb b/test/unit/extensions/tc_dns.rb index f6fe67687..0a9dde0bd 100644 --- a/test/unit/extensions/tc_dns.rb +++ b/test/unit/extensions/tc_dns.rb @@ -58,7 +58,7 @@ class TC_Dns < Test::Unit::TestCase # Tests that DNS server runs correctly on desired address and port def test_04_run_server address = @@dns_config['address'] - port = @@dns_config['port'] + port = @@dns_config['port'] @@dns.run_server(address, port) sleep(3) @@ -193,12 +193,12 @@ class TC_Dns < Test::Unit::TestCase # Tests the retrieval of the entire DNS ruleset def test_12_get_ruleset ruleset = @@dns.get_ruleset - ruleset.sort! {|a, b| a[:pattern] <=> b[:pattern] } + ruleset.sort! { |a, b| a[:pattern] <=> b[:pattern] } assert_equal(Array, ruleset.class) assert_equal(5, ruleset.length) - check_rule(ruleset[0], {:pattern=>'(?-mix:i\\.(love|hate)\\.beef\\.com?)', + check_rule(ruleset[0], {:pattern => '(?-mix:i\\.(love|hate)\\.beef\\.com?)', :type => 'A', :response => '9.9.9.9'}) @@ -287,7 +287,7 @@ class TC_Dns < Test::Unit::TestCase # Confirms that a query for the rule given in 'id' returns a 'type' failure status def check_failure_status(id, type) - rule = @@dns.get_rule(id) + rule = @@dns.get_rule(id) status = type.to_s.force_encoding('UTF-8').upcase assert_equal(status, rule[:response][0]) @@ -305,6 +305,8 @@ end # Suppresses unnecessary output from RubyDNS module Kernel - def puts(*args); end + def puts(*args) + ; + end end diff --git a/test/unit/tc_grep.rb b/test/unit/tc_grep.rb index 92e8e3a52..d28d277e6 100644 --- a/test/unit/tc_grep.rb +++ b/test/unit/tc_grep.rb @@ -9,12 +9,12 @@ class TC_Grep < Test::Unit::TestCase def test_grep_eval Dir['../../**/*.rb'].each do |path| - File.open( path ) do |f| + File.open(path) do |f| next if /tc_grep.rb/.match(path) # skip this file next if /\/msf-test\//.match(path) # skip this file next if /extensions\/dns/.match(path) # skip this file - f.grep( /\Weval\W/im ) do |line| + f.grep(/\Weval\W/im) do |line| assert(false, "Illegal use of 'eval' in framework: " + path + ':' + line) end end diff --git a/test/unit/ts_unit.rb b/test/unit/ts_unit.rb index d4b12ed81..571f35942 100644 --- a/test/unit/ts_unit.rb +++ b/test/unit/ts_unit.rb @@ -48,13 +48,13 @@ class TS_BeefTests suite << TC_Xssrays.suite suite << TC_Vnc.suite suite << TC_Obfuscation.suite - suite << TC_Logger.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_Hooks.suite + suite << TC_Hooks.suite suite << TC_Redirector.suite suite << TC_Dns.suite