前言
免责声明
文章仅用作网络安全人员对自己网站、服务器等进行自查检测,不可用于其他用途,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作
本次测试只作为学习用处,请勿未授权进行渗透测试,切勿用于其它用途!
最新代码请在GitHub查看:https://github.com/birdy02-com/onlySubDomainBurst
作用
子域名爆破是一种技术,用于枚举潜在存在的子域名以寻找可被攻击的目标。它可以帮助发现一个组织的所有已知和未知资产,并且可以通过在Internet上公开可用的数据源中搜索与给定父域名相关的信息来提高网络安全状况。
github查看
https://github.com/birdy02-com/onlySubDomainBurst
避免
避免泛解析
避免使用单一的dns服务
并发扫描
前提
不保证该思路为最合适的(网上还有很多类似的工具)
请抱着学习和汲取经验的态度阅读
编写代码
初始配置
导入使用的库
import asyncio, aiodns, sys, time, os, openpyxl, re
from requests import get
import logging, colorlog
判断系统版本、针对系统优化性能
创建输出目录
if sys.platform == 'win32': asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
out_path = "output_zcsj"
if not os.path.exists(out_path): os.mkdir(out_path)
创建log输出代码
# 创建一个log
log = logging.getLogger(__name__)
# 创建一个Handler,用于写入日志文件
handler = logging.StreamHandler()
# 定义每个日志级别的颜色
log_colors = {
'DEBUG': 'yellow',
'INFO': 'green',
'WARNING': 'bold_purple',
'ERROR': 'red',
'CRITICAL': 'bold_red,bg_white',
}
# 创建一个格式器,将日志级别转换为颜色
formatter = colorlog.ColoredFormatter(
"%(log_color)s[%(asctime)s] %(levelname)s: %(message)s",
datefmt='%Y-%m-%d %H:%M:%S',
log_colors=log_colors
)
# 给Handler添加格式器
handler.setFormatter(formatter)
# 给log添加Handler
log.addHandler(handler)
# 设置日志级别
log.setLevel(logging.DEBUG)
创建主要class
设置DNS Server 列表
class DnsDomain:
nameservers = [
'114.114.114.114', '114.114.115.115', '114.114.114.119', '114.114.115.119', '114.114.114.110',
'114.114.115.110',
'223.5.5.5', '223.6.6.6',
'180.76.76.76',
'119.29.29.29', '119.28.28.28', '182.254.116.116', '182.254.118.118', '1.12.12.12', '120.53.53.53',
'1.2.4.8', '210.2.4.8',
'117.50.11.11', '52.80.66.66', '117.50.10.10', '52.80.52.52', '117.50.60.30', '52.80.60.30',
'101.6.6.6',
'202.141.162.123', '202.141.176.93', '202.38.93.153'
]
nameservers.extend(
['112.4.0.55', '112.4.0.55', '112.4.1.36', '112.4.1.36', '112.4.12.200', '112.4.12.200', '120.196.122.69',
'120.196.122.69', '120.196.141.86', '120.196.141.86', '120.196.165.7', '120.196.165.7', '203.142.100.18',
'203.142.100.18', '203.142.100.21', '203.142.100.21', '211.136.17.97', '211.136.17.98', '211.136.17.107',
'211.136.17.107', '211.136.112.50', '211.136.112.50', '211.136.150.66', '211.136.150.66', '211.136.192.6',
'211.136.192.6', '211.137.32.178', '211.137.32.178', '211.137.130.2', '211.137.130.3', '211.137.130.19',
'211.137.130.19', '211.137.160.5', '211.137.160.5', '211.137.160.185', '211.137.160.185', '211.137.241.34',
'211.137.241.34', '211.138.75.123', '211.138.75.123', '211.138.91.1', '211.138.91.2', '211.138.106.19',
'211.138.106.19', '211.138.180.2', '211.138.180.3', '211.138.200.69', '211.138.200.69', '211.138.240.100',
'211.138.240.100', '211.138.245.1', '211.138.245.1', '211.138.245.180', '211.138.245.180', '211.139.5.29',
'211.139.5.30', '211.139.73.34', '211.139.73.34', '211.140.13.188', '211.140.13.188', '211.140.188.188',
'211.140.188.188', '211.140.197.58', '211.140.197.58', '211.141.16.99', '211.141.16.99', '211.141.90.68',
'211.141.90.68', '218.201.17.2', '218.201.17.2', '218.202.152.130', '218.202.152.131', '218.203.160.195',
'218.203.160.195', '221.130.252.200', '221.130.252.200', '221.131.143.69', '221.131.143.69', '61.132.163.68',
'202.102.213.68', '219.141.136.10', '219.141.140.10', '61.128.192.68', '61.128.128.68', '218.85.152.99',
'218.85.157.99', '202.100.64.68', '61.178.0.93', '202.96.128.86', '202.96.128.166', '202.96.134.33',
'202.96.128.68', '202.103.225.68', '202.103.224.68', '202.98.192.67', '202.98.198.167', '222.88.88.88',
'222.85.85.85', '219.147.198.230', '219.147.198.242', '202.103.24.68', '202.103.0.68', '222.246.129.80',
'59.51.78.211', '218.2.2.2', '218.4.4.4', '61.147.37.1', '218.2.135.1', '202.101.224.69', '202.101.226.68',
'219.148.162.31', '222.74.39.50', '219.146.1.66', '219.147.1.66', '218.30.19.40', '61.134.1.4',
'202.96.209.133', '116.228.111.118', '202.96.209.5', '108.168.255.118', '61.139.2.69', '218.6.200.139',
'219.150.32.132', '219.146.0.132', '222.172.200.68', '61.166.150.123', '202.101.172.35', '61.153.177.196',
'61.153.81.75', '60.191.244.5', '123.123.123.123', '123.123.123.124', '202.106.0.20', '202.106.195.68',
'221.5.203.98', '221.7.92.98', '210.21.196.6', '221.5.88.88', '202.99.160.68', '202.99.166.4',
'202.102.224.68', '202.102.227.68', '202.97.224.69', '202.97.224.68', '202.98.0.68', '202.98.5.68',
'221.6.4.66', '221.6.4.67', '202.99.224.68', '202.99.224.8', '202.102.128.68', '202.102.152.3',
'202.102.134.68', '202.102.154.3', '202.99.192.66', '202.99.192.68', '221.11.1.67', '221.11.1.68',
'210.22.70.3', '210.22.84.3', '119.6.6.6', '124.161.87.155', '202.99.104.68', '202.99.96.68', '221.12.1.227',
'221.12.33.227', '202.96.69.38', '202.96.64.68'])
nameservers.extend(
['37.235.1.174', '37.235.1.177', '216.146.35.35', '216.146.36.36', '8.26.56.26', '8.20.247.20', '64.6.64.6',
'64.6.65.6', '77.88.8.8', '77.88.8.1', '80.80.80.80', '80.80.81.81', '94.140.14.14', '94.140.15.15',
'94.140.14.15', '94.140.15.16', '156.154.70.1', '156.154.71.1', '156.154.70.5', '156.154.71.5',
'103.197.104.178', '103.197.106.75', '203.189.136.148', '203.112.2.4', '84.200.69.80', '84.200.70.40',
'195.46.39.39', '195.46.39.40', '109.69.8.51', '91.239.100.100', '89.233.43.71', '81.218.119.11',
'209.88.198.133', '185.222.222.222', '45.11.45.11', '74.82.42.42', '66.220.18.42', '104.236.210.29',
'45.55.155.25', '185.228.168.9', '185.228.169.9', '185.228.168.10', '185.228.169.11', '185.228.168.168',
'185.228.169.168', '202.79.32.33', '202.79.32.34'])
获取子域名列表方法
def get_subdomains
@classmethod
def get_subdomains(cls, dom: str) -> list:
try:
sub_pre = []
with open('config/sub.txt', 'r') as f:
[sub_pre.append(i.strip() + '.') for i in f.read().split('\n') if
i.strip() and i.strip() not in sub_pre]
return [i + dom for i in sub_pre]
except FileNotFoundError as e:
raise e
dns控制初始化方法
获取子域名
运行子域名监测主程序
@classmethod
def main(cls, dom):
log.info('DNS subDomain: ' + dom)
sub_dom = cls.get_subdomains(dom)
t = time.time()
_ = asyncio.run(cls.async_run(sub_dom))
log.info('[*] DnsDomain 耗时 {}'.format(time.time() - t))
return [i for i in _ if i]
异步执行方法
使用aiodns库进行监测,nameservers传入dns列表
tasks获取返回值
@classmethod
async def async_run(cls, sub_domains: list) -> tuple:
resolver = aiodns.DNSResolver(nameservers=cls.nameservers)
tasks = [asyncio.create_task(cls.resolve_dns(resolver, _)) for _ in sub_domains]
return await asyncio.gather(*tasks)
异步DNS解析方法
获取A记录
输出解析信息
@classmethod
async def resolve_dns(cls, resolver, hostname: str, slf: bool = False) -> dict:
try:
result = await resolver.query(hostname, 'A')
ipv4 = [i.host for i in result]
log.info(f'DNS: {hostname} => {",".join(ipv4)}')
return {'name': hostname, 'ipv4': ipv4}
except Exception as e:
if re.search("Timeout while contacting DNS servers", str(e)) and not slf:
return await cls.resolve_dns(resolver, hostname, True)
if re.search("Could not contact DNS servers", str(e)) and not slf:
return await cls.resolve_dns(resolver, hostname, True)
return {}
主程序控制方法
res获取返回值
将返回值输出到xlsx文件中
def main(dom: str):
res = DnsDomain.main(dom)
workbook = openpyxl.Workbook()
worksheet = workbook.create_sheet("子域名")
worksheet.append(["子域名", "ip"])
for _ in res: worksheet.append([_['name'], ",".join(_['ipv4'])])
workbook.save(os.path.join(out_path, dom.replace('.', '_') + '_zcsj' + '.xlsx'))
程序入口
if __name__ == '__main__':
domain = input('请输入域名: ')
main(domain)
使用方法
python.exe onlySubDomain.py
[*] 请输入域名: birdy02.com
[2024-10-14 13:46:38] INFO: DNS subDomain: birdy02.com
[2024-10-14 13:47:07] INFO: DNS: www.birdy02.com => 38.147.170.156
[2024-10-14 13:47:08] INFO: DNS: w.birdy02.com => 38.147.170.156
[2024-10-14 13:47:10] INFO: DNS: oss.birdy02.com => 38.147.170.156
[2024-10-14 13:47:19] INFO: DNS: dash.birdy02.com => 38.147.170.156
[2024-10-14 13:47:20] INFO: DNS: home.birdy02.com => 10.16.3.1
[2024-10-14 13:47:25] INFO: DNS: bt.birdy02.com => 38.147.170.156
[2024-10-14 13:47:30] INFO: DNS: tools.birdy02.com => 38.147.170.156
[2024-10-14 13:47:38] INFO: DNS: api.birdy02.com => 38.147.170.156
[2024-10-14 13:47:44] INFO: [*] DnsDomain 耗时 41.98999381065369
输出xlsx文件