2014 年 4 月 7 日,OpenSSL 发布了修复 Heartbleed 的版本。这个日期为源代码里的漏洞画下句点,任何仍在运行的机器上,事件都尚未就此结束。运维人员仍要找出每一个存在漏洞的 TLS 端点,安装或重新构建 OpenSSL,重启已经加载旧版库的进程,更换那些在此前流量中已有外泄风险的秘密数据,并在操作真正安全后通知其他人。
Heartbleed 的事后复盘,核心就在这一区别。编程错误只是小型协议处理程序漏掉一次长度检查,恢复工作却散落在软件版本、运行中进程、私钥、证书、浏览器行为、会话、密码,以及无法证明某段 64 KiB 内存是否曾被返回的各系统负责人之间。软件包更新能够阻断下一次读取,却无法还原此前发生过哪些读取,也无法让已经复制出去的秘密重归私密。[1][6]
上方照片摄于披露九天后的东京新闻简报会。[8] 这个现场同样属于技术故事。面对不完整的证据,维护者、供应商、证书颁发机构、服务运维人员、安全研究人员与用户仍需依照安全次序行动。若把这些动作一概称为“打补丁”,一些恢复为何成功、另一些为何只改了版本字符串,也就被遮住了。
请求带着两个长度,OpenSSL 信了错误的那个
TLS 和 DTLS Heartbeat Extension 原本用于检查连接是否存活。对端发送含有 payload 的 HeartbeatRequest,接收方再把这段 payload 原样回送到 HeartbeatResponse。消息同时带有两个长度:外围 TLS 记录限定的实际长度,以及发送方声明的 payload_length 字段。RFC 6520 对边界要求写得很清楚:声明的 payload 若大于收到的消息所能容纳的范围,接收方必须静默丢弃该消息。[2]
受影响的 OpenSSL 代码读取了发送方声明的长度,却跳过了先行验证:接收缓冲区是否确实含有相应数量的 payload 字节,以及必要的封装和填充。恶意对端可以只发送一小段 payload,同时将长度声明得大得多,随后收到原 payload 及其相邻的进程内存。OpenSSL 公告称,无论有漏洞的是客户端还是服务器,每次请求最多都可泄露 64 KiB。1.0.1 至 1.0.1f 版本以及当时的 1.0.2 beta 版均受影响;1.0.1g 补上了缺失的边界检查,编译时关闭 heartbeat 支持则是文档列出的临时方案。[1][2]
这是缓冲区越界读取(over-read),与写入无关。攻击路径绕过了破解 TLS 加密、猜测账户密码或让服务崩溃这些环节,直接诱使 TLS 实现复制超出所供 payload 边界的字节。这些字节里会出现什么,取决于进程近期分配过什么:普通请求数据、用户名、密码、会话材料,或私钥片段。重复发送请求即可对更多内存取样;正常的 heartbeat 流量又不会留下应用层审计轨迹,事后无从证明究竟有哪些字节已经外泄。[3][6]
最后这一特性改变了响应标准。如果入侵日志圈定了一批被盗记录,运维人员便可轮换这些记录。Heartbleed 通常只留下暴露时间窗,以及一张清单,列明哪些秘密曾有机会进入有漏洞的进程内存。恢复因此要按披露风险处置,确认盗取不再是启动条件。
密钥提取问题在九小时内改写了答案
起初,私钥是否暴露没有定论,而这份不确定性影响重大。私钥被盗后,只要对应证书仍受信任,攻击者便能冒充服务。4 月 11 日,Cloudflare 在自测未能取出密钥之后,开放了一项刻意保留漏洞的挑战。约九小时后,首位成功者仅借助 Heartbleed 就提取出密钥。五天的实验中,Cloudflare 记录了超过 7500 万次攻击请求和 8,000 次提交;多名参与者从进程内存中残留的 RSA 素数因子里恢复了密钥。[3]
这项实验没有表明每台有漏洞的服务器都能随取随得地泄露密钥。堆布局、流量、服务器软件、密钥类型和时机会改变一次取样暴露的内容。实验确认了一点:“我们试过却没看到密钥”不足以成为旧密钥继续服役的理由。Cloudflare 随后为其管理的每张证书申请重新签发,并吊销相应旧证书,同时建议有漏洞的运维方升级至 1.0.1g 或更新版本,并更换密钥。[3]
这为复盘划出了一条事实界线:Heartbleed 让披露变得可行且无声,具体泄露却因环境而异,事后也无从重建。至于某个组织是否遭到利用,仍需另有证据。可信测试一旦证明密钥可以被实际提取,恢复行动便不能以逐把密钥的盗取证明为前提。
四座时钟必须依次运行
把 Heartbleed 响应拆成四座时钟,脉络会更清晰。它们在时间上重叠,各自对应的控制却不能互换。
1. 阻断新的内存读取
首先,运维人员要识别有漏洞的运行时,安装修复版本,并重启或替换每一个仍持有旧版 OpenSSL 代码的进程。只更新磁盘上的共享库软件包,已经把旧代码映射进内存的长期运行 Web 服务器、邮件守护进程、VPN 端点或设备进程仍会继续使用旧代码。版本清单只是起点;要关闭这个环节,还需拿出正在执行的二进制文件或库的证据,以及启用新版本的服务重启记录。
范围远超公开网站。漏洞同时存在于 TLS 或 DTLS 连接两端的 OpenSSL heartbeat 实现。面向互联网的 HTTPS 是最醒目的大规模目标,但邮件、消息、VPN、嵌入式和客户端软件同样存在携带受影响库的情况。不受支持的设备和静态链接应用,也落在“一次操作系统更新就能覆盖全部”这一设想之外。[1][6]
要求用户更改凭证以前,这座时钟必须走完。若端点仍有漏洞,新密码一经发送,就成了刚放入可读内存的新秘密。
2. 更换密钥和证书
端点安全后,运维人员要生成新私钥,并取得与它绑定的新证书。单纯再下载一份证书、延长有效期,或在重新签发时复用旧私钥,都清除不了那项疑似泄露的秘密。
这一区别在实际处置中经常被忽略。首项大型测量研究估计,披露刚发生时,Alexa Top Million 中的 HTTPS 服务器有 24–55% 存在漏洞。研究发现,73% 的有漏洞站点完成修补,但只有 10% 更换证书;在更换证书的站点中,14% 复用了同一把私钥。这些站点换掉了公开外壳,却保留了被 Heartbleed 置于泄露风险中的那项资产。[5]
更换动作还需要一个可信的起点。在仍有漏洞的 TLS 终止器上生成新密钥,随后在修复版运行时启用前开始服务流量,恰好颠倒了安全次序。只有内存读取路径关闭后,才能生成并部署新密钥。
3. 吊销旧证书
新证书不会自动关闭旧证书。潜在失陷的证书必须吊销,客户端才能获知对应序列号已不再受信任。这是另一项控制,依赖另一套基础设施:证书颁发机构的处理流程、证书吊销列表、OCSP 响应器、浏览器策略与缓存。
Heartbleed 暴露了这项控制的参差程度。Cloudflare 挑战证书的私钥已经确定泄露,各浏览器对吊销状态的处理却不一致。在互联网规模下,大批量吊销也给相关系统带来压力;这些系统原先的设计容量承受不了大量紧急变更同时涌入。因此,事件台账需把“重新签发”和“已吊销”分列,并明确记录旧序列号及吊销状态。[3]
吊销可以降低日后冒充风险;它收不回已经复制的密钥,无法保证每个客户端都检查状态,也无法恢复已经泄露的明文。这些剩余局限恰恰要求认真完成吊销。
4. 让次级秘密失效
走到这一步,运维人员才能作废 session cookie 和 bearer token,轮换曾驻留于进程、因而处于暴露范围内的应用凭证,并要求用户修改密码。具体集合随服务而变。TLS 终止器有时只保存连接与密钥材料;直接链接 OpenSSL 的应用进程还会保存认证标头、数据库凭证或消息正文。
Mozilla 的公开响应把这些动词背后的次序完整呈现出来。它升级了受影响的基础设施,更换了面向用户的关键证书,并重置用户 session token。它还建议用户出于预防更改密码,同时区分两类系统:TLS 终止于有漏洞的 AWS 负载均衡器的系统,以及后端内存不在同一暴露范围的系统。[4]
这座时钟能让仍可授予日后访问权的秘密失效,却修复不了已经从内存读出的内容。消息一旦泄露,修改密码无法让它重新保密。事件关闭因此要同时说明两件事:哪些授权凭据已经失效,哪些历史保密损失仍然无从查明。
公开传播很快,资产清单仍由负责人逐项推进
Heartbleed 引发了罕见的广泛关注,处置完成度却未随之同步。披露两个月后,测量研究在 Alexa Top Million 样本中仍发现约 3% 的 HTTPS 站点存在漏洞。广泛报道与自动更新带来了迅速的第一波处置,随后修补速度进入平台期。研究人员直接通知网络运维人员,指出其遗漏的系统后,这批系统的修补率提高了 47%。[5]
这一结果显示,“知晓”的控制力弱于明确到人的责任归属。新闻标题能让所有人知道漏洞存在,却无法把 IP 地址映射到负责其 TLS 进程的团队,无法找到被遗忘的设备、安排重启、申请替换证书,或确认会话存储已经清空。直接通知之所以有效,是因为证据抵达了能够完成具体端点处置的人。
组织内部同样如此。一份经得起审计的 Heartbleed 台账至少应记录:
- 端点及负责团队;
- 有漏洞及已修复运行时的证据,包括重启时间;
- 新旧密钥指纹或证书序列号;
- 签发、部署和吊销状态;
- 会话失效及凭证轮换的范围;
- 未能修复且已隔离或退役的设备或服务。
这份台账就是工程处置的一部分。四座相互独立的时钟由此汇入一套可审计的恢复过程。
项目层面的教训关乎维护能力,道德寓言解释不了它
Heartbleed 引出了一种简化说法:开放代码理应保证会有人发现那道缺失的检查。这起事件支持的结论更窄:可供审查与实际完成审查是两件事,依赖范围再广,也不会自动带来维护人员、测试基础设施、协调披露能力或资金。
响应随后带来了机构层面的动作。Linux Foundation 的 Core Infrastructure Initiative 后来资助 OpenSSL 维护人员和一项独立审计,同时支持其他关键项目。[7] 资金无法让内存不安全代码永不出错,单次审计也无法为持续变化的库提供永久认证;这些投入把开源世界里分散的依赖转化为职责明确的工程能力。
对开源软件使用方,责任边界十分具体。上游维护者负责项目;部署方负责运行中的资产清单,以及放在其周围的秘密。软件物料清单可以显示受影响的 OpenSSL 版本进入了某项产品,单凭它却无法证明哪个进程加载了该版本、进程是否重启、哪把私钥曾驻留于堆中,也无法确认旧证书是否吊销。这些都属于实际运行中的关系,不在依赖扫描器所含信息之内。
Heartbleed 漏掉的检查多年前已经补上。这起事件留下的长期模式,是移除有漏洞的代码与撤销一切曾处于暴露范围的授权要素之间的落差。修补、换钥、吊销、退役:四座时钟依照这个顺序运转,每一步都要单独留证。少掉任何一环,仪表板仍会变绿,旧秘密却会继续代表服务行使权限。
来源
- OpenSSL Project,《TLS heartbeat read overrun (CVE-2014-0160)》,安全公告,2014 年 4 月 7 日——受影响版本、64 KiB 泄露上限、修复版本及编译时临时方案。
- IETF,RFC 6520,《Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) Heartbeat Extension》,2012 年 2 月——消息构造,以及声明的 payload 过大时必须丢弃消息的要求。
- Nick Sullivan,Cloudflare,《The Heartbleed Aftermath: all CloudFlare certificates revoked and reissued》,2014 年 4 月 17 日——挑战结果、密钥提取原理、响应规模,以及换钥与吊销建议。
- Mozilla Security Blog,《Heartbleed Security Advisory》,2014 年 4 月 8 日——涉及 AWS TLS 终止、证书更换、session token 重置和密码建议的运维响应。
- Zakir Durumeric 等,《The Matter of Heartbleed》,ACM Internet Measurement Conference,2014 年——对暴露、修补、证书更换、密钥复用、直接通知和残余漏洞所作的独立互联网规模测量。
- Nathan Willis,LWN.net,《Heartbleed bug exposes OpenSSL installations》,2014 年 4 月 9 日——同时期的独立技术记录,涉及越界读取、缺少日志轨迹、客户端与服务器范围,以及超出软件包更新的恢复工作。
- Linux Foundation,《Announcing Rapid Progress on Core Infrastructure Initiative》,2014 年 10 月 14 日——事件发生后的机构响应,包括为 OpenSSL 维护人员及独立代码审计提供资金。
- ScanNetSecurity,《Symantecによる「Heartbleed」の状況整理と対策方針》,2014 年 4 月 18 日——文章所用 4 月 16 日东京新闻简报会照片的来源页及身份说明。