在 macOS 上使用 cURL 与特定站点的 HTTPS 连接失败

信息安全 tls 证书 苹果系统 卷曲
2021-08-18 20:34:59

curl在我的 Mac 上,使用macOS 10.14的内置二进制文件与某些站点的 HTTPS 连接失败。它们适用于不同的浏览器,以及同一系统上的其他 cURL 版本。受影响的站点之一是https://kapeli.com/,它是实用程序“Dash”的下载站点。另一个是https://electroncash.org

cURL 抱怨证书过期:

curl: (60) SSL certificate problem: certificate has expired
More details here: https://curl.haxx.se/docs/sslcerts.html

我在安装Homebrew-Cask时遇到了这个问题,它使用 macOS 的内置 cURL 来下载软件。

4个回答

上述站点(ComodoUSERTrust)使用的 CA 证书已于今天早上(UTC 时间)过期。虽然我发现两个不同的 Root CA 证书会在同一秒过期,但我发现这很了不起,这可以通过隶属于 Comodo(现为 Sectigo)的 USERTrust来解释。


编辑:这两个实际上从来都不是根 CA 证书,而是由"AddTrust External CA Root"签名的中间CA。因此,它们的到期日期取决于“AddTrust External CA Root”证书的有效性,该证书也恰好在同一秒到期。


现在,已在 2010 年发布了更新的证书(与过期的证书共享其私钥)(ComodoUSERTrust)。这些证书是当今常见的 Root CA 存储(包括 Apple 的系统信任存储)的一部分,因此浏览器可以完美地建立连接。对于大多数 cURL 变体(例如来自 MacPorts 或 Homebrew)也是如此,它们是针对自定义 OpenSSL 安装构建的。

macOS 10.14 的内置 cURL 变体是针对 LibreSSL 构建的,并/etc/ssl/cert.pem用作其根 CA 存储,其中还包括新证书。但是,似乎有些东西会导致 cURL 或 LibreSSL 更喜欢旧证书进行有效性检查。我想 cURL 至少在某种程度上涉及到问题,因为我无法使用/usr/bin/openssl s_client/usr/bin/openssl实际上是从 LibreSSL 构建的)连接失败

我的假设是问题是由站点将过期的根 CA 证书作为其证书链的一部分发送的。在此类链中包含根 CA 是允许的,但不是必需的,在这种情况下似乎会破坏证书验证。


编辑:这是围绕“AddTrust External CA Root”到期的一系列问题的一部分。请参阅Andrew Ayer 的这篇博客文章或Ryan Sleevi 的这个Twitter 线程以了解更大的图景。Ryan Sleevi 也有一系列因过期而失败的东西。

在 macOS 10.15 上,cURL 默认使用 OpenSSL 0.9.8,显然可以通过设置 environment variable来缓解这个问题CURL_SSL_BACKEND=secure-transport这不适用于带有 LibreSSL 的 10.14,根据 Christian Heimes的说法,它通常会受到该问题的影响。

只需注释掉 中的AddTrust条目/etc/ssl/cert.pem,因为最终证书是交叉签名的,它们将针对USERTrust.

从理论上讲,不需要注释掉该条目,但实际上,mac 附带的 LibreSSL 版本(Catalina 上为 2.8.3)破坏了证书路径验证,因为它基于旧版本的 OpenSSL,其中也包含相同的错误(< 1.1.1)。

根据 LibreSSL 文档(https://www.libressl.org/releases.html),他们开始在他们的 3.xx 系列中加入 OpenSSL 1.1.1 功能,我可以找到一种手动更新它的方法,但我很懒惰并且将等待Apple修复它。

至少有一个解决方法macOS 10.15.4

我今天与 codecov bash 脚本一起遇到了同样的问题。我的快速修复:按照建议brew install curlbrew link curl您可以检查是否选择了正确的卷曲which curl(应指向/usr/local/opt/curl/bin/curl)。

我没有时间或耐心等待🍏解决这些问题。

我发现的所有这些站点似乎都在其链中具有相同的过期 CA 证书:

openssl s_client -connect kapeli.com:443
CONNECTED(00000003)
depth=3 C = SE, O = AddTrust AB, OU = AddTrust External TTP Network, CN = AddTrust External CA Root
verify error:num=10:certificate has expired
notAfter=May 30 10:48:38 2020 GMT

我现在看到许多不同的网站上出现了关于此的问题。当站点未在响应中发送过期证书时,像@jmibanez 建议的那样编辑 ca cert 文件可能会起作用。我尝试了来自https://curl.haxx.se/ca/cacert.pem最新 CA 证书文件curl --cacert path/to/cacert.pem,但没有成功。浏览器似乎很好,因此它们似乎忽略了网站响应中包含的过期 CA 证书。

编辑:我在这里不好。我错误地使用了 curl 7.54。较新的版本正在运行。使用 curl 7.67/7.70 时不存在该错误。