Monday, January 2, 2012

Python - TestZoneTransfer

Here's a python script to help find world-transferable DNS domains within your organization. Alternatively, you could search through your .conf files for ACL weaknesses/misconfigurations, but that can become quite cumbersome when dealing with large datasets.

* * * Note: The script below is out of date. Please use the script found here instead:

This script queries NS records for a given domain and then attempts to transfer the supplied zone from each name server.

#!/usr/bin/env python
Info:     Query a supplied dns zone for it's NS records
          and test if it's offering transfers out to the world.

          This script could be replaced by using a couple dig commands.

          e.g. dig -tns
          dig axfr
          dig axfr
           ... etc.

          Or even nslookup

Required: DNS python, available here:
          or via easy_install, e.g.:
          `easy_install dnspython`
import dns.query,, dns.resolver, sys, socket

# Get NS records
def getNameservers(zonename):
    nameservers = dns.resolver.query(zonename, 'NS') 
    return nameservers

# Check for and get mandatory zone argument
def getArgs(zonename):
    if  len(sys.argv) != 2:
        print '\n     Usage: \n\n     {0}  fqdn\n'.format(sys.argv[0]) 
        print '\n     Purpose: \n\n     Test a domain for wide-open zone transfer\n'
        return sys.argv[1]

zonename = ''
zonename = getArgs(zonename)

# Get nameserver records
    if len(getNameservers(zonename)):
        print "Number of NS records:", len(getNameservers(zonename))
except dns.resolver.NXDOMAIN:
    print "Invalid name" , zonename

# Attempt to transfer the zone from each nameserver, exit if 1 server gives up the zone 
for nameserver in getNameservers(zonename):

        print '\n   - Querying nameserver {0} for DNS zone {1}\n'.format(nameserver,zonename)

        tryxfer =, zonename))
        names = tryxfer.nodes.keys()

        for n in names:
             print tryxfer[n].to_text(n)


# Trap errors
    except dns.resolver.NoAnswer: 
        print "\nproblem getting NS record\n"

    except dns.exception.FormError:
        print "\nXfer refused, good work dns admin\n"

    except dns.resolver.NoAnswer:
        print "\nNo Answer\n"

    except EOFError:
        print "\nEOFError\n"

    except KeyboardInterrupt:
        print "\nUser cancelled\n"

    except socket.error:
        print "\nFailed: connection refused\n"

No comments: