def detect_wildcard(domain): """ 探测域名是否使用泛解析 :param str domain: 域名 :return: 如果没有使用泛解析返回False 反之返回泛解析的IP集合和ttl整型值 """ logger.log('INFOR', f'正在探测{domain}是否使用泛解析') token = secrets.token_hex(4) random_subdomain = f'{token}.{domain}' try: resolver = resolve.dns_resolver() answers = resolver.query(random_subdomain, 'A') # 如果查询随机域名A记录出错 说明不存在随机子域的A记录 即没有开启泛解析 except Exception as e: logger.log('DEBUG', e) logger.log('INFOR', f'{domain}没有使用泛解析') return False, None, None ttl = answers.ttl name = answers.name ips = {item.address for item in answers} logger.log('ALERT', f'{domain}使用了泛解析') logger.log('ALERT', f'{random_subdomain} 解析到域名: {name} ' f'IP: {ips} TTL: {ttl}') return True, ips, ttl
def check(self): """ 正则匹配响应头中的内容安全策略字段以发现子域名 """ resolver = resolve.dns_resolver() try: answers = resolver.query(self.domain, "NS") except Exception as e: logger.log('ERROR', e) return self.nsservers = [str(answer) for answer in answers] if not len(self.nsservers): logger.log('ALERT', f'没有找到{self.domain}的NS域名服务器记录') return for nsserver in self.nsservers: logger.log('DEBUG', f'正在尝试对{self.domain}的域名服务器{nsserver}进行域传送') try: xfr = dns.query.xfr(nsserver, self.domain) zone = dns.zone.from_xfr(xfr) except Exception as e: logger.log('DEBUG', str(e)) logger.log('DEBUG', f'对{self.domain}的域名服务器{nsserver}进行域传送失败') continue else: names = zone.nodes.keys() for name in names: subdomain = utils.match_subdomain(self.domain, str(name) + '.' + self.domain) self.subdomains = self.subdomains.union(subdomain) record = zone[name].to_text(name) self.results.append(record) if self.results: logger.log('DEBUG', f'发现{self.domain}在{nsserver}上的域传送记录') logger.log('DEBUG', '\n'.join(self.results)) self.results = []
def collect_wildcard_record(domain, authoritative_ns): logger.log('INFOR', f'正在收集{domain}的泛解析记录') if not authoritative_ns: return list(), int() resolver = resolve.dns_resolver() resolver.nameservers = authoritative_ns resolver.rotate = True resolver.cache = None ips = set() ips_stat = dict() while True: token = secrets.token_hex(4) random_subdomain = f'{token}.{domain}' ip, ttl = get_wildcard_record(random_subdomain, resolver) if ip is None: continue ips = ips.union(ip) # 统计每个泛解析IP出现次数 for addr in ip: count = ips_stat.setdefault(addr, 0) ips_stat[addr] = count + 1 # 筛选出出现次数2次以上的IP地址 addrs = list() for addr, times in ips_stat.items(): if times >= 2: addrs.append(addr) # 大部分的IP地址出现次数大于2次停止收集泛解析IP记录 if len(addrs) / len(ips) >= 0.8: break logger.log('DEBUG', f'收集到{domain}的泛解析记录\n{ips}\n{ttl}') return ips, ttl
def get_cname(subdomain): resolver = resolve.dns_resolver() try: answers = resolver.query(subdomain, 'CNAME') except Exception as e: logger.log('TRACE', e.args) return None for answer in answers: return answer.to_text() # 一个子域只有一个CNAME记录
def query_domain_ns(domain): resolver = resolve.dns_resolver() try: answer = resolver.query(domain, 'NS') except Exception as e: logger.log('ERROR', e.args) logger.log('ERROR', f'查询{domain}的NS记录出错') return list() ns = [item.to_text() for item in answer] logger.log('INFOR', f'{domain}的权威DNS名称服务器 {ns}') return ns
def check(self): """ 正则匹配响应头中的内容安全策略字段以发现子域名 """ resolver = resolve.dns_resolver() try: answers = resolver.query(self.domain, "NS") except Exception as e: logger.log('ERROR', e) return nsservers = [str(answer) for answer in answers] if not len(nsservers): logger.log('ALERT', f'没有找到{self.domain}的NS域名服务器记录') return for nsserver in nsservers: self.axfr(nsserver)
def query_domain_ns_a(ns_list): if not isinstance(ns_list, list): return list() ns_ip_list = [] resolver = resolve.dns_resolver() for ns in ns_list: try: answer = resolver.query(ns, 'A') except Exception as e: logger.log('ERROR', e.args) logger.log('ERROR', f'查询权威DNS名称服务器{ns}的A记录出错') continue if answer: for item in answer: ns_ip_list.append(item.address) logger.log('INFOR', f'权威DNS名称服务器对应A记录 {ns_ip_list}') return ns_ip_list
def dns_query(qname, qtype): """ 查询域名DNS记录 :param str qname: 待查域名 :param str qtype: 查询类型 :return: 查询结果 """ logger.log('TRACE', f'尝试查询{qname}的{qtype}记录') resolver = resolve.dns_resolver() try: answer = resolver.query(qname, qtype) except Exception as e: logger.log('TRACE', e.args) logger.log('TRACE', f'查询{qname}的{qtype}记录失败') return None else: logger.log('TRACE', f'查询{qname}的{qtype}记录成功') return answer
def get_wildcard_record(domain, authoritative_ns): if not authoritative_ns: return list(), int() resolver = resolve.dns_resolver() resolver.nameservers = authoritative_ns token = secrets.token_hex(4) random_subdomain = f'{token}.{domain}' logger.log('INFOR', f'查询{random_subdomain}在权威DNS名称服务器的泛解析记录') try: answer = resolver.query(random_subdomain, 'A') except Exception as e: logger.log('ERROR', e.args) logger.log('ERROR', f'查询{random_subdomain}在权威DNS名称服务器泛解析记录出错') return None, None name = answer.name ips = {item.address for item in answer} ttl = answer.ttl logger.log( 'INFOR', f'{random_subdomain} 在权威DNS上解析到域名: {name} ' f'IP: {ips} TTL: {ttl}') return ips, ttl
def do_query_a(domain): resolver = resolve.dns_resolver() try: answer = resolver.query(domain, 'A') # 如果查询随机域名A记录时抛出Timeout异常则重新探测 except Timeout as e: logger.log('ALERT', f'探测超时重新探测中') logger.log('DEBUG', e.args) raise TryAgain # 如果查询随机域名A记录时抛出NXDOMAIN,YXDOMAIN,NoAnswer,NoNameservers异常 # 则说明不存在随机子域的A记录 即没有开启泛解析 except Exception as e: logger.log('DEBUG', e.args) logger.log('INFOR', f'{domain}没有使用泛解析') return False if isinstance(answer, Answer): ttl = answer.ttl name = answer.name ips = {item.address for item in answer} logger.log('ALERT', f'{domain}使用了泛解析') logger.log('ALERT', f'{domain} 解析到域名: {name} ' f'IP: {ips} TTL: {ttl}') return True
def detect_wildcard(domain, authoritative_ns): """ 探测域名是否使用泛解析 :param str domain: 域名 :param list authoritative_ns: 权威DNS :return: 是否使用泛解析 """ logger.log('INFOR', f'正在探测{domain}是否使用泛解析') token = secrets.token_hex(4) random_subdomain = f'{token}.{domain}' resolver = resolve.dns_resolver() resolver.nameservers = authoritative_ns resolver.rotate = True resolver.cache = None try: wildcard = do_query_a(random_subdomain, resolver) except Exception as e: logger.log('DEBUG', e.args) logger.log('FATAL', f'探测{domain}是否使用泛解析失败') exit(1) else: return wildcard
def __init__(self, domain): Module.__init__(self) self.domain = self.register(domain) self.module = 'dnsquery' self.source = "BruteSRV" self.resolver = resolve.dns_resolver()
def __init__(self, names_que, answers_que): threading.Thread.__init__(self) self.names_que = names_que self.answers_que = answers_que self.resolver = resolve.dns_resolver()