Merge remote branch 'bonsaiviking/axfr' into bonsai-afxr

This commit is contained in:
Tod Beardsley 2012-09-04 16:16:41 -05:00
commit 2edf4a676a
2 changed files with 187 additions and 112 deletions

View File

@ -995,12 +995,54 @@ module Net # :nodoc:
#
# Performs a zone transfer for the zone passed as a parameter.
#
# It is actually only a wrapper to a send with type set as Net::DNS::AXFR,
# since it is using the same infrastucture.
# Returns a list of Net::DNS::Packet (not answers!)
#
def axfr(name,cls=Net::DNS::IN)
@logger.info "Requested AXFR transfer, zone #{name} class #{cls}"
send(name,Net::DNS::AXFR,cls)
if @config[:nameservers].size == 0
raise Resolver::Error, "No nameservers specified!"
end
method = :send_tcp
packet = make_query_packet(name, Net::DNS::AXFR, cls)
# Store packet_data for performance improvements,
# so methods don't keep on calling Packet#data
packet_data = packet.data
packet_size = packet_data.size
if @raw
@logger.warn "AXFR query, switching to TCP over RAW socket"
method = :send_raw_tcp
else
@logger.warn "AXFR query, switching to TCP"
method = :send_tcp
end
answers = []
soa = 0
self.old_send(method, packet, packet_data) do |ans|
@logger.info "Received #{ans[0].size} bytes from #{ans[1][2]+":"+ans[1][1].to_s}"
begin
response = Net::DNS::Packet.parse(ans[0],ans[1])
if response.answer[0].type == "SOA"
soa += 1
if soa >= 2
break
end
end
answers << response
rescue NameError => e
@logger.warn "Error parsing axfr response: #{e.message}"
end
end
if answers.empty?
@logger.fatal "No response from nameservers list: aborting"
raise NoResponseError
end
return answers
end
#
@ -1119,38 +1161,56 @@ module Net # :nodoc:
@config[:nameservers].each do |ns|
begin
buffer = ""
socket = Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)
socket.bind(Socket.pack_sockaddr_in(@config[:source_port],@config[:source_address].to_s))
sockaddr = Socket.pack_sockaddr_in(@config[:port],ns.to_s)
@config[:tcp_timeout].timeout do
socket.connect(sockaddr)
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
socket.write(length+packet_data)
ans = socket.recv(Net::DNS::INT16SZ)
len = ans.unpack("n")[0]
catch "next nameserver" do
socket.connect(sockaddr)
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
socket.write(length+packet_data)
got_something = false
loop do
buffer = ""
ans = socket.recv(Net::DNS::INT16SZ)
if ans.size == 0
if got_something
break #Proper exit from loop
else
@logger.warn "Connection reset to nameserver #{ns}, trying next."
throw "next nameserver"
end
end
got_something = true
len = ans.unpack("n")[0]
@logger.info "Receiving #{len} bytes..."
@logger.info "Receiving #{len} bytes..."
if len == 0
@logger.warn "Receiving 0 lenght packet from nameserver #{ns}, trying next."
next
end
if len == 0
@logger.warn "Receiving 0 length packet from nameserver #{ns}, trying next."
throw "next nameserver"
end
while (buffer.size < len)
left = len - buffer.size
temp,from = socket.recvfrom(left)
buffer += temp
end
while (buffer.size < len)
left = len - buffer.size
temp,from = socket.recvfrom(left)
buffer += temp
end
unless buffer.size == len
@logger.warn "Malformed packet from nameserver #{ns}, trying next."
next
unless buffer.size == len
@logger.warn "Malformed packet from nameserver #{ns}, trying next."
throw "next nameserver"
end
if block_given?
yield [buffer,["",@config[:port],ns.to_s,ns.to_s]]
else
return [buffer,["",@config[:port],ns.to_s,ns.to_s]]
end
end
end
end
return [buffer,["",@config[:port],ns.to_s,ns.to_s]]
rescue Timeout::Error
@logger.warn "Nameserver #{ns} not responding within TCP timeout, trying next one"
next
@ -1158,6 +1218,7 @@ module Net # :nodoc:
socket.close
end
end
return nil
end
def send_udp(packet,packet_data)

View File

@ -1,5 +1,5 @@
##
# $Id$
# $Id: enum_dns.rb 15475 2012-06-18 23:39:04Z rapid7 $
##
##
@ -26,7 +26,7 @@ class Metasploit3 < Msf::Auxiliary
},
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>' ],
'License' => MSF_LICENSE,
'Version' => '$Revision$',
'Version' => '$Revision: 15475 $',
'References' =>
[
['CVE', '1999-0532'],
@ -100,7 +100,7 @@ class Metasploit3 < Msf::Auxiliary
query.answer.each do |rr|
next unless rr.class == Net::DNS::RR::A
print_status("Domain: #{target} IP address: #{rr.address} Record: A ")
report_note(:host => rr.address.to_s,
report_note(:host => @nsinuse.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
@ -115,7 +115,7 @@ class Metasploit3 < Msf::Auxiliary
if (query1)
query1.answer.each do |ip|
print_status("Start of Authority: #{rr.mname} IP address: #{ip.address} Record: SOA")
report_note(:host => ip.address.to_s,
report_note(:host => @nsinuse.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
@ -133,7 +133,7 @@ class Metasploit3 < Msf::Auxiliary
query1.answer.each do |ip|
next unless ip.class == Net::DNS::RR::A
print_status("Name Server: #{rr.nsdname} IP address: #{ip.address} Record: NS")
report_note(:host => ip.address.to_s,
report_note(:host => @nsinuse.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
@ -175,6 +175,7 @@ class Metasploit3 < Msf::Auxiliary
target.chomp!
if not nssrv.nil?
@res.nameserver=(nssrv)
@nsinuse = nssrv
end
i, a = 0, []
tlds = [
@ -209,7 +210,7 @@ class Metasploit3 < Msf::Auxiliary
if (query1)
query1.answer.each do |rr|
print_status("Domain: #{target}.#{tld} Name: #{rr.name} IP address: #{rr.address} Record: A ") if rr.class == Net::DNS::RR::A
report_note(:host => rr.address.to_s,
report_note(:host => @nsinuse.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53,
@ -229,13 +230,14 @@ class Metasploit3 < Msf::Auxiliary
::File.open(wordlist, "rb").each_line do |line|
if not nssrv.nil?
@res.nameserver=(nssrv)
@nsinuse = nssrv
end
query1 = @res.search("#{line.chomp}.#{target}")
if (query1)
query1.answer.each do |rr|
if rr.class == Net::DNS::RR::A
print_status("Hostname: #{line.chomp}.#{target} IP address: #{rr.address.to_s}")
report_note(:host => rr.address.to_s,
report_note(:host => @nsinuse.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
@ -256,6 +258,7 @@ class Metasploit3 < Msf::Auxiliary
arr = IO.readlines(wordlist)
if not nssrv.nil?
@res.nameserver=(nssrv)
@nsinuse = nssrv
end
arr.each do |line|
query1 = @res.search("#{line.chomp}.#{target}", "AAAA")
@ -263,7 +266,7 @@ class Metasploit3 < Msf::Auxiliary
query1.answer.each do |rr|
if rr.class == Net::DNS::RR::AAAA
print_status("Hostname: #{line.chomp}.#{target} IPv6 Address: #{rr.address.to_s}")
report_note(:host => rr.address.to_s,
report_note(:host => @nsinuse.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
@ -284,6 +287,7 @@ class Metasploit3 < Msf::Auxiliary
print_status("Running reverse lookup against IP range #{iprange}")
if not nssrv.nil?
@res.nameserver = (nssrv)
@nsinuse = nssrv
end
ar = Rex::Socket::RangeWalker.new(iprange)
tl = []
@ -297,7 +301,7 @@ class Metasploit3 < Msf::Auxiliary
query = @res.query(tip)
query.each_ptr do |addresstp|
print_status("Hostname: #{addresstp} IP address: #{tip.to_s}")
report_note(:host => tip,
report_note(:host => @nsinuse.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
@ -354,6 +358,7 @@ class Metasploit3 < Msf::Auxiliary
print_status("Performing zone transfer against all nameservers in #{target}")
if not nssrv.nil?
@res.nameserver=(nssrv)
@nsinuse = nssrv
end
@res.tcp_timeout=15
query = @res.query(target, "NS")
@ -361,96 +366,105 @@ class Metasploit3 < Msf::Auxiliary
(query.answer.select { |i| i.class == Net::DNS::RR::NS}).each do |nsrcd|
print_status("Testing nameserver: #{nsrcd.nsdname}")
nssrvquery = @res.query(nsrcd.nsdname, "A")
begin
if nssrvquery.answer.length == 0
nssrvip = Rex::Socket.gethostbyname(nsrcd.nsdname)[3].bytes.reduce {|a,b| [a,b].join(".")}
else
nssrvip = nssrvquery.answer[0].address.to_s
end
begin
@res.nameserver=(nssrvip)
@nsinuse = nssrvip
zone = []
zone = @res.query(target,Net::DNS::AXFR)
if zone.answer.length != 0
namesrvips = @res.query(nsrcd.nsdname,"A")
nsip = namesrvips.answer[0]
zone = @res.axfr(target)
if zone.length != 0
print_status("Zone transfer successful")
report_note(:host => nsip.address.to_s,
report_note(:host => nssrvip,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "Zone transfer successful")
#Prints each record according to its type
zone.answer.each do |rr|
case rr.type
when "A"
print_status("Name: #{rr.name} IP address: #{rr.address} Record: A ")
report_note(:host => rr.address.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.address.to_s},#{rr.name},A")
when "SOA"
print_status("Name: #{rr.mname} Record: SOA")
report_note(:host => nsip.address.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.name},SOA")
when "MX"
print_status("Name: #{rr.exchange} Preference: #{rr.preference} Record: MX")
report_note(:host => nsip.address.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.exchange},MX")
when "CNAME"
print_status("Name: #{rr.cname} Record: CNAME")
report_note(:host => nsip.address.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.cname},CNAME")
when "HINFO"
print_status("CPU: #{rr.cpu} OS: #{rr.os} Record: HINFO")
report_note(:host => nsip.address.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "CPU:#{rr.cpu},OS:#{rr.os},HINFO")
when "AAAA"
print_status("IPv6 Address: #{rr.address} Record: AAAA")
report_note(:host => rr.address.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.address.to_s}, AAAA")
when "NS"
print_status("Name: #{rr.nsdname} Record: NS")
report_note(:host => nsip.address.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.nsdname},NS")
when "TXT"
print_status("Text: #{rr.inspect}")
report_note(:host => nsip.address.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => rr.inspect)
when "SRV"
print_status("Host: #{rr.host} Port: #{rr.port} Priority: #{rr.priority} Record: SRV")
report_note(:host => nsip.address.to_s,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.host},#{rr.port},#{rr.priority},SRV")
zone.each do |response|
response.answer.each do |rr|
begin
case rr.type
when "A"
print_status("Name: #{rr.name} IP address: #{rr.address} Record: A ")
report_note(:host => nssrvip,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.address.to_s},#{rr.name},A")
when "SOA"
print_status("Name: #{rr.mname} Record: SOA")
report_note(:host => nssrvip,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.name},SOA")
when "MX"
print_status("Name: #{rr.exchange} Preference: #{rr.preference} Record: MX")
report_note(:host => nssrvip,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.exchange},MX")
when "CNAME"
print_status("Name: #{rr.cname} Record: CNAME")
report_note(:host => nssrvip,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.cname},CNAME")
when "HINFO"
print_status("CPU: #{rr.cpu} OS: #{rr.os} Record: HINFO")
report_note(:host => nssrvip,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "CPU:#{rr.cpu},OS:#{rr.os},HINFO")
when "AAAA"
print_status("IPv6 Address: #{rr.address} Record: AAAA")
report_note(:host => nssrvip,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.address.to_s}, AAAA")
when "NS"
print_status("Name: #{rr.nsdname} Record: NS")
report_note(:host => nssrvip,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.nsdname},NS")
when "TXT"
print_status("Text: #{rr.inspect}")
report_note(:host => nssrvip,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => rr.inspect)
when "SRV"
print_status("Host: #{rr.host} Port: #{rr.port} Priority: #{rr.priority} Record: SRV")
report_note(:host => nssrvip,
:proto => 'udp',
:sname => 'dns',
:port => 53 ,
:type => 'dns.enum',
:data => "#{rr.host},#{rr.port},#{rr.priority},SRV")
end
rescue ActiveRecord::RecordInvalid
#Do nothing. Probably tried to store :host => 127.0.0.1
end
end
end
else