ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

浏览器插件做互联网资产梳理:子域名枚举与指纹识别实操

浏览器插件做互联网资产梳理:子域名枚举与指纹识别实操

互联网资产梳理这件事,很多团队第一次做的时候都以为是"把域名列个表",真干起来才发现完全不是这么回事。主域下面挂着一堆自己都忘了的子域,云上还有几台临时开的机器,外包做完项目留下的测试环境,再加上历史并购带过来的老资产——台账上写着三百个,实际扫出来两千多。标题里这个能做互联网资产梳理服务的浏览器插件,切入的正是这个场景:它不解决"大规模全自动测绘",而是解决"我手里有一个目标,怎么在几分钟内把它周边的资产线索摸清楚"的问题。

这篇内容面向三类人:一是刚接手资产盘点、安全运营或运维台账的同行,需要一套能落地的流程;二是做安全评估、需要快速核验目标范围的从业者;三是对这块完全陌生、想弄明白"资产梳理到底在梳理什么"的新手。下面我会讲清楚插件这种形态的取舍、它的核心能力该怎么用、完整跑一遍的实操流程、参数和字典的细节,以及踩过的坑。

1. 为什么用插件做资产梳理:形态选择背后的逻辑

1.1 传统资产盘点方式的三个痛点

先说清楚痛点,才能理解插件这个形态为什么有存在价值。我在几个不同规模的团队里都推进过资产台账,几乎每一轮都卡在同样三个地方。

第一是变更滞后。台账通常是季度或半年更新一次,但业务侧开一个测试环境可能就一下午的事,用完不关,域名解析还留着。等你下一次盘点时,台账和现实已经差了半年。台账的本质问题是它是一份"快照",而资产是"流",快照永远追不上流。

第二是口径不统一。安全团队说"资产"指的是暴露在公网的域名和 IP,运维团队说的资产是 CMDB 里的机器和应用,业务团队理解的是"我负责的那个系统"。三套口径对不上,最后汇总出来的表格谁都不认。我见过最典型的情况是:同一个域名,安全那边标了高风险,运维那边查无此机,一追查发现是外包团队注册的、业务方自己都不知道。

第三是单点核验效率低。真正做梳理的时候,大量时间不是花在批量扫描上,而是花在"这一个域名到底是个什么东西、归谁、还活着吗"这种零碎的核验上。你打开浏览器查证书、看响应头、翻页面标题、对一下 IP 归属,一个目标五分钟,两百个目标就是一整天。这种活没有技术含量,但省不掉。

插件这个形态真正打的,是第三个痛点,同时也间接缓解前两个——因为它足够轻,轻到你愿意在每次接触目标时顺手跑一下,台账就有了持续更新的可能。

1.2 浏览器插件形态的天然优势与边界

把资产梳理能力做成浏览器插件,思路其实很朴素:资产梳理的第一现场就在浏览器里。你访问一个系统,浏览器已经拿到了证书、响应头、页面标题、favicon、跳转链路、加载的第三方资源域名,这些恰恰是判断资产归属和技术指纹最有价值的信息。插件只是把这些"已经在眼前但没人看"的信息抽出来,再做一层扩展查询。

这个形态的优势很明确。一是零部署,装完就能用,不需要你准备服务器、配置扫描器、维护依赖环境,对临时接手项目的人特别友好。二是上下文完整,插件知道"你现在正在看哪个站",所以能把当前页面的信息作为一个种子去做关联扩展,而不是让你手工复制粘贴。三是门槛低,不懂命令行的人也能上手,这点在跨团队协作时很重要——你让运维同事装个插件他能接受,你让他配一套扫描框架他直接不理你。

但边界也必须讲清楚,否则容易用错地方。浏览器的资源调度天然受限,并发能力弱,几百个目标的批量任务跑起来会明显卡顿;没有分布式能力,做不了大规模测绘;网络出口单一,高频率请求很容易触发目标侧的限制;结果依赖前端呈现,复杂的数据关联和长期存储能力不足。

我的判断标准很直接:目标数量在几十到几百这个量级、需要快速核验和交叉验证、要拿着结果去跟业务方对齐——用插件。目标数量上千、要做周期性全量测绘、需要留存历史快照做变更对比——上专业测绘平台加自建调度。两者不冲突,插件更像是"随身工具",而不是"作战平台"。

注意:所有资产梳理动作都必须建立在明确授权的基础上。对自己负责的资产、或已获得书面授权范围内部署的资产做梳理,是正常的运维和安全运营工作;对范围外的目标做扫描,无论用什么工具都不合适,这一点没有讨论空间。

2. 核心能力拆解:一个资产梳理插件应该具备什么

2.1 域名与子域名的发现链路

资产梳理的骨架是域名。一个组织在公网上的"面积",很大程度上由它拥有的域名和子域数量决定。所以评价这类插件,第一个要看的就是它的子域发现链路是否完整。

完整的链路通常包含几个来源。被动来源优先,因为它不打草惊蛇也不产生额外请求:证书透明度日志里记录了每一张签发过的证书及其包含的域名,这是目前性价比最高的子域来源之一;公开的被动 DNS 数据集能反映历史解析记录;搜索引擎和公开网页里散落的链接、JS 文件里硬编码的接口地址,也常常能捞出内部域名。主动来源则是基于字典的枚举,用常见前缀去拼接主域做解析探测。

我特别看重的一点是证书关联能力。一张多域名证书的 SAN 字段里往往塞着同一批业务的好几个域名,你从一个入口拿到证书,就能顺着拖出一串相关资产。这是"从一个点撬开一片"最经典的路径,插件如果能在你访问页面时自动解析当前站点的证书并列出 SAN 里的其他域名,这一条就值回票价了。

另一条容易被忽略的链路是页面资源的域名提取。你打开一个业务系统,页面里往往加载了静态资源域、接口域、埋点域,这些域名和主站同属一个组织,但前缀完全不同,靠字典是猜不出来的。插件能直接读当前页面的资源清单,把这些域名抽出来,这是人工做起来最费劲的一步。

2.2 指纹、证书与IP归属的关联分析

光有域名列表没用,你得知道每个域名背后"是什么"。这就是指纹识别要解决的问题。

指纹的本质是特征匹配。一个 Web 应用在响应头、Cookie 名、特定路径的返回内容、页面 title、favicon 的哈希值上,都会留下相对稳定的特征。favicon 哈希是我个人最推荐的手段,原因是成本极低、误报率也低——同一套系统部署在不同域名下,favicon 往往是同一张图,哈希一比对就能归堆。响应头里的 Server、X-Powered-By 这类字段信息量也很大,虽然经常被改,但改不干净的情况更多。

IP 归属的关联则是另一条线。域名解析出来的 IP,如果能判断出所属网段和归属特征,就能反推出一批同网段资产。云环境里这个特征尤其明显,同一批业务往往部署在同一片地址段内。反解域名也是个好线索,很多云主机的反解记录里带着业务标识。这里要注意的是,同 IP 不等于同归属,共享托管环境下几百个站挤在一个 IP 上是常态,不能简单按 IP 归堆,必须结合证书、favicon、页面特征综合判断。

提示:指纹识别一定会有误判。同一套 CMS 建的站、同一家外包做的系统,特征会高度相似。判断归属时至少要有两个独立维度互相印证,单靠一个 title 相同就下结论,后面核对阶段会返工。

2.3 资产去重与归属判定

这一节讲的是整个流程里最枯燥但最影响结果质量的部分:去重和归属。

去重的难点在于"同一个资产有多种表示形式"。https://a.example.com、http://a.example.com:80、a.example.com、解析到同一个 IP 的另一个别名域名,在原始结果里是四条记录,但业务上是一台机器。常见的归一化规则是:统一协议和端口表示、去掉默认端口、URL 去掉查询参数和路径、域名统一小写并去掉末尾的点。做完这层归一化,重复率通常能降下来一大截。

更麻烦的是归属判定。一个域名解析在某个 IP 上,不代表这个 IP 属于你;一个页面长得像你们的系统,也不代表它就是你们的资产。我一般用三级判定:一级是直接证据,比如域名的主域在授权清单内、证书主体信息匹配;二级是间接证据,比如页面出现组织名称、备案主体匹配、favicon 与已知资产一致;三级是人工确认,前两级都模棱两可的,一律标记为"待确认",交给业务方核实,绝不能凭感觉划进范围。

这个"待确认"状态非常关键。我见过太多团队在做梳理时,把疑似资产直接算进范围,结果评估报告里出现了根本不属于自己的系统,既浪费了人力,也带来了不必要的麻烦。宁可少划十个,不能错划一个,这是我在实际项目里坚持的原则。

3. 实操流程:从零跑通一次完整的资产梳理

3.1 准备阶段:授权、范围与时间窗口

正式动手之前,有三件事必须先落地,不然后面全是白干。

授权文件。明确写清楚梳理的域名范围、IP 范围、时间窗口、允许的动作类型(只做被动信息收集,还是允许主动探测)、紧急联系人。这不是走形式,是出现问题时唯一的依据。

范围清单。把已知的主域、已知 IP 段、已知的业务系统清单列出来,作为种子。这份清单不需要完整,它只是起点。我通常会把清单分成"确定在范围内"和"疑似在范围内"两栏,后者在前面的归属判定环节会用到。

时间窗口和速率约定。梳理动作会产生大量请求,对业务系统是有压力的。如果目标是生产环境,尽量安排在业务低峰期,并且明确速率上限。我的经验值是单个目标每秒不超过 5 个请求,对核心业务系统还要再降。这个约定要提前跟运维和业务方对齐,不要自己拍脑袋。

准备阶段还要做一件事:确定台账字段。很多人上来就开扫,扫完发现结果导出后字段乱七八糟,没法入库也没法交付。字段设计应该在动手前定好,后面所有动作都围绕字段来。我常用的最小字段集如下:

字段名说明是否必填
资产名称业务方认可的名称,便于沟通是
域名归一化后的完整域名是
解析 IP当前解析结果,多个用分号分隔是
端口/协议如 443/https是
技术指纹识别出的组件与版本线索否
归属部门业务或运维确认的责任方是
状态在用 / 闲置 / 待确认 / 已下线是
首次发现时间用于判断资产新旧是
最后存活时间用于判断是否已下线是
备注记录判定依据和疑点否

3.2 第一步:种子域名的组织维度扩展

拿到种子之后,第一步不是急着枚举子域,而是先把"组织维度"的信息补齐。

具体做法是:以已知主域为起点,通过公开的证书信息、页面上的组织标识、已知系统的页面底部信息,找到这个组织的其他主域。很多组织不止一个主域,尤其是历史较久的,可能有三四个不同后缀的域名同时在用。这一步漏了,后面枚举做得再细也是白费。

插件形态在这里的优势是"顺手"。你打开一个业务系统,插件读取当前证书和页面资源,把关联的域名一次性列出来,你只需要判断哪些是新的、哪些已经在清单里。这个过程不需要额外工具,也不需要切换上下文。

这一阶段还要做一件容易被跳过的事:记录来源。每一条新增的种子域名,都记下它是从哪个入口发现的。后面出现争议时,来源信息就是判定依据。我吃过这个亏——一批域名进了清单,两个月后没人记得它们是怎么来的,最后只能全部标成"待确认",前面的工夫白搭。

3.3 第二步:子域名枚举与存活探测

有了种子,就可以做子域枚举了。我的建议是被动优先、主动补充、递归有限。

被动方式先跑一遍:证书透明度日志、公开被动 DNS 数据集、页面资源提取、搜索引擎结果。这一步几乎不产生直接请求,风险最低,产出通常能占到总量的六七成。主动字典枚举放在后面,作为补充,用来覆盖那些从没签发过证书、也没被公开记录过的内部子域。

字典的选择直接影响产出效率。中文环境下高频前缀有明显的行业特征,我把常用的整理成几类:

类别常见前缀说明
业务门户portal、sso、oa、mail、home命中率高,优先
环境标识dev、test、uat、stage、pre、beta测试环境常暴露问题
管理入口admin、manage、console、dashboard价值高但风险也高
接口与文档api、open、gateway、doc、swagger常用于排查暴露面
静态与资源static、cdn、img、file、upload辅助判断资产归属
历史遗留old、bak、temp、v1、v2常常是无人认领的资产

递归深度我建议控制在两到三层。比如api.dev.example.com这种,从example.com枚举到dev.example.com是第一层,再往下枚举dev下的子域是第二层。三层以上产出增长很快但有效率急剧下降,而且请求量会成倍放大。实测下来,两层的性价比最高。

存活探测这一步,插件的做法通常是发一个请求看响应。判断存活的依据不能只看状态码,200 是活,301/302 也是活,401/403 同样是活(只是需要认证),甚至 500 也可能是个真实存在的有问题的系统。真正要排除的是 DNS 解析失败、连接超时、以及泛解析产生的假结果——这个坑后面单独讲。

3.4 第三步:端口与指纹识别

存活确认之后,进入信息提取阶段。这一步的目标是把"这是一个域名"变成"这是一个什么系统"。

端口探测的范围要克制。全端口扫描在插件形态下既不现实也不合适,通常是拿一份常见端口清单(Web 类的 80/443/8080/8443,数据库类的 3306/6379/27017,远程管理类的 22/3389),再结合页面特征做针对性补充。这里有个重要认知:端口开放不等于服务可用,很多云环境安全组配置了只放行特定来源,你从外部探测看到的"关闭"不代表内部不可达,反过来"开放"也不代表服务真的在跑,可能只是一个负载均衡在前面挡着。

指纹识别在插件里通常是自动完成的:读取响应头、Cookie 名、页面 title、favicon 哈希,跟内置的特征库做匹配。我要提醒的是版本号的处理。有些系统会在响应头或页面里暴露精确版本号,这些信息对资产梳理的价值是"判断资产新旧、是否需要重点关注",但它同时是敏感信息,台账里记录时要控制范围,只在内部流转,不要出现在任何对外交付物里。

指纹结果的用法是聚类。把 favicon 哈希相同、响应头特征一致的资产归成一组,组内选一个代表做深入核验,比一个个看效率高得多。我在一个项目里用这个方法,把两千多条原始记录压缩成了不到一百个技术栈分组,后续核对的工作量直接降了一个数量级。

3.5 第四步:资产归集、台账落地与复核

扫描做完,真正的工作才开始。原始结果是一堆无序的记录,必须经过归集才能变成可用的台账。

归集的动作按顺序是:归一化 → 去重 → 分组 → 标注 → 复核。归一化和去重前面讲过,这里说分组和标注。

分组有两条主线。一条是技术分组,按指纹、favicon、响应特征聚类,目的是找出同一批部署的资产。另一条是业务分组,按域名前缀、页面内容、归属线索分组,目的是把资产挂到业务方名下。两条线交叉,才能形成"这个业务用了这套技术栈、部署在这批 IP 上"的完整图景。

标注阶段要敢于写"待确认"。我一般把结果分成三类:明确归属的(有直接证据)、疑似归属的(有间接证据)、无法判断的。第三类不要硬塞,原样交给业务方,让他们认领。实践中经常出现的情况是,业务方一看就说"这个我们早就不用了",这种信息比你自己猜一百次都准。

复核环节我建议做抽样回访。从每个分组里随机抽几个,手工再核验一遍,确认工具的判定逻辑没有系统性偏差。抽样比例不用高,百分之五到十就够,但一定要做。我遇到过指纹库把某类通用框架全部误判的情况,因为当时没抽样,最后整份台账的技术栈字段都是错的,返工量极大。

4. 实操心得与参数细节:让结果可用而不是好看

4.1 字典与递归深度:怎么配才不浪费请求

字典这件事,我的观点是小字典精跑,好过大字典乱跑。一个两万行的通用字典,跑完可能产生几万次请求,产出几百个有效结果,有效率不到百分之一,而且很容易触发目标侧的限制。用一份两三千行、经过业务特征筛选的字典,有效率能提到百分之五以上,整体效率反而更高。

字典要按目标定制。做法是先从被动来源拿到一批已知子域,分析它们的前缀规律——比如这个组织特别喜欢用xxx-prod、xxx-test这种命名,那字典里就把-prod、-test这种后缀组合加进去。这种"从已知推未知"的方式,产出质量远高于盲目堆字典。

递归深度控制在两层,前面说过。这里补充一个细节:递归要有边界条件。比如某一层枚举出的结果全部解析到同一个泛解析 IP,那就应该立即停止这一层的递归,因为再往下都是无效产出。插件如果能自动识别这种情况并提示,会省掉很多时间。

还有一个经验:把高价值前缀单独跑一轮。管理入口、接口文档、测试环境这几类,命中率不高但价值极高,值得单独用一份小字典跑,跑完单独人工看。混在大批量结果里,很容易被淹没。

4.2 并发、超时与误报控制

插件形态下,并发不能开太大。我的经验配置是:并发 20 到 50,单请求超时 3 到 5 秒,DNS 解析超时单独放到 5 到 8 秒。DNS 超时要比 HTTP 长,因为很多解析失败其实是解析慢,超时设短了会产生大量假阴性。

误报控制的核心是泛解析检测。做法很简单:随机生成几个不可能存在的前缀,去解析主域,如果这些随机前缀都能解析成功,说明这个域配置了泛解析,那么所有枚举结果都要打上问号,必须靠响应内容进一步区分(比如响应体长度是否一致、返回页面是否完全相同)。这一步不做,结果里可能有八成都是假的。

另一个误报来源是默认页。很多服务器对任意子域都返回同一个默认页面,状态码 200、内容一模一样。处理方式是对比响应体指纹,如果一批结果的响应体完全一致,就归为默认页,单独标注。

还有一个细节是重定向链。一个子域解析成功、返回 301 跳到主站,这算不算有效资产?我的判断是算,但要标注"重定向至主站",因为它在 DNS 层面是独立存在的,可能是遗留配置,也可能是业务入口。区别对待,不要一律剔除。

提示:所有速率和并发参数都不是固定的,要根据目标系统的承载能力和授权约定动态调整。对核心生产系统,宁可慢十倍,不要出问题。

4.3 结果导出与台账字段设计

导出这一步,很多人不当回事,结果交付时被业务方退回重做。我的经验是导出前先想清楚谁来用这份表。

给安全团队用的,字段要偏技术:IP、端口、指纹、暴露面判断。给运维用的,字段要偏管理:归属部门、责任人、状态、变更记录。给管理层看的,只需要汇总数字和趋势。同一份原始数据,导出三个视图,比导出一份大而全的表更实用。

字段设计上有几个具体的坑。一是多值字段的分隔符要统一,多个 IP 用分号还是逗号,必须全表一致,否则后续做数据透视会出错。二是时间格式统一成同一时区同一格式,不要一半是"2024/1/5"一半是"2024-01-05 10:30"。三是状态字段要有明确的取值枚举,不能自由填写,否则会出现"在用""使用中""正常"三种写法表达一个意思的情况。

还有一点:保留原始结果。归一化、去重之后的数据是用来交付的,但原始数据一定要留档。后面出现争议、需要追溯某条记录是怎么来的,只有原始数据能回答。我一般会把原始结果和加工结果分两个文件存,文件名里带日期,方便做历史对比。

5. 常见问题与排查速查表

5.1 高频问题实录

做了这么多轮梳理,问题其实高度集中。我把最常见的整理成一张速查表,遇到问题先对一遍,能省掉大半排查时间。

现象最可能的原因排查与处理
枚举出几千条结果,绝大多数打不开域名配置了泛解析用随机前缀测试,确认后改为按响应内容区分
大量结果返回同一个页面服务器默认页比对响应体哈希,相同的归为默认页单独标注
同一个资产在表里出现多次未做归一化去重统一协议端口、去默认端口、去 URL 参数后重新去重
指纹识别结果明显不对特征库匹配过于宽松抽样人工核验,收紧匹配规则,要求多特征同时命中
扫描中途大量超时并发过高触发限速降并发到 20 以下,加长超时,分批执行
插件结果与命令行工具不一致判定口径不同统一存活判定标准,明确哪些状态码算存活
部分子域能解析但访问无响应服务已下线但 DNS 未清理标注为"疑似下线",交业务方确认后清理
证书里出现完全无关的域名共享托管或 CDN 共用证书不能直接纳入范围,需结合其他证据判断
导出表格打不开或乱码编码与分隔符问题统一用 UTF-8 带 BOM 导出 CSV
结果无法挂到具体业务方缺少归属线索补充页面内容、备案信息等间接证据,标记待确认

5.2 避坑清单与合规红线

除了技术问题,还有几条是流程和合规层面的,我觉得比技术问题更重要。

第一条,范围要写死在纸面上。"我以为这个域名是我们的"这种事,在任何一次梳理里都不应该出现。范围清单要由业务方或资产归属方书面确认,梳理过程中发现的新资产,先标记、后确认、再纳入。

第二条,速率要克制。梳理不是压测,大量请求打在生产系统上,轻则影响体验,重则造成故障。我见过因为扫描频率过高把一台老旧设备打挂的情况,后续处理非常麻烦。低峰期、低速率、分批跑,这是基本纪律。

第三条,敏感信息要控制流转。梳理结果里必然包含一些不该广泛传播的信息,比如内部系统的地址、组件的版本、管理入口的位置。这些内容只在必要范围内流转,交付物要做脱敏,台账要控制访问权限。

第四条,结果要有人认领。一份没人认领的资产台账,三个月后就会变成历史文件。每一轮梳理结束,都要推动归属确认和责任人登记,否则下一轮还得从头再来。

第五条,别把工具当答案。插件能帮你把信息收集的效率提高几倍,但归属判断、风险定级、后续处置,这些都得靠人。工具产出的是线索,不是结论。

最后分享一个我自己一直在用的小习惯:每完成一轮梳理,我会额外花半小时写一份"变更说明",记录这一轮相比上一轮新增了什么、下线了什么、哪些归属发生了变化。这份说明的篇幅通常不超过一页,但它是整个台账真正产生价值的地方——资产管理的核心不是"知道现在有什么",而是"知道什么在变"。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进