This commit is contained in:
Jing Ling
2020-05-11 21:40:32 +08:00
parent 74d5354ead
commit fc7a5353d9
14 changed files with 47 additions and 48 deletions
+6 -6
View File
@@ -32,7 +32,7 @@ def do_query_a(domain, resolver):
answer = resolver.query(domain, 'A') answer = resolver.query(domain, 'A')
# If resolve random subdomain raise timeout error, try again # If resolve random subdomain raise timeout error, try again
except Timeout as e: except Timeout as e:
logger.log('ALERT', f'DNS resolve timeout, retrying...') logger.log('ALERT', f'DNS resolve timeout, retrying')
logger.log('DEBUG', e.args) logger.log('DEBUG', e.args)
raise tenacity.TryAgain raise tenacity.TryAgain
# If resolve random subdomain raise NXDOMAIN, YXDOMAIN, NoAnswer, NoNameservers error # If resolve random subdomain raise NXDOMAIN, YXDOMAIN, NoAnswer, NoNameservers error
@@ -47,7 +47,7 @@ def do_query_a(domain, resolver):
exit(1) exit(1)
else: else:
if answer.rrset is None: if answer.rrset is None:
logger.log('ALERT', f'DNS resolve dont have result, retrying...') logger.log('ALERT', f'DNS resolve dont have result, retrying')
raise tenacity.TryAgain raise tenacity.TryAgain
ttl = answer.ttl ttl = answer.ttl
name = answer.name name = answer.name
@@ -309,7 +309,7 @@ def gen_records(items, records, subdomains, ip_times, wc_ips, wc_ttl):
def stat_ip_times(result_paths): def stat_ip_times(result_paths):
logger.log('INFOR', f'Counting IP...') logger.log('INFOR', f'Counting IP')
times = dict() times = dict()
for result_path in result_paths: for result_path in result_paths:
logger.log('DEBUG', f'Reading {result_path}') logger.log('DEBUG', f'Reading {result_path}')
@@ -339,7 +339,7 @@ def stat_ip_times(result_paths):
def deal_output(output_paths, ip_times, wildcard_ips, wildcard_ttl): def deal_output(output_paths, ip_times, wildcard_ips, wildcard_ttl):
logger.log('INFOR', f'Processing result...') logger.log('INFOR', f'Processing result')
records = dict() # 用来记录所有域名解析数据 records = dict() # 用来记录所有域名解析数据
subdomains = list() # 用来保存所有通过有效性检查的子域 subdomains = list() # 用来保存所有通过有效性检查的子域
for output_path in output_paths: for output_path in output_paths:
@@ -547,7 +547,7 @@ class Brute(Module):
def main(self, domain): def main(self, domain):
start = time.time() start = time.time()
logger.log('INFOR', f'Blasting {domain} ...') logger.log('INFOR', f'Blasting {domain} ')
massdns_dir = setting.third_party_dir.joinpath('massdns') massdns_dir = setting.third_party_dir.joinpath('massdns')
result_dir = setting.result_save_dir result_dir = setting.result_save_dir
temp_dir = result_dir.joinpath('temp') temp_dir = result_dir.joinpath('temp')
@@ -579,7 +579,7 @@ class Brute(Module):
output_path = temp_dir.joinpath(output_name) output_path = temp_dir.joinpath(output_name)
log_path = result_dir.joinpath('massdns.log') log_path = result_dir.joinpath('massdns.log')
check_dict() check_dict()
logger.log('INFOR', f'Running massdns to resolve subdomains')
utils.call_massdns(massdns_path, dict_path, ns_path, output_path, utils.call_massdns(massdns_path, dict_path, ns_path, output_path,
log_path, quiet_mode=self.quite, log_path, quiet_mode=self.quite,
process_num=self.process_num, process_num=self.process_num,
-1
View File
@@ -1 +0,0 @@
# coding=utf-8
+1 -1
View File
@@ -1,4 +1,4 @@
from .module import Module from common.module import Module
class Crawl(Module): class Crawl(Module):
+2 -2
View File
@@ -24,7 +24,7 @@ class Database(object):
:param db_path: Database path :param db_path: Database path
:return: db_conn: SQLite database connection :return: db_conn: SQLite database connection
""" """
logger.log('TRACE', f'Establishing database connection...') logger.log('TRACE', f'Establishing database connection')
if isinstance(db_path, Connection): if isinstance(db_path, Connection):
return db_path return db_path
protocol = 'sqlite:///' protocol = 'sqlite:///'
@@ -94,7 +94,7 @@ class Database(object):
:param str module_name: mo :param str module_name: mo
""" """
logger.log('TRACE', logger.log('TRACE',
f'Saving the subdomain results of {table_name} found by module {module_name} into database...') f'Saving the subdomain results of {table_name} found by module {module_name} into database')
table_name = table_name.replace('.', '_') table_name = table_name.replace('.', '_')
if results: if results:
try: try:
+1 -1
View File
@@ -1,4 +1,4 @@
from .module import Module from common.module import Module
from common import utils from common import utils
+5 -5
View File
@@ -11,8 +11,8 @@ import time
import requests import requests
from config.log import logger from config.log import logger
from config import setting from config import setting
from . import utils from common import utils
from .domain import Domain from common.domain import Domain
from common.database import Database from common.database import Database
lock = threading.Lock() lock = threading.Lock()
@@ -45,7 +45,7 @@ class Module(object):
:return bool: check result :return bool: check result
""" """
if not all(apis): if not all(apis):
logger.log('ALERT', f'{self.source} module is not configured, skip') logger.log('DEBUG', f'{self.source} module is not configured')
return False return False
return True return True
@@ -62,7 +62,7 @@ class Module(object):
self.end = time.time() self.end = time.time()
self.elapse = round(self.end - self.start, 1) self.elapse = round(self.end - self.start, 1)
logger.log('DEBUG', f'Finished {self.source} module to collect {self.domain}\'s subdomains') logger.log('DEBUG', f'Finished {self.source} module to collect {self.domain}\'s subdomains')
logger.log('INFOR', f'The {self.source} module took {self.elapse} seconds, ' logger.log('INFOR', f'The {self.source} module took {self.elapse} seconds '
f'found {len(self.subdomains)} subdomains') f'found {len(self.subdomains)} subdomains')
logger.log('DEBUG', f'{self.source} module found subdomains of {self.domain}\n' logger.log('DEBUG', f'{self.source} module found subdomains of {self.domain}\n'
f'{self.subdomains}') f'{self.subdomains}')
@@ -252,7 +252,7 @@ class Module(object):
""" """
Generate results Generate results
""" """
logger.log('DEBUG', f'Generating final results...') logger.log('DEBUG', f'Generating final results')
if not len(self.subdomains): # 该模块一个子域都没有发现的情况 if not len(self.subdomains): # 该模块一个子域都没有发现的情况
logger.log('DEBUG', f'{self.source} module result is empty') logger.log('DEBUG', f'{self.source} module result is empty')
result = {'id': None, result = {'id': None,
+1 -1
View File
@@ -1,4 +1,4 @@
from .module import Module from common.module import Module
class Query(Module): class Query(Module):
+4 -4
View File
@@ -22,7 +22,7 @@ def get_limit_conn():
def get_ports(port): def get_ports(port):
logger.log('DEBUG', f'Getting port range...') logger.log('DEBUG', f'Getting port range')
ports = set() ports = set()
if isinstance(port, (set, list, tuple)): if isinstance(port, (set, list, tuple)):
ports = port ports = port
@@ -40,7 +40,7 @@ def get_ports(port):
def gen_req_data(data, ports): def gen_req_data(data, ports):
logger.log('INFOR', f'Generating request urls...') logger.log('INFOR', f'Generating request urls')
new_data = [] new_data = []
for data in data: for data in data:
resolve = data.get('resolve') resolve = data.get('resolve')
@@ -203,7 +203,7 @@ async def bulk_request(data, port):
to_req_data = gen_req_data(data, ports) to_req_data = gen_req_data(data, ports)
method = setting.request_method method = setting.request_method
logger.log('INFOR', f'Use {method} method to request') logger.log('INFOR', f'Use {method} method to request')
logger.log('INFOR', f'Async subdomains request in progress...') logger.log('INFOR', f'Async subdomains request in progress')
connector = get_connector() connector = get_connector()
header = get_header() header = get_header()
async with ClientSession(connector=connector, headers=header) as session: async with ClientSession(connector=connector, headers=header) as session:
@@ -255,7 +255,7 @@ def run_request(domain, data, port):
# 在关闭事件循环前加入一小段延迟让底层连接得到关闭的缓冲时间 # 在关闭事件循环前加入一小段延迟让底层连接得到关闭的缓冲时间
loop.run_until_complete(asyncio.sleep(0.25)) loop.run_until_complete(asyncio.sleep(0.25))
count = utils.count_alive(data) count = utils.count_alive(data)
logger.log('INFOR', f'After verify, found {domain} have {count} alive subdomains') logger.log('INFOR', f'Request module found {domain} have {count} alive subdomains')
return data return data
+6 -5
View File
@@ -14,7 +14,7 @@ def filter_subdomain(data):
:param list data: 待过滤的数据列表 :param list data: 待过滤的数据列表
:return: 符合条件的子域列表 :return: 符合条件的子域列表
""" """
logger.log('DEBUG', f'Filtering subdomains to be resolved...') logger.log('DEBUG', f'Filtering subdomains to be resolved')
subdomains = [] subdomains = []
for data in data: for data in data:
if not data.get('content'): if not data.get('content'):
@@ -31,7 +31,7 @@ def update_data(data, records):
:param dict records: 解析结果字典 :param dict records: 解析结果字典
:return: 更新后的数据列表 :return: 更新后的数据列表
""" """
logger.log('DEBUG', f'Updating resolved results...') logger.log('DEBUG', f'Updating resolved results')
if not records: if not records:
logger.log('ERROR', f'No valid resolved result') logger.log('ERROR', f'No valid resolved result')
return data return data
@@ -52,7 +52,7 @@ def save_data(name, data):
:param str name: 保存表名 :param str name: 保存表名
:param list data: 待保存的数据 :param list data: 待保存的数据
""" """
logger.log('INFOR', f'Saving resolved results...') logger.log('INFOR', f'Saving resolved results')
db = Database() db = Database()
db.drop_table(name) db.drop_table(name)
db.create_table(name) db.create_table(name)
@@ -61,7 +61,7 @@ def save_data(name, data):
def save_subdomains(save_path, subdomain_list): def save_subdomains(save_path, subdomain_list):
logger.log('DEBUG', f'Saving resolved subdomain...') logger.log('DEBUG', f'Saving resolved subdomain')
subdomain_data = '\n'.join(subdomain_list) subdomain_data = '\n'.join(subdomain_list)
if not utils.save_data(save_path, subdomain_data): if not utils.save_data(save_path, subdomain_data):
logger.log('FATAL', 'Save resolved subdomain error') logger.log('FATAL', 'Save resolved subdomain error')
@@ -69,7 +69,7 @@ def save_subdomains(save_path, subdomain_list):
def deal_output(output_path): def deal_output(output_path):
logger.log('INFOR', f'Processing resolved results...') logger.log('INFOR', f'Processing resolved results')
records = dict() # 用来记录所有域名解析数据 records = dict() # 用来记录所有域名解析数据
with open(output_path) as fd: with open(output_path) as fd:
for line in fd: for line in fd:
@@ -161,6 +161,7 @@ def run_resolve(domain, data):
ns_path = setting.brute_nameservers_path ns_path = setting.brute_nameservers_path
logger.log('INFOR', f'Running massdns to brute subdomains')
utils.call_massdns(massdns_path, save_path, ns_path, utils.call_massdns(massdns_path, save_path, ns_path,
output_path, log_path, quiet_mode=True) output_path, log_path, quiet_mode=True)
-1
View File
@@ -3,7 +3,6 @@ import re
from config import setting from config import setting
from config.log import logger from config.log import logger
from common.module import Module from common.module import Module
from common import utils
class Search(Module): class Search(Module):
+10 -10
View File
@@ -99,7 +99,7 @@ def get_domains(target):
:return list: domain list :return list: domain list
""" """
domains = list() domains = list()
logger.log('DEBUG', f'Getting domains...') logger.log('DEBUG', f'Getting domains')
if isinstance(target, (set, tuple)): if isinstance(target, (set, tuple)):
domains = list(target) domains = list(target)
elif isinstance(target, list): elif isinstance(target, list):
@@ -171,7 +171,7 @@ def check_path(path, name, format):
logger.log('ALERT', f'{parent_dir} does not exist, directory will be created') logger.log('ALERT', f'{parent_dir} does not exist, directory will be created')
parent_dir.mkdir(parents=True, exist_ok=True) parent_dir.mkdir(parents=True, exist_ok=True)
if path.exists(): if path.exists():
logger.log('ALERT', f'{path} exists, file will be overwritten') logger.log('ALERT', f'The {path} exists and will be overwritten')
return path return path
@@ -487,7 +487,7 @@ def delete_file(*paths):
@tenacity.retry(stop=tenacity.stop_after_attempt(3)) @tenacity.retry(stop=tenacity.stop_after_attempt(3))
def check_net(): def check_net():
logger.log('INFOR', 'Checking Internet environment...') logger.log('INFOR', 'Checking Internet environment')
urls = ['http://www.example.com', 'http://www.baidu.com', urls = ['http://www.example.com', 'http://www.baidu.com',
'http://www.bing.com', 'http://www.taobao.com', 'http://www.bing.com', 'http://www.taobao.com',
'http://www.linkedin.com', 'http://www.msn.com', 'http://www.linkedin.com', 'http://www.msn.com',
@@ -498,18 +498,18 @@ def check_net():
rsp = requests.get(url) rsp = requests.get(url)
except Exception as e: except Exception as e:
logger.log('ERROR', e.args) logger.log('ERROR', e.args)
logger.log('ALERT', 'Can not access Internet, retrying...') logger.log('ALERT', 'Can not access Internet, retrying')
raise tenacity.TryAgain raise tenacity.TryAgain
if rsp.status_code != 200: if rsp.status_code != 200:
logger.log('ALERT', f'{rsp.request.method} {rsp.request.url} ' logger.log('ALERT', f'{rsp.request.method} {rsp.request.url} '
f'{rsp.status_code} {rsp.reason}') f'{rsp.status_code} {rsp.reason}')
logger.log('ALERT', 'Can not access Internet normally, retrying...') logger.log('ALERT', 'Can not access Internet normally, retrying')
raise tenacity.TryAgain raise tenacity.TryAgain
logger.log('INFOR', 'Access to Internet OK') logger.log('INFOR', 'Access to Internet OK')
def check_pre(): def check_pre():
logger.log('INFOR', 'Checking dependent environment...') logger.log('INFOR', 'Checking dependent environment')
system = platform.system() system = platform.system()
implementation = platform.python_implementation() implementation = platform.python_implementation()
version = platform.python_version() version = platform.python_version()
@@ -531,7 +531,7 @@ def check_pre():
def check_env(): def check_env():
logger.log('INFOR', 'Checking the environment...') logger.log('INFOR', 'Checking the environment')
try: try:
check_net() check_net()
except Exception as e: except Exception as e:
@@ -548,7 +548,7 @@ def get_maindomain(domain):
def call_massdns(massdns_path, dict_path, ns_path, output_path, log_path, def call_massdns(massdns_path, dict_path, ns_path, output_path, log_path,
query_type='A', process_num=1, concurrent_num=10000, query_type='A', process_num=1, concurrent_num=10000,
quiet_mode=False): quiet_mode=False):
logger.log('INFOR', f'Start running massdns') logger.log('DEBUG', f'Start running massdns')
quiet = '' quiet = ''
if quiet_mode: if quiet_mode:
quiet = '--quiet' quiet = '--quiet'
@@ -561,9 +561,9 @@ def call_massdns(massdns_path, dict_path, ns_path, output_path, log_path,
f'--resolve-count {resolve_num} --type {query_type} ' \ f'--resolve-count {resolve_num} --type {query_type} ' \
f'--flush --output J --outfile {output_path} ' \ f'--flush --output J --outfile {output_path} ' \
f'--root --error-log {log_path} {dict_path}' f'--root --error-log {log_path} {dict_path}'
logger.log('INFOR', f'Run command {cmd}') logger.log('DEBUG', f'Run command {cmd}')
subprocess.run(args=cmd, shell=True) subprocess.run(args=cmd, shell=True)
logger.log('INFOR', f'Finished massdns') logger.log('DEBUG', f'Finished massdns')
def get_massdns_path(massdns_dir): def get_massdns_path(massdns_dir):
+1 -1
View File
@@ -46,7 +46,7 @@ def export(table, db=None, alive=False, limit=None, path=None, format='csv', sho
data = rows.export(format) data = rows.export(format)
database.close() database.close()
utils.save_data(path, data) utils.save_data(path, data)
logger.log('INFOR', f'{table}\'s subdomains result: {path}') logger.log('ALERT', f'Subdomain result for {table}: {path}')
data_dict = rows.as_dict() data_dict = rows.as_dict()
return data_dict return data_dict
+7 -7
View File
@@ -20,7 +20,7 @@ HEADERS = {
def github_takeover(url): def github_takeover(url):
# 读取config配置文件 # 读取config配置文件
repo_name = url repo_name = url
print('[*]正在读取配置文件...') print('[*]正在读取配置文件')
user = api.github_api_user user = api.github_api_user
token = api.github_api_token token = api.github_api_token
CHECK_HEADERS = { CHECK_HEADERS = {
@@ -34,7 +34,7 @@ def github_takeover(url):
if repos_r.json()['message'] == 'Bad credentials': if repos_r.json()['message'] == 'Bad credentials':
print('[*]请检查Token是否正确') print('[*]请检查Token是否正确')
elif repos_r.json()['message'] == 'Not Found': elif repos_r.json()['message'] == 'Not Found':
print('[*]正在生成接管库...') # 生成接管库 print('[*]正在生成接管库') # 生成接管库
creat_repo_dict = { creat_repo_dict = {
"name": repo_name, "name": repo_name,
"description": "This is a subdomain takeover Repository", "description": "This is a subdomain takeover Repository",
@@ -45,7 +45,7 @@ def github_takeover(url):
data=json.dumps(creat_repo_dict)) data=json.dumps(creat_repo_dict))
creat_repo_status = creat_repo_r.status_code creat_repo_status = creat_repo_r.status_code
if creat_repo_status == 201: if creat_repo_status == 201:
print('[*]创建接管库' + repo_name + '成功,正在进行自动接管...') print('[*]创建接管库' + repo_name + '成功,正在进行自动接管')
# 接管文件生成 # 接管文件生成
# index.html文件 # index.html文件
html = b''' html = b'''
@@ -81,7 +81,7 @@ def github_takeover(url):
headers=CHECK_HEADERS) # 上传CNAME headers=CHECK_HEADERS) # 上传CNAME
rs = cname_r.status_code rs = cname_r.status_code
if rs == 201: if rs == 201:
print('[*]生成接管库成功,正在开启Github pages...') print('[*]生成接管库成功,正在开启Github pages')
page_url = "https://api.github.com/repos/" + user + "/" + url + "/pages" page_url = "https://api.github.com/repos/" + user + "/" + url + "/pages"
page_dict = { page_dict = {
"source": { "source": {
@@ -94,9 +94,9 @@ def github_takeover(url):
if page_r.status_code == 201: if page_r.status_code == 201:
print('[+]自动接管成功,请稍后访问http://' + str(url) + '查看结果') print('[+]自动接管成功,请稍后访问http://' + str(url) + '查看结果')
else: else:
print('[+]开启Github pages失败,请检查网络或稍后重试...') print('[+]开启Github pages失败,请检查网络或稍后重试')
else: else:
print('[+]生成接管库失败,请检查网络或稍后重试...') print('[+]生成接管库失败,请检查网络或稍后重试')
elif url in repos_r.json()['name']: elif url in repos_r.json()['name']:
print('[*]生成接管库失败,请检查https://github.com/' + user + print('[*]生成接管库失败,请检查https://github.com/' + user +
'?tab=repositories是否存在同名接管库...') '?tab=repositories是否存在同名接管库')
+2 -2
View File
@@ -78,7 +78,7 @@ class Takeover(Module):
self.results = Dataset() self.results = Dataset()
def save(self): def save(self):
logger.log('DEBUG', 'Saving results...') logger.log('DEBUG', 'Saving results')
if self.format == 'txt': if self.format == 'txt':
data = str(self.results) data = str(self.results)
else: else:
@@ -138,7 +138,7 @@ class Takeover(Module):
name = f'takeover_check_result_{timestamp}' name = f'takeover_check_result_{timestamp}'
self.path = utils.check_path(self.path, name, self.format) self.path = utils.check_path(self.path, name, self.format)
if self.subdomains: if self.subdomains:
logger.log('INFOR', f'Checking subdomain takeover...') logger.log('INFOR', f'Checking subdomain takeover')
self.fingerprints = get_fingerprint() self.fingerprints = get_fingerprint()
self.results.headers = ['subdomain', 'cname'] self.results.headers = ['subdomain', 'cname']
# 创建待检查的子域队列 # 创建待检查的子域队列