基于证书透明日志与MassDNS的高效子域名发现实战指南
1. 项目概述:从证书透明日志到精准子域名发现
在安全测试和资产梳理的日常工作中,子域名发现是信息收集环节里最基础、也最考验耐心和技巧的一环。传统的枚举方式,比如基于字典的暴力破解,效率低下且噪音巨大,常常是“一顿操作猛如虎,一看结果二百五”。而证书透明日志,这个由各大CA机构维护的公开数据库,为我们打开了一扇新的大门。它记录了几乎所有公开信任的SSL/TLS证书的签发信息,其中就包含了证书申请时提交的域名。这意味着,只要一个子域名申请过HTTPS证书,它就有很大概率被记录在案。
MassDNS,一个用C语言编写的高性能DNS解析器,正是处理海量域名解析任务的利器。它的设计初衷就是为了速度而生,单机就能轻松应对每秒数万甚至数十万次的DNS查询。将MassDNS与证书透明日志结合,就形成了一套高效、精准的子域名发现流水线:从公开日志中提取潜在的域名列表,再用MassDNS进行快速解析验证,剔除无效记录,最终得到真实、可访问的子域名资产。这套方法的核心优势在于“有的放矢”——我们不再盲目猜测,而是基于确切的证书申请记录进行探测,极大地提高了发现效率和准确率。无论你是安全工程师、渗透测试人员,还是负责企业资产管理的运维,掌握这套组合拳,都能让你的信息收集工作事半功倍。
2. 核心思路与工具链解析
2.1 为什么是证书透明日志?
要理解这套方法的威力,首先得弄明白证书透明日志是什么。简单来说,它是一个公开的、只能追加的日志系统。全球主要的证书颁发机构在签发一张SSL/TLS证书时,除了把证书给申请者,还必须将证书的“指纹”提交到一个或多个公开的CT日志服务器上。这个举措的初衷是为了防止CA错误签发或恶意签发证书,通过公开透明来加强监督。
对我们而言,这个日志就是一座金矿。每一份提交的记录都包含证书的完整信息,其中最关键的就是Subject Alternative Name扩展字段。一个证书不仅可以用于一个域名,还可以同时授权给多个域名甚至通配符域名。因此,通过持续地监控或批量下载这些日志,我们就能获取到大量正在使用或曾经使用过HTTPS的域名,其中不乏许多内部系统、测试环境、第三方服务等不易通过常规扫描发现的子域名。
与传统的子域名发现方法相比,CT日志的优势非常明显:
- 高准确性:数据来源于真实的证书申请,目标存在HTTPS服务的可能性极高。
- 覆盖广:几乎涵盖了所有公开信任的证书,包括Let‘s Encrypt自动签发的证书,能发现大量自动化系统创建的子域名。
- 实时性:日志是近乎实时更新的,有助于发现最新上线的资产。
- 被动性:整个过程只是查询公开数据,属于被动信息收集,对目标系统没有主动探测流量,隐蔽性好。
2.2 MassDNS:海量解析的引擎
有了高质量的域名列表,下一步就是验证它们是否真实存在并且可解析。这就是MassDNS的舞台。普通的dig命令或者Python的dnspython库在处理几万、几十万个域名时,会慢得让人无法忍受,因为它们通常是串行或并发数很低的查询。
MassDNS则采用了截然不同的设计:
- 异步无状态查询:它自己实现了高性能的DNS解析客户端,采用异步I/O模型,可以同时发出成千上万个查询请求,而不需要等待单个响应返回。
- 绕过系统解析器:它不依赖系统的
/etc/resolvers.conf或本地DNS缓存,直接向指定的DNS解析器发送原始的DNS请求包,减少了中间环节的开销。 - 简洁的输出:它的输出格式非常干净,通常就是“域名 IP地址”,便于后续用
grep、awk等命令行工具进行处理。
它的工作模式通常是:从一个包含大量域名的文本文件(每行一个)读取输入,然后向一批公共DNS解析器(如8.8.8.8,1.1.1.1)发起查询,最后将解析成功的记录输出。它的速度仅受限于你的网络带宽和所配置的DNS解析器的响应能力。
2.3 工具链工作流程全景
整个实战过程可以清晰地分为三个主要阶段,形成一个高效的流水线:
第一阶段:数据获取与预处理这个阶段的目标是从CT日志中提取出干净的域名列表。我们需要使用专门的工具(如certstream、ctfr或直接下载日志)来获取数据,然后进行清洗,去除重复项、过滤掉无关的顶级域名(比如我们只关心example.com的子域),并将数据整理成每行一个域名的标准格式,供MassDNS使用。
第二阶段:高速解析与过滤这是MassDNS的核心工作阶段。我们将上一阶段产出的域名列表文件喂给MassDNS,并配置好可靠且快速的公共DNS解析器列表。MassDNS会进行爆破式解析,输出所有能成功解析到IP地址的记录。此阶段可以快速将几十万的可能域名,缩减到几千或几百个真实存在的子域名。
第三阶段:结果后处理与验证MassDNS输出的结果还需要进一步加工。比如,我们需要识别并剔除那些指向CDN节点、云WAF或负载均衡器IP的域名(这些可能不是目标的真实资产),对解析出的IP进行端口扫描或HTTP标题抓取,以确认服务的真实性,最后将结果整理成结构化的报告(如CSV、JSON格式),便于导入其他安全工具进行深度测试。
注意:在使用公共DNS解析器时,务必注意查询速率。过高的查询频率可能会被这些公共服务器限制或屏蔽。MassDNS允许你通过线程数和重试机制来控制速率,在实际操作中建议先从小批量开始测试。
3. 实战环境搭建与数据获取
3.1 基础环境准备
工欲善其事,必先利其器。我们首先需要在Linux环境下搭建好整个工具链。一个常见的选择是Ubuntu或Kali Linux。以下是在Ubuntu系统上的准备步骤:
安装MassDNS: MassDNS的安装非常直接,因为它是一个C语言项目,需要从源码编译。确保系统已安装
git和make。sudo apt update sudo apt install -y git make gcc git clone https://github.com/blechschmidt/massdns.git cd massdns make编译完成后,当前目录下会生成一个名为
bin/massdns的可执行文件。你可以将它移动到系统路径下,比如/usr/local/bin/,方便随时调用。sudo cp bin/massdns /usr/local/bin/准备DNS解析器列表: MassDNS需要一个包含DNS服务器IP地址的列表文件,每行一个。你可以自己收集一批可靠的公共DNS,也可以使用项目自带的或网络上分享的列表。一个简单的创建方法是:
cat > resolvers.txt << EOF 8.8.8.8 8.8.4.4 1.1.1.1 1.0.0.1 9.9.9.9 208.67.222.222 208.67.220.220 EOF为了提高解析成功率和速度,建议使用一个包含几十甚至上百个DNS服务器的列表。网络上可以找到一些专门为MassDNS优化的
resolvers.txt文件。
3.2 获取证书透明日志数据
获取CT日志数据有几种方式,这里介绍两种最实用的:
方法一:使用CertStream(实时流式获取)CertStream提供了一个WebSocket接口,可以实时监听新提交的证书。这对于监控新出现的资产特别有用。我们可以使用Python库certstream来轻松获取。
pip install certstream然后编写一个简单的Python脚本,只提取我们感兴趣的主域(例如example.com)的子域名,并保存到文件。这种方式的优点是实时,缺点是需要长时间运行脚本,且数据流巨大,需要做好过滤。
方法二:使用离线工具批量获取(推荐)对于针对特定目标的资产发现,更高效的方式是使用能批量查询CT日志的工具。这里强烈推荐ctfr这个工具。
git clone https://github.com/UnaPibaGeek/ctfr.git cd ctfr pip3 install -r requirements.txt使用ctfr非常简单,指定目标域名即可:
python3 ctfr.py -d example.com -o subdomains_ct.txt这条命令会从多个CT日志源查询example.com相关的证书,并将其所有找到的子域名(包括SAN字段里的)输出到subdomains_ct.txt文件中。这是目前最快、最直接获取某个目标CT日志子域名的方式。
方法三:手动下载与解析(高阶)如果你需要海量、全量的数据,可以直接从Google、Cloudflare等运营的CT日志服务器下载日志。这涉及到下载json文件,并使用golang的ct工具库进行解析,过程较为复杂,数据量也极其庞大(每天数十GB),通常用于构建自己的子域名数据库,而非针对单次任务。
实操心得:对于绝大多数单目标或少量目标的信息收集任务,
ctfr工具足以满足需求。它的速度很快,结果也相当全面。在运行前,最好检查一下工具的更新情况,因为CT日志的API接口有时会发生变化。
3.3 数据清洗与格式化
无论用哪种方法获取数据,原始数据通常都需要清洗。ctfr的输出已经比较干净,但为了给MassDNS提供最佳输入,我们通常还需要做以下处理:
去重:使用
sort和uniq命令去除完全重复的行。sort subdomains_ct.txt | uniq > subdomains_ct_unique.txt格式统一:确保文件是每行一个域名,且域名格式正确(没有
http://或https://前缀,也没有路径)。(可选)按目标过滤:如果你获取的是广谱数据,需要用
grep过滤出包含你目标主域的行。grep ‘\.example\.com$’ all_domains.txt > target_domains.txt
至此,我们得到了一个名为target_domains.txt的纯净域名列表文件,接下来就交给MassDNS进行“压力测试”了。
4. MassDNS核心配置与解析实战
4.1 MassDNS命令详解与参数调优
准备好域名列表target_domains.txt和解析器列表resolvers.txt后,就可以运行MassDNS了。一个最基础的命令如下:
massdns -r resolvers.txt -t A -o S -w massdns_results.txt target_domains.txt让我们拆解一下这几个关键参数:
-r resolvers.txt:指定包含DNS解析器IP的列表文件。-t A:指定查询记录类型为A记录(IPv4地址)。你也可以查询AAAA(IPv6)、CNAME等。-o S:指定输出格式为“简单”格式。这种格式每行一条记录,形如域名 A记录 IP地址,非常易于后续处理。其他格式如J(JSON)更适合程序解析。-w massdns_results.txt:指定输出结果写入的文件。target_domains.txt:输入文件,包含要解析的域名。
然而,直接使用基础命令可能遇到性能或完整性问题,我们需要根据实际情况调优:
- 控制速率与超时:
-s 100:限制并发查询数为100。这是防止被DNS服务器屏蔽的关键参数。对于公共DNS,建议从50-200开始尝试。数值太高可能导致大量超时或 SERVFAIL 错误。--retry 2:设置重试次数为2次。对于第一次查询失败的域名,MassDNS会自动重试,提高解析成功率。--root:允许回退到根服务器查询。当配置的解析器都无法回答时,这是一个备选方案。-i:忽略解析器文件中的错误行。
一个经过调优的、更健壮的命令示例如下:
massdns -r resolvers.txt -t A -o S -s 150 --retry 2 --root -w massdns_resolved.txt target_domains.txt 2>massdns_errors.log这里还将标准错误输出(2>)重定向到了massdns_errors.log文件,方便查看运行过程中的警告或错误信息。
4.2 解析过程监控与结果解读
执行上述命令后,MassDNS会开始高速解析。你可以在终端看到它飞速滚动的处理信息。处理时间取决于域名列表的大小和你的网络环境。一个包含10万个域名的列表,在良好的网络和合适的并发下,可能在几分钟到十几分钟内完成。
解析完成后,我们打开massdns_resolved.txt查看结果:
www.example.com A 93.184.216.34 api.example.com A 192.0.2.1 test.example.com A 203.0.113.1 *.internal.example.com A 198.51.100.1你会看到成功解析出IP地址的域名。注意,这里也可能包含通配符记录(如*.internal.example.com),这表示所有以.internal.example.com结尾的子域名都指向同一个IP。这是一个重要的发现,说明目标可能存在一个泛解析配置。
同时,我们还需要关注那些没有出现在结果文件中的域名。它们可能因为以下原因解析失败:
- 域名不存在(NXDOMAIN)。
- 域名存在,但没有
A记录。 - 查询超时或被拒绝。 MassDNS的简单输出格式默认只输出成功的记录,失败的不会写入结果文件。这也是我们需要错误日志的原因。
4.3 结果初步处理:提取与去重
得到原始解析结果后,我们通常只需要域名和IP两列。使用awk命令可以轻松提取:
awk ‘{print $1“ ”$3}’ massdns_resolved.txt > domains_ips.txt这个domains_ips.txt文件就是我们的核心成果,它包含了所有已验证存活的子域名及其对应的IP地址。
注意事项:MassDNS解析出的IP,需要谨慎对待。一个IP可能对应多个域名(虚拟主机),一个域名也可能对应多个IP(负载均衡)。此外,很多IP属于云服务商或CDN(如Cloudflare, Akamai, AWS CloudFront)。直接对这些IP进行端口扫描可能触犯云服务商的安全策略。更稳妥的做法是,先对域名进行HTTP/HTTPS请求,获取网站标题、状态码等信息,再做进一步判断。
5. 结果后处理、验证与深度利用
5.1 识别与过滤“非目标”资产
拿到domains_ips.txt后,直接使用仍然包含很多噪音。我们需要进行智能过滤。
过滤CDN/云WAF IP段: 很多公司使用CDN服务,其子域名解析到的IP是CDN的边缘节点,并非真实服务器。我们需要将这些IP过滤掉。可以维护一个常见的CDN IP段列表文件(
cdn_ip_ranges.txt),然后进行匹配过滤。这里假设我们有一个IP段列表文件,每行格式如1.2.3.4/24。# 这是一个示例性的过滤脚本思路,实际需要根据你的CDN IP列表格式调整 # 假设domains_ips.txt格式为:域名 IP # 假设cdn_ip_ranges.txt格式为:IP段(CIDR) # 可以使用ipcalc或自定义脚本进行CIDR匹配,这里给出一个简单grep排除的思路(不精确,仅示意) # 更精确的做法是使用Python的ipaddress库进行判断由于精确的CIDR匹配在命令行下较复杂,通常我会写一个简单的Python脚本完成这个工作。脚本读取两个文件,判断每个IP是否属于任何一个CDN IP段,如果不属于,则输出该记录。
过滤泛解析记录: 如果发现大量随机字符串的子域名都指向同一个IP,那很可能就是泛解析。我们可以通过统计IP出现的频率来初步判断。
cut -d‘ ’ -f2 domains_ips.txt | sort | uniq -c | sort -nr | head -20这条命令会统计每个IP被多少个子域名解析,并按次数降序排列。如果某个IP的出现次数异常高(比如几百上千),且对应的子域名看起来是随机的(如
a.example.com,b.example.com,123.example.com),那么这个IP很可能就是泛解析的目标。对于这类IP,除非有特殊需求,否则在后续渗透测试中可以降低其优先级,因为它们往往指向一个默认或空白的页面。
5.2 HTTP服务探测与指纹识别
过滤掉明显的噪音后,我们对剩下的“高质量”子域名进行HTTP/HTTPS服务探测,以确认其真实性和获取更多信息。
可以使用httpx或httprob这类工具,它们能快速地对域名列表进行批量请求。
# 使用httpx示例,首先从domains_ips.txt中提取域名 cut -d‘ ’ -f1 filtered_domains_ips.txt > final_domains.txt httpx -l final_domains.txt -title -status-code -tech-detect -o http_results.txt-title:获取页面标题。-status-code:获取HTTP状态码。-tech-detect:进行技术栈指纹识别(如Nginx, Apache, WordPress, React等)。-o:输出结果。
http_results.txt文件会包含每个域名的访问状态、标题、使用的技术等信息。这能帮助我们快速识别出哪些是有效的Web应用,哪些返回404(可能已下线),哪些是默认页,哪些使用了有趣的技术框架(可能存在已知漏洞)。
5.3 资产整合与报告生成
最后,我们将所有信息整合起来,形成一份结构化的资产报告。一个简单的CSV格式报告就非常实用,可以包含以下列:子域名、IP地址、HTTP状态码、页面标题、识别到的技术、备注。
你可以用Python脚本将domains_ips.txt和http_results.txt的信息合并起来。也可以使用像aquatone这样的工具,它能对子域名列表进行截图、标题抓取、技术识别,并生成一个漂亮的HTML报告,直观地展示所有发现的可访问Web资产。
实操心得:整个流程中最容易出错的环节是DNS解析器列表的质量和MassDNS的并发参数设置。解析器不稳定会导致大量超时,并发太高会被限速。我的经验是,定期从公开来源更新
resolvers.txt,并在每次大规模扫描前,先用一个包含1000个域名的小样本列表测试不同的并发数(-s 50, 100, 200),观察成功率和速度,找到当前网络环境下的最优值。另外,将整个流程脚本化(Bash或Python)是必须的,这样可以一键完成从数据获取到报告生成的全过程,提高效率并保证可重复性。
6. 常见问题、排查技巧与进阶优化
6.1 问题排查速查表
在实际操作中,你可能会遇到以下典型问题:
| 问题现象 | 可能原因 | 排查与解决方法 |
|---|---|---|
| MassDNS运行速度极慢,大量超时。 | 1. DNS解析器列表失效或响应慢。 2. 并发数 ( -s) 设置过高,被DNS服务器限制。 | 1. 更换或更新resolvers.txt文件,使用massdns --test测试解析器响应。2. 降低并发数,如从200降至50,并添加 --retry 2。 |
| 解析结果为空或非常少。 | 1. 输入文件格式错误(有空行、非域名内容)。 2. 查询类型 ( -t) 不对,目标可能只有CNAME或AAAA记录。3. 目标域名确实不存在或未配置A记录。 | 1. 检查输入文件,确保每行是一个合法域名。 2. 尝试同时查询 A和CNAME记录:massdns -r resolvers.txt -t A -t CNAME ...。3. 手动用 dig命令验证几个样本域名。 |
输出文件中包含大量SERVFAIL错误。 | DNS服务器拒绝回答或遇到了问题。 | 1. 这是正常现象,MassDNS会重试。确保使用了--retry参数。2. 从解析器列表中移除频繁返回 SERVFAIL的服务器。 |
ctfr工具运行报错或没有结果。 | 1. 目标域名没有在CT日志中记录。 2. 工具的API接口已更新,脚本失效。 3. 网络问题导致无法访问CT日志源。 | 1. 尝试其他工具或方法(如amass enum -passive -d example.com)。2. 查看 ctfr的GitHub仓库,更新到最新版本。3. 检查网络连接和代理设置。 |
| 结果中混入了大量非目标主域的子域名。 | 数据清洗阶段过滤不严格。 | 在运行ctfr或处理原始数据时,使用grep进行严格的主域匹配,例如grep ‘.*\\.example\\.com$’。注意转义点号。 |
6.2 性能与准确性进阶优化
当你熟练基础流程后,可以通过以下方法进一步提升效果:
- 使用高质量解析器列表:不要依赖一个固定的列表。可以定期从公开项目(如
v2fly/domain-list-community中附带的DNS列表)或通过扫描获取开放DNS解析器来更新自己的列表。使用前用MassDNS自带的测试功能筛选出延迟低、响应快的解析器。 - 组合多种数据源:CT日志只是被动信息收集的一个来源。为了更全面,应该结合其他数据源,例如:
- DNS聚合查询:使用
amass,subfinder等工具,它们会查询Virustotal, SecurityTrails, Censys等多个在线API和数据库。 - 搜索引擎语法:利用Google、Bing的
site:语法进行搜索(需注意速率限制)。 - 历史DNS记录:查询DNS历史记录数据库,可能会发现已过期但仍有用的子域名。 将所有这些来源的结果去重合并,形成一个更全面的初始域名列表,再交给MassDNS解析,覆盖率会大大提升。
- DNS聚合查询:使用
- 分布式解析:如果域名列表达到百万级别,单机MassDNS可能成为瓶颈。可以考虑将列表分割,在多台机器上并行运行MassDNS,最后合并结果。这需要一些简单的脚本编排。
- 结果自动化集成:将最终的子域名和HTTP结果列表,自动导入到你的漏洞扫描器(如Nessus, Nuclei)、代理工具(如Burp Suite)或资产管理平台中,形成自动化的工作流。
6.3 法律与道德边界
最后,也是最重要的一点,必须强调合规性。这套技术威力强大,但必须用于合法授权的范围内。
- 仅测试授权目标:绝对不要对未经明确书面授权的任何系统、网络或域名进行扫描或探测。
- 控制扫描速率:即使对授权目标,过于激进的扫描也可能对对方的DNS服务器或网络设备造成压力,甚至触发警报。合理设置MassDNS的并发数和间隔。
- 尊重Robots.txt和服务条款:对Web服务进行探测时,注意目标网站的
robots.txt文件和相关服务条款。 - 数据妥善保管:收集到的资产信息属于敏感数据,应妥善保管,仅在授权项目团队内分享,项目结束后应安全地销毁。
这套“CT日志 + MassDNS”的组合,是我在多年渗透测试和信息收集工作中总结出的高效方法。它改变了以往“盲人摸象”式的子域名发现,让整个过程变得有迹可循、精准高效。关键在于理解每个工具的原理,并将它们像乐高积木一样灵活地拼接起来,同时时刻保持对性能瓶颈和结果质量的关注。记住,工具是死的,思路是活的,根据不同的目标规模和网络环境调整你的策略和参数,才能 consistently 获得最佳效果。
