添加当查询多个主域时结果自动合并导出功能

This commit is contained in:
Jing Ling
2019-12-27 18:54:10 +08:00
parent 7c8bd44c37
commit d5f478654b
5 changed files with 73 additions and 19 deletions
+11 -13
View File
@@ -111,36 +111,33 @@ def get_title(markup):
title = soup.title title = soup.title
if title: if title:
return title.text.strip() return title.text
h1 = soup.h1 h1 = soup.h1
if h1: if h1:
return h1.text.strip() return h1.text
h2 = soup.h2 h2 = soup.h2
if h2: if h2:
return h2.text.strip() return h2.text
h3 = soup.h3 h3 = soup.h3
if h2: if h2:
return h3.text.strip() return h3.text
desc = soup.find('meta', attrs={'name': 'description'}) desc = soup.find('meta', attrs={'name': 'description'})
if desc: if desc:
return desc['content'].strip() return desc['content']
word = soup.find('meta', attrs={'name': 'keywords'}) word = soup.find('meta', attrs={'name': 'keywords'})
if word: if word:
return word['content'].strip() return word['content']
if len(markup) <= 200:
return markup.strip()
text = soup.text text = soup.text
if len(text) <= 200: if len(text) <= 200:
return text.strip() return text
return None return ''
def request_callback(future, index, datas): def request_callback(future, index, datas):
@@ -164,9 +161,10 @@ def request_callback(future, index, datas):
'Via': headers.get('Via'), 'Via': headers.get('Via'),
'X-Powered-By': headers.get('X-Powered-By')}) 'X-Powered-By': headers.get('X-Powered-By')})
datas[index]['banner'] = banner[1:-1] datas[index]['banner'] = banner[1:-1]
datas[index]['title'] = get_title(text) title = get_title(text).strip()
datas[index]['title'] = utils.remove_string(title)
datas[index]['header'] = str(dict(headers))[1:-1] datas[index]['header'] = str(dict(headers))[1:-1]
datas[index]['response'] = text datas[index]['response'] = utils.remove_string(text)
else: else:
datas[index]['reason'] = 'Something error' datas[index]['reason'] = 'Something error'
datas[index]['valid'] = 0 datas[index]['valid'] = 0
+53 -3
View File
@@ -1,10 +1,12 @@
# coding=utf-8 # coding=utf-8
import re import re
import time
import random import random
import ipaddress import ipaddress
import platform import platform
import config import config
from pathlib import Path from pathlib import Path
from records import Record, RecordCollection
from common.domain import Domain from common.domain import Domain
from config import logger from config import logger
@@ -144,7 +146,7 @@ def get_semaphore():
return 800 return 800
def check_dpath(dpath): def check_dpath(dpath=None):
""" """
检查目录路径 检查目录路径
@@ -163,21 +165,26 @@ def check_dpath(dpath):
return dpath return dpath
def check_format(format): def check_format(format, line):
""" """
检查导出格式 检查导出格式
:param format: 传入的导出格式 :param format: 传入的导出格式
:param line: 行数
:return: 导出格式 :return: 导出格式
""" """
formats = ['txt', 'rst', 'csv', 'tsv', 'json', 'yaml', 'html', formats = ['txt', 'rst', 'csv', 'tsv', 'json', 'yaml', 'html',
'jira', 'xls', 'xlsx', 'dbf', 'latex', 'ods'] 'jira', 'xls', 'xlsx', 'dbf', 'latex', 'ods']
if format == 'xls' and line > 65000:
logger.log('ALERT', 'xls文件限制为最多65000行')
logger.log('ALERT', '使用xlsx格式导出')
return 'xlsx'
if format in formats: if format in formats:
return format return format
else: else:
logger.log('ALERT', f'不支持{format}格式导出') logger.log('ALERT', f'不支持{format}格式导出')
logger.log('ALERT', '默认使用csv格式导出') logger.log('ALERT', '默认使用csv格式导出')
return 'xls' return 'csv'
def save_data(fpath, data): def save_data(fpath, data):
@@ -233,3 +240,46 @@ def mark_subdomain(old_data, new_data):
item['new'] = 1 item['new'] = 1
new_data[index] = item new_data[index] = item
return new_data return new_data
def remove_string(string):
# Excel文件中单元格值不能直接存储以下非法字符
return re.sub(r'[\000-\010]|[\013-\014]|[\016-\037]', r'', string)
def check_value(values):
for i, value in enumerate(values):
# Excel文件中单元格值长度不能超过32767
if value is None:
continue
if isinstance(value, str) and len(value) > 32767:
values[i] = value[:32767]
return values
def export_all(format, datas):
line = len(datas)
format = check_format(format, line)
dpath = check_dpath()
timestamp = get_timestamp()
fpath = dpath.joinpath(f'all_subdomain_{timestamp}.{format}')
row_list = list()
for row in datas:
row.pop('header')
row.pop('response')
row.pop('module')
row.pop('source')
row.pop('elapsed')
row.pop('count')
keys = row.keys()
values = row.values()
if format in {'xls', 'xlsx'}:
values = check_value(values)
row_list.append(Record(keys, values))
rows = RecordCollection(iter(row_list))
content = rows.export(format)
save_data(fpath, content)
def get_timestamp():
return int(time.time())
+3 -1
View File
@@ -34,10 +34,12 @@ def export(table, db=None, valid=None, dpath=None, format='csv', show=False):
:param str dpath: 导出目录(默认None) :param str dpath: 导出目录(默认None)
:param bool show: 终端显示导出数据(默认False) :param bool show: 终端显示导出数据(默认False)
""" """
format = utils.check_format(format)
dpath = utils.check_dpath(dpath) dpath = utils.check_dpath(dpath)
database = Database(db) database = Database(db)
rows = database.export_data(table, valid) # 意外情况导出全部子域 rows = database.export_data(table, valid) # 意外情况导出全部子域
line = len(rows)
format = utils.check_format(format, line)
if show: if show:
print(rows.dataset) print(rows.dataset)
if format == 'txt': if format == 'txt':
+4
View File
@@ -80,6 +80,7 @@ class OneForAll(object):
self.domains = set() self.domains = set()
self.domain = str() self.domain = str()
self.data = list() self.data = list()
self.datas = list()
self.brute = brute self.brute = brute
self.dns = dns self.dns = dns
self.req = req self.req = req
@@ -159,6 +160,7 @@ class OneForAll(object):
# 请求子域 # 请求子域
task = request.bulk_get_request(self.data, self.port) task = request.bulk_get_request(self.data, self.port)
self.data = loop.run_until_complete(task) self.data = loop.run_until_complete(task)
self.datas.extend(self.data)
# 在关闭事件循环前加入一小段延迟让底层连接得到关闭的缓冲时间 # 在关闭事件循环前加入一小段延迟让底层连接得到关闭的缓冲时间
loop.run_until_complete(asyncio.sleep(0.25)) loop.run_until_complete(asyncio.sleep(0.25))
@@ -190,6 +192,8 @@ class OneForAll(object):
if self.domains: if self.domains:
for self.domain in self.domains: for self.domain in self.domains:
self.main() self.main()
if len(self.domains) >= 2:
utils.export_all(self.format, self.datas)
else: else:
logger.log('FATAL', f'获取域名失败') logger.log('FATAL', f'获取域名失败')
logger.log('INFOR', f'结束运行OneForAll') logger.log('INFOR', f'结束运行OneForAll')
+2 -2
View File
@@ -83,8 +83,8 @@ class Takeover(Module):
data = str(self.results) data = str(self.results)
else: else:
data = self.results.export(self.format) data = self.results.export(self.format)
ts = int(time.time()) timestamp = utils.get_timestamp()
fpath = self.dpath.joinpath(f'takeover_{ts}.{self.format}') fpath = self.dpath.joinpath(f'takeover_{timestamp}.{self.format}')
utils.save_data(fpath, data) utils.save_data(fpath, data)
def compare(self, subdomain, cname, responses): def compare(self, subdomain, cname, responses):