ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

ccTLD 注册局被劫持拆解:CA 全程合规,谷歌的 HTTPS 证书为什么还是被人签走了

2026/10/7 19:08:09 拓冰建站 浏览量
ccTLD 注册局被劫持拆解:CA 全程合规,谷歌的 HTTPS 证书为什么还是被人签走了 三个后缀失守谷歌的证书被别人签走了上周有攻击者拿下三个国家级顶级域名注册局然后用它们签出了谷歌的 HTTPS 证书。出事的后缀是 .gh、.sl 和 .as分别属于加纳、塞拉利昂和美属萨摩亚。谷歌在 10 月 6 日的安全博客里确认这轮事件里失守的是第三方注册局。同一篇博客里谷歌还补了一句签发这批证书的 CA 没有做错任何事。这句话才是整件事最值得细读的地方。证书颁发机构的流程全部合规域名控制验证也全部通过签出来的证书却给了攻击者。攻击者修改了这些命名空间下若干域名的权威 DNS 记录。改完记录他们顺理成章地通过了域名控制验证。拿到验证结果他们就去申请覆盖谷歌多个域名的未授权证书。除了谷歌还有若干头部品牌和常用在线服务被同一批攻击波及。这些受害者不是谷歌自己数出来的是证书透明度日志先暴露的。谷歌随后不等对方确认先把这些证书在 Chrome 里全部拦截再逐个去通知。Chrome 用户不需要做任何操作但其他浏览器和客户端的用户未必被覆盖。官方给的补救建议里最容易被忽略的一条是监控证书透明度日志。第二条是发布限制性的 CAA 记录并且绑定到具体的 ACME 账户和验证方式。攻击链从注册局到 DNS 记录再到一纸证书把这条链拆开看每一步都在用前一步的合法产物换下一步的信任。第一步是注册局失守攻击者拿到的是国家顶级域名的管理面。国家顶级域名通常由当地机构运营体量和预算都远不如通用顶级域名。它们的运营方往往没有谷歌那种持续对抗的团队。第二步是改权威 DNS 记录和名字服务器委派。这些记录一旦可写攻击者就能把选定域名的 IP 指向自己控制的机器。第三步是域名控制验证也就是各家 CA 用来确认申请者拥有该域名的流程。这个流程的常见形态是让申请者在域名下放一个特殊文件或 TXT 记录。攻击者既然已经能改 DNS自然也就能放上这个文件。验证通过的那一刻从 CA 的视角看申请者就是域名所有者。第四步是签发一张合法外观、正常签名、浏览器默认信任的证书就此诞生。整条链里没有任何一个环节被攻破每个环节都在按设计工作。问题出在整套设计假设了域名控制权等于身份。域名控制权一旦被劫持这套假设立刻失效而链上的 CA 无从判断。谷歌说他们没有理由认为 CA 做错了这话在技术上站得住。但它同时说明靠 CA 单点把关这条路本身就是有边界的。攻击者不需要攻破任何一家大厂只需要找到链条上最弱的一环。这轮事件里最弱的一环是三个预算有限的国家域名注册局。选择标准也很清楚流量不大、机构小、但下面挂着大厂的镜像或区域域名。这也是为什么受害者名单里会出现头部品牌。浏览器拉黑很快吊销很慢证书出问题之后行业有两条处置路径速度差了一个数量级。第一条是正式吊销走 CA 的撤销流程最终体现在 CRL 和 OCSP 里。第二条是浏览器厂商直接把自己认定的问题证书拉黑。Chrome 用的是 CRLSets可以理解为一份随浏览器更新下发的黑名单。谷歌这次一边把识别出的未授权证书塞进黑名单一边去推动 CA 正式吊销。Ars Technica 的报道里点得很直白正式吊销的过程又慢又繁琐。所以浏览器厂商才会自己发明更快的阻断办法。这就带来一个不对称的结果不同客户端的防护水平并不一致。Chrome 用户当天就安全了用其他浏览器或非浏览器客户端的人未必。谷歌自己也在博客里承认不能指望浏览器侧的干预来保护用户。原因有两个第一个是分析未必覆盖全部受害域名。第二个是 Chrome 的处理对非 Chrome 用户完全不生效。还有一个更麻烦的尾巴没有被发现的证书依然是威胁。已确认的那部分被拦住风险被削掉一大截但不确定的部分仍在。所以这轮事件的真实受损范围到今天也是模糊的。有多少未授权证书被签出来除了谷歌之外还有谁中招官方都没有说。对外公布的口径克制对运维人员来说却意味着必须自己动手查。CAA 挡不住进行中的劫持它挡的是劫持之后CAA 是 DNS 里的一类记录作用是声明哪些 CA 有权为这个域名签发证书。很多人的第一反应是既然有 CAA为什么没挡住这次攻击。谷歌在博客里直接给了答案CAA 无法阻止正在进行的 DNS 劫持。道理不复杂攻击者能改 DNS就能顺手把 CAA 记录也改掉或删掉。在劫持发生的窗口里CAA 记录的约束力等于零。但劫持总有结束的时候控制权恢复之后 CAA 才开始发挥作用。这里的关键是 CA 被允许缓存并复用已经完成的域名控制验证结果。也就是说验证做一次可以支撑后续多次签发。攻击者在劫持期间完成的验证很可能在劫持结束后还能继续用。如果恢复控制权的同时把 CAA 收紧这条复用路径就被掐断了。具体做法是限制到指定的 CA进一步绑定到具体的 ACME 账户。RFC 8659 定义了 CAA 记录本身RFC 8657 定义了账户绑定。绑定账户之后即使某个 CA 被允许签发也只能由指定账户发起。谷歌还提到CAA 能完全挡住一部分基于路由和 HTTP 的攻击。这类攻击不需要碰 DNS自然也就不会顺手清掉 CAA。把 CAA 理解成一道只在特定时刻生效的闸门比理解成常开的安全网更准确。它不负责阻止入侵它负责让入侵结束后无法继续搭便车。证书透明度日志才是能提前看到签发的面CT 日志是这轮事件里真正发挥检测作用的设施。它的规则很简单凡是被 Chrome 默认信任的证书都必须公开披露。披露的动作是把证书提交到公开的、只可追加的日志里。只可追加意味着攻击者事后无法删掉自己留下的痕迹。域名所有者只要盯着日志就能在证书签发后近乎实时地收到警报。这次谷歌识别出更多受害组织靠的正是 CT 日志数据。这里有一条容易踩空的地方监控范围必须覆盖全部域名组合。包括那些闲置不用的域名以及挂在区域后缀下的资产。本轮出事的三个后缀都是国家顶级域名很多公司压根没把它们纳入资产清单。谷歌的建议很具体如果你有 .gh、.sl 或 .as 下的域名现在就去翻最近的日志记录。监控 CT 的成本很低一个定时任务加一份域名清单就能跑起来。它的价值在于把发现时间从新闻曝光提前到签发当天。对安全团队来说签发当天的告警意味着还能抢在钓鱼活动之前处置。新闻曝光之后的告警剩下的动作只有复盘。这轮事件里谷歌是被动发现后主动通知普通公司没有这个待遇。能自己看到签发的组织不需要等别人来通知。一段可以跑起来的 CAA 自查脚本说了这么多建议落到操作层面其实可以先做一件小事。下面这段脚本只用 Python 标准库通过 DNS over HTTPS 查任意域名的 CAA 记录。它会打印出每个域名当前授权的 CA以及不在白名单里的条目。把域名清单换成你自己的资产扔进定时任务就能当巡检用。import json import urllib.request ALLOWED {letsencrypt.org, digicert.com, pki.goog} def caa_records(domain: str) - list: url fhttps://cloudflare-dns.com/dns-query?name{domain}typeCAA req urllib.request.Request(url, headers{accept: application/dns-json}) with urllib.request.urlopen(req, timeout8) as resp: return json.load(resp).get(Answer, []) def authorized_issuers(domain: str) - set: issuers set() for record in caa_records(domain): if record.get(type) ! 5: continue value record.get(data, ) # data 形如0 issue letsencrypt.org if issue in value and in value: issuers.add(value.split()[1].strip()) return issuers if __name__ __main__: for domain in (google.com, example.com): issuers authorized_issuers(domain) if not issuers: print(f{domain}: 没有 CAA 记录任何 CA 都可以为它签发) continue rogue issuers - ALLOWED print(f{domain}: 已授权 {sorted(issuers)}白名单外 {sorted(rogue) or 无})这段代码只做只读查询不修改任何 DNS 配置。它的输出可以直接回答一个问题我的域名到底允许谁来签证书。如果输出是空的说明当前处于谁都能签的状态。如果输出里有不认识的 CA那才是真正需要立刻处理的信号。CAA 查询本身也要走 DNSSEC 校验才有意义否则劫持者可以连答案一起篡改。把 DNSSEC 和 CAA 一起上的时候这条链的强度才接近设计预期。三层防御各自能挡住什么把这次事件涉及的机制摆在一起能力边界立刻清楚了。关键的分界线是它发生在劫持进行中还是劫持结束之后。机制劫持进行中劫持结束后性质权威 DNS 控制权失守即全失守恢复后仍可被复用根因CAA 记录拦不住能掐断 DCV 复用事后闸门CT 日志监控能看见签发能追溯全部签发检测CRLSet 浏览器拉黑可快速阻断仍生效阻断CRL / OCSP 吊销滞后最终收敛阻断DNSSEC取决于签名链恢复后可验证完整性表里最扎眼的一行是 CAA 在劫持进行中的空白。第二扎眼的是吊销的滞后它决定了有多少客户端在窗口期内毫无保护。CT 和 CRLSet 是这轮事件里真正起到作用的两层。前者让攻击被看见后者让攻击被阻断。值得注意的是这两层都不在 CA 的职责范围内。浏览器厂商和公开日志基础设施承担了实际的风险兜底。这也解释了谷歌那句提醒的分量不要指望浏览器侧干预来保护用户。浏览器会尽力但它不是设计上该承担这个责任的一层。对域名所有者来说能自己控制的那几行配置才是真正的责任田。十五年前的 DigiNotar这次结构上哪里不同伪造证书不是新鲜事最有名的一次是 2011 年的 DigiNotar。那家荷兰 CA 被攻破后攻击者签出了谷歌以及两百多个高流量域名的证书。这些证书被用来针对至少三十万名与伊朗有关联的人。那起事件最终以 CA 破产收场也直接催生了 CT 日志这套机制。把两次放在一起相同点是伪造目标都指向最难伪造的身份。不同点在失守的位置。DigiNotar 是 CA 自己被打穿属于信任根被污染。这次被打穿的是域名注册局属于身份来源被污染。前者靠清理 CA 生态解决后者需要重新审视域名控制权等于身份的假设。RSA 那次是私钥泄露思科与赛门铁克那几次是签发流程失控。这些年出事的位置一直在换唯一不变的是攻击者总挑最薄的一层。CT 能解决发现的问题但发现不等于阻止。浏览器拉黑能解决阻断的问题但它是事后补救。CAA 能解决复用的问题但它在窗口期内完全沉默。三层各管一段拼起来才勉强覆盖从签发的第一秒到吊销生效的全过程。这轮事件没有被任何一层单独挡住说明这套拼图仍然有缝。证书有效期要从 398 天压到 47 天行业对这类事件的长期回答是压缩证书本身的有效期和验证数据的复用期。CA/Browser Forum 的 SC-081v3 给出了明确的时间表。证书最大有效期要从三百九十八天降到四十七天。域名控制验证数据的复用期要从三百九十八天压到十天。域名之外的其它验证数据复用期从八百二十五天降到三百九十八天。整个过渡从二零二六年三月开始到二零二九年三月结束。这张选票由 Apple 提出Sectigo 与谷歌 Chrome 附议Mozilla 参与联署。投票结果是二十五家签发方赞成、零反对四家浏览器厂商全票赞成。逻辑很朴素证书描述的是签发那一刻的现实。时间越久证书里的信息偏离现实的可能性越大。把有效期压短等于把这个偏离窗口一起压短。复用期压到十天则让攻击者在劫持结束后能搭的便车变得极其有限。再加上缩短有效期会逼着全行业把自动化签发真正跑起来。这件事的另一面是运维成本手动换证书的组织会最先感到压力。谷歌还在推进 Chrome 根计划以及一个面向抗量子的新根计划。前者管的是能不能信任后者管的是未来算法被攻破时能不能快速切换。这些动作都不解决注册局失守但它们让单次失守的伤害窗口变短。压缩窗口是被动防御里性价比最高的一种。域名所有者现在该做的四件事把官方建议按优先级排一下最先做的是资产盘点。把你名下所有域名列出来重点是闲置域名和挂在冷门区域后缀下的那些。第二步是打开证书透明度日志的监控覆盖全部域名组合。第三步是发布限制性的 CAA 记录并绑定到指定 ACME 账户与验证方式。第四步是确认 DNSSEC 状态没有签名保护的 CAA 记录说服力有限。顺序不能颠倒不知道有什么资产就谈不上监控也谈不上配置。四件事都不需要采购新的安全产品全部是配置与巡检工作。它们的共同点是发生在本轮事件之前做成本几乎为零。发生在新闻曝光之后做就变成了一次被动整改。这轮事件最值得记住的一句是谷歌承认无法保证覆盖所有受害域名。这句话的另一层含义是任何一家公司都可能已经中招而不自知。查一遍自己域名的 CT 记录和 CAA 配置是当前最低成本的一次确认。