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: |
---|
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. Thedns-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 for rocket scientists: http://www.zytrax.com/books/dns/
- How the AXFR protocol works: http://cr.yp.to/djbdns/axfr-notes.html
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).
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 server. If set, this argument will enable the script for the "Script Pre-scanning phase".
newtargetsIf specified, adds returned DNS records onto Nmap scanning queue.
max-newtargetsSets 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
- https://nmap.org/nsedoc/scripts/dns-zone-transfer.html
- https://github.com/nmap/nmap/tree/master/scripts/dns-zone-transfer.nse
- http://www.zytrax.com/books/dns/
- http://cr.yp.to/djbdns/axfr-notes.html
- http://www.broadband-forum.org/ftp/pub/approved-specs/af-saa-0069.000.pdf
- https://tools.ietf.org/html/draft-eastlake-kitchen-sink-02
- https://tools.ietf.org/html/rfc6698
See Also
Related NSE scripts to the dns-zone-transfer.nse script:
- dns-blacklist.nse
- dns-brute.nse
- dns-cache-snoop.nse
- dns-check-zone.nse
- dns-client-subnet-scan.nse
- dns-fuzz.nse
- dns-ip6-arpa-scan.nse
- dns-nsec3-enum.nse
- dns-nsec-enum.nse
- dns-nsid.nse
- dns-random-srcport.nse
- dns-random-txid.nse
- dns-recursion.nse
- dns-service-discovery.nse
- dns-srv-enum.nse
- dns-update.nse
- dns-zeustracker.nse
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.