1a253f92a1
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.
104 lines
3.4 KiB
Ruby
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
|