摘要

  • 未受保护的 SRV 查询可能把客户端引向一台确实拥有自身合法凭据的错误服务器。主机认证可以完全成功,却没有回答它是否有权代表目标域提供该服务。
  • RFC 5178 用 service [AT] domain [AT] hostname 保存缺失的授权范围;这里的 [AT] 表示 RFC 语法中的 ASCII 半角 at 符号。签发这一三元名称的接受方凭据,本身就是一项可执行的委托决定。

一次错误连接不一定需要伪造所有环节。

发现结果可以是假的,后续认证却可以是真的。攻击者让一条未受保护的 DNS SRV 记录指向自己控制的服务器;该服务器不冒充原来的主机,只用自己的真实凭据完成认证。如果客户端根据发现结果临时构造 service [AT] hostname,那么认证成功只能证明:它确实到达了那条错误记录所写的主机。

用户原本要访问的却不是“一台能认证的机器”,而是某个组织的目录、文件根或其他域级服务。

RFC 5178 的关键不是让 DNS 变得可信,而是让客户端在离开 DNS 之后仍然记得自己要验证什么。

三层名称保留三种责任

GSS_C_NT_DOMAINBASED_SERVICE 的查询与显示形式包含三个必填项:服务、被服务的域、具体主机。IANA 在 GSS-API 名称类型弧下为它登记值 5。形式写成:

service [AT] domain [AT] hostname

服务字段说明功能。域字段说明该功能所代表的行政或资源范围。主机字段说明这次会话连接到哪个接受方。域和主机通常都是 DNS 名称,但它们并非重复数据;一个说明“代表谁”,另一个说明“由谁执行”。

发现系统只负责提出候选。域服务凭据负责证明候选被授权。应用随后还要决定这个已认证身份可以执行什么操作。最后,真实数据与用户结果才说明服务是否完成。

把四层压成“连接成功”,就会让最关键的授权范围消失。

RFC 5178 明确把域服务凭据的存在视为授权的体现。因此,签发 nfs [AT] example.net [AT] nfs2.example.net 不是给一台机器补一个易读别名。它是在允许该机器以 example.net 的 NFS 服务身份说话。谁能签发、复制、更新和撤销这张凭据,谁就参与了服务控制面。

认证成功仍然是有边界的事实

客户端若按预期构造三元名称,并与能证明相应凭据的服务器建立 GSS 安全上下文,它获得了一项强证据:在当前机制下,对方控制了与服务、域和主机范围相符的凭据。

这项证据并不自动证明 SRV 回答真实,也不证明凭据今天仍应有效。它没有说明用户是否被允许读取目录、文件根是否正确、租户边界是否执行,或一次业务操作是否完成。误签、过度签发、未撤销或被窃取的凭据,都可以让协议认证成功而管理意图失败。

因此需要同时留存:最初目标域、查询与 DNSSEC 状态、所有候选、选择算法、最终主机、GSS 名称类型、输入字符串、机制规范名称、realm 推导、凭据签发者与有效期、上下文结果、应用授权结果和独立服务探测。

“Kerberos 成功”是其中一行,不是整份收据。

兼容回退也会改变问题

RFC 5178 没有假设新名称类型能一次部署完成。有些 GSS 机制不能协商它,有些服务端不支持它。既有 LDAP 客户端可能长期使用基于主机的名称,而服务器也没有域服务凭据。客户端单方面切换会造成互操作失败。

规范允许回退,但附带重要条件:如果改用主机名称,发起方仍必须另行确认该主机有权为原本目标域提供该服务。完全不支持域服务名称的客户端也承担同样责任。

这意味着自动重试不能只记录“第二次连上了”。它必须指出哪一份独立授权清单把该主机与服务域联系起来、清单由谁维护、何时失效。如果所谓授权仍来自同一条未受保护的发现回答,验证就形成循环。

一个兼容开关可以恢复流量,同时删掉安全属性。正确的状态模型应至少区分:三元名称成功;三元名称不可用但存在等价主机授权;三元名称不可用且客户端只接受发现目标。第三种不是普通降级,而是授权问题被换掉。

Unicode 显示不是规范身份

RFC 5178 还把国际化名称带进了 GSS 接口。传统 GSS_Import_name() 必须接受域与主机的 ACE 编码。建议的 UTF-8 导入函数必须接受 UTF-8 和 ACE。传统显示只能输出 ASCII 或 ACE;UTF-8 显示函数必须输出 UTF-8,且不得输出 ACE。

这些规则处理表示,并不授予等价性。

GSS-API 本来就区分内部名称、可显示字符串、机制名称和导出名称。RFC 2743 指出,把字符串导入后再显示,不保证得到原字符串,也不保证返回原名称类型。授权比较应依赖 GSS_Compare_name()、机制规范化或规定的导出形式,而不是比较两段日志文字。

历史边界也必须保留。RFC 5178 采用当时的 RFC 3490/IDNA2003 模型;后来 IDNA2008 以 A-label 与 U-label 等概念取代它。新实现需要说明实际使用哪个处理规范,但不能假装后来规则改写了旧 RFC。运维记录应同时保存人看到的 Unicode 形式、线上的 ACE 形式、输入类型与最终机制名称。

否则,人可能批准了一个显示字符串,系统却认证了另一个规范结果,而审计只剩其中一面。

Kerberos 映射没有把三层压平

RFC 5179 说明 Kerberos V 如何承接域服务名称:服务成为 principal 的第一组件,主机是第二组件,域是第三组件;建议使用值为 12 的 NT-SRV-HST-DOMAIN,也允许 NT-UNKNOWN。

realm 仍是独立推导。安全考虑特别要求从 hostname 推导 realm,而不是直接相信输入名称里的 domain 字段。域说明服务范围,不能同时自我任命验证它的认证领域。

所以“字符串能解析”不是上线验收。应检查库最终生成哪个 principal、询问哪个 realm、哪张凭据响应,以及应用是否按预期服务域授权该身份。

RFC 5179 在 Kerberos 国际化尚未完成时要求主机与域使用 ACE,这进一步说明表示兼容和授权语义必须分开记录。

NFS 案例显示每层的职责

RFC 6641 后来把这一结构用于 NFSv4 全局命名空间。客户端用 DNS SRV 找到组织文件根的候选服务器;可用时仍应使用 DNSSEC。域服务名称作为额外控制,让客户端验证被选主机确实持有 nfs [AT] 组织域 [AT] 具体主机 的授权凭据。

SRV 发布一份候选集合。凭据系统发布一份授权集合。两份集合应当核对,却不应合并。

某主机已从 SRV 移除但凭据仍有效,说明它不再被正常发现,却仍可能在缓存、静态配置或恶意回答下通过认证。某主机已进入 SRV 却没有对应凭据,说明发现面已经开放而授权面尚未准备。集合一致也只说明配置协调;NFS 挂载、返回内容与用户任务仍需后续证明。

这一设计的价值不在于制造一个新的中心权威。它用最小共享语法保存问题,把发现、凭据签发和应用决策分别留给真正承担责任的参与者。清楚的分层会让责任更难模糊:错误主机若拥有正确三元凭据,问题就在授权签发或撤销;回退若只接受主机身份,问题就在谁批准了范围缩水。

一台机器是谁,与它能代表谁,始终是两个事实。

来源