Sectigo AddTrust根证书过期引发的https请求失败问题

系统访问了一个公网https地址,报错https证书过期,但在chrome上查看证书,还没有到过期时间,最后排查是证书颁发机构的根证书过期了。

 

背景:

系统访问了一个https地址,证书校验未通过,报错如下:

20-12-10.10:11:59.244 [xxx] ERROR HttpClientUtil          - sendPostRequest 发送HTTP异常 Exception url=[https://wodeyuming.com/xxx],requestData=
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1884)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1439)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:209)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:878)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:814)
        .................(省略)
Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
        at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:350)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:260)
        at sun.security.validator.Validator.validate(Validator.java:260)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1421)
        ... 81 common frames omitted
Caused by: java.security.cert.CertPathValidatorException: timestamp check failed
        at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:159)
        at sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:351)
        at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:191)
        at java.security.cert.CertPathValidator.validate(CertPathValidator.java:279)
        at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:345)
        ... 87 common frames omitted
Caused by: java.security.cert.CertificateExpiredException: NotAfter: Sat May 30 18:48:38 CST 2020
        at sun.security.x509.CertificateValidity.valid(CertificateValidity.java:273)
        at sun.security.x509.X509CertImpl.checkValidity(X509CertImpl.java:575)
        at sun.security.provider.certpath.BasicChecker.verifyTimestamp(BasicChecker.java:184)
        at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:136)
        at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:133)
        ... 91 common frames omitted

 

问题排查:

timestamp check failed,时间校验失败,第一反应是查看证书是否过期,通过chrome查看证书信息,到过期时间还有一段时间,排除域名证书过期问题。

难道是服务器时间不对?登录服务查看也没有问题,时间是准确的。

Sectigo AddTrust根证书过期引发的https请求失败问题_第1张图片

继续排查,日志中打印了证书过期时间,是2020年5月30号:NotAfter: Sat May 30 18:48:38 CST 2020

为了验证确实是时间的问题,我把服务器的时间修改到了5月30日之前,经过验证,访问成功了,确实是获取到的证书的时间问题,难道域名使用的证书和代码获取到的不是同一个吗?

到这里,又开始怀疑是不是服务器上缓存了过期的证书,但是又不知道缓存位置在哪里,多次查找和更新,仍然无果...但确定的是,服务器上肯定有一个证书,过期时间是5月30日,这个证书被用到连接校验过程中了。

其实,如果清楚https的校验原理,问题很快也就明确了...

最后的突破点还是这个过期时间,因为时间是固定的,可以尝试查找跟这个时间有关的信息,拿Sat May 30 18:48:38 CST 2020这个时间去搜索,最后还真的找到了原因。

其实想查看证书是否有效,这里还有一个方法,是在解决过程中知道的,就是openssl这个命令,这里也记录一下,

命令:openssl s_client -connect httpsyuming.com:443,可以看到,这里提示很明确了,包括过期证书的名称、签发机构等,

[my@*** ~]$ openssl s_client -connect httpsyuming.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
---
Certificate chain
 0 s:/OU=Domain Control Validated/OU=PositiveSSL Wildcard/CN=*.httpsyuming.com
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
 1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
 2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
---
Server certificate
-----BEGIN CERTIFICATE-----
...(省略)

 

原因:

我访问的https域名,证书是由Sectigo颁发的,其根证书名为AddTrust External CA root,这个根证书在2020年5月30日已经到期了。
官方还发过一个通告:Sectigo AddTrust External CA Root Expiring May 30, 2020
原地址:https://support.sectigo.com/articles/Knowledge/Sectigo-AddTrust-External-CA-Root-Expiring-May-30-2020
国内上海锐成的中文版说明:https://www.racent.com/blog/about-sectigo-addtrust-root-expiration

在官方的公告中,已经将根证书的原理、到期影响,以及解决方案进行了说明,这里把中文版贴在文末,方便后续查看(附在文末)。

 

解决方法:

更新证书信任列表,将下载的证书导入信任列表。证书下载地址如下:

●    USERTrust RSA CA- https://crt.sh/?id=1199354
●    USERTrust ECC CA- https://crt.sh/?id=2841410
●    COMODO RSA CA- https://crt.sh/?id=1720081
●    COMODO ECC CA- https://crt.sh/?id=2835394

 

导入方法:

1、java使用HttpClient访问https,所以需要将证书导入到jre下的lib/security/cacerts文件作为信任证书

(1)找到jdk的目录,查看证书文件cacerts中,过期的根证书别名

查看所有的证书,可以拿 AddTrust External CA这里的关键字去搜索

/jdk1.7.0_71/jre/bin/keytool -list -v -keystore /jdk1.7.0_71/jre/lib/security/cacerts | less

因为我已经找到了,这里直接接了-alias参数,指定别名把证书信息列出来了,要求输入keystore password,密码默认是:changeit。(下面的路径都是处理过的,要根据实际去操作)

所以,这个过期的证书Alias name: addtrustexternalca

[xx@*** ~]$ /jdk1.7.0_71/jre/bin/keytool -list -v -alias addtrustexternalca -keystore /jdk1.7.0_71/jre/lib/security/cacerts
Enter keystore password:  
Alias name: addtrustexternalca
Creation date: May 2, 2006
Entry type: trustedCertEntry

Owner: CN=AddTrust External CA Root, OU=AddTrust External TTP Network, O=AddTrust AB, C=SE
Issuer: CN=AddTrust External CA Root, OU=AddTrust External TTP Network, O=AddTrust AB, C=SE
Serial number: 1
Valid from: Tue May 30 18:48:38 CST 2000 until: Sat May 30 18:48:38 CST 2020
...(省略)

(2)删除过期证书

/jdk1.7.0_71/jre/bin/keytool -delete -trustcacerts -alias "addtrustexternalca" -keystore /jdk1.7.0_71/jre/lib/security/cacerts -storepass changeit

(3)导入下载的新证书(新证书的校验原理也不是直接替换原证书的,具体见后面的官方文档,但我们使用上没有区别)

/jdk1.7.0_71/jre/bin/keytool -import -keystore "/jdk1.7.0_71/jre/lib/security/cacerts" -storepass changeit -keypass changeit -alias usertrustrsaca -file 1199354.crt
/jdk1.7.0_71/jre/bin/keytool -import -keystore "/jdk1.7.0_71/jre/lib/security/cacerts" -storepass changeit -keypass changeit -alias usertrusteccca -file 2841410.crt
/jdk1.7.0_71/jre/bin/keytool -import -keystore "/jdk1.7.0_71/jre/lib/security/cacerts" -storepass changeit -keypass changeit -alias comodorsaca -file 1720081.crt
/jdk1.7.0_71/jre/bin/keytool -import -keystore "/jdk1.7.0_71/jre/lib/security/cacerts" -storepass changeit -keypass changeit -alias comodoeccca -file 2835394.crt

 这里我把4个证书都导入了,实际上应该不需要这么多(因为我的环境验证不方便,所以没有具体验证,直接全部导入了,感兴趣可以验证下)

 

2、更新linux证书信任列表

如果是使用java的HttpClient访问https,那第一种方案就可以了,但通过openssl s_client -connect httpsyuming.com:443这种方法还是不行的,因为系统上的证书信任列表还没有更新。

系统上的证书信任列表更新方法如下:

(1)把前面下载的crt格式证书转换为pem格式

openssl x509 -in 1199354.crt -out 1199354.pem -outform PEM
openssl x509 -in 1720081.crt -out 1720081.pem -outform PEM
openssl x509 -in 2835394.crt -out 2835394.pem -outform PEM
openssl x509 -in 2841410.crt -out 2841410.pem -outform PEM

(2)删除过期证书

直接使用vim编辑即可,注意是选择过期的证书内容进行删除,不要删错了,可以先备份。

vim /etc/pki/tls/certs/ca-bundle.crt

删除下面这段

# AddTrust External Root
-----BEGIN CERTIFICATE-----
MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
...(省略)
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
-----END CERTIFICATE-----

(3)导入pem证书(将证书内容追加到/etc/pki/tls/certs/ca-bundle.crt即可)

cat 1199354.pem >> /etc/pki/tls/certs/ca-bundle.crt
cat 1720081.pem >> /etc/pki/tls/certs/ca-bundle.crt
cat 2835394.pem >> /etc/pki/tls/certs/ca-bundle.crt
cat 2841410.pem >> /etc/pki/tls/certs/ca-bundle.crt

除了上面更新证书的信任列表外,也可以修改代码,跳过https证书的验证,但这样风险就比较大,不太建议。

最后,附上将官方说明中的根证书原理概述、到期影响,以及解决方案,以供学习。

 

**********************************************************************

本篇将详细讲解交叉签名、AddTrust根证书过期和过期后的可行性替代方案的相关内容。

什么是根证书?

根证书是自签名证书,它是CA认证中心给自己颁发的证书,所以颁发者和使用者都是它本身。根证书之所以成为受信任的根证书,是因为它默认存储在浏览器或操作系统等软件的信任库中。

这些信任库通常会作为安全更新的一部分,随着浏览器或者OS系统的定期升级而更新,但是在比较老旧的设备或系统中,信任库仅作完整软件更新的一个部分——比如Windows Service补丁或可选Windows升级版本进行更新。

可能有一些设备的信任库没有更新以包含最新的现代根证书,其结果就是满足不了现代互联网所要求的标准。Android就是一个很好的例子。Android 2.3 Gingerbread依赖于AddTrust却没有安装最新的根,所以它也不支持TLS 1.2或1.3,同时它也不被供应商支持并且标记为过时。

什么是交叉签名证书?

CA通常拥有多个根证书,越老的根证书,在一些老的平台上分布就越广。为了利用这一点,CA生成交叉证书以确保其根证书可以尽可能广泛的支持应用。交叉证书就是使用一个根证书去签署另一个根证书。

交叉证书和与被签名的根证书是使用相同的公钥和名字。

举一个交叉签名证书例子:

证书名: COMODO RSA Certification Authority

颁发者: AddTrust External CA Root

https://crt.sh/?id=1044348

新的根证书使用的是与自签名的COMODO根证书相同的名字和公钥。

AddTrust External CA 根证书到期

Sectigo拥有一个名为AddTrust External CA root的根证书,该根证书用于创建Sectigo的现代根证书,如COMODO RSA CA和USERTrust RSA CA这类经交叉签名认证后颁发的根证书(以及这些证书的ECC算法版本)。这类新的根证书直到2038年才到期。

但是,AddTrust根证书将于2020年5月30日到期。

在此之后,客户端和浏览器将链接回之前使用老旧的AddTrust根证书进行交叉签名后的现代根证书。在已更新的设备或平台上将不会显示错误提示。

证书链图

Sectigo AddTrust根证书过期引发的https请求失败问题_第2张图片

没有包含最新USERTrust根证书的旧版浏览器或老式设备将不再信任您的证书,同时会进一步在证书链中查找可信任的根证书,即AddTrust根证书。已安装了USERTrust根证书的最新浏览器就会信任您的证书,而无需依赖旧的AddTrust根证书。

您需要做的事

大多数情况下,包括为现代客户端或服务器系统提供服务的证书,无论您是否已将证书交叉链接到AddTrust根目录,都无需执行任何操作。

从2020年4月30日开始,对于依赖于非常老式系操作统的业务,Sectigo CA已提供一个用于交叉签名的遗留根(默认包含在证书捆绑包中),即“ AAA证书”根。但是,需要值得注意的是,那些没有进行必要更新以支持新根(如Sectigo的Comodo根目录)的系统将不可避免的缺少其他重要更新,并被视为不安全。

如果您仍然想要交叉签名到AAA证书根,请直接联系锐成客服人员协助处理。

常见问题解答

1. 2020年5月30日之后,我的证书是否仍将继续受信任?

答:是。所有新的客户端和操作系统都已有较新的COMODO和USERTrust根证书,这些根证书直到2038年才过期。

在信任库中受到人为限制或无法更新的平台上(例如,嵌入式设备),您将需要自己更新并安装新的Sectigo根证书。请确保这些设备的供应商已经为您的系统进行了必要的安全更新。如有疑惑可向锐成客服人员寻求帮助。

2. 我是否需要重新签发或重新安装我的证书?

答:不用。直到该证书自然到期日为止,您的证书将会一直受信任,不需要重新签发或重新安装。当然如果您愿意,您也可以选择停止在服务器上安装交叉证书。如果考虑到AddTrust到期后需要兼容旧版,我们可以提供替代的交叉证书,您可以在服务器上安装该证书来代替AddTrust交叉证书。

3. 我可以测试是否能看到错误提示吗?

答:可以的。如果您的证书在2020年6月及之后仍然有效,则可以将系统上的时钟设置为2020年6月1日,然后测试站点。

最新的浏览器不会显示任何错误,并且您可以看到证书链回到了COMODO或USERTrust根。(注意:某些浏览器(例如Google Chrome)会检测到您的时钟“错误”,并因此会提示一个与证书无关的警告。)

这是一个测试站点,您可以点击这里http://testsites.test.certificatetest.com/来进行测试评估。

● 这些链接提供了从特定证书链签发的有效证书。

● 它们可用于测试哪些客户端支持哪些根。

● 您还可以将系统时钟调整到2020年6月,以查看客户端在AddTrust根证书和交叉证书到期后如何工作。

新根颁发机构:COMODO RSA / ECC CA和USERTrust RSA / ECC CA:

● USERTrust RSA CA- https://crt.sh/?id=1199354

● USERTrust ECC CA- https://crt.sh/?id=2841410

● COMODO RSA CA- https://crt.sh/?id=1720081

● COMODO ECC CA- https://crt.sh/?id=2835394

* 单击以上链接可提供证书下载。

以上根证书已在大部分主流浏览器和系统如苹果,微软,谷歌等中更新。

此外,带有AAA证书服务的交叉证书仍可与下列旧版本兼容:

• 苹果iOS 3。

• 苹果macOS 10.4。

• Google Android 2.3。

• Mozilla Firefox 1。

• Oracle Java JRE 1.5.0_08。

AAA证书服务自签名根证书[到期2028] - https://crt.sh/?id=331986

AAA证书服务-交叉证书:

AAA证书服务- USERTrust RSA CA- https://crt.sh/?id=1282303295

AAA证书服务- USERTrust ECC CA- https://crt.sh/?id=1282303296 

(COMODO的CA将很快提供交叉证书。)

4. 如果我的基础架构或应用程序仅信任AddTrust根证书怎么办?

答:如果系统或应用程序仅信任AddTrust根证书而不信任新的Comodo或USERTrust根,那么将会在2020年5月30日之后提示错误警告。

针对传统老式系统设备的预防措施和注意事项:

● 必要的话,您可能需要更新此类系统以包含更多新的根证书。如果平台不支持新的算法(例如SHA-2),那么您需要联系系统供应商进行更新。

● 在应用程序或旧版设备中植入了AddTrust根证书的客户可能需要在2020年5月到期日之前嵌入新的USERTrust RSA CA 根进行替换。

● 除了AddTrust根以外,Sectigo还有其他一些比较老旧的根,并且我们从其中一个生成了交叉证书,以扩展向后兼容性。该交叉证书由名为“ AAA证书服务”的根签名。

 

你可能感兴趣的:(运维笔记,https)