def execute(**kwargs): if handler.SIGINT: Output().warn("Aborted plugin: %s" % NAME, False) return None try: domain = kwargs['domain'].split('.') config = kwargs['config'] subfuz = kwargs['subfuz'] ms_targets = [ domain[-2] + '.sharepoint.com', domain[-2] + '-my.sharepoint.com', domain[-2] + '-myfiles.sharepoint.com', domain[-2] + '-files.sharepoint.com', domain[-2] + '.onmicrosoft.com', '%s-%s.mail.protection.outlook.com' % (domain[-2], domain[-1]), 'selector1-%s-%s._domainkey.%s.onmicrosoft.com' % (domain[-2], domain[-1], domain[-2]), 'selector2-%s-%s._domainkey.%s.onmicrosoft.com' % (domain[-2], domain[-1], domain[-2]) ] i = 0 for ms in ms_targets: ans = lookup(ms, 'ANY', '8.8.8.8', 'UDP', subfuz.timeout) if ans: i += 1 subfuz.parse_record(ans, ms) Output().neutral("%d subdomains found" % i, False) except: raise
def check_wildcard(self, domain_addr): try: wildcard = ''.join(random.choice(string.ascii_lowercase) for _ in range(15)) ans = lookup( (wildcard + '.' + domain_addr), 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(traceback.print_exc()) print (e) return False
def execute(**kwargs): if handler.SIGINT: Output().warn("Aborted plugin: %s" % NAME, False) return None try: domain = kwargs['domain'].split('.') config = kwargs['config'] subfuz = kwargs['subfuz'] citrix_targets = [domain[-2] + '.sharefile.com'] redirect = requests.get('https://' + citrix_targets[0]) if 'secure.sharefile.com' not in redirect.url: authlogin = redirect.url.split('/')[2] ans = lookup(authlogin.encode('utf-8'), 'ANY', '8.8.8.8', 'UDP', subfuz.timeout) if ans: subfuz.parse_record(ans, authlogin) except: raise
def execute(**kwargs): if handler.SIGINT: Output().warn("Aborted plugin: %s" % NAME, False) return None try: subfuz = kwargs['subfuz'] domain = kwargs['domain'].split('.') aws_target = [domain[-2] + '.s3.amazonaws.com'][0] query = requests.get('https://' + aws_target) if query.status_code == 404: return None elif query.status_code == 200: Output().good('Bucket %s is open' % aws_target,False) ans = lookup(aws_target, 'ANY', '8.8.8.8', 'UDP', subfuz.timeout) if ans: subfuz.parse_record(ans, aws_target) Output().neutral("AWS bucket found", False) except: raise
def execute(**kwargs): if handler.SIGINT: Output().warn("Aborted plugin: %s" % NAME, False) return None try: domain = kwargs['domain'].split('.') config = kwargs['config'] subfuz = kwargs['subfuz'] ms_targets = [domain[-2] + '.sharepoint.com', domain[-2] + '-my.sharepoint.com', domain[-2] + '-myfiles.sharepoint.com', domain[-2] + '-files.sharepoint.com', domain[-2] + '.onmicrosoft.com', '%s-%s.mail.protection.outlook.com' % (domain[-2], domain[-1])] for ms in ms_targets: ans = lookup(ms.encode('utf-8'), 'ANY', '8.8.8.8', 'UDP', subfuz.timeout) if ans: subfuz.parse_record(ans, ms) except: raise
def check_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', True) 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: print(dns_server_name) dns_servers.append( [lookup(dns_server_name,'A', self.config['config']['dns_fallback'], self.protocol, self.timeout)[0][0].address, y.target.to_text()]) except: self.log.fatal(self.f4.format(dns_server_name) + '{:15}'.format('Unable to resolv DNS server'), True) 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: nameserver = gethostbyname_ex(dns_server[0].encode('idna'))[2][0] if self.zone: try: z = dns.zone.from_xfr(dns.query.xfr(nameserver, 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 == 'PTR': tests = ['PTR'] subdomain = self.sl.ptr_unscanned_ip.pop(0) self.sl.ptr_scanned += 1 else: subdomain = self.sl.unscanned.pop(0) #print(subdomain) if self.args.record: tests = [self.record] elif self.record == 'A': if subdomain == '': tests = ['A', 'TXT', 'MX'] else: tests = ['A'] else: tests = ['ANY'] except: if len(self.sl.unscanned) == 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 == 'PTR': d = subdomain else: d = (subdomain + u'.' + self.domain).lower().lstrip('.') try: ans = lookup(d, 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 != 'PTR': self.new_targets(d) self.sl.found.append(d) elif ans == False and self.record != '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 != '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(traceback.print_exc()) print (e)
def parse_record(self, ans, query): wildcard = False try: for r in ans: if r.rdtype == 1: # A RECORD d = r.name.to_text().rstrip('.').encode('utf-8').decode('idna') for x in r.items: item = x.to_text() if item in self.a_wildcard: wildcard = True else: self.sl.items.append([d, item]) self.log.log_queue.append(self.f1.format(d +' ') + self.f2.format('A') + self.f3.format(item)) self.log.csv_queue.append("%s,A,%s,%s,%s" % (d, item,item,self.domain)) if r.rdtype == 5: # CNAME RECORD d = r.name.to_text().rstrip('.').encode('utf-8').decode('idna') for x in r.items: item = x.to_text() if item in self.cname_wildcard: wildcard = True else: self.sl.items.append([d, item]) self.log.log_queue.append(self.f1.format(d +' ') + self.f2.format('CNAME') + self.f3.format(item.rstrip('.'))) if self.csv: cname_ans = lookup(d, 'A') for line in cname_ans: if line.rdtype == 1: for dns_entry in line.items: self.log.csv_queue.append("%s,CNAME,%s,%s,%s" % (d, item.rstrip('.'), dns_entry.to_text(), self.domain)) if r.rdtype == 12: # PTR RECORD #d = r.name.to_text().rstrip('.').decode('utf-8').decode('idna') for x in r.items: item = x.to_text() if self.domain.split('.')[-2] in item: if not [y for y in self.sl.items if item.rstrip('.') in y if query in y[1]]: self.sl.items.append([item, query]) self.log.log_queue.append(self.f1.format(item.rstrip('.') +' ') + self.f2.format('PTR') + self.f3.format(query)) self.log.csv_queue.append("%s,PTR,%s,%s,%s" % (item.rstrip('.'), query,query,self.domain)) else: wildcard = True if r.rdtype == 16: # TXT RECORD d = r.name.to_text().rstrip('.').encode('utf-8').decode('idna') for x in r.items: item = x.to_text() if item in self.txt_wildcard: wildcard = True else: if [t for t in self.config['config']['txt_record_search'] if t in item]: self.sl.items.append([d, item]) self.log.log_queue.append(self.f1.format(d +' ') + self.f2.format('TXT') + self.f3.format(item)) self.log.csv_queue.append("%s,TXT,%s,,%s" % (d, item,self.domain)) if r.rdtype == 28: # AAAA RECORD d = r.name.to_text().rstrip('.').encode('utf-8').decode('idna') for x in r.items: item = x.to_text() if item in self.aaaa_wildcard: wildcard = True else: self.sl.items.append([d, item]) self.log.log_queue.append(self.f1.format(d +' ') + self.f2.format('AAAA') + self.f3.format(item)) self.log.csv_queue.append("%s,AAAA,%s,%s,%s" % (d, item, item, self.domain)) if r.rdtype == 15: # MX RECORD d = r.name.to_text().rstrip('.').encode('utf-8').decode('idna') for x in r.items: item = x.to_text() if item in self.mx_wildcard: wildcard = True else: self.sl.items.append([d, item]) self.log.log_queue.append(self.f1.format(d +' ') + self.f2.format('MX') + self.f3.format(item.split(' ')[1].rstrip('.'))) if self.csv: mx_value = item.split(' ')[1].rstrip('.') mx_ans = lookup(mx_value, 'A') for line in mx_ans: if line.rdtype == 1: for dns_entry in line.items: self.log.csv_queue.append("%s,MX,%s,%s,%s" % (d, mx_value, dns_entry.to_text(), self.domain)) new = ['mail._domainkey', '_dmarc', 'default._domainkey', 'selector1._domainkey', 'selector2._domainkey', 's2._domainkey', 's2._domainkey'] for n in new: if d == self.domain: self.append_target(n) else: self.append_target(n + '.' + d.replace(self.domain, '').strip('.')) except Exception as e: self.log.fatal(('Parsing records for: %s with answer %s' % (query, ans)), False) print(traceback.print_exc()) print (e) return wildcard