Blog |Follow Nick on Twitter| About

Back in the day - Windows 2000 era - we would block TCP/53 on the firewall, at the time this was because DNS queries were on UDP/53 and TCP at the time was used for Zone Transfer.

A zone transfer, is where you ask a DNS server to give you all it's records, the legitimate reason for this is creating resilient scalable DNS infrastructure where you need & want the DNS records stored in multiple places.. or maybe closer to the user for speed/performance.

The dark side of zone transfers is that an attacker can use these to map a network, externally a zone transfer is a document describing all your internet assets and internal zone is practically a full network map.

On the modern day network, we can no longer block TCP/53, the original spec stated that if a DNS response exceeds 512 byte then the client should query again via TCP. Twenty years ago a TCP response was barely need but now, DNS records such as DNSSEC, SRV, TXT mean that TCP is actively in use, in fact internally on a Microsoft Active Directory network you will find many things start to fail if TCP/53 is blocked.

This shift from DNS being equally UDP or TCP has opened the door for an old vulnerability. DNS servers now-a-days come by default with zone transfers disabled however the opportunity for miss-configuration is back, with no firewall protection human error is possible (probable?!).

There's about 60 servers in my scope for testing at work, so I figured a quick script was worth a punt!

I've uploaded it to github gist, or a zipfile here ->


Not a lot to do, 2x text files...

  1. Update domains.txt with the domain names (zones) you want to try and transfer
  2. Update servers.txt with the DNS Servers you want to run the script against
  3. Either install Docker/Docker-Compose or Python with dnspython


If Docker, then docker-compose up.
If Native python, just run it python

Here's an example run against's public NS...

$ docker-compose up
Starting dns_xfer_test_py_dnspython_1 ... done
Attaching to dns_xfer_test_py_dnspython_1
py_dnspython_1  | [CRITICAL] 2019-03-10 20:20:20,647 Zone Tranfser Failed: |
py_dnspython_1  | [DEBUG] 2019-03-10 20:20:20,647 Exception: <class 'dns.query.TransferError'> Zone transfer error: FORMERR
py_dnspython_1  | [INFO] 2019-03-10 20:20:20,647 XFR Failed: -
py_dnspython_1  | [CRITICAL] 2019-03-10 20:20:20,690 Zone Tranfser Failed: | 
py_dnspython_1  | [DEBUG] 2019-03-10 20:20:20,690 Exception: <class 'dns.query.TransferError'> Zone transfer error: FORMERR
py_dnspython_1  | [INFO] 2019-03-10 20:20:20,691 XFR Failed: -
py_dnspython_1  | [CRITICAL] 2019-03-10 20:20:20,741 Zone Tranfser Failed: |
py_dnspython_1  | [DEBUG] 2019-03-10 20:20:20,742 Exception: <class 'dns.query.TransferError'> Zone transfer error: FORMERR
py_dnspython_1  | [INFO] 2019-03-10 20:20:20,742 XFR Failed: -
py_dnspython_1  | [CRITICAL] 2019-03-10 20:20:20,785 Zone Tranfser Failed: |
py_dnspython_1  | [DEBUG] 2019-03-10 20:20:20,786 Exception: <class 'dns.query.TransferError'> Zone transfer error: FORMERR
py_dnspython_1  | [INFO] 2019-03-10 20:20:20,786 XFR Failed: -
py_dnspython_1  | [INFO] 2019-03-10 20:20:20,787
py_dnspython_1  |
py_dnspython_1  |  !! Finished !!
py_dnspython_1  |
py_dnspython_1  | [INFO] 2019-03-10 20:20:20,787 xfer_summary_190310-202020.csv
dns_xfer_test_py_dnspython_1 exited with code 0

... obviously, nothing open there ;-)


The script results will be in a date/timestamp CSV file -> xfer_summary_xx-yy.csv

If you got lucky and found a vulnerable DNS server, the zone will be dumped to date/timestamp text file -> server_domain_xx-yy.txt

I however didn't get lucky, all servers clean, maybe you will!


Nick Bettison ©