diff --git a/scripts/dns-zone-transfer.nse b/scripts/dns-zone-transfer.nse index 3e52fb14f..f7eb70a6c 100644 --- a/scripts/dns-zone-transfer.nse +++ b/scripts/dns-zone-transfer.nse @@ -8,16 +8,30 @@ server's hostname, or it can be specified with the successful all domains and domain types are returned along with common type specific data (SOA/MX/NS/PTR/A). -If we don't have the "true" hostname for the DNS server we cannot -determine a likely zone to perform the transfer on. +This script can run at different phases of an Nmap scan: +* Script Pre-scanning: in this phase the script will run before any +Nmap scan and use the defined DNS server in the arguments. The script +arguments in this phase are: dnszonetransfer.server the +DNS server to use, can be a hostname or an IP address and must be +specified. The dnszonetransfer.port argument is optional +and can be used to specify the DNS server port. +* Script scanning: in this phase the script will run after the other +Nmap phases and against an Nmap discovered DNS server. If we don't +have the "true" hostname for the DNS server we cannot determine a +likely zone to perform the transfer on. -Useful resources: +Useful resources * DNS for rocket scientists: http://www.zytrax.com/books/dns/ * How the AXFR protocol works: http://cr.yp.to/djbdns/axfr-notes.html ]] --- -- @args dnszonetransfer.domain Domain to transfer. +-- @args dnszonetransfer.server DNS server. If set, this argument will +-- enable the script for the "Script Pre-scanning phase". +-- @args dnszonetransfer.port DNS server port, this argument concerns +-- the "Script Pre-scanning phase" and it's optional, the default +-- value is 53. -- @output -- 53/tcp open domain -- | dns-zone-transfer: @@ -60,6 +74,7 @@ author = "Eddie Bell" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {'default', 'intrusive', 'discovery'} +prerule = function() return true end portrule = shortport.portnumber(53, 'tcp') --- DNS query and response types. @@ -301,33 +316,66 @@ function dump_zone_info(table, data) end action = function(host, port) - local soc, status, data - local catch = function() soc:close() end - local try = nmap.new_try(catch) - - local domain = nil - local args = nmap.registry.args + local soc, status, data + local dns_server, dns_port + local catch = function() soc:close() end + local try = nmap.new_try(catch) + + local domain = nil + local args = nmap.registry.args - if args.dnszonetransfer and args.dnszonetransfer.domain then - domain = args.dnszonetransfer.domain - elseif args['dnszonetransfer.domain'] then - domain = args['dnszonetransfer.domain'] - elseif args.domain then - domain = args.domain - elseif host.targetname then - domain = host.targetname - elseif host.name ~= "" then - domain = host.name - else - -- can't do anything without a hostname - return - end + if args.dnszonetransfer and args.dnszonetransfer.domain then + domain = args.dnszonetransfer.domain + elseif args['dnszonetransfer.domain'] then + domain = args['dnszonetransfer.domain'] + elseif args.domain then + domain = args.domain + end + + -- script running at the Script Pre-scanning phase. + if SCRIPT_TYPE == "prerule" then + if not domain then + stdnse.print_debug(3, + "Skipping '%s' %s, 'dnszonetransfer.domain' argument is missing.", + SCRIPT_NAME, SCRIPT_TYPE) + return + end + if args['dnszonetransfer.server'] then + dns_server = args['dnszonetransfer.server'] + else + stdnse.print_debug(3, + "Skipping '%s' %s, 'dnszonetransfer.server' argument is missing.", + SCRIPT_NAME, SCRIPT_TYPE) + return + end + if args['dnszonetransfer.port'] then + dns_port = args['dnszonetransfer.port'] + else + dns_port = 53 + end + -- script running at the Script Scan phase. + elseif SCRIPT_TYPE == "portrule" then + if not domain then + if host.targetname then + domain = host.targetname + elseif host.name ~= "" then + domain = host.name + else + -- can't do anything without a hostname + return stdnse.format_output(false, + string.format("'%s' script needs a dnszonetransfer.domain argument.", + SCRIPT_TYPE)) + end + end + dns_server = host.ip + dns_port = port.number + end assert(domain) soc = nmap.new_socket() soc:set_timeout(4000) - try(soc:connect(host.ip, port.number)) + try(soc:connect(dns_server, dns_port)) local req_id = '\222\173' local table = tab.new(3)