子域名收集实战:从Google语法到JSFinder的资产发现进阶指南
1. 项目概述:为什么子域名收集是安全测试的“敲门砖”
在网络安全领域,尤其是渗透测试和资产测绘的初期,子域名收集是绕不开的第一步。你可以把它想象成侦察兵在进攻前绘制敌方阵地地图。一个主域名(比如example.com)背后,往往隐藏着成百上千个子域名,例如mail.example.com、admin.example.com、dev.example.com、vpn.example.com等等。这些子域名承载着企业不同的业务系统、开发环境、管理后台,甚至是遗留的、安全防护薄弱的测试站点。攻击面的大小,很大程度上就取决于你能发现多少个子域名。因此,一套高效、全面的子域名收集方法,直接决定了后续渗透测试的深度和广度。
传统的收集方法可能只是简单地猜测或者使用有限的字典爆破,效率低下且覆盖面窄。而进阶的技巧,则是将被动信息收集(如搜索引擎)、主动枚举(如工具扫描)和智能关联(如JS文件分析)结合起来,形成一套自动化或半自动化的“组合拳”。今天要聊的,就是从最基础但威力巨大的Google搜索语法(Google Dorks)开始,一直深入到利用JSFinder这类工具进行深度关联挖掘的完整实战路径。无论你是刚入门的安全爱好者,还是想优化自己工作流的资深工程师,这套方法都能帮你显著提升资产发现的效率和质量。
2. 核心思路与工具链设计:构建分层收集体系
高效的子域名收集从来不是靠单一工具或方法就能完成的,它需要一个层次分明、互为补充的体系。我的实战思路通常分为三层:被动收集层、主动枚举层和智能关联层。这个分层设计能确保在资源消耗、隐蔽性和发现率之间取得最佳平衡。
被动收集层的核心是“借力”,利用互联网上已有的公开信息,不直接与目标系统交互。这包括搜索引擎(Google、Bing)、证书透明度日志(CT Log)、DNS历史记录、威胁情报平台等。这层的优势是完全隐蔽,不会触发目标的任何告警,是侦察初期的最佳选择。主动枚举层则更为直接,通过向目标的DNS服务器发送查询请求,或尝试与可能的子域名建立连接来验证其存在。常用工具包括subfinder、amass、massdns以及经典的字典爆破工具。这层能发现那些未被公开索引的“暗”资产,但会产生明显的流量痕迹。智能关联层是更高阶的玩法,它从已发现的资产中(如网页、JS文件)提取新的线索(如新的域名、API接口),再进行递归发现。JSFinder正是这一层的代表性工具。
工具链的选型上,我倾向于“组合”而非“单一”。例如,我会用amass进行被动的数据源收集,用subfinder配合多个API进行快速枚举,再用自研或altdns进行智能变形以发现那些可能被遗漏的域名。JSFinder则作为从Web资产中提取线索的利器。整个流程可以脚本化,形成从输入一个主域名到输出一个庞大、干净的子域名列表的自动化流水线。关键在于,要理解每层、每个工具的原理和局限,才能灵活搭配。
2.1 为什么从Google语法开始?—— 低成本高回报的起点
很多新手会忽略搜索引擎,直接上工具爆破,这其实浪费了一座金矿。Google语法,或称Google Dorks,是一套利用搜索引擎高级运算符进行精准过滤的查询方法。对于子域名收集,它的价值在于:
- 零成本且合法:你只是在用公开的搜索引擎,没有发送任何攻击流量。
- 发现意外资产:可能搜出一些早已被遗忘、但未从DNS记录中删除的测试站点、备份站点,这些往往是安全漏洞的重灾区。
- 获取关联信息:不仅能找到子域名,还能直接看到网页快照、目录结构,甚至暴露的文档,为后续测试提供上下文。
例如,最基本的语法site:example.com会返回所有Google索引的、属于example.com及其子域名的页面。但这只是开始。
3. 实战进阶:Google语法的精准运用与组合拳
仅仅使用site:操作符是远远不够的。高效的收集在于组合使用多个操作符,进行精准过滤和排除,从而从海量结果中快速定位有价值的子域名。
3.1 核心操作符解析与实战查询
以下是我在实战中最常用、最高效的几个操作符组合:
site::这是基石。site:example.com搜索该域名下的所有内容。-site::排除。这在过滤泛解析结果时特别有用。例如,很多云服务商或建站平台会使用泛解析,导致*.example.com都解析到同一个IP。你可以用site:example.com -site:www.example.com -site:blog.example.com来排除已知的、无意义的子域名,专注于未知结果。inurl:/intitle::在URL或标题中包含特定关键词。这能帮你快速定位特定功能的子站。比如:site:example.com inurl:admin寻找管理后台。site:example.com intitle:"login"寻找登录页面。site:example.com inurl:api寻找API接口子域名。
filetype::搜索特定文件类型。泄露的配置文件、文档可能包含内部域名。site:example.com filetype:pdf或site:example.com filetype:conf。- 组合查询示例:
- 寻找可能的开发或测试环境:
site:example.com (inurl:dev OR inurl:test OR inurl:staging) - 寻找后台登录,并排除已知的Wordpress后台:
site:example.com inurl:login -inurl:wp-login - 搜索可能包含子域名列表的文档:
site:example.com filetype:xls | filetype:csv | filetype:txt "子域名" OR "subdomain"
- 寻找可能的开发或测试环境:
注意:Google对查询频率和复杂度有限制。过于频繁或复杂的查询可能导致IP被暂时屏蔽。建议在查询间加入随机延时,并考虑使用
-www来排除主站,有时能获得更独特的结果。
3.2 自动化与技巧:让Google搜索更高效
手动构造查询效率太低。我通常会编写简单的脚本,读取一个关键词字典(如admin, test, dev, staging, api, mobile, mail等),自动生成并执行一系列site:example.com inurl:[keyword]的查询,然后从搜索结果页的HTML中提取子域名。Python的googlesearch-python库(需注意其稳定性)或直接调用Google Custom Search JSON API(有免费额度)可以实现这一点。
另一个高级技巧是利用“类似网页”功能。当你找到一个有价值的子域名(如devops.example.com)时,在Google搜索结果中点击“类似网页”,可能会发现同一组织使用的其他技术栈或服务对应的子域名。
4. 从搜索引擎到本地工具:主动枚举的核心工具链
当被动收集的“低垂果实”摘完后,就需要转向主动枚举。这里我主要依赖几个成熟可靠的工具。
4.1 Subfinder:快速、模块化的收集器
Subfinder是用Go写的,速度极快。它的强大之处在于其模块化设计,集成了数十个被动数据源(如 SecurityTrails, Censys, PassiveTotal 等 API)以及爬虫源。基本使用很简单:
subfinder -d example.com -o subdomains.txt但要想用好,必须配置API密钥。编辑其配置文件~/.config/subfinder/config.yaml,填入你在各个情报平台申请的免费或付费API Key(如 VirusTotal, AlienVault OTX, Censys 等)。配置好后,subfinder的收集能力会成倍增长。它默认使用被动源,隐蔽性好。
实操心得:我会将subfinder与massdns结合使用。subfinder负责收集大量可能的域名,massdns则用一份庞大的DNS解析器列表来快速验证这些域名是否真实存在(有A/AAAA/CNAME记录)。
subfinder -d example.com -silent | massdns -r resolvers.txt -t A -o S -w resolved_domains.txt这里的resolvers.txt是一份公开的、可用的公共DNS服务器列表。这种组合能在几分钟内完成对数万个子域名的验证。
4.2 Amass:全方位的网络空间测绘引擎
Amass比subfinder更重量级,功能也更全面。它集成了被动收集、主动爆破、递归抓取、数据可视化等多种功能。它的主动爆破模块非常强大,内置了智能学习功能,能从已发现的域名中提取单词,扩充自己的爆破字典。
一个深度的amass命令可能长这样:
amass enum -active -d example.com -brute -w ./wordlists/subdomains-top1million-5000.txt -o amass_output.txt -dir amass_db-active:进行主动解析和抓取。-brute:启用子域名爆破。-w:指定爆破字典。-dir:指定工作目录,它会将本次扫描的所有数据(包括历史)存入一个数据库,下次扫描同一目标时可以增量更新,非常高效。
注意事项:amass的主动模式(-active)会产生大量HTTP请求和DNS查询,动静很大,务必在授权测试范围内使用。对于大型目标,建议先在被动模式下(不加-active)运行,然后再用小范围的主动爆破查漏补缺。
4.3 字典的选用与定制:爆破的灵魂
工具再强,也离不开一份好的字典。通用的字典如subdomains-top1million-5000.txt是个不错的起点,但针对特定目标,定制字典往往有奇效。
如何定制字典?
- 从已有结果中提取:用已发现的子域名(如
api1.example.com,dev-uk.example.com)来提取单词(api1,dev,uk),组合生成新词。 - 从目标内容中提取:爬取目标网站,提取所有单词(去除常见英语单词),这些很可能是其内部命名习惯。工具如
cewl可以干这个。 - 行业特定词汇:如果目标是金融行业,加入
banking, trade, finance, payment;如果是云服务,加入aws, azure, gcp, bucket, storage等。 - 常见前后缀组合:
dev-, test-, staging-, prod-, uat-, internal-, vpn-, mail-等。
你可以使用altdns工具,它专门用于生成排列组合。给它一个域名列表和一个单词列表,它能生成大量如dev-api.example.com、api-dev.example.com这样的变体,极大提高发现边缘子域名的概率。
5. 深度关联挖掘:JSFinder的核心原理与实战
这是真正体现“进阶”的地方。现代Web应用大量依赖JavaScript,而JS文件中常常硬编码着后端API接口、第三方服务域名、内部跳转地址等敏感信息。JSFinder这类工具的思路,就是从这些JS文件中“淘金”。
5.1 JSFinder 工作流程解析
JSFinder的核心工作流程可以概括为:爬取 -> 提取 -> 过滤 -> 递归。
- 爬取:给定一个初始URL(通常是主站或已发现的子域名),它会爬取页面中的所有链接,特别是
.js文件链接,以及包含JS代码的<script>标签。 - 提取:使用正则表达式从JS文件内容中提取出所有看起来像URL或域名的字符串。这包括完整的
http(s)://链接、相对路径、以及诸如api.example.com这样的裸域名。 - 过滤与归类:将提取出的字符串进行清洗和分类。例如,区分出属于目标主域的子域名、外部域名、以及可能是API接口的路径。
- 递归:将新发现的、属于目标域的URL(特别是JS文件链接)作为新的起点,重复上述过程,形成递归发现。
5.2 实战操作与参数详解
假设我们已安装JSFinder(通常为Python脚本)。一个基础的命令如下:
python3 JSFinder.py -u https://www.example.com -d -o jsfinder_results.txt-u:指定起始URL。-d:启用深度爬取(递归)。-o:输出结果。
但这样可能不够精细。更高效的做法是:
# 1. 先获取网站的所有JS文件链接 python3 JSFinder.py -u https://www.example.com -ou js_urls.txt # 2. 然后用这些JS链接,专门进行内容分析,提取域名和接口 python3 JSFinder.py -f js_urls.txt -d -o all_findings.txt这样做的好处是将“发现JS文件”和“分析JS内容”解耦,在分析大量目标时更灵活。
输出结果分析:JSFinder的输出通常包含:
- 子域名:从JS中发现的新的
xxx.example.com。 - 接口路径:如
/api/v1/user,/internal/config。这些路径可能未在网站地图中公开,是重要的测试入口点。 - 外部依赖:引用的第三方CDN、统计、客服域名,有助于绘制完整的资产依赖图。
5.3 进阶技巧与避坑指南
- 处理混淆代码:现代JS经常被压缩或混淆,变量名变成
a,b,c,字符串被打散。简单的正则可能失效。此时可以尝试先使用像de4js这样的在线或本地反混淆工具对JS文件进行预处理,然后再用JSFinder分析。不过,对于深度混淆的代码,自动化提取的难度会急剧上升。 - 关注特定关键词:在JS中搜索一些特定关键词,能快速定位高价值目标:
- API相关:
api,endpoint,url,baseURL,fetch,axios,ajax,get,post - 认证相关:
token,auth,login,password,secret,key - 配置相关:
config,setting,environment,debug你可以用grep或脚本在提取的JS内容中进行二次过滤。
- API相关:
- 结合浏览器手动分析:自动化工具总有遗漏。打开浏览器开发者工具(F12)的Network(网络)面板,刷新页面,过滤
JS类型请求,手动查看一些大的、非公共库的JS文件响应内容,常有意外发现。特别是那些在页面加载后通过XHR或Fetch动态请求的JS文件。 - 注意误报:JS中常有模拟数据、示例代码或注释掉的旧配置,提取出的域名可能已失效或从未使用。务必对
JSFinder发现的所有子域名进行DNS解析验证,将其纳入统一的验证步骤(如前文提到的massdns),否则会得到一堆“脏数据”。
6. 流程整合与自动化:打造属于你的子域名收集系统
单独使用每个工具都很强大,但将它们串联起来,形成一条自动化流水线,才是效率最大化的关键。下面分享一个我常用的简化版自动化流程,用Shell脚本或Python脚本都可以实现。
#!/bin/bash TARGET="example.com" OUTPUT_DIR="./results/$TARGET" mkdir -p $OUTPUT_DIR echo "[*] 开始收集子域名: $TARGET" # 1. 被动收集 (Subfinder + API) echo "[1/5] 被动收集 (Subfinder)..." subfinder -d $TARGET -silent -o $OUTPUT_DIR/subfinder.txt # 2. 搜索引擎联想 (自定义脚本) echo "[2/5] 搜索引擎收集 (Google Dorks)..." python3 google_dork_collector.py -d $TARGET -o $OUTPUT_DIR/google.txt # 假设 google_dork_collector.py 是你根据第三节内容编写的脚本 # 3. 使用Amass进行综合枚举 (被动+轻度主动) echo "[3/5] 综合枚举 (Amass)..." amass enum -passive -d $TARGET -o $OUTPUT_DIR/amass_passive.txt amass enum -active -brute -d $TARGET -w ./wordlists/common.txt -o $OUTPUT_DIR/amass_active.txt # 4. 从已知Web资产中挖掘 (JSFinder) echo "[4/5] JS文件分析 (JSFinder)..." # 首先从主站和已发现的子域名中获取JS链接 cat $OUTPUT_DIR/*.txt | grep -E "^https?://" | sort -u | head -20 > $OUTPUT_DIR/web_urls.txt # 取部分URL作为种子 python3 JSFinder.py -f $OUTPUT_DIR/web_urls.txt -d -o $OUTPUT_DIR/jsfinder.txt # 5. 合并、去重、解析验证 echo "[5/5] 合并与验证..." cat $OUTPUT_DIR/*.txt | grep -E ".*\.$TARGET$" | sed 's/^.*\/\///;s/\/.*$//' | sort -u > $OUTPUT_DIR/all_subdomains_raw.txt # 使用massdns进行批量解析验证 massdns -r ./resolvers.txt -t A -o S -w $OUTPUT_DIR/resolved.txt $OUTPUT_DIR/all_subdomains_raw.txt # 从massdns输出中提取成功解析的域名 grep -E " A | CNAME " $OUTPUT_DIR/resolved.txt | cut -d' ' -f1 | sed 's/\.$//' | sort -u > $OUTPUT_DIR/final_subdomains.txt echo "[+] 收集完成!有效子域名数: $(wc -l < $OUTPUT_DIR/final_subdomains.txt)" echo "[+] 结果文件: $OUTPUT_DIR/final_subdomains.txt"这个脚本只是一个框架,你可以根据需求增加更多步骤,比如用altdns进行智能变形爆破,或者用httpx/nuclei对验证存活的子域名进行快速指纹识别和漏洞扫描。
7. 常见问题、排查技巧与经验实录
即使有了自动化流程,在实际操作中还是会遇到各种问题。这里记录几个典型场景和我的解决思路。
问题1:收集到的子域名数量极少,远低于预期。
- 排查思路:
- 检查目标是否泛解析:随便构造一个不存在的子域名如
random123456.example.com,用dig或nslookup查一下。如果返回一个IP,说明存在泛解析,很多枚举结果会指向这个IP,需要过滤。在工具中通常有-nW(amass)或-filter-wildcard参数来处理。 - 检查字典和API:你的爆破字典是否太小儿科?被动收集的API密钥是否配置正确且未过期?用
subfinder -list-sources检查可用源,用-v参数运行看是否有API报错。 - 目标本身可能就很“小”:并非所有公司都有成百上千个子域名。结合其他信息(如公司规模、业务类型)综合判断。
- 检查目标是否泛解析:随便构造一个不存在的子域名如
问题2:工具运行缓慢或卡住。
- 排查思路:
- 并发与速率限制:主动爆破工具(如amass active模式)的线程数或速率是否设置过高?降低并发数(如
-max-dns-queries 50)。对于网络请求,添加延时。 - DNS解析器问题:
massdns使用的resolvers.txt列表中的DNS服务器可能大量失效或响应慢。定期更新一份高质量的DNS解析器列表至关重要。可以用dnsvalidator工具来验证和筛选。 - 目标屏蔽:如果从单一IP发起大量请求,可能被目标的防火墙或WAF屏蔽。考虑使用代理池或降低攻击性。
- 并发与速率限制:主动爆破工具(如amass active模式)的线程数或速率是否设置过高?降低并发数(如
问题3:JSFinder提取出大量无关或错误域名。
- 解决方案:
- 强化过滤规则:修改
JSFinder的正则表达式或过滤逻辑,只保留符合目标域名后缀或特定模式的字符串。这通常需要阅读其源码并进行小修改。 - 后处理清洗:对
JSFinder的原始输出进行后处理。用grep严格匹配\.example\.com$,并排除掉明显是本地地址(localhost)、私有IP段、常见公共CDN域名的行。 - 人工复核:对于关键目标,自动化提取后,人工抽查一些JS文件是必要的,可以帮你理解其代码结构,优化提取策略。
- 强化过滤规则:修改
问题4:如何持续监控和发现新增子域名?
- 方案:将上述收集流程定期(如每周)运行,并与历史结果进行对比。可以用
git管理结果目录,每次运行后diff一下新旧文件。更专业的做法是使用Amass的数据库模式(-dir参数),它内置了跟踪变化的功能。也可以将结果导入到类似TheHive、Cortex或自建的资产管控平台中,实现自动化监控和告警。
最后一点个人体会:子域名收集是一个“量变引起质变”的过程,也是一个需要持续维护的技能。工具在迭代,目标的防御和建设方式也在变。最宝贵的不是某一份庞大的字典或某一个神奇的脚本,而是你根据目标特点灵活组合各种思路、调试工具参数、分析异常结果的那套思维模式。保持好奇心,多看看别人怎么写爬虫、怎么处理JS混淆、怎么设计分布式扫描架构,你的“武器库”和“战术库”才会越来越丰富。每次测试后,花点时间复盘一下:哪些方法最有效?哪个工具漏报了关键资产?为什么?这些反思才是让你从“会用工具”进阶到“真正懂行”的关键。
