Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/auxiliary/spoof/dns/compare_results.rb
Views: 11623
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'net/dns'6require 'resolv'78class MetasploitModule < Msf::Auxiliary910def initialize(info = {})11super(update_info(info,12'Name' => 'DNS Lookup Result Comparison',13'Description' => %q{14This module can be used to determine differences15in the cache entries between two DNS servers. This is16primarily useful for detecting cache poisoning attacks,17but can also be used to detect geo-location load balancing.18},19'Author' => [ 'hdm' ],20'License' => MSF_LICENSE,21'References' =>22[23],24'DisclosureDate' => '2008-07-21'25))2627register_options(28[29OptAddress.new('BASEDNS', [ true, 'The DNS cache server to use as a baseline', '4.2.2.3' ]),30OptAddress.new('TARGDNS', [ true, 'The DNS cache server to test', nil ]),31OptString.new('NAMES', [ true, 'The list of host names that should be tested (comma separated)', 'www.google.com,www.yahoo.com,www.msn.com']),32OptBool.new('CHECK_AUTHORITY', [ false, 'Set this to true to verify authority records', false ]),33OptBool.new('CHECK_ADDITIONAL', [ false, 'Set this to true to verify additional records', false ]),3435])3637end383940def run41base_addr = datastore['BASEDNS']42targ_addr = datastore['TARGDNS']43check_ar = datastore['CHECK_ADDITIONAL']44check_aa = datastore['CHECK_AUTHORITY']45names = datastore['NAMES'].split(",").map {|c| c.strip }46recurse = true47results = {}4849print_status("Comparing results between #{base_addr} and #{targ_addr}...")5051base_sock = Rex::Socket.create_udp(52'PeerHost' => base_addr,53'PeerPort' => 5354)5556targ_sock = Rex::Socket.create_udp(57'PeerHost' => targ_addr,58'PeerPort' => 5359)6061names.each do |entry|62entry.strip!63next if (entry.length == 0)6465req = Resolv::DNS::Message.new66req.add_question(entry, Resolv::DNS::Resource::IN::A)67req.rd = recurse ? 1 : 06869buf = req.encode70print_status("Querying servers for #{entry}...")71base_sock.put(buf)72targ_sock.put(buf)7374base_res, base_saddr = base_sock.recvfrom(65535, 3.0)75targ_res, targ_saddr = targ_sock.recvfrom(65535, 3.0)7677if !(base_res and targ_res and base_res.length > 0 and targ_res.length > 0)78print_error(" Error: The baseline server did not respond to our request.") if ! (base_res and base_res.length > 0)79print_error(" Error: The target server did not respond to our request.") if ! (targ_res and targ_res.length > 0)80next81end8283base_res = Resolv::DNS::Message.decode(base_res)84targ_res = Resolv::DNS::Message.decode(targ_res)8586[base_res, targ_res].each do |res|87hkey = (res == base_res) ? :base : :targ8889rrset = res.answer90rrset += res.authority if check_aa91rrset += res.additional if check_ar9293(rrset).each do |ref|94name,ttl,data = ref9596name = name.to_s97anst = data.class.to_s.gsub(/^.*Resolv::DNS::Resource::IN::/, '')98case data99when Resolv::DNS::Resource::IN::NS100data = data.name.to_s101when Resolv::DNS::Resource::IN::MX102data = data.exchange.to_s103when Resolv::DNS::Resource::IN::A104data = data.address.to_s105when Resolv::DNS::Resource::IN::TXT106data = data.strings.join107when Resolv::DNS::Resource::IN::CNAME108data = data.name.to_s109else110data = anst111end112113results[entry]||={}114results[entry][hkey]||={}115results[entry][hkey][anst]||=[]116results[entry][hkey][anst] << data117end118end119end120121[ base_sock, targ_sock ].each {|s| s.close }122123124print_status("Analyzing results for #{results.keys.length} entries...")125126results.each_key do |entry|127128n_add = []129n_sub = []130131# Look for additional entries in the target NS132if(results[entry][:targ])133results[entry][:targ].each_key do |rtype|134if(not results[entry][:base] or not results[entry][:base][rtype])135results[entry][:targ][rtype].sort.each do |ref|136n_sub << (" + #{entry} #{rtype} #{ref}")137end138end139end140end141142if (results[entry][:base])143results[entry][:base].each_key do |rtype|144145# Look for missing entries in the target NS146if(not results[entry][:targ] or not results[entry][:targ][rtype])147results[entry][:base][rtype].sort.each do |ref|148n_sub << (" - #{entry} #{rtype} #{ref}")149end150next151end152153# Look for differences154if( results[entry][:base][rtype].sort != results[entry][:targ][rtype].sort )155results[entry][:base][rtype].sort.each do |ref|156if(not results[entry][:targ][rtype].include?(ref))157n_sub << (" - #{entry} #{rtype} #{ref}")158end159end160results[entry][:targ][rtype].sort.each do |ref|161if(not results[entry][:base][rtype].include?(ref))162n_add << (" + #{entry} #{rtype} #{ref}")163end164end165end166end167end168169n_sub.each {|s| print_status(s) }170n_add.each {|s| print_status(s) }171end172173end174end175176177