Go 首次走紧急通道发安全版本:eMudhra 中间证书私钥泄露,Linux 上的 Go 程序必须重新编译
原文信息:本文译自 Go 官方博客文章《Our Response To The eMudhra Key Disclosure Incident》,作者 Roland Shoemaker(代表 Go 安全团队),发布于 2026 年 10 月 26 日。原文链接:https://go.dev/blog/emudhra-incident 。原文采用 CC BY 4.0 许可,代码采用 BSD 许可。本文为翻译,文末附译者注。
译者导语:10 月 19 日,Go 团队第一次启用"紧急通道"(URGENT track)发布安全版本 Go 1.27.3 和 1.26.10,从接到通知到补丁全球可用不到七个半小时。起因是 eMudhra 旗下 8 张中间证书的私钥弱到"几微秒就能算出来"。如果你的 Go 服务跑在 Linux 上、通过 HTTPS 或 gRPC 调用外部接口,这件事和你直接相关:只更新系统证书包不够,必须用新版本重新编译二进制。下面是 Go 团队的完整复盘。
10 月 19 日,Go 团队启动了一次加急安全发布,让 Go 用户及其应用免受一次严重的公钥基础设施(PKI)失陷事件影响,事件涉及 eMudhra 签发的证书。
接到通知后大约七个半小时,我们就发出了针对性补丁,它被包含在 Go 有史以来第一个"紧急通道"(URGENT track)安全版本中。
下面介绍事件背景、Go 为什么要在运行时层面出手保护用户,以及我们的应急响应过程。
eMudhra 事件
10 月 17 日,Mozilla 把由 eMudhra 控制的一张根证书签发的 8 张中间证书(6 张用于 TLS,2 张用于代码签名)加入了 OneCRL,相当于在 Firefox 中封禁了它们。随后,不少安全研究人员注意到这一变化,开始追查原因。
10 月 19 日,Go 安全团队得知了这些调查及其结论:这些中间证书对应的密钥弱到不堪一击,几微秒内就能恢复出私钥。
eMudhra 的根证书被大多数受信任根证书计划收录,因此一旦私钥被恢复,任何攻击者都可以为任意域名签发 TLS 证书,而无需像平常那样证明自己控制该域名。攻击者由此可以对 TLS 连接发起中间人(MITM)攻击,为自己并不控制的域名出示一张"合法"证书,等于能冒充目标机器尝试连接的任何 TLS 服务器。
Go 在标准库中自带 TLS 证书验证器。用户通过 net/http 或 crypto/tls 连接 TLS 服务时,验证器会检查对端出示的证书是否有效。在 Windows 和 macOS 上,我们把这些检查交给平台 API;而 Linux 没有对应的平台 API,所以使用我们自己的验证器实现。
Linux 没有统一的内置吊销检查机制;另外,其他平台上也可能有用户收不到及时的系统更新。为了尽快给这些用户提供修复,我们认为保护 Go 用户的最好办法,是走紧急通道发布安全版本,同样撤销对这些证书的信任。
事件时间线
通常的 Go 安全发布要花好几天,并会提前预告,好让依赖 Go 的团队做准备。但这一次,我们判断私钥随时可能公开,于是第一次启用紧急通道,赶在大规模公开利用开始之前把防护发出去。
以下时间均为 10 月 19 日太平洋夏令时(PDT)。
11:45
一位独立的外部研究人员通知了我们的安全团队,指出 Mozilla 等机构在没有公开说明的情况下撤销了对 8 张 eMudhra 中间证书的信任。我们很快弄清楚,原因是这些证书使用的私钥太弱。
12:30
Mozilla 也独立向我们的安全团队报告了此事,确认了问题,请我们不要立即公开细节,同时鼓励我们尽快发布修复。
14:00
我们完成了补丁:凡是证书链经过这些失陷中间证书的,一律拒绝使用。最初报告问题的研究人员还提供了一组用恢复出的私钥签发的证书,供我们测试。
15:00
我们开始发布包含补丁的小版本 Go 1.27.3 和 1.26.10。考虑到问题的紧迫性和可利用程度,并且我们认为私钥很可能在几小时内就会公开,立即发布是最稳妥的选择。
19:13
我们完成发布并公开宣布。此时问题的根源还没有广为人知。为了让其他防守方有机会保护尽可能多的用户,同时不向攻击者透露利用方法,我们的补丁和公告措辞有意比较含糊,只提醒用户"由于这几张中间证书在运营方面存在特定安全隐患,我们撤销了对它们的信任",并敦促大家立即升级。
从最初接到通知算起不到七个半小时,打了补丁的 Go 版本就已在全球上线,用户在私钥公开之前就拿到了保护自己部署所需的一切。
到 10 月 20 日上午,已有多位独立研究人员公开披露了这些弱密钥。
经验教训与后续改进
这是我们第一次走紧急通道发布安全版本,发布过程中遇到了一些问题,耗时比预期更长。
能在接到通知的当天发出版本,我们感到欣慰;但在今天的安全形势下,我们认为应该能把时间压得更短。这次遇到的问题让发布流程从开始到结束花了将近四小时十五分钟。
这些问题以前并不突出,因为常规发布流程本来就分散在好几天里完成。
此后我们对流程做了多项改进,以提高发布效率,应该能显著缩短发布所需时间,增强我们应对紧急安全威胁的能力。
PRIVATE 通道的安全修复会在发布前 3 到 7 天预告。URGENT 通道的时间表更短,但其实我们可以在开始发布流程时就预告即将发布的版本,至少给用户留出几个小时准备。
在 Windows 和 macOS 上,我们依赖平台 API 提供的吊销机制;而在 Linux 上,目前还没有类似机制。缺少这项支持,正是我们决定加急发布的主要原因之一:我们不希望 Linux 用户暴露在风险中的时间超过必要限度。
因此,我们计划优先推进 Linux 上的证书吊销支持,让它与其他平台看齐,以便将来缓解这类问题。其中一项工作是研究对 upki 项目的支持。该项目的目标是为 Linux"提供可靠、保护隐私且高效的证书吊销机制"(见 Go issue #82402)。
升级并核查你的部署
如果你运行的 Go 程序会通过 TLS 访问网络服务(无论是直接使用 net/http、crypto/tls,还是通过 gRPC 等依赖),请确认使用的是最新的小版本。用 Go 1.27.3 或 1.26.10 重新编译的二进制会自动拒绝由失陷 eMudhra 中间证书签发的证书。
用 go version 可以查看当前工具链版本;用 go version -m <二进制文件路径> 可以查看某个二进制是用哪个 Go 版本编译的。
也可以用 govulncheck 工具判断某个二进制是否受此问题影响:
$ GOTOOLCHAIN=go1.27.3+auto go install golang.org/x/vuln/cmd/govulncheck@latest
$ govulncheck -mode=binary <二进制文件路径>
让各处的 Go 部署都安全
对我们来说,保护 Go 及其用户,不只是修复我们发布的运行时和库中的直接漏洞。要让整个生态保持安全,我们认为还需要为用户提供编写安全软件的合适工具,前瞻密码算法与协议的未来,并在力所能及时主动应对影响整个生态的问题。
感谢各位独立安全研究人员和 Mozilla 安全团队在这次事件中迅速通报、密切协作。
译者注
- 为什么"更新系统证书包"不够:被攻破的是中间证书,而签发它们的 eMudhra 根证书本身仍在各大根证书库中。Linux 上的 Go 程序会读取系统根证书(如 /etc/ssl/certs),只要根证书还在、又没有吊销检查,由这些中间证书签出的伪造证书就能通过验证。Go 1.27.3 / 1.26.10 的修复写在标准库代码里,所以必须用新工具链重新编译,只升级操作系统或 ca-certificates 包解决不了。
- 容器场景尤其要注意:Go 程序常被静态编译后放进 scratch、distroless 等精简镜像,镜像里的二进制不会随宿主机升级。在云容器引擎 CCE 等 Kubernetes 平台上跑 Go 服务的团队,建议在 CI 流水线中把构建镜像的 Go 版本升到 1.27.3 / 1.26.10 及以上,重新构建并滚动发布;再用
go version -m或 govulncheck 对线上镜像里的二进制逐个核对。依赖第三方 Go 编写的工具(各类 CLI、Operator、Sidecar)也要确认其发布版本是否已重编译。 - 时间换算:文中 10 月 19 日 11:45 PDT 约合北京时间 10 月 20 日 02:45,正式发布的 19:13 PDT 约合北京时间 10 月 20 日 10:13。
- "紧急通道"是什么:Go 安全策略把修复分为 PUBLIC、PRIVATE、URGENT 等不同通道。PRIVATE 通道提前 3–7 天预告;URGENT 用于已经或即将被利用的严重问题,可以不经预告直接发布。这次是 URGENT 通道首次启用,说明 Go 团队对"私钥即将公开"的判断非常严肃。
相关阅读
- gopls 交互式重构上线:结构体标签、接口实现、移动声明都能"先问再改":https://bbs.huaweicloud.com/blogs/412452f8a1434bb9a01771d1c81ba9bd
- 点赞
- 收藏
- 关注作者
评论(0)