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 -> test_xfer_py.zip
Setup
Not a lot to do, 2x text files...
- Update
domains.txt
with the domain names (zones) you want to try and transfer - Update
servers.txt
with the DNS Servers you want to run the script against - Either install Docker/Docker-Compose or Python with dnspython
Run
Simples...
If Docker, then docker-compose up
.
If Native python, just run it python test_xfer.py
Here's an example run against linickx.com'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: coco.ns.cloudflare.com | linickx.com
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: coco.ns.cloudflare.com - linickx.com
py_dnspython_1 | [CRITICAL] 2019-03-10 20:20:20,690 Zone Tranfser Failed: coco.ns.cloudflare.com | linickx.co.uk
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: coco.ns.cloudflare.com - linickx.co.uk
py_dnspython_1 | [CRITICAL] 2019-03-10 20:20:20,741 Zone Tranfser Failed: nash.ns.cloudflare.com | linickx.com
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: nash.ns.cloudflare.com - linickx.com
py_dnspython_1 | [CRITICAL] 2019-03-10 20:20:20,785 Zone Tranfser Failed: nash.ns.cloudflare.com | linickx.co.uk
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: nash.ns.cloudflare.com - linickx.co.uk
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 ;-)
Results
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!