Files
metasploit-gs/modules/auxiliary/server/dns/native_server.rb
T
RageLtMan 1a253f92a1 Finalize DNS spoofing module
DNS spoofing module should be feature complete, with forwarding of
requests which do not have cached answers (can be disabled same as
the native server module), empty replies to reduce client wait on
outstanding DNS requests, and post-send output in verbose mode
to reduce garbage and execution time in the critical/racy path.

This module is best used in conditions where MITM is achieved by
way of MAC spoofing, route interception, or compromise of an inline
host on the datapath. The attacker should avoid forwarding
original requests to the intended destination, or if this is not
possible, prevent replies from traversing the MITM space in order
to avoid race conditions between the spoofer and victim.

Example iptables configuration on MITM host:
 iptables -t nat -A POSTROUTING -o eth0 -p udp ! --dport 53 -j ...

Testing:
  Internal testing in Virtualbox local network, atop 802.11, and
mostly in Neutron (with port security disabled on the VIFs) atop
OpenStack Liberty ML2+OVS.
2017-06-23 19:59:02 -04:00

104 lines
3.4 KiB
Ruby

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core/exploit/dns'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::DNS::Client
include Msf::Exploit::Remote::DNS::Server
def initialize(info = {})
super(update_info(info,
'Name' => 'Native DNS Server (Example)',
'Description' => %q{
This module provides a Rex based DNS service which can store static entries,
resolve names over pivots, and serve DNS requests across routed session comms.
DNS tunnels can operate across the the Rex switchboard, and DNS other modules
can use this as a template. Setting static records via hostfile allows for DNS
spoofing attacks without direct traffic manipulation at the handlers. handlers
for requests and responses provided here mimic the internal Rex functionality,
but utilize methods within this module's namespace to output content processed
in the Proc contexts via vprint_status.
},
'Author' => 'RageLtMan <rageltman[at]sempervictus>',
'License' => MSF_LICENSE,
'References' => []
))
end
#
# Wrapper for service execution and cleanup
#
def run
begin
start_service
service.wait
ensure
stop_service(true)
end
end
#
# Creates Proc to handle incoming requests
#
def on_dispatch_request(cli,data)
req = Packet.encode_net(data)
peer = "#{cli.peerhost}:#{cli.peerport}"
asked = req.question.map(&:qName).join(', ')
vprint_status("Received request for #{asked} from #{peer}")
answered = []
# Find cached items, remove request from forwarded packet
req.question.each do |ques|
cached = service.cache.find(ques.qName, ques.qType.to_s)
if cached.empty?
next
else
req.answer = (req.answer + cached).uniq
answered << ques
cached.map do |hit|
if hit.respond_to?(:address)
hit.name + ':' + hit.address.to_s + ' ' + hit.type
else
hit.name + ' ' + hit.type
end
end.each {|h| vprint_status("Cache hit for #{h}")}
end
end unless service.cache.nil?
# Forward remaining requests, cache responses
if answered.count < req.question.count and service.fwd_res
if !req.header.recursive?
vprint_status("Recursion forbidden in query for #{req.question.first.name} from #{peer}")
else
forward = req.dup
forward.question = req.question - answered
forwarded = service.fwd_res.send(Packet.validate(forward))
forwarded.answer.each do |ans|
rstring = ans.respond_to?(:address) ? "#{ans.name}:#{ans.address}" : ans.name
vprint_status("Caching response #{rstring} #{ans.type}")
service.cache.cache_record(ans)
end unless service.cache.nil?
# Merge the answers and use the upstream response
forwarded.answer = (req.answer + forwarded.answer).uniq
req = forwarded
end
end
service.send_response(cli, Packet.validate(Packet.generate_response(req)).data)
end
#
# Creates Proc to handle outbound responses
#
def on_send_response(cli,data)
res = Packet.encode_net(data)
peer = "#{cli.peerhost}:#{cli.peerport}"
asked = res.question.map(&:qName).join(', ')
vprint_status("Sending response for #{asked} to #{peer}")
cli.write(data)
end
end