subdomainCol - 子域名收集接口工具

subdomainCol - 子域名收集接口工具

前情提要

  1. 自己想要个纯粹的子域名收集接口小工具,Just Wrapper。
  2. 目前没发现单独的泛解析处理工具,或许会有人需要。
  3. 之前没有做过比较完整的python项目,练手For Fun。
  4. 代码质量垃圾警告

TL;DR

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
               __        __                      _       ______      __
_______ __/ /_ ____/ /___ ____ ___ ____ _(_)___ / ____/___ / /
/ ___/ / / / __ \/ __ / __ \/ __ `__ \/ __ `/ / __ \/ / / __ \/ /
(__ ) /_/ / /_/ / /_/ / /_/ / / / / / / /_/ / / / / / /___/ /_/ / /
/____/\__,_/_.___/\__,_/\____/_/ /_/ /_/\__,_/_/_/ /_/\____/\____/_/

Example:
python3 ./subdomainCol/subdomaincol.py --target xxx.com run
python3 ./subdomainCol/subdomaincol.py --targets ./domains.txt run
python3 ./subdomainCol/subdomaincol.py --mode filter --targets ./subfinder_xxxx.txt run
python3 ./subdomainCol/subdomaincol.py --targets ./domains.txt --dic_path ./dic.txt --timeout 7200 run

:param str target: One domain
:param str targets: File path of one domain per line
:param str mode: Select the collection subdomain mode or filter mode,
the default is collection mode (default/filter)
:param str dic_path: The dictionary path used by ksubdomain
:param int timeout: Timeout time for each subprocess (seconds)

功能

  1. 调用subfinder和ksubdomian进行子域名收集并进行泛解析过滤。
  2. 独立的泛解析过滤接口,即可直接对子域名集合进行泛解析过滤。

使用方式

  1. 对单个域名meituan.com进行子域名收集
    1
    $ python3 ./subdomainCol/subdomaincol.py --target "meituan.com" run
  2. ~/Downloads/meituan.txt文件内的域名进行子域名收集
    1
    2
    3
    4
    5
    6
    7
    $ cat ~/Downloads/meituan.txt
    meituan.com
    meituan.net
    dianping.com
    neixin.cn

    $ python3 ./subdomainCol/subdomaincol.py --targets ~/Downloads/meituan.txt run
  3. 对子域名集合~/Downloads/subfinder_xxxx.txt进行泛解析过滤
    1
    $ python3 ./subdomainCol/subdomaincol.py --mode filter --targets ~/Downloads/subfinder_xxxx.txt run

配置文件

  1. SubdomainCol配置文件位置固定于SubdomainCol/config/config.yaml,根据需求进行修改。
  2. 被调用的subfinder配置文件固定于SubdomainCol/bin/subfinder/config.yaml,根据需求进行修改。

原理

  1. 如何安装轮子A
    纯粹的调用了别的子域名工具:subfinder、ksubdomian。
    后面可能还会装别家的轮子。
  2. 如何组装轮子B
    找寻后发现oneforall的泛解析是实现的比较完善的,但是估计因为一些考虑没有做独立接口。
    于是把oneforall的泛解析实现给单独抽成了个泛解析过滤模块。

泛解析

subfinder

看readme的时候发现有泛解析处理参数-nW,代码中实现位于InitWildcards函数,原理比较简单粗暴:随机生成一个字符串拼接在域名前面,如果nslookup不存在解析到的ip即不存在泛解析。

ksubdomain

原理是把结果集中的ip数量进行统计,即某个ip在结果中出现了多少次。再根据此数据进行一个权重计算,类似一种比例划分把,由此过滤掉一些可能有泛解析嫌疑的ip,且由此过滤域名结果集。

oneforall

  1. oneforall.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 以一定的格式获取从target/targets参数传入的域名
    self.domains = utils.get_domains(self.target, self.targets)
    ...
    # 处理域名后转到main函数
    for domain in self.domains:
    self.domain = utils.get_main_domain(domain)
    self.main()
    ...
    # 判断主域名是否存在泛解析
    self.enable_wildcard = wildcard.detect_wildcard(self.domain)
    ...
    # 处理泛解析
    if self.enable_wildcard:
    # deal wildcard
    self.data = wildcard.deal_wildcard(self.data)
  2. wildcard.py
    该模块有3个主要逻辑处理入口:detect_wildcard/collect_wildcard_record/deal_wildcard
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    # 通过随机请求主域名的3个子域名并进行相似度判断,以判定该主域名是否存在泛解析现象
    def detect_wildcard(domain):
    is_enable = to_detect_wildcard(domain)
    if is_enable:
    logger.log('ALERT', f'The domain {domain} enables wildcard')
    else:
    logger.log('ALERT', f'The domain {domain} disables wildcard')
    return is_enable
    ...
    # collect_wildcard_record用于获取wildcard_ips, wildcard_ttl;这两个参数最终会作为wildcard.is_valid_subdomain(ip, ip_num, cname, cname_num, ttl, wc_ttl, wc_ips)的wc_ttl, wc_ips参数。最终是用于判断domain的子域名到底是不是泛解析。并且这个函数也会被deal_wildcard调用。
    def collect_wildcard_record(domain, authoritative_ns):
    ...
    # 通过各种方式(只看懂了黑名单部分的代码)过滤掉子域名合集里的泛解析子域名
    def deal_wildcard(data):
    new_data = list()
    appear_times = stat_times(data)
    for info in data:
    subdomain = info.get('subdomain')
    isvalid, reason = check_valid_subdomain(appear_times, info)
    logger.log('DEBUG', f'{subdomain} is {isvalid} subdomain reason because {reason}')
    if isvalid:
    new_data.append(info)
    return new_data

subdomainCol-泛解析实现逻辑

  1. 输入子域名 - domains
    1
    2
    3
    4
    xxx1.xxx2.xxx3.xxx4
    yyy1.yyy2.yyy3
    zzz1.zzz2.zzz3.zzz4
    ...
  2. get_upper_domains(domains)获取上一级域名集合并去重 - upper_domains
    1
    2
    3
    4
    xxx2.xxx3.xxx4
    yyy2.yyy3
    zzz2.zzz3.zzz4
    ...
  3. get_upper_domain_infos(upper_domains)
    获取upper_domains所需的三个信息:
    (1)enable_wc - 通过detect_wildcard()函数判断该域名是否开启泛解析
    如果开启泛解析则调用collect_wildcard_record()函数获取信息(2)(3),反之不需要。
    (2)wc_ips - 泛解析IP列表
    (3)wc_ttl - 泛解析TTL整型值
  4. 遍历step1输入的子域名 - domains
    (1)如果其上一级域名upper_domain没有开启泛解析则直接认为是有效子域名
    (2)反之加入域名列uncertain_subdomains继续判断
  5. get_uncertain_subdomain_infos(uncertain_subdomains)获取域名的以下信息
    ttl/cnames/ips/max_ip_num/max_cname_num
  6. 遍历uncertain_subdomain_infos,对每个uncertain_subdomain进行is_valid_subdomain()判断
  7. is_valid_subdomain()
    (1)通过cname黑名单和ip黑名单过滤子域名
    (2)check_by_compare提取有效ip
    (3)通过cname和ip出现次数过滤子域名

环境依赖

  1. 安装所调用工具subfinderksubdomain的配置。
  2. 替换以下两个二进制文件为对应平台版本
    1
    2
    SubdomainCol/bin/ksubdomain/ksubdomain
    SubdomainCol/bin/subfinder/subfinder

推荐

Linux-CentOS - 已测试可运行,丢服务器上很自由。

不推荐

macOS - 已测试可运行,但ksubdomain耗资源,不想吹风扇/心疼电脑的不推荐。
Win - 未测试,同理因为耗资源不推荐。不过推测安装依赖+替换bin下的工具程序为win版本即可。

TODO

subdomainCol

  1. xray高级版的子域名功能集成
    主要是自己没有,有的话就加上。不过自己写也很快。
  2. 更多可控参数
    比如被调用的subfinder和ksubdomain的运行参数控制,输出文件位置控制等等。但纠结部分的必要性。
  3. 暂时想不到,欢迎提需求
    但作为一个纯粹的子域名收集工具还需要别的吗🤔好像也没有。

相关

  1. 主/被动子域名字典收集
    被动 - chrome插件?burp插件?
    主动 - 每次对收集结果进行处理的小脚本?
    还没有搜集过这块的已经实现的轮子或者其他相关信息,若有希望大佬评论区推荐一下。
  2. 扫title和判断指纹的调用脚本

未完待续

这段时间再做一些完善和测试再把项目放到github上。