#!/usr/bin/python # -*- coding: utf-8 -*- ''' python dnslookup.py www.telpin.com.ar www.lanacion.com.ar www.telpin.com.ar : 201.219.64.50 www.lanacion.com.ar : 23.21.247.181 ''' from dnslookup import lookup import sys domain = sys.argv[1:] for x in domain: dns = lookup(x) print "{0} : {1}".format(x, dns)
def dns_server(self): # If dns override is not specified dns_servers = [] if not self.args.dns: ns_record = lookup(self.domain, 'NS', self.config['config']['dns_fallback'], self.protocol, self.timeout) if not ns_record: ns_record = lookup(".".join(self.domain.split('.')[-2:]), 'NS', self.config['config']['dns_fallback'], self.protocol, self.timeout) # TODO very ugly way of doing it, https://publicsuffix.org/list/public_suffix_list.dat is on the to-do list # currently doesn't handle target domain inputs like subdomain.domain.co.uk or similar domains very well yet. if not ns_record: # Exit early if ns_record is not found. self.log.fatal('Unable to lookup NS server', False) return False nameservers = [x for x in ns_record if x.rdtype == 2] if nameservers: self.log.normal('Name Servers:', True) # For every NS record found for y in nameservers[0]: dns_server_name = y.target.to_text() # get DNS server IP try: dns_servers.append([ lookup(dns_server_name, 'A', self.config['config']['dns_fallback'], self.protocol, self.timeout)[0].items[0].to_text(), y.target.to_text() ]) except: self.log.fatal( self.f4.format(dns_server_name) + '{:15}'.format( 'Unable to resolv DNS server - Likely due to unstable network connection' ), False) sys.exit() else: self.log.warn('No Name Servers found for %s' % self.domain, True) return False else: dns_servers.append([self.args.dns, self.args.dns]) # Zone transfer for dns_server in dns_servers: if self.zone: try: z = dns.zone.from_xfr( dns.query.xfr(dns_server[0], self.domain, timeout=10, lifetime=10)) self.log.good( self.f4.format(dns_server[1]) + '{:15}'.format(dns_server[0]) + ' - Zone Transfer allowed.', True) names = z.nodes.keys() for n in names: self.log.normal(z[n].to_text(n), True) except: self.log.warn( self.f4.format(dns_server[1]) + '{:15}'.format(dns_server[0]) + ' - Zone Transfer not allowed.', True) else: self.log.neutral( self.f4.format(dns_server[1]) + '{:15}'.format(dns_server[0]), True) # Testing for open TCP and UDP ports for DNS servers, and what type of records are permitted. # TCP - ANY dns_result = [] start = time.time() tany = lookup(self.domain, 'ANY', dns_server[0], 'TCP', self.timeout) end = time.time() if tany: if [ x for x in tany if x.rdtype == 1 or x.rdtype == 28 or x.rdtype == 5 or x.rdtype == 15 or x.rdtype == 16 ]: dns_result.append( ['TCP', dns_server[0], 'ANY', end - start]) # TCP - A start = time.time() ta = lookup(self.domain, 'A', dns_server[0], 'TCP', self.timeout) end = time.time() if ta: if [x for x in ta if x.rdtype == 1]: dns_result.append(['TCP', dns_server[0], 'A', end - start]) # UDP - ANY start = time.time() uany = lookup(self.domain, 'ANY', dns_server[0], 'UDP', self.timeout) end = time.time() if uany: if [ x for x in uany if x.rdtype == 1 or x.rdtype == 28 or x.rdtype == 5 or x.rdtype == 15 or x.rdtype == 16 ]: dns_result.append( ['UDP', dns_server[0], 'ANY', end - start]) # UDP - A start = time.time() ua = lookup(self.domain, 'A', dns_server[0], 'UDP', self.timeout) end = time.time() if ua: if [x for x in ua if x.rdtype == 1]: dns_result.append(['UDP', dns_server[0], 'A', end - start]) # Figure out the best combination to use dns_result = sorted(dns_result, key=lambda x: (x[3], x[1], x[0], x[2])) a = [i for i in dns_result if i[0] == 'UDP' and i[2] == 'ANY'] b = [i for i in dns_result if i[0] == 'TCP' and i[2] == 'ANY'] c = [i for i in dns_result if i[0] == 'UDP' and i[2] == 'A'] d = [i for i in dns_result if i[0] == 'TCP' and i[2] == 'A'] if a: # ANY + UDP self.dns, self.protocol, self.record, delay = a[0][1], a[0][0], a[ 0][2], a[0][3] elif b: # ANY + TCP self.dns, self.protocol, self.record, delay = b[0][1], b[0][0], b[ 0][2], b[0][3] elif c: # A + UDP self.dns, self.protocol, self.record, delay = c[0][1], c[0][0], c[ 0][2], c[0][3] elif d: # A + TCP self.dns, self.protocol, self.record, delay = d[0][1], d[0][0], d[ 0][2], d[0][3] else: #fallback self.dns, self.protocol, self.record, delay = self.config[ 'config']['dns_fallback'], self.config['config'][ 'dns_fallback_protocol'], self.config['config'][ 'dns_fallback_record'], 0 self.log.warn( 'Unable to find information about %s, falling back to DNS %s, Proto %s, Type %s ' % (self.domain, self.dns, self.protocol, self.record), True) # Compensate for override override_dns = self.args.dns override_record = self.args.record override_protocol = self.args.protocol if override_record: self.record = override_record if override_dns: self.dns = override_dns if override_protocol: self.protocol = override_protocol self.log.neutral( 'Using nameserver %s, query type %s over %s with RTT of %.4f seconds' % (self.dns, self.record, self.protocol, delay), True) return True
def scan_worker(self): while True: if self.handler.SIGINT: return self.mutex.acquire() try: if self.record is 'PTR': tests = ['PTR'] subdomain = self.sl.ptr_unscanned_ip.pop(0) self.sl.ptr_scanned += 1 else: subdomain = self.sl.unscanned.pop(0) if self.args.record: tests = [self.record] elif self.record is 'A': if subdomain == '': tests = ['A', 'TXT', 'MX'] else: tests = ['A'] else: tests = ['ANY'] except: if len(self.sl.unscanned) is 0: return finally: self.mutex.release() time.sleep(self.throttle) # if domain already has been scanned (remove duplicates) # else, add domain to "scanned" list. if subdomain in self.sl.scanned: continue else: self.sl.scanned.append(subdomain) for t in tests: if self.record is 'PTR': d = subdomain else: d = (subdomain + u'.' + self.domain).lower().lstrip('.') try: ans = lookup(d.encode('utf-8'), t, self.dns, self.protocol, self.timeout) if ans: wildcard = self.parse_record(ans, d) if ans and not wildcard and d != self.domain and self.record is not 'PTR': self.new_targets(d) self.sl.found.append(d) elif ans == False and self.record is not 'PTR': hit = [ x for x in self.sl.scan_failed if x[0] == subdomain ] if hit: z = self.sl.scan_failed.index(hit[0]) self.sl.scan_failed[z][1] += 1 if hit[0][1] > self.retry: self.sl.failcounter += 1 if self.args.verbose: self.log.status( 'Failed lookup on %s' % d + ' ' * 20, False) self.log.error_queue.append( 'Failed lookup on %s' % d) continue else: self.sl.scan_failed.append([subdomain, 1]) self.sl.scanned.remove(subdomain) self.sl.unscanned.insert(0, subdomain) if ans != False and self.record is not 'PTR' and ( (t == 'ANY' or t == 'A') or t == self.args.record): # basically don't count queries that's TXT or MX if querying a server doesn't respond to ANY self.sl.n_scanned += 1 self.sl.n_unscanned -= 1 except Exception as e: try: self.log.fatal(('Domain Query failed on %s.' % d), False) except: pass print(e)
def check_wildcard(self, domain_addr): try: wildcard = ''.join( random.choice(string.ascii_lowercase) for _ in range(15)) ans = lookup((wildcard + '.' + domain_addr.encode('utf-8')), self.record, self.dns, self.protocol, self.timeout) if ans: wc = False d = domain_addr.encode('utf-8') for r in ans: if r.rdtype == 1: # A RECORD item = [] for x in r.items: item.append(x.to_text()) self.a_wildcard += item self.log.warn( self.f1.format("Wildcard A record found for %s: " % d) + ", ".join(item), True) wc = True if r.rdtype == 5: # CNAME RECORD item = [] for x in r.items: item.append(x.to_text()) self.cname_wildcard += item self.log.warn( self.f1.format( "Wildcard CNAME record found for %s: " % d) + ", ".join(item), True) wc = True if r.rdtype == 16: # TXT RECORD item = [] for x in r.items: item.append(x.to_text()) self.txt_wildcard += item self.log.warn( self.f1.format( "Wildcard TXT record found for %s: " % d) + ", ".join(item), True) wc = True if r.rdtype == 28: # AAAA RECORD item = [] for x in r.items: item.append(x.to_text()) self.aaaa_wildcard += item self.log.warn( self.f1.format( "Wildcard AAAA record found for %s: " % d) + ", ".join(item), True) wc = True if r.rdtype == 15: # MX RECORD item = [] for x in r.items: item.append(x.to_text()) self.mx_wildcard += item self.log.warn( self.f1.format( "Wildcard MX record found for %s: " % d) + ", ".join(item), True) wc = True if wc == True: return True #if not wc: # return False except Exception as e: self.log.fatal(('Wildcard check on %s.' % domain_addr), False) print(e) return False
def dns_server(self): ns_record = lookup(self.domain, 'NS', self.config['config']['dns_fallback'], self.protocol, self.timeout) if not ns_record: ns_record = lookup(".".join(self.domain.split('.')[-2:]), 'NS', self.config['config']['dns_fallback'], self.protocol, self.timeout) # TODO very ugly way of doing it, https://publicsuffix.org/list/public_suffix_list.dat is on the to-do list # currently doesn't handle target domain inputs like subdomain.domain.co.uk or similar domains very well yet. # Grab NS record data # rdtype 2=NS nameservers = [x for x in ns_record if x.rdtype == 2] dns_servers = [] self.log.normal('Name Servers:', True) if nameservers: # For every NS record found for y in nameservers[0]: dns_server_name = y.target.to_text() # get DNS server IP dns_server = lookup(dns_server_name, 'A', self.config['config']['dns_fallback'], self.protocol, self.timeout)[0].items[0].to_text() # Zone transfer if self.zone: try: z = dns.zone.from_xfr( dns.query.xfr(dns_server, self.domain, timeout=10, lifetime=10)) self.log.good( self.f4.format(dns_server_name) + '{:15}'.format(dns_server) + ' - Zone Transfer allowed.', True) names = z.nodes.keys() for n in names: self.log.normal(z[n].to_text(n), True) except: self.log.warn( self.f4.format(dns_server_name) + '{:15}'.format(dns_server) + ' - Zone Transfer not allowed.', True) else: self.log.neutral( self.f4.format(dns_server_name) + '{:15}'.format(dns_server), True) # Testing for open TCP and UDP ports for DNS servers, and what type of records are permitted. # TCP tans = lookup(self.domain, 'ANY', dns_server, 'TCP', self.timeout) if tans: if [ x for x in tans if x.rdtype == 1 or x.rdtype == 28 or x.rdtype == 5 or x.rdtype == 15 or x.rdtype == 16 ]: dns_servers.append(['TCP', dns_server, 'ANY']) else: dns_servers.append(['TCP', dns_server, 'A']) # UDP uans = lookup(self.domain, 'ANY', dns_server, 'UDP', self.timeout) if uans: if [ x for x in uans if x.rdtype == 1 or x.rdtype == 28 or x.rdtype == 5 or x.rdtype == 15 or x.rdtype == 16 ]: dns_servers.append(['UDP', dns_server, 'ANY']) else: dns_servers.append(['UDP', dns_server, 'A']) # pick the best type of nameserver and record combination if not self.args.dns and dns_servers: a = [i for i in dns_servers if i[0] == 'UDP' and i[2] == 'ANY'] b = [i for i in dns_servers if i[0] == 'TCP' and i[2] == 'ANY'] c = [i for i in dns_servers if i[0] == 'UDP' and i[2] == 'A'] d = [i for i in dns_servers if i[0] == 'TCP' and i[2] == 'A'] if a: # ANY + UDP self.dns, self.protocol, self.record = a[0][1], a[0][0], a[ 0][2] elif b: # ANY + TCP self.dns, self.protocol, self.record = b[0][1], b[0][0], b[ 0][2] elif c: # A + UDP self.dns, self.protocol, self.record = c[0][1], c[0][0], c[ 0][2] elif d: # A + TCP self.dns, self.protocol, self.record = d[0][1], d[0][0], d[ 0][2] override_dns = self.args.dns override_record = self.args.record override_protocol = self.args.protocol if override_record: self.record = override_record if override_dns: self.dns = override_dns if override_protocol: self.protocol = override_protocol self.log.neutral( 'Using nameserver %s, query type %s over %s' % (self.dns, self.record, self.protocol), True)
def scan_worker(self): while True: if self.handler.SIGINT: return self.mutex.acquire() try: if self.record is 'PTR': tests = ['PTR'] self.sl.ptr_scanned += 1 subdomain = self.sl.ptr_unscanned_ip.pop(0) else: if self.args.record: tests = [self.record] elif self.record is 'A': tests = ['A', 'TXT', 'MX'] else: tests = ['ANY'] self.sl.n_scanned += 1 self.sl.n_unscanned -= 1 subdomain = self.sl.unscanned.pop(0) except: if len(self.sl.unscanned) is 0: return finally: self.mutex.release() time.sleep(self.throttle) # if domain already has been scanned (remove duplicates) # else, add domain to "scanned" list. if subdomain in self.sl.scanned: continue else: self.sl.scanned.append(subdomain) for t in tests: if self.record is 'PTR': d = subdomain else: d = (subdomain + u'.' + self.domain).lower().lstrip('.') try: ans = lookup(d.encode('utf-8'), t, self.dns, self.protocol, self.timeout) if ans: wildcard = self.parse_record(ans, d) if ans and not wildcard and d != self.domain and self.record is not 'PTR': self.new_targets(d) self.sl.found.append(d) elif ans == False and self.record is not 'PTR': hit = [ x for x in self.sl.scan_failed if x[0] == subdomain ] if hit: z = self.sl.scan_failed.index(hit[0]) self.sl.scan_failed[z][1] += 1 if hit[0][1] > self.retry: continue else: self.sl.scan_failed.append([subdomain, 1]) self.sl.unscanned.insert(0, subdomain) except Exception as e: try: self.log.fatal(('Domain Query failed on %s.' % d), False) except: self.log.fatal( ('Domain Query failed on %s. (HEX ENCODED)' % d.encode('hex')), False) # added to in an attempt to resolve a bug related to invalid UTF-8 characters print(e)