164 lines
4.1 KiB
Ruby
164 lines
4.1 KiB
Ruby
# -*- coding: binary -*-
|
|
require 'msf/core'
|
|
require 'rex/proto/dns'
|
|
require 'msf/core/exploit/dns/common'
|
|
|
|
module Msf
|
|
|
|
###
|
|
#
|
|
# This module exposes methods for querying a remote DNS service
|
|
#
|
|
###
|
|
module Exploit::Remote::DNS
|
|
module Server
|
|
include Exploit::Remote::DNS::Common
|
|
include Exploit::Remote::SocketServer
|
|
|
|
#
|
|
# Initializes an exploit module that serves DNS requests
|
|
#
|
|
def initialize(info = {})
|
|
super
|
|
|
|
register_options(
|
|
[
|
|
OptPort.new('SRVPORT', [true, 'The local port to listen on.', 53]),
|
|
OptString.new('STATIC_ENTRIES', [ false, "DNS domain search list (hosts file or space/semicolon separate entries)"]),
|
|
OptBool.new('DISABLE_RESOLVER', [ false, "Disable DNS request forwarding", false]),
|
|
OptBool.new('DISABLE_NS_CACHE', [ false, "Disable DNS response caching", false])
|
|
], Exploit::Remote::DNS::Server
|
|
)
|
|
|
|
register_advanced_options(
|
|
[
|
|
OptBool.new('DnsServerUdp', [true, "Serve UDP DNS requests", true]),
|
|
OptBool.new('DnsServerTcp', [true, "Serve TCP DNS requests", false])
|
|
], Exploit::Remote::DNS::Server
|
|
)
|
|
end
|
|
|
|
attr_accessor :service # :nodoc:
|
|
|
|
#
|
|
# Process static entries
|
|
#
|
|
# @param entries [String] Filename or String containing static entries
|
|
# @param type [String] Type of record for which to add static entries
|
|
#
|
|
# @return [Array] List of static entries in the cache
|
|
def add_static_hosts(entries = datastore['STATIC_ENTRIES'], type = 'A')
|
|
return if entries.nil? or entries.empty?
|
|
if File.file?(File.expand_path(entries))
|
|
data = File.read(File.expand_path(entries)).split("\n")
|
|
else
|
|
data = entries.split(';')
|
|
end
|
|
data.each do |entry|
|
|
next if entry.gsub(/\s/,'').empty?
|
|
addr, names = entry.split(' ', 2)
|
|
names.split.each do |name|
|
|
name << '.' unless name[-1] == '.' or name == '*'
|
|
service.cache.add_static(name, addr, type)
|
|
end
|
|
end
|
|
service.cache.records.select {|r,e| e == 0}
|
|
end
|
|
|
|
#
|
|
# Flush all static entries
|
|
#
|
|
def flush_static_hosts
|
|
data.cache.records.select {|r,e| e == 0}.each do |flush|
|
|
data.cache.delete(flush)
|
|
end
|
|
end
|
|
|
|
#
|
|
# Flush cache entries
|
|
# @param static [TrueClass, FalseClass] flush static hosts
|
|
def flush_cache(static = false)
|
|
self.service.cache.stop(true)
|
|
flush_static_hosts if static
|
|
self.service.cache.start
|
|
end
|
|
|
|
#
|
|
# Handle incoming requests
|
|
# Override this method in modules to take flow control
|
|
#
|
|
def on_dispatch_request(cli, data)
|
|
service.default_dispatch_request(cli,data)
|
|
end
|
|
|
|
#
|
|
# Handle incoming requests
|
|
# Override this method in modules to take flow control
|
|
#
|
|
def on_send_response(cli, data)
|
|
cli.write(data)
|
|
end
|
|
|
|
#
|
|
# Starts the server
|
|
#
|
|
def start_service
|
|
begin
|
|
|
|
comm = _determine_server_comm
|
|
self.service = Rex::ServiceManager.start(
|
|
Rex::Proto::DNS::Server,
|
|
datastore['SRVHOST'],
|
|
datastore['SRVPORT'],
|
|
datastore['DnsServerUdp'],
|
|
datastore['DnsServerTcp'],
|
|
(use_resolver? ? setup_resolver : false),
|
|
comm,
|
|
{'Msf' => framework, 'MsfExploit' => self}
|
|
)
|
|
|
|
self.service.dispatch_request_proc = Proc.new do |cli, data|
|
|
on_dispatch_request(cli,data)
|
|
end
|
|
self.service.send_response_proc = Proc.new do |cli, data|
|
|
on_send_response(cli,data)
|
|
end
|
|
|
|
add_static_hosts
|
|
self.service.start(!datastore['DISABLE_NS_CACHE'])
|
|
|
|
rescue ::Errno::EACCES => e
|
|
raise Rex::BindFailed.new(e.message)
|
|
end
|
|
end
|
|
|
|
#
|
|
# Stops the server
|
|
# @param destroy [TrueClass,FalseClass] Dereference the server object
|
|
def stop_service(destroy = false)
|
|
Rex::ServiceManager.stop_service(self.service) if self.service
|
|
if destroy
|
|
@dns_resolver = nil if @dns_resolver
|
|
self.service = nil if self.service
|
|
end
|
|
end
|
|
|
|
#
|
|
# Resets the DNS server
|
|
#
|
|
def reset_service
|
|
stop_service(true)
|
|
start_service
|
|
end
|
|
|
|
#
|
|
# Determines if resolver is available and configured for use
|
|
#
|
|
def use_resolver?
|
|
!datastore['DISABLE_RESOLVER'] and self.respond_to?(:setup_resolver)
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|