了解 OCSP Stapling 证书吊销验证机制

Published: 2024-09-25

Tags: TLS

本文总阅读量

最开始是在 Bitiful CDN 上看到开启 OCSP stapling 开关,才知道有这个技术概念

从吊销证书说起

非对称加密是证书体系的基础,每个公钥都有一个关联的私钥,该私钥由网站所有者私密保存,如果有人窃取到证书的私钥,他们就可以冒充该网站,私钥泄露属于严重风险。

只要存在私钥泄露的概率,那么它就一定就会发生,所以私钥泄露后第一时间应该 吊销证书,证书吊销是降低密钥泄露风险的一种方法,网站所有者可以通过通知证书颁发者不应再信任该证书来撤销受损的证书。

回到用户视角,当网站管理员吊销了证书,用户借助浏览器请求网站,浏览器如何判断网站证书存在安全风险,并给出提示或禁止用户访问呢?

网络浏览器可以通过多种方式检查网站的证书是否被吊销。最著名的机制是证书吊销列表 Certificate revocation list (CRL) 和在线证书状态协议 (OCSP)。 CRL 是由 CA 撤销的证书序列号的签名列表,OCSP 是一种协议,可用于向 CA 查询给定证书的吊销状态,OCSP 响应包含证书未吊销的签名断言

查看网站证书

在进一步了解其它概念之前,我们可以通过浏览器获取到网站的证书,查看其信息以便稍后更好的理解概念

上图是在 FireFox 浏览器,点击绿色锁头,进入到 “View Certificate” 看到的信息,从左到右依次是网站的终端实体证书,R11 是 Let's Encrypt 的中级证书(Intermediate Certificate),用于签发网站终端实体证书

ISRG Root X1 是 Let's Encrypt 的根证书(Root Certificate),这个证书是整个信任链的起点,由受信任的根证书颁发机构(CA)签发

大多数操作系统和浏览器都内置了 ISRG Root X1 证书,因此用户可以信任由 Let's Encrypt 颁发的证书,R11 证书的存在是为了在根证书和终端实体证书之间建立信任链

我们可以点击 PEM (cert) 下载网站的证书,另外两个证书同理,我这里下载了三者并重命名

接下来回到上节提到的 CRL 和 OCSP,之后我们将进一步了解 OCSP Stapling 的作用和实现

证书吊销列表 (CRL)

证书吊销列表(Certificate Revocation List,简称 CRL)是公钥基础设施(PKI)中的一种重要机制,用于列出已被吊销的数字证书。CRL 由证书颁发机构(CA)发布,包含已吊销证书的序列号和其他相关信息。客户端(如浏览器)可以使用 CRL 来检查证书的有效性,确保不会使用已被吊销的证书。

在 FireFox 浏览器查看 Let's Encrypt 签发的证书,切换到证书链中的 R11 中间证书,其通过 CRL 来验证自身证书是否有效

补充:使用命令行也可以查询 CRL URI

$ openssl x509 -in r11.pem -text -noout | grep -A 4 "CRL Distribution Points"

证书中列出的 CRL 文件下载地址是:http://x1.c.lencr.org/

浏览器打开链接可下载到二进制文件,它就是二进制格式的 CRL,不能直接用文本编辑器打开,稍后会补充如何查看和验证

关于 Let's Encrypt 的 lencr.org 域名,有篇文章对其进行了说明,有兴趣了解可以看:Let's Encrypt - lencr.org

简要说就是:

由 c.lencr.org 子域名提供证书吊销列表 (CRL)

由 o.lencr.org 子域名提供在线证书状态协议(OCSP)

由 i.lencr.org 子域名提供中间 “颁发者” 证书的副本,这些证书要么由我们的根证书之一签名,要么由另一个证书颁发机构 (CA)“交叉签名”。

另外使用短域名能减小证书大小,这在互联网海量的证书请求下能节省很多资源

除了域名,我们也可以见到 Let's Encrypt 的证书吊销列表下载地址不带 .crl 后缀(猜测也是为了减少链接长度),很多证书集成的证书吊销列表都带有 .crl 路径

例如 Amazon 证书 CRL 下载地址

以及 Google 证书 CRL 下载地址

接下来可以进一步了解 CRL 文件

CRL 文件的解析与校验(可跳过不影响阅读)

可以使用这个在线工具:Parse CRL

可以选择 “From file” 上传 crl 文件,也可以选择 “From URI” 填写证书中列出的 CRL Endpoints 地址(例如:http://x1.c.lencr.org/),然后点击 “Parse CRL”

从解析的内容来看,Version 版本是 2,Issuer name 是 ISRG Root X1,也就是 Let's Encrypt 的 Root 根证书

其中的 CRL Entries 表示吊销记录,当前为空表示这个 CRL 承载的信息中 ISRG Root X1 没有吊销过其签发的证书

查看完 CRL 文件内容,这里还有一些重点:

为什么 CRL 下载地址提供 HTTP 而不是 HTTPS?(Let's Encrypt 文档对 OCSP HTTP 做了解释,CRL 的获取同理)

OCSP 响应始终通过 HTTP 提供。如果通过 HTTPS 提供服务,则会出现“无限循环”问题:为了验证 OCSP 服务器的证书,客户端必须使用 OCSP。

请求 CRL 文件的地址是 HTTP 的 http://x1.c.lencr.org/ 而非 HTTPS 加密,如何确保浏览器请求到的 CRL 未被篡改?

OCSP 响应本身带有时间戳和加密签名,因此在这种情况下不需要 TLS 的防篡改属性。

还是这个网页,点击 “Verify CRL” 来验证其有效性

选择 “From certificate”,选择上文下载回来的 ISRG-Root-X1.pem

点击校验,验证签名成功,符合预期

我们手动加载 CRL 文件并校验,浏览器也是这样经过验签确定获取到的 CRL 真实完整,同时确认 R11 证书有效后,R11 中间证书也可以验证其签发的网站终端实体证书有效性,反之,R11 被吊销,那么由其签发的叶子证书也不再可信

CRL 存在的部分问题

CRL(证书吊销列表)存在一些时效性和规模问题,时效性问题主要体现在 CRL 更新频率低和延迟高,可能导致客户端无法及时获取最新的吊销信息。规模问题则表现为 CRL 文件随着时间的推移变得越来越大,下载和解析时间增加,影响性能。

CRL 虽然有写问题,但不影响使用,例如 Delta CRL、Partitioned CRL、Caching 等技术都可以缓解其问题,此处不做过多发散,仅需知道 CRL 并不是被抛弃的技术即可,很多证书中 CRL 和 OCSP 同时使用,互为补充,确保证书的吊销状态能够及时、准确地被验证

接下来了解 OCSP 协议

OCSP 在线证书状态协议

为了克服 CRL 的时效性和规模问题,OCSP(Online Certificate Status Protocol,在线证书状态协议)提供了一种更实时的查询证书状态的方法。

Let's Encrypt 签发的网站叶子证书使用的是 OCSP 验证,所以在学习之前,先在 FireFox 浏览器切换到网站证书的标签页

可以看到 OCSP 服务器地址为:http://r11.o.lencr.org

使用如下命令可以实时验证证书有效性

$ openssl ocsp -issuer r11.pem -cert blog-yasking-org.pem -url http://r11.o.lencr.org -text -no_nonce

R11 证书有效性已在上文借助 CRL 通过 Root 证书的有效性验证

输出校验成功,可以确定博客 blog.yasking.org 证书是有效状态

OCSP 也并非完美的方案,下节回讲到可用性验证的左右为难

迷失在 CRL 和 OCSP 中的浏览器

本小节内容整理自:https://blog.cloudflare.com/high-reliability-ocsp-stapling/

有任何疑问建议阅读原文,讲解的更加详细

支持 OCSP 的证书包含响应者的 URL,同样支持 CRL 的证书包含可获取 CRL 的 URL,当浏览器获得作为 HTTPS 连接一部分的证书时,它可以使用证书中嵌入的 URL 下载 CRL 或 OCSP 响应,并在呈现网页之前检查证书是否已被吊销。那么问题就变成了:如果 CRL 或 OCSP 响应请求失败,浏览器应该做什么?

事实证明,这个问题的两个答案都有问题。

Hard-fail 硬失败 —— 不起作用

当浏览器无法获取吊销信息时,硬失败策略会阻止页面并显示警告,这种策略虽然保守、安全但很容易因为网络波动或其它因素误报,导致用户警告疲劳并教会用户单击忽略安全警告,这是一个坏主意

硬故障策略的另一个缺点是,它增加了证书颁发机构保持 OCSP 和 CRL 端点可用和在线的负担,损坏的 OCSP 或 CRL 服务器会成为证书颁发机构颁发的所有证书的中心故障点,如果浏览器遵循硬故障策略,则 OCSP 中断将成为 Internet 中断,整个网络的可用性受到 CA 始终保持其 OCSP 服务在线的能力的限制,构成系统性风险

Soft-fail 软失败 —— 也好不了多少

为避免硬故障策略的缺点,大多数浏览器采用软失败策略进行证书吊销检查,如果吊销信息可用,他们就会依赖该信息,否则会假设证书未吊销并显示没有任何错误的页面

软故障策略存在严重的安全缺陷:一旦攻击者可以阻止 OCSP 请求并拥有网站私钥,他们就可以拦截该站点的传出连接并将已吊销的证书提供给浏览器,浏览器页面将在不提醒用户的情况下加载攻击者页面

在首次访问尚未缓存证书的吊销信息时,软故障策略也会使连接速度变慢

实时 OCSP 检查还有一个额外的缺点:OCSP 请求通过未加密的 HTTP 发送,并绑定到特定证书,它会泄露私人访问站点信息

另外,还有一种方案 —— 预打包 CRL

浏览器预先打包已撤销证书的列表,并通过浏览器更新来分发它们,由于所有被撤销证书的列表非常庞大,因此该列表中仅包含少数高影响力的证书。该技术在 Firefox 中称为 OneCRL,在 Chrome 中称为 CRLSet,这对于一些备受瞩目的撤销来说是有效的,但它绝不是一个完整的解决方案,这种技术不仅没有覆盖所有证书,而且在证书被吊销和证书列表到达浏览器之间留下了一个漏洞窗口

火候差不多了,我们是时候该请出 OCSP Stapling (OCSP 装订)

OCSP Stapling 技术

OCSP 装订就像是服务器在返回证书的同时,也将 OCSP 状态一并返回给客户端,使得客户端不用单独请求证书颁发机构(CA)的服务器进行校验,这个过程就像是用订书器将两份文件订在一起一样,因此得名“装订”。

OCSP 允许 Web 服务器通过与证书颁发机构验证来确定 SSL/TLS 证书的状态。这种提高的安全性伴随着一些性能损失:由于浏览器必须与 Web 服务器和证书颁发机构进行通信,网站的加载时间会增加。

OCSP Stapling 优化了 SSL/TLS 握手过程,它允许服务器在握手过程中直接提供证书的状态信息,而不需要客户端去查询 OCSP 服务器。

在某些情况下,OCSP 装订可将连接时间缩短高达 30%,与此同时, OCSP Stapling 修复了与实时 OCSP 获取相关的一些性能和隐私问题

查询网站是否开启了 OCSP Stapling

$ openssl s_client -connect blog.yasking.org:443 -status -servername blog.yasking.org

从输出看到 “OCSP Response Data” 说明网站服务器支持 OCSP 装订

测试了一个未开启 OCSP 装订的网站,返回内容如下

也可以使用在线工具,例如:https://entrust.ssllabs.com

国内用户可以使用在线网站:https://myssl.com/

Nginx 开启 OCSP Stapling

示例配置如下

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /path/to/your/certificate.crt;
    ssl_certificate_key /path/to/your/private.key;

    # 启用 OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;

    # 指定用于验证 OCSP 响应的根证书
    ssl_trusted_certificate /path/to/your/trusted_ca_certs.pem;

    # 可选:设置 OCSP 响应的缓存时间
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # 其他配置...
}

写在做后

当前大多主流的服务和客户端库都支持 OCSP stapling,如果可以,开启它!

参考