只要你在提供 HTTPS 服务,你的服务器几乎可以肯定就跑在 OpenSSL(或兼容实现)之上。你从不直接接触它,它的缺陷却会波及每一个人——下面就讲清楚这个底层库究竟是什么,以及如何防御它。
它处在哪一层——你「继承」而来的根基
OpenSSL 棘手的地方在于,你在使用它,却从未亲自选择过它。你的应用把 TLS 委托给 Web 服务器,Web 服务器把加密委托给 OpenSSL,而那个 OpenSSL 又由操作系统附带提供——一层套一层的技术栈。
通常这是件好事——加密被交给了由专家编写的共享实现。但当这个共享根基出现漏洞时,坐在它上面的每一个人都会同时受到影响。这正是「底层库的缺陷影响范围巨大」的含义。
为何可怕:一个 bug 曾威胁全球的密钥
2014 年的 Heartbleed(CVE-2014-0160)源于 OpenSSL 一个很小的实现错误(未经校验就信任了对方申报的长度),它让外部人员能一点点读取服务器内存——其中可能包含私钥与会话数据。由于 OpenSSL 使用得如此广泛,全球大量服务器在同一时刻成了攻击目标(完整故事 → Heartbleed)。
教训直白得很:依赖越是底层,影响范围就越广。 所以需要关注的不只是应用直接引入的依赖——像 OpenSSL 这样运行在底层的库,在监控与打补丁上同样值得认真对待。
如何防御:避开 EOL,监控你的根基
弄清你的技术栈使用的是哪个 OpenSSL
看不见的东西无法防御。盘点一下你的服务器、容器基础镜像以及语言运行时各自依赖的是哪个 OpenSSL(发行版本线与具体版本)。
不要运行已停止支持(EOL)的版本
一旦某个发行版本线过了支持期,在其中新发现的漏洞就不会再有修复。运行 EOL 版本,等于留着一道即使发现了洞也不会有人来关的门。请规划升级到受支持的版本线上。
把底层一并纳入 CVE 监控
应用依赖用 osv-scanner 之类的工具很容易追踪,但操作系统附带的 OpenSSL 却很容易被忽视。请确保底层库中的新 CVE 也能浮现出来(→ CVE 修复实操手册)。
一旦严重就尽快打补丁
Heartbleed 这一类的 bug,往往在披露的那一刻就遭到攻击。请让你的更新链路足够轻便,使得在严重程度需要时,底层补丁能够当天就发布上线——而不是「等到下一次例行更新」。
本站的看法:用机器盯住你的根基
底层库的缺陷无法靠人脑记忆来追踪。本站把自身的依赖与底层都置于机器化的 CVE 监控之下。你通过 Let's Encrypt 签发的证书,其加密在底层依然是经由 OpenSSL 家族的实现来运行的——所以把「看不见的根基」盘点清楚并纳入监控,正是预防高影响范围事件的最短路径。
接下来阅读
- 从事件中学习:Heartbleed(一个曾威胁全球密钥的 OpenSSL 缺陷)
- 相关:什么是 Let's Encrypt(免费 TLS 证书+自动续期)/ 术语:什么是 CVE
- 实战:CVE 修复实操手册/用 osv-scanner 监控依赖
FAQ
Q我从没装过 OpenSSL——我有可能仍在使用它吗?
几乎可以肯定是的。OpenSSL 是一个底层库,被 Web 服务器(Nginx/Apache)、操作系统以及语言运行时在内部使用。即使你从未在代码里引用它,只要你在提供 HTTPS 服务,那么底层很可能就在运行 OpenSSL(或兼容实现)。想当然地认为『我没用它』,恰恰是底层漏洞被漏掉的典型原因。
Q它和 LibreSSL 或 BoringSSL 有什么区别?
两者都是 OpenSSL 的分支。LibreSSL 是 OpenBSD 项目在 Heartbleed 之后为清理代码库而创建的;BoringSSL 是 Google 自用的变体。多数用户无需在它们之间做选择——远比这更重要的,是让你的平台所附带的那个实现保持在受支持的、最新的版本上。
Q我该如何查看版本或更新它?
在许多系统上 `openssl version` 就能显示版本,而更新则通过操作系统的包管理器、或重新构建容器的基础镜像来完成。关键在于不要继续运行已停止支持(EOL)的版本:一旦某个发行版本线进入 EOL,在其中新发现的漏洞就不会再有修复。要像追踪应用依赖那样,同样追踪你的底层依赖。