摘要

  • Debian 在 2008 年 5 月修复了其 OpenSSL 软件包特有的随机数生成缺陷。更新只能保证此后经该路径生成的密钥,不会自动改变 2006 年 9 月以来已经产生、复制并获得授权的 SSH、OpenVPN、DNSSEC 或 X.509 密钥。
  • 完整修复是一条分布式撤权链:确认生成来源,识别或保守圈定可疑凭据,在正确熵源下生成替代品,认证并分发新凭据,删除旧授权或吊销旧证书,最后从重要依赖方一侧证明旧密钥已被拒绝。

补丁修复的是下一把钥匙

2008 年 5 月 13 日,Debian 发布 DSA-1571-1,说明其 OpenSSL 软件包中的随机数生成器可被预测。公告很短,却把修补软件与撤销权力之间的断层暴露得十分清楚。

安装新版 OpenSSL 后,下一次生成操作会走正确路径。前一天生成的私钥不会因此改变;已经签发的证书不会因此失效;远端服务器里的 authorized_keys 不会自动删掉对应公钥;一台从未运行过有缺陷软件的机器,也不会自动识别自己导入的弱密钥。

弱密钥甚至可能看起来完全正常。格式可解析,公私钥可以匹配,SSH 证明可以通过,证书仍在有效期内并带有正确的签发者签名。问题藏在生成历史里:秘密并不是从足够大的不可预测空间中选出的。

因此,Debian 的处置不是一句“升级即可”。DSA-1571-1 要求重新生成受影响版本自 0.9.8c-1 起产生的加密密钥材料,并单独警告 DSA 使用场景:哪怕密钥最初生成正常,只要在受影响系统上使用了可预测的签名随机数,私钥也可能暴露。

补丁是面向未来的代码状态;凭据已经取得的权限,是散落在别处的历史状态。

一个庞大密钥背后的狭小世界

Debian 缺陷记录 #363516 始于 2006 年 4 月。问题最初围绕 Valgrind 对 OpenSSL 随机数生成器读取未初始化内存的告警展开。讨论涉及怎样消除这些噪声。记录后来专门澄清:真正进入编译路径的脆弱改动从 0.9.8c-1 开始,因为修改后的 md_rand.c 在该版本被移动到了实际构建使用的位置。

Debian 的 SSLkeys 文档给出了可操作的解释。故障生成器实际上主要由进程号提供种子;在三类架构上,每类有 32,767 个可能流,共计 98,301 个候选流。对常见算法与长度,攻击者可以预先生成候选,再根据公开密钥寻找对应私钥,而不必面对预期的加密搜索空间。

98,301 不是所有弱密钥的数量,也不是攻击次数。应用调用生成器的方式、算法、长度与架构都有差异,黑名单也并非覆盖一切。它说明的是安全经济学被倒置:公钥原本可以公开,是因为从公钥求私钥不可行;在这个事件中,公钥反而帮助攻击者从一个可枚举目录中定位秘密。

密钥仍保持“稀缺”的外表,却已经失去授权所依赖的真实稀缺性。

Debian 先修代码,再暂停信任

Debian 自身的基础设施响应提供了最直接的机制证据。DSA-1571 发布后不久,项目即暂停所有项目系统上的 SSH 公钥登录。依赖密钥进行文件传输、构建触发或运维的服务,需要先证明密钥安全或完成替换。

如果安装软件包就等于撤销旧钥匙,这个动作没有必要。暂停登录恰恰说明:被修复的库和仍在接受旧凭据的服务器,是两个控制面。

次日的 DSA-1576-1 为 OpenSSH 增加 openssh-blacklistssh-vulnkey。已知弱用户密钥可以在接收端被拒绝;主机密钥可在管理员确认后重新生成;用户还需要检查自己的身份文件、系统主机密钥和授权列表。

主机密钥与用户密钥的传播方向不同。服务器更换主机密钥后,客户端会出现“远端主机身份已改变”的警告。这个警告不是要批量关闭的障碍,而是客户端保留的本地否决权。用户必须通过另一条可信渠道核实新指纹,才能区分合法轮换与中间人攻击。

用户密钥则由持有人生成新密钥对,再把新公钥送到所有服务器,并从每个 authorized_keys 文件中删去旧条目。仅添加新钥匙而保留旧钥匙,会增加入口,而不是撤销旧权力。

软件包、黑名单、新密钥、指纹认证渠道和远端授权条目属于不同所有者。把它们统称为“SSH 修复”,会掩盖旧权力残留的位置。

黑名单是有边界的本地否决

候选空间有限,让防守方获得一个罕见工具:把已知弱公钥编成集合,在凭据到达时执行比较并拒绝。公开证据由此变成接收端的运行规则。

但发布名单本身并不关闭任何门。只有相关列表已安装、解析器理解该格式、密钥类型与长度受到覆盖、应用执行拒绝分支时,否决才生效。Debian 明确写着“在可能时”拒绝;Ubuntu 也说明 ssh-vulnkey 返回 Unknown (no blacklist information) 时,只代表没有足够黑名单信息,不能译成“安全”。来源无法高可信确认时,稳妥做法仍是更换。

第一轮工具很快暴露了自己的边界。DSA-1576-2 修复了一个解析问题:以强制命令、禁用端口转发等选项开头的 authorized_keys 行,可能被扫描器忽略。服务器仍接受该键,报告却可能漏掉它。随后 Ubuntu 又扩展了 X.509、证书请求、原始模数和更多 RSA 长度的检查范围。

这不是黑名单无用,而是自动化的证据等级必须写清。命中已知弱键,足以本地拒绝;没有命中,只能说明在当前解析器与语料范围内未发现。列表还能防止弱键以后被重新上传到一台从未受生成器缺陷影响的主机。它的正当权力与证据成比例:拒绝已知坏项,诚实报告未知项,不凭沉默制造安全证明。

同一故障没有统一撤销按钮

CERT 将 SSH、OpenVPN、DNSSEC 和 X.509 列入影响范围。它们共享缺陷熵源,却不共享同一种退役方式。

SSH 用户密钥的权力存在于远端授权文件。闭环证据是旧私钥在所有重要服务器上登录失败。SSH 主机密钥的信任存在于客户端的 known_hosts 与用户对新指纹的认证过程中;替换不当会把正确修复伪装成攻击,或把真实攻击伪装成修复。

OpenVPN 共享密钥必须在全部对端协调替换。证书模式还需要新密钥、新证书与拒绝旧证书的规则。USN-612-3 特别提醒:为其他系统生成的材料,必须到那些系统上寻找并替换。

X.509 中,生成新私钥只是开始。主体需要新证书,签发者需要按制度吊销旧证书,服务器需要部署新链,客户端则需要取得足够新的状态。RFC 5280 规定证书与撤销列表的处理,但撤销机制存在,并不等于每一个客户端都及时执行。

DNSSEC 密钥可能已经进入签名委派和缓存验证状态,必须走协议特定的轮换流程。自动化密钥可能藏在镜像、备份、构建机器人或合作伙伴系统中。删除原始机器上的文件,无法改变这些接收端的决定。

所以修复单位不是“那台 Debian 服务器”,而是凭据谱系:谁生成、复制到哪里、声明什么身份、由谁接受、由哪个动作撤权。

数学有效,授权基础已经消失

SSH 的正确加密证明回答的是:提交者是否掌握与该公钥对应的私钥。它不回答这个秘密是否仍具有排他性、是否已被推算、持有人是否仍获授权。攻击者重建弱私钥后,可以提交数学上完全正确的证明。

有效性仍在,合法性却已失去事实基础。

卢恒关于运行代码优先和实践控制的公开论述,可以作为分析镜头,但不是本事件的时间线证据。Debian 公告、补丁、黑名单或证书状态都是规则与证据;真正的拒绝发生在 SSH 服务器、VPN 对端或 PKI 客户端执行它们的地方。Debian 可以控制自己的软件包和项目服务器,却没有跨越全球授权文件的总开关。

反过来,一台从未运行脆弱 OpenSSL 的机器,只要仍接受从受影响系统导入的密钥,就不能把自己排除在事故之外。实际控制位于本地依赖点;这既保留否决权,也带来核验责任。

要关闭事故,需要四本账

第一本是生成账:生成日期、软件包版本、库、应用、架构、算法、长度以及是否使用了独立生成器。第二本是分发账:私钥副本、证书、服务器、授权文件、VPN 对端、镜像、备份与外部伙伴。

第三本是替换账:旧指纹、新指纹、认证新指纹的渠道、责任人和期限。第四本是拒绝账:旧用户键登录失败,旧主机键不再服务,旧证书在测试客户端上被拒绝,旧 VPN 秘密不能建链,例外均有名称、范围和到期日。

补丁合规属于第一本账。事故关闭属于第四本账。

证据边界

官方材料证明缺陷、版本、应用范围与处置流程,却没有给出弱密钥或成功攻击的完整总数。98,301 个流是有边界的模型,不是所有调用的统一语料。Unknown 既不证明安全,也不证明脆弱。文件时间可能被备份或错误时钟改变。GnuPG 与 GnuTLS 使用不同随机源。自动主机键处理取决于软件包和管理员选择。证书重签不保证所有客户端已经检查撤销。

最可靠的结论不需要夸张数字:生成器修复阻止了该路径上的未来错误;旧凭据取得的权力,只有在每个接受点被找出并拒绝后才会结束。

来源