接到一个授权测试目标之后,我做的第一件事往往不是打开浏览器去看官网,而是先花一个晚上把目标的所有子域名摸一遍。这个习惯源于一次真实经历:主站 WAF 严严实实,连目录扫描都要小心谨慎,结果一个类似 test.example.com 的老测试子域直接裸奔着后台,登录框连验证码都没做。子域名收集在渗透测试里属于信息收集阶段的核心动作,子域名越多,意味着攻击面越大,拿到权限的概率也越高。这篇文章会把我在 Kali 下常用的 7 种子域名批量抓取技巧完整整理出来,从被动数据源到主动爆破,每一条都附上实际命令和踩坑记录,适合刚接触 Kali 但对信息收集还没有体系概念的读者,也适合想把自己的子域名收集流程补全的同行参考。
1. 子域名收集到底在收集什么:攻击面逻辑与7种技巧总览
1.1 为什么子域名往往比主域名更值得投入时间
很多新人会困惑:目标不就是 example.com 一个域名吗,直接开扫不就行了?这是对资产理解还不够。大型企业的数字资产通常分散在几十上百个子域里,主站由安全团队重点防守,WAF、CDN、风控体系一套套;但子域名往往是不同业务线、不同时期、不同外包团队留下的,管理水平参差不齐。
我见过不少目标,官网是 example.com,但还有 old.example.com、test.example.com、api-dev.example.com 这类子域挂着老旧版本的管理后台、接口文档甚至数据库管理面板。子域名的存在说明这个域名下的 HTTP 服务更多、解析记录更复杂、暴露的端口和中间件更多。从红队角度看,子域名的数量基本决定了攻击面的上限;从蓝队角度看,这也是资产测绘和收敛的第一步。
所以子域名收集的核心价值不是"把名字找齐",而是把目标组织的数字资产脉络梳理出来。收集到的子域名清单,后续还要配合 DNS 解析、IP 归属、端口探测、指纹识别继续往下走,形成完整的攻击面地图。
1.2 被动收集与主动爆破的分野
子域名收集方法虽然多,但本质上只有两大流派。
被动收集不直接向目标发送请求,靠的是证书透明日志、搜索引擎、第三方情报库这些公开数据源。优点是不接触目标,不会触发目标侧的任何告警,几乎没有法律风险;缺点是覆盖面有限,过时或隐藏较深的子域可能看不到。
主动爆破则会向目标 DNS 服务器发送大量解析请求,或者直接对候选子域发起 HTTP 探测。优点是结果更全,能发现很多第三方数据源里没有收录的内网映射记录;缺点是有流量特征,可能触发目标的 DNS 监控或 WAF 告警,而且速度太快的话容易被封 IP。
真正成熟的流程,从来不是"二选一",而是先用被动方式把底子铺好,再用主动方式做扩展。下面这 7 种技巧里,前四种偏被动,后面三种偏主动,正好对应这条思路。
1.3 七种技巧总览
| 顺序 | 技巧 | 类型 | 特点与速度 | 适合场景 |
|---|---|---|---|---|
| 1 | 证书透明日志(crt.sh) | 被动 | 稳定,数据质量高 | 第一手信息,通用 |
| 2 | 搜索引擎语法 | 被动 | 比较随缘,反爬严重 | 补充发现,遗漏排查 |
| 3 | Sublist3r | 被动 | 聚合多源搜索引擎结果 | 快速粗筛 |
| 4 | assetfinder | 被动 | 来源广,输出快到离谱 | 大规模资产初步摸底 |
| 5 | Amass | 被动+主动 | 数据源最多,深度玩法 | 重点目标深挖 |
| 6 | ffuf 子域爆破 | 主动 | 高度可控,过滤器强大 | 有字典后的定向爆破 |
| 7 | massdns + dnsx | 主动 | 量级大,速度极快 | 超大规模子域枚举 |
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技巧一、二:证书透明日志与搜索引擎的被动收集
2.1 crt.sh:把证书日志当作子域名数据库
证书透明日志(Certificate Transparency)是一个公开的日志系统,所有公开签发的 TLS 证书都会被记录在里面。每张证书的 SAN(主题备用名称)字段会列出该证书覆盖的所有域名,所以只要查一下 CT 日志,就能把一个域名下所有出现在证书里的子域名捞出来。这个思路是我最常用的第一招,因为它完全不需要接触目标服务器,只需要向公开接口发一次查询。
crt.sh 是最常用的 CT 日志查询接口,Kali 下直接用 curl 结合 jq 就能解析:
bash复制curl -s "https://crt.sh/?q=%25.example.com&output=json" \
-A "Mozilla/5.0" \
--max-time 60 | \
jq -r '.[].name_value' | \
sed 's/\*\.//g' | \
sort -u > crtsh_subs.txt
这里有几个细节值得说明。%25.example.com 中的 %25 是 * 的 URL 编码,意思是查询所有以 .example.com 结尾的证书域名,包括通配符证书。jq 提取 name_value 字段后,sed 负责把形如 *.dev.example.com 的通配符前缀去掉。最后 sort -u 去重,得到一个干净的列表。
实际使用中 crt.sh 有两个小毛病:一是查询量大的时候响应很慢,所以我习惯加 --max-time 60 做超时保护,避免命令卡死;二是偶尔会返回重复数据或者过期证书的数据,不过只要最后一步做统一去重,问题不大。如果你觉得 crt.sh 的 JSON 解析太麻烦,也可以用 CertSpotter 的公开 API,命令形式类似。
2.2 搜索引擎语法:site 操作符的另类用法
搜索引擎收录过很多目标域名的 URL,通过 site 语法可以筛出搜索引擎索引里出现的所有子域。这个方法听起来原始,但往往能挖到 CT 日志里没有的冷门子域,比如某些只在内网引用过、但被搜索引擎爬虫抓到过的地址。
以 Bing 为例,直接在浏览器里搜 site:*.example.com,就能看到大量结果。如果要在 Kali 终端里批量处理,可以用 curl 拼接请求再提取域名:
bash复制curl -s "https://www.bing.com/search?q=site%3A%2A.example.com&count=50" \
-A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" | \
grep -oP 'https?://[a-zA-Z0-9._-]+\.example\.com' | \
sed 's|https\?://||' | \
sort -u > bing_subs.txt
需要提醒的是,搜索引擎的反爬机制越来越严格,这个命令的返回结果量不稳定,有时候能抓到几百条,有时候翻几页就被要求验证了。我的经验是:搜索引擎法适合作为兜底手段,跑完 crt.sh 或者 Sublist3r 之后再顺带看一眼,不要过度依赖它。免费接口里 SecurityTrails、AlienVault OTX 这些也可以配合 curl 查询,但部分需要注册 API key,这里就不展开讲了。
2.3 被动数据的处理细节
被动数据源返回的内容五花八门,最常见的几个问题包括:证书里可能包含邮件地址格式的记录、空行、大小写不统一、泛解析符号等。所以在合并前,我基本都会统一做一遍清洗:
bash复制cat crtsh_subs.txt bing_subs.txt | \
sed 's/^\.//; s/^\*\.//' | \
tr 'A-Z' 'a-z' | \
grep -E '^[a-z0-9._-]+\.example\.com$' | \
sort -u > passive_raw.txt
grep -E 这步很关键,它能过滤掉脏数据,只保留形如 sub.example.com 的合法域名格式。被动收集阶段得出的数据量通常不会特别大,但胜在干净、安全,可以毫无顾虑地直接进入下一步探测流程。
3. 技巧三、四:Sublist3r 与 assetfinder 的快速被动收集
3.1 Sublist3r 的安装与使用
Sublist3r 是老牌的子域名收集工具,原理是同时调用多个搜索引擎和公开数据源(Bing、Yahoo、DNSDumpster 等)做关键字查询,再把结果聚合起来。Kali 默认没有装 Sublist3r,需要从 GitHub 拉取:
bash复制git clone https://github.com/aboul3la/Sublist3r.git
cd Sublist3r
pip install -r requirements.txt
python sublist3r.py -d example.com -o sublist3r_subs.txt
核心参数说几个。-d 指定目标域名,-o 指定输出文件。默认线程是 30,如果不想把目标站的搜索引擎接口打得太猛,可以用 -t 10 降低并发。-b 参数可以启用在暴力枚举时的常见子域名字典,但 Sublist3r 内置字典非常小,实际爆破效果远不如后面的 ffuf,所以我一般不用它做爆破,只把它当纯被动工具用。
这个工具的真实体验是"下限很稳,上限不高":只要网络正常,它总能跑出一些结果,而且基本不会误伤目标。缺点也很明显,它依赖的搜索引擎接口响应慢,跑完一次常常要三五分钟,遇到搜索引擎反爬时还会漏结果。所以 Sublist3r 更适合作为被动收集的基线工具,而不是唯一工具。
3.2 assetfinder:一行命令输出所有结果
assetfinder 是 Tomnomnom 写的 Go 工具,核心逻辑是从证书日志、DNS 数据集、互联网扫描数据库等二十多个公开来源拉取与目标域名相关的记录。它的最大特点就是快,经常几秒钟就扫完,而且输出格式非常简单,一行一个域名,方便直接进入管道处理。
安装方式推荐用 go install:
bash复制go install github.com/tomnomnom/assetfinder@latest
然后把 Go 的 bin 目录加入 PATH,或者直接把二进制文件复制到 /usr/local/bin/:
bash复制cp ~/go/bin/assetfinder /usr/local/bin/
echo example.com | assetfinder -subs-only > assetfinder_subs.txt
echo 把目标域名送到标准输入,-subs-only 参数让它只输出子域名,不带根域名本身。assetfinder 的源代码里集成了证书透明日志、Common Crawl、HackerTarget、ThreatCrowd 等多个数据源,覆盖面比 Sublist3r 更广,输出也更快,非常适合在目标域名比较多的时候做快速筛选。
3.3 两个工具怎么搭配才高效
Sublist3r 和 assetfinder 看起来功能接近,但数据源并不完全重叠。Sublist3r 更依赖搜索引擎结果,assetfinder 更依赖数据库和证书日志,两者跑出来的结果肯定有差异。我的用法是同时跑,然后合并:
bash复制cat sublist3r_subs.txt assetfinder_subs.txt | \
tr 'A-Z' 'a-z' | \
sort -u > passive_subs_all.txt
做完整合之后,你就会发现结果里既有两个工具都发现的"公共子域",也有各自独有的"冷门发现"。对于冷门发现,我通常会单独标记一下,因为这类子域往往对应着搜索引擎收录较少、防护相对薄弱的历史系统,挖掘价值可能更高。
4. 技巧五:Amass 综合枚举的深度玩法
4.1 为什么需要 Amass 这种重型选手
如果说 Sublist3r 和 assetfinder 是子域名收集界的"快枪手",那 Amass 就是重型坦克。这个项目由 OWASP 维护,聚合了开放数据源、证书日志、DNS 记录、搜索引擎、互联网扫描引擎等上百个数据源,还支持自定义 API key 扩展。它枚举出来的结果里不仅包含子域名,还会带上数据源标签,方便你判断这条结果是从哪个渠道来的。
Kali 里安装 Amass 很简单:
bash复制sudo apt update
sudo apt install amass
或者直接去 GitHub Releases 下载编译好的二进制。amass -h 能看到完整的子命令,枚举相关的主要是 amass enum。
4.2 配置 API 密钥让结果翻倍
Amass 默认配置能用,但数据源有限。想让它发挥真正实力,最好申请几个公开情报服务的 API key,写进配置文件。配置文件默认路径是 ~/.config/amass/config.ini,里面按 [data_source_name] 分节,需要改的地方主要是 apikey 和 username。
我常用的配置项包括 Censys、SecurityTrails、VirusTotal、PassiveTotal 等。申请这些 key 基本都要注册账号,部分服务有免费额度。配置完成后可以用 amass enum -passive -d example.com 跑一遍对比,你会发现结果数量会有明显提升。这一步是很多教程不会细讲的,但实际效果非常显著。
4.3 passive 与 active 两阶段使用
Amass 的枚举分为 passive 和 active 两种模式。passive 模式只从公开数据源收集,不主动向目标 DNS 发送请求,适合先跑一轮做资产摸底:
bash复制amass enum -passive -d example.com -o amass_passive.txt
active 模式会主动进行 DNS 解析和爆破,需要配合字典使用:
bash复制amass enum -active -d example.com \
-w /usr/share/wordlists/amass/small.txt \
-o amass_active.txt
-w 指定子域名字典。Kali 里默认带了一份 /usr/share/wordlists/amass/small.txt,虽然不大,但覆盖了常见的 dev、test、api、stage 等前缀,足够快速验证效果。如果你想跑得更猛,可以把路径换成 -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt,这个我们下一节细说。
Amass 有一个需要适应的地方:输出非常啰嗦,会打印大量日志和状态信息。建议始终带上 -o 文件名,最后只看文件内容,别盯着终端刷屏。另外 Amass 的子命令和参数版本更新比较频繁,老教程里的参数在新版本可能已经改名,跑之前先用 amass enum -h 确认一下当前版本的参数。
5. 技巧六:ffuf 与字典的子域名爆破
5.1 子域爆破的原理解释
子域爆破的本质是"猜":拿着一个常见子域名字典,逐个拼成 dict.example.com 这样的域名,然后尝试解析。如果 DNS 返回了 A 记录或 CNAME,说明这个子域存在;如果返回 NXDOMAIN,说明字典里这个词对应的子域不存在。
之所以要用 ffuf,而不是自己写个循环脚本,是因为 ffuf 在并发和过滤上都做得非常好。它可以用上百个线程同时发请求,同时通过状态码、响应长度、正则表达式等维度自动过滤掉无效结果,输出格式也清晰。
记得有一次我用 bash 循环配合 dig 做子域爆破,跑 5000 条字典花了一个多小时,期间还频繁被目标 DNS 限流。换成 ffuf 之后,同样的字典 3 分钟跑完,命中结果一条不落。这个差距就是专业工具和手工脚本的差距。
5.2 字典是半条命
爆破效果好不好,一半取决于字典。Kali 里安装了 seclists 的话,可以直接使用 ProjectDiscovery 维护的 DNS 字典:
bash复制sudo apt install seclists
ls /usr/share/seclists/Discovery/DNS/
最常用的是 subdomains-top1million-5000.txt,收录了互联网上出现频率最高的 5000 个子域前缀,适合快速跑:另外还有 subdomains-top1million-20000.txt、namelist.txt 等更全的版本,按需选择。如果总觉得现成字典不够贴脸,可以手动加一些目标相关的词,比如公司名、产品名、城市名、年份、项目代号等,组合成一个小型补充字典:
code复制dev
staging
test2023
api-gateway
jenkins
grafana
gitlab
这种自定义字典对于针对性测试的效果经常出乎意料。
5.3 ffuf 实战命令与结果过滤
ffuf 做子域爆破有两种常用姿势。一种是直接让 FUZZ 占位符出现在域名前缀里:
bash复制ffuf -u http://FUZZ.example.com \
-w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \
-t 100 \
-timeout 3 \
-ac \
-o ffuf_subs.json
这里 -u 指定目标 URL,FUZZ 是占位符,ffuf 会把字典里的每一行依次替换进去。-ac 是自动校准,它会先请求一个随机不存在的子域,拿到"默认无效响应"的长度和状态码,然后自动过滤掉相同特征的响应。这个参数一定要开,它能极大降低误报率。
另一种姿势是通过 Host 头来做爆破:
bash复制ffuf -u http://127.0.0.1 \
-w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \
-H "Host: FUZZ.example.com" \
-t 100 \
-ac
这种方式在目标服务器只能用 IP 访问、但允许通过 Host 头区分虚拟主机的时候特别有用。不过需要注意,-ac 自动校准在 Host 头模式下偶尔会误伤真实子域,建议跑完后再人工核对一遍。
跑完 ffuf 后,除了 JSON 输出,终端会直接显示类似下面的结果表:
text复制[Status: 200, Size: 11745, Words: 2132, Lines: 234, Duration: 312ms]
* FUZZ: api.example.com
如果你的目标站点泛解析严重,即任何不存在的子域名都返回同一个 IP 或同一个页面,那 -ac 会自动把这类响应过滤掉。如果自动校准的效果不够理想,还可以手动用 -fs 11745 忽略指定响应长度,用 -fc 403 忽略指定状态码。多试几轮,找到正确的过滤参数,爆破结果会干净很多。
6. 技巧七:massdns + dnsx 的高速组合拳
6.1 massdns:用大规模 DNS 解析器批量轰炸
ffuf 虽然快,但本质上还是串行对每个候选域名做 HTTP 请求,带宽和连接数都会成为瓶颈。当你需要爆破几十万甚至上百万条域名记录时,真正的利器是 massdns。
massdns 是一个高速 DNS 解析器,它一次能向多个 DNS 服务器并发发送大量解析请求,原理上和 DNS 放大攻击类似,但这里是合法使用——对自己授权目标做子域枚举。Kali 自带 massdns,如果没有,先安装:
bash复制sudo apt install massdns
使用方式很简单,把准备爆破的候选域名列表存成一个纯文本文件,每行一个域名,然后用下面的命令跑:
bash复制massdns -r /usr/share/massdns/lists/resolvers.txt \
-t A \
-o S \
-w massdns_output.txt \
-s 1000 \
subdomains_candidates.txt
几个参数的含义:-r 指定 DNS 解析器列表,Kali 自带的 resolver 列表里包含了大量公共 DNS 服务器;-t A 表示解析 A 记录;-o S 表示简化输出格式,方便后续处理;-w 指定输出文件;-s 指定每秒发送的请求数,1000 是比较稳妥的起步值,如果你想更快,可以调高到 3000 甚至 5000,但要看目标 DNS 和本机网络能否扛住。
运行结束后,massdns_output.txt 的内容大致是:
text复制api.example.com. A 203.0.113.10
old.example.com. CNAME old-cdn.example.net.
bad.example.com. NXDOMAIN
6.2 dnsx:把结果整理成干净列表
massdns 输出里包含类型、IP、状态等大量信息,直接用不太方便。这时候就该 dnsx 出场了。dnsx 是 ProjectDiscovery 团队开发的 DNS 查询与验证工具,擅长做基于 STDIN 的管道处理:
bash复制sudo apt install dnsx
先从 massdns 输出里提取存在解析记录的域名,再交给 dnsx 做二次验证:
bash复制grep -E '\.example\.com\.? A ' massdns_output.txt | \
awk '{print $1}' | \
sed 's/\.$//' | \
sort -u > massdns_hits.txt
然后对命中的域名做一次干净的解析验证:
bash复制dnsx -l massdns_hits.txt -a -resp -silent
-a 表示查询 A 记录,-resp 显示解析结果,-silent 让输出更简洁,只保留域名加解析结果。如果不加 -resp,dnsx 默认只输出存在的域名;加上 -resp 就会输出类似下面的内容:
text复制api.example.com [A: 203.0.113.10]
old.example.com [A: 198.51.100.24]
6.3 组合拳的实际价值
massdns 加 dnsx 这套组合拳最大的价值在于"量大"。用 seclists 里的 namelist.txt 或者自己生成的几百万行域名列表喂给 massdns,几分钟内就能完成数百万次 DNS 解析,这是任何 HTTP 层爆破工具都做不到的。
但量大的代价是输出噪音也大。massdns 跑完的原始文件可能有几百 MB,处理起来非常吃内存。我的建议是:先用 grep 筛选出包含 A 记录的行,再交给 dnsx 做过滤,不要直接把整个原始文件丢给 dnsx。另外,如果目标 DNS 服务器有比较严格的速率限制,-s 参数值不要拉得太高,否则容易触发封禁或者限流,反而拖慢整体进度。
7. 七种技巧的实战编排:合并去重、存活验证与授权边界
7.1 把 7 个结果合并成一份目标清单
做完全部收集之后,你会得到一堆文件:crtsh_subs.txt、bing_subs.txt、sublist3r_subs.txt、assetfinder_subs.txt、amass_passive.txt、amass_active.txt、ffuf_subs.json、massdns_hits.txt。这时候不要急着去翻每个文件,第一步是把它们全部合并到同一个清单里:
bash复制cat crtsh_subs.txt \
bing_subs.txt \
sublist3r_subs.txt \
assetfinder_subs.txt \
amass_passive.txt \
amass_active.txt \
massdns_hits.txt | \
sed 's/^\.//; s/^\*\.//' | \
tr 'A-Z' 'a-z' | \
grep -E '^[a-z0-9._-]+\.example\.com$' | \
sort -u > all_subs_raw.txt
如果 ffuf 用了 JSON 输出,可以多一步把结果字段提出来再合并。合并到 all_subs_raw.txt 之后,这份清单就是你这轮信息收集的全部子域名候选。
7.2 存活子域的最终筛选
拿到全部子域名后,还要做一次存活验证。因为有些子域名虽然在 DNS 里有记录,但对应的 HTTP 服务可能已经下线,或者只在内网解析、公网根本访问不通。为了方便后续渗透,我们需要过滤出"公网可访问并且确实开放了 Web 服务"的子域。
最常用的工具是 httpx(ProjectDiscovery 出品),Kali 里可以直接安装:
bash复制sudo apt install httpx
使用方式:
bash复制httpx -l all_subs_raw.txt \
-title \
-status-code \
-tech-detect \
-follow-redirects \
-o live_subs.txt
这个命令会对清单里每个域名发起 HTTP/HTTPS 请求,并记录响应状态码、页面标题和识别的技术栈。跑完后的 live_subs.txt 就是真正的攻击面清单,可以直接交给后续端口扫描、目录扫描、指纹识别等流程使用。
7.3 泛解析与误报处理
泛解析是子域名收集中最常见的误报来源。很多云厂商或运维团队会在 DNS 里配置 *.example.com 指向同一个 IP,这样任何随机子域名都能解析到某个服务器页面上。如果目标配置了泛解析,你的爆破工具会把大量不存在的"假子域名"当作命中结果返回。
判断泛解析的方法很简单:随便取一个几乎不可能存在的名字,比如 a9x7k3q2.example.com,看它能不能解析通。如果解析通了,说明目标有泛解析配置。这种情况下,建议把泛解析返回的固定 IP 或固定响应长度找出来,然后在过滤阶段统一排除:
bash复制grep -v "203.0.113.10$" all_subs_raw.txt
或者更规范一点,在跑 httpx 之前先通过 DNS 解析结果把泛解析的 IP 拉黑。这一步做得好不好,直接决定你后续扫描会不会浪费大量时间在无效目标上。
7.4 授权边界与合规底线
最后必须强调一个原则:以上所有技巧,只适用于你拥有合法授权或明确获得目标方书面许可的场景。子域名收集本身是信息收集手段,但主动爆破会产生大量 DNS 查询,存在一定的请求特征,可能触发目标的安全告警,做之前要确认自己有权执行这些操作。未授权测试不仅可能触犯法律,也是对自己职业操守的背叛。
从合规角度,我建议在每次项目开始前就把授权范围落到书面上,明确列出允许测试的域名列表。实际操作中遇到目标域名归属不清的情况,宁可先停下来沟通,也不要抱着侥幸心理"先试一下"。技术本身没有立场,但使用技术的人必须有边界意识。
结尾:一个半自动化的资产监控思路
踩过几次坑之后,我把这套流程沉淀成了一个小脚本,结合 crontab 定期跑一遍被动收集,每月生成一份新的子域名清单。效果非常明显,曾经在一次例行巡检中,我发现一个新增的 .dev.example.com 子域在第二天就上线了一个演示环境,里面直接挂着明文数据库连接配置,连密码都没改。
最后再分享一个小技巧:被动收集结果和主动爆破结果可以分开存储,被动结果适合作为长期资产档案保留,主动爆破结果适合当作当次测试的攻击面快照。两者分开之后,你不仅能在当下测试中用到,还能持续观察到目标网络资产的变化趋势,这对于乙方项目复测和甲方防御建设都有很大的参考价值。子域名收集虽然只是信息收集的一小步,但它决定了后面所有测试动作的上限,值得多花一点时间把它做扎实。
