Nmap dns-zone-transfer NSE Script


This page contains detailed information about how to use the dns-zone-transfer NSE script. For list of all NSE scripts, visit the Nmap NSE Library.

Select:
Overview
Error Messages

Script Overview


Script source code: https://github.com/nmap/nmap/tree/master/scripts/dns-zone-transfer.nse
Script categories: intrusive, discovery
Target service / protocol: dns, tcp
Target network port(s): 53
List of CVEs: -

Script Description


The dns-zone-transfer.nse script requests a zone transfer (AXFR) from a DNS server.

The script sends an AXFR query to a DNS server. The domain to query is determined by examining the name given on the command line, the DNS server's hostname, or it can be specified with the dns-zone-transfer.domain script argument. If the query is successful all domains and domain types are returned along with common type specific data (SOA/MX/NS/PTR/A).

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: dns-zone-transfer.server the DNS server to use, can be a hostname or an IP address and must be specified. The dns-zone-transfer.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

Dns-zone-transfer NSE Script Arguments


This is a full list of arguments supported by the dns-zone-transfer.nse script:

dns-zone-transfer.addall

If specified, adds all IP addresses including private ones onto Nmap scanning queue when the script argument newtargets is given. The default behavior is to skip private IPs (non-routable).

dns-zone-transfer.domain

Domain to transfer.

dns-zone-transfer.port

DNS server port, this argument concerns the "Script Pre-scanning phase" and it's optional, the default value is 53.

dns-zone-transfer.server

DNS server. If set, this argument will enable the script for the "Script Pre-scanning phase".

newtargets

If specified, adds returned DNS records onto Nmap scanning queue.

max-newtargets

Sets the number of the maximum allowed new targets. If set to 0 or less then there is no limit. The default value is 0.

- - -
To use these script arguments, add them to the Nmap command line using the --script-args arg1=value,[arg2=value,..] syntax. For example:

nmap --script=dns-zone-transfer --script-args dns-zone-transfer.addall=value,dns-zone-transfer.domain=value <target>

Dns-zone-transfer NSE Script Example Usage


Here's an example of how to use the dns-zone-transfer.nse script:

nmap --script dns-zone-transfer.nse \
--script-args dns-zone-transfer.domain=<domain>

Dns-zone-transfer NSE Script Example Output


Here's a sample output from the dns-zone-transfer.nse script:

53/tcp   open     domain
|  dns-zone-transfer:
|  foo.com.            SOA     ns2.foo.com. piou.foo.com.
|  foo.com.            TXT
|  foo.com.            NS      ns1.foo.com.
|  foo.com.            NS      ns2.foo.com.
|  foo.com.            NS      ns3.foo.com.
|  foo.com.            A       127.0.0.1
|  foo.com.            MX      mail.foo.com.
|  anansie.foo.com.    A       127.0.0.2
|  dhalgren.foo.com.   A       127.0.0.3
|  drupal.foo.com.     CNAME
|  goodman.foo.com.    A       127.0.0.4 i
|  goodman.foo.com.    MX      mail.foo.com.
|  isaac.foo.com.      A       127.0.0.5
|  julie.foo.com.      A       127.0.0.6
|  mail.foo.com.       A       127.0.0.7
|  ns1.foo.com.        A       127.0.0.7
|  ns2.foo.com.        A       127.0.0.8
|  ns3.foo.com.        A       127.0.0.9
|  stubing.foo.com.    A       127.0.0.10
|  vicki.foo.com.      A       127.0.0.11
|  votetrust.foo.com.  CNAME
|  www.foo.com.        CNAME
|_ foo.com.            SOA     ns2.foo.com. piou.foo.com.

Dns-zone-transfer NSE Script Example XML Output


There is no sample XML output for this module. However, by providing the -oX <file> option, Nmap will produce a XML output and save it in the file.xml file.

Author


  • Eddie Bell

References


See Also


Related NSE scripts to the dns-zone-transfer.nse script:

Visit Nmap NSE Library for more scripts.

The dns-zone-transfer.nse script may fail with the following error messages. Check for the possible causes by using the code snippets highlighted below found in the script source code. This can often times help in identifying the root cause of the problem.

<parse error>


Here is a relevant code snippet related to the "<parse error>" error message:

203:	--- Parse an RFC 1035 domain name.
204:	--@param data String of data.
205:	--@param offset Offset in the string to read the domain name.
206:	function parse_domain(data, offset)
207:	  local offset, domain = dns.decStr(data, offset)
208:	  domain = domain or "<parse error>"
209:	  return offset, string.format("%s.", domain)
210:	end
211:	
212:	--- Build RFC 1035 root domain name from the name of the DNS server
213:	--  (e.g ns1.website.com.ar -> \007website\003com\002ar\000).

More then 1 question record, something has gone wrong


Here is a relevant code snippet related to the "More then 1 question record, something has gone wrong" error message:

589:	
590:	    -- move to beginning of first section
591:	    offset = offset + 12
592:	
593:	    if questions > 1 then
594:	      return false, 'More then 1 question record, something has gone wrong'
595:	    end
596:	
597:	    if answers == 0 then
598:	      return false, 'transfer successful but no records'
599:	    end

transfer successful but no records


Here is a relevant code snippet related to the "transfer successful but no records" error message:

593:	    if questions > 1 then
594:	      return false, 'More then 1 question record, something has gone wrong'
595:	    end
596:	
597:	    if answers == 0 then
598:	      return false, 'transfer successful but no records'
599:	    end
600:	
601:	    -- skip over the question section, we don't need it
602:	    if questions == 1 then
603:	      offset, line = parse_domain(data, offset)

Error: failed to add all Node Names.


Here is a relevant code snippet related to the "Error: failed to add all Node Names." error message:

617:	
618:	  tab.addrow(outtab, "Domains", "Added Targets")
619:	  for rdata in pairs(RR['Node Names']) do
620:	    status, ret = target.add(rdata)
621:	    if not status then
622:	      stdnse.debug3("Error: failed to add all Node Names.")
623:	      break
624:	    end
625:	    newhosts_count = newhosts_count + ret
626:	  end
627:	  if newhosts_count == 0 then

Error: failed to add DNS records.


Here is a relevant code snippet related to the "Error: failed to add DNS records." error message:

623:	      break
624:	    end
625:	    newhosts_count = newhosts_count + ret
626:	  end
627:	  if newhosts_count == 0 then
628:	    return false, ret and ret or "Error: failed to add DNS records."
629:	  end
630:	  tab.addrow(outtab, "Node Names", newhosts_count)
631:	  nhosts = newhosts_count
632:	
633:	  tab.nextrow(outtab)

Error: failed to add all 'A' records.


Here is a relevant code snippet related to the "Error: failed to add all 'A' records." error message:

639:	    if rectype == 'A' then
640:	      for rdata in pairs(RR[rectype]) do
641:	        if dns_opts.addall or not ipOps.isPrivate(rdata) then
642:	          status, ret = target.add(rdata)
643:	          if not status then
644:	            stdnse.debug3("Error: failed to add all 'A' records.")
645:	            break
646:	          end
647:	          newhosts_count = newhosts_count + ret
648:	        end
649:	      end

Error: failed to add all '%s' records.


Here is a relevant code snippet related to the "Error: failed to add all '%s' records." error message:

649:	      end
650:	    elseif rectype ~= 'Node Names' then
651:	      for rdata in pairs(RR[rectype]) do
652:	        status, ret = target.add(rdata)
653:	        if not status then
654:	          stdnse.debug3("Error: failed to add all '%s' records.", rectype)
655:	          break
656:	        end
657:	        newhosts_count = newhosts_count + ret
658:	      end
659:	    end

Error: failed to add DNS records.


Here is a relevant code snippet related to the "Error: failed to add DNS records." error message:

661:	    if newhosts_count ~= 0 then
662:	      tab.addrow(outtab, rectype, newhosts_count)
663:	      nhosts = nhosts + newhosts_count
664:	    elseif nhosts == 0 then
665:	      -- error: we can't add new targets
666:	      return false, ret and ret or "Error: failed to add DNS records."
667:	    end
668:	  end
669:	
670:	  -- error: no *valid records* or we can't add new targets
671:	  if nhosts == 0 then

Error: failed to add valid DNS records.


Here is a relevant code snippet related to the "Error: failed to add valid DNS records." error message:

667:	    end
668:	  end
669:	
670:	  -- error: no *valid records* or we can't add new targets
671:	  if nhosts == 0 then
672:	    return false, "Error: failed to add valid DNS records."
673:	  end
674:	
675:	  return true, tab.dump(outtab) .. "\n" ..
676:	    string.format("Total new targets added to Nmap scan queue: %d.",
677:	    nhosts)

More then 1 question record, something has gone wrong


Here is a relevant code snippet related to the "More then 1 question record, something has gone wrong" error message:

689:	
690:	    -- move to beginning of first section
691:	    offset = offset + 12
692:	
693:	    if questions > 1 then
694:	      return false, 'More then 1 question record, something has gone wrong'
695:	    end
696:	
697:	    if answers == 0 then
698:	      return false, 'transfer successful but no records'
699:	    end

transfer successful but no records


Here is a relevant code snippet related to the "transfer successful but no records" error message:

693:	    if questions > 1 then
694:	      return false, 'More then 1 question record, something has gone wrong'
695:	    end
696:	
697:	    if answers == 0 then
698:	      return false, 'transfer successful but no records'
699:	    end
700:	
701:	    -- skip over the question section, we don't need it
702:	    if questions == 1 then
703:	        offset, line = parse_domain(data, offset)

Version


This page has been created based on Nmap version 7.92.

Go back to menu.