用户登录

技术文章

外部链接将在新标签页打开。

eMudhra 弱密钥事件:八把弱密钥如何击穿证书信任,补丁进度怎么核对

一句话回答

eMudhra 的八把弱中间 CA 私钥可从公开证书直接恢复,任何人能为任意域名签发证书。补丁进度需分三层核对:CA 侧停用、服务端出站验证、终端信任库。全网进度只能靠间接探针估计,而探针口径变更与机器人流量会制造修补假象。

核心要点 TL;DR
  • 这次不是私钥泄露,而是私钥可被任何人从公开证书推导出来;未修补且不强制 CT 的客户端会接受伪造证书。
  • 自查重点在出站验证组件与终端信任库;CT 日志只能证明签发发生过,不能证明终端已停止信任。
  • 公开的修补率曲线受流量构成影响,读之前先对齐平台口径变更的时间点。

先给结论:eMudhra 事件里不存在一个统一的“补丁进度”数字。它至少分三层——CA 侧是否停止用弱密钥签发、服务端是否拒绝由这些密钥签出的链、终端信任库是否已移除对应锚点。开发者能自己核对的是后两层;全网层面只能靠间接探针估计,而探针口径会随平台变更漂移。把三层混成一个百分比,几乎一定会读错。

顺带纠正一处标题歧义:从Cloudflare 的事后分析看,原文标题“4 real?”是双关,指最弱的那把密钥值就是数字 4。事件实际涉及八把弱密钥,值为 4、56、66、115、155、156、230、237。

为什么这次和以往的 CA 事故不同#

过去的 CA 事故(DigiNotar、TÜRKTRUST、TrustWave)中,私钥被少数攻击者或组织掌握,影响范围有限。这次不是。Cloudflare 指出,受影响的中间 CA 私钥可以从公开证书本身几乎即时恢复。任何人不需入侵任何系统,就能独立恢复出同样的签名密钥,为任意域名签发证书——只要目标客户端没有修补,且不强制证书透明度(Certificate Transparency,CT)。

eMudhra 宣布退出公共 CA 业务,称密钥生成脚本存在错误,但至今未公开该脚本。它还曾用一把可能是正确生成的密钥签署 CRL(证书吊销列表),随后又改为用弱密钥签署。审计方与交叉签名方在其中扮演什么角色,材料没有给出结论,仍待澄清。

Cloudflare 的处置时间线,可当作核对基线#

  • 10 月 19 日:高影响系统开始修补。面向客户源站的 Pingora 代理在数小时内改为拒绝这些弱密钥;同时用 AI 辅助分析源码,四小时内完成相关系统的全量梳理。
  • 10 月 21 日:Pingora 日志铺开,记录任何呈现 eMudhra 弱密钥签名证书的握手。
  • 一周内:约 22,000 次此类握手尝试。三分之二是抓取测试站点 emudhra.we-have-a-problem.com;剩余部分几乎都是源站自己用弱中间证书配的证书。所有启用了证书验证的握手都被拒绝。
  • 约 160 次握手值得单独看:证书 SAN(主题备用名称)指向与 SNI 无关的其他组织域名,部分与消费级 IoT 有关;有的证书有效期超过两年,长于公共 CA 允许的上限;同一张证书从多个地点出现,说明它来自服务器本身,而不是某条网络路径上的注入。结论是没有拦截证据,但不能排除定向拦截。

探针法:全网进度为什么只能估#

要判断访客是否仍信任弱密钥,不能为了测试而中断真实连接。Cloudflare 的做法是在一部分 challenge 页面上额外发起两个探测连接:ca1.cloudflarecaptcha.com 装 eMudhra 签名证书,ca2.cloudflarecaptcha.com 装正常签名证书作对照,记录探测是否成功。一周约 5000 万次。

这个方法有三个先天偏差:challenge 流量本身高度偏斜,含大量未确认的机器人;只有执行 JavaScript 的客户端才会发出探测;内嵌浏览器(如 Android WebView)与独立浏览器行为不同。

更麻烦的是口径漂移。期间至少发生五次变更:10 月 23 日 15:30,对照端点也改为提供不带 SCT(签名证书时间戳)的 eMudhra 证书;16:30,challenge 平台因无关问题回滚,探测中断到 10 月 27 日 10:00;10 月 27 日 16:37,补上此前缺失的 G3 交叉签名,并从两端移除 SCT;16:49,ca2 改为链到 AAA Certificate Services 根;18:18,探测比例从 1% 提升到 10%(仅非付费客户 zone)。这些都会在曲线上造成跳变,读图前必须先对齐口径。

读结论时的三个陷阱#

把流量分类变化当成修补

10 月 29 日约 18:00 UTC,Cloudflare 上线一条检测,捕获大量伪装成 macOS 上 Chrome 150–154 的机器人流量。在按浏览器分类的图上,接受率看起来在下降;实际上是分母变了——同一批 User-Agent 在带机器人信号的流量里,接受率反而上升。Linux 上的 Chrome 150–154 是例外,接受率持续下降,与这批客户端确实在修补相符,但材料称这只是提示性证据,不是定论。

把平台差异当成进度差异

现代浏览器大多已修补,机器人和旧浏览器没有。Android WebView 等内嵌浏览器仍有 30–40% 接受。按网络(ASN)看,大型网络中超过一半的探测仍接受被攻陷的链,无论是否带机器人信号。首个周末之后,曲线基本走平。

把“没有拦截证据”当成“没被拦截”

日志只覆盖 Cloudflare 自己的出站路径。定向拦截可以绕开任何单点观测,只能靠系统失陷的间接信号推断,而材料称目前未见这类信号。

开发者自查清单#

  1. 列出所有会验证对端证书的组件:出站代理、反爬、webhook 回调、包管理器、CI 拉取依赖、监控探测。确认信任库不含相关锚点,或在验证层显式拒绝这些中间证书。
  2. 检查终端:macOS 开发者尤其需要按指引更新信任设置;Android WebView 需随系统或应用更新,不能只等浏览器升级。
  3. 用 CT 日志发现签发:监控自有域名是否出现由 eMudhra 链签发的证书。CT 能证明“有签发发生”,不能证明“终端已停止信任”。
  4. 采集可复核的证据:不要只记“报错/不报错”。记录 SNI、对端呈现的完整链、验证结果、时间与出口位置,才能区分源站默认证书与路径注入。

下面两个命令只用于说明核对思路,本次未执行,输出随环境和目标而异,不构成“是否安全”的结论。示例域名 example.com 为占位。

# 未执行示例:抓取对端呈现的证书链并打印 issuer / subject
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null \
  | openssl crl2pkcs7 -nocrl -certfile /dev/stdin \
  | openssl pkcs7 -print_certs -noout
# 未执行示例:在 macOS 系统信任库中查找名称含 emudhra 的证书
security find-certificate -a -p /System/Library/Keychains/SystemRootCertificates.keychain \
  | openssl crl2pkcs7 -nocrl -certfile /dev/stdin \
  | openssl pkcs7 -print_certs -noout \
  | grep -i emudhra

第一条用于看链里实际出现了什么;第二条只覆盖系统根证书库,用户域、应用自带信任库和容器镜像里的 CA 包都需要另外检查。

还没有答案的部分#

材料没有交代 eMudhra 密钥生成脚本的具体内容、审计与交叉签名方的责任划分、以及 CRL 签署反复的原因。Cloudflare 的探测数据截至其发文时,且明确受机器人流量影响,不能直接外推为全体用户比例。文中提到的众包修补指引与 upki 项目,本文未核实其当前状态,使用前需自行确认。

可迁移的经验只有一条:信任库不能当作静态的根证书列表。弱密钥公开后,伪造证书在数小时内就出现了——一张观察到的伪造证书时间为 10 月 20 日 18:19 UTC,距 Mozilla 的 bug 报告公开不到一小时。核对补丁进度时,先问“这一层是谁在验证、信任库多久能更新一次”,再问“百分比是多少”。

常见问题(FAQ)

服务端启用了证书校验就一定安全吗?
取决于信任库是否仍含对应锚点、是否校验完整链与主机名。Cloudflare 材料称其启用验证的握手全部被拒绝,可作为参照,但不能替代对自己组件的逐项核对。
证书透明度日志能证明客户端已经修补吗?
不能。CT 只能证明某张证书被签发过,用于发现异常签发;终端是否仍信任弱密钥,需要在验证侧另行确认。
标题里的“四把”是什么意思?
从原文看是双关:最弱的一把密钥值就是数字 4,原题 “4 real?” 由此而来。事件实际涉及八把弱密钥,值为 4、56、66、115、155、156、230、237。

参考来源

  1. 4 real? Tracking exploitation and patching of eMudhra’s weak keys

以上为本文写作时的参考资料,引用观点以原文为准。

作者:沐小悠

本文约 9 分钟读完 · 关键词:eMudhra 弱密钥、证书信任链、中间CA、补丁进度核对、证书透明度

更多文章 GET 示例接口

「」标签下的其他文章