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/scanner/dns/dns_amp.rb
Views: 11783
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Auxiliary::Report7include Msf::Exploit::Capture8include Msf::Auxiliary::UDPScanner9include Msf::Auxiliary::DRDoS1011def initialize12super(13'Name' => 'DNS Amplification Scanner',14'Description' => %q{15This module can be used to discover DNS servers which expose recursive16name lookups which can be used in an amplification attack against a17third party.18},19'Author' => [ 'xistence <xistence[at]0x90.nl>'], # Original scanner module20'License' => MSF_LICENSE,21'References' =>22[23['CVE', '2006-0987'],24['CVE', '2006-0988'],25]26)2728register_options( [29Opt::RPORT(53),30OptString.new('DOMAINNAME', [true, 'Domain to use for the DNS request', 'isc.org' ]),31OptString.new('QUERYTYPE', [true, 'Query type(A, NS, SOA, MX, TXT, AAAA, RRSIG, DNSKEY, ANY)', 'ANY' ]),32])33end3435def rport36datastore['RPORT']37end3839def setup40super4142# Check for DNS query types byte43case datastore['QUERYTYPE']44when 'A'45querypacket="\x01"46when 'NS'47querypacket="\x02"48when 'SOA'49querypacket="\x06"50when 'MX'51querypacket="\x0f"52when 'TXT'53querypacket="\x10"54when 'AAAA'55querypacket="\x1c"56when 'RRSIG'57querypacket="\x2e"58when 'DNSKEY'59querypacket="\x30"60when 'ANY'61querypacket="\xff"62else63print_error("Invalid query type!")64return65end6667targdomainpacket = []68# Before every part of the domainname there should be the length of that part (instead of a ".")69# So isc.org divided is 3isc3org70datastore['DOMAINNAME'].split('.').each do |domainpart|71# The length of the domain part in hex72domainpartlength = "%02x" % domainpart.length73# Convert the name part to a hex string74domainpart = domainpart.each_byte.map { |b| b.to_s(16) }.join()75# Combine the length of the name part and the name part76targdomainpacket.push(domainpartlength + domainpart)77end78# Convert the targdomainpacket to a string79targdomainpacket = targdomainpacket.join.to_s80# Create a correct hex character string to be used in the packet81targdomainpacket = targdomainpacket.scan(/../).map { |x| x.hex.chr }.join82# DNS Packet including our target domain and query type83@msearch_probe = "\x09\x8d\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00" + targdomainpacket + "\x00\x00" + querypacket + "\x00\x01"84end8586def scanner_prescan(batch)87print_status("Sending DNS probes to #{batch[0]}->#{batch[-1]} (#{batch.length} hosts)")88# Standard packet is 60 bytes. Add the domain size to this89sendpacketsize = 60 + datastore['DOMAINNAME'].length90print_status("Sending #{sendpacketsize} bytes to each host using the IN #{datastore['QUERYTYPE']} #{datastore['DOMAINNAME']} request")91@results = {}92end9394def scan_host(ip)95if spoofed?96datastore['ScannerRecvWindow'] = 097scanner_spoof_send(@msearch_probe, ip, datastore['RPORT'], datastore['SRCIP'], datastore['NUM_REQUESTS'])98else99scanner_send(@msearch_probe, ip, datastore['RPORT'])100end101end102103def scanner_process(data, shost, sport)104105# Check the response data for \x09\x8d and the next 2 bytes, which contain our DNS flags106if data =~/\x09\x8d(..)/107flags = $1108flags = flags.unpack('B*')[0].scan(/./)109# Query Response110qr = flags[0]111# Recursion Available112ra = flags[8]113# Response Code114rcode = flags[12] + flags[13] + flags[14] + flags[15]115116# If these flags are set, we get a valid response117# don't test recursion available if correct answer received118# at least the case with bind and "additional-from-cache no" or version < 9.5+119if qr == "1" and rcode == "0000"120sendlength = 60 + datastore['DOMAINNAME'].length121receivelength = 42 + data.length122amp = receivelength / sendlength.to_f123print_good("#{shost}:#{datastore['RPORT']} - Response is #{receivelength} bytes [#{amp.round(2)}x Amplification]")124report_service(:host => shost, :port => datastore['RPORT'], :proto => 'udp', :name => "dns")125report_vuln(126:host => shost,127:port => datastore['RPORT'],128:proto => 'udp', :name => "DNS",129:info => "DNS amplification - #{data.length} bytes [#{amp.round(2)}x Amplification]",130:refs => self.references)131end132133# If these flags are set, we get a valid response but recursion is not available134if qr == "1" and ra == "0" and rcode == "0101"135print_status("#{shost}:#{datastore['RPORT']} - Recursion not allowed")136report_service(:host => shost, :port => datastore['RPORT'], :proto => 'udp', :name => "dns")137end138end139end140end141142143