從sslyze看TLS證書的點點滴滴

縱觀眼下,https已經深入大街小巷,成爲網絡生活中不可或缺的一部分了。提到了https,我們又不得不想到TLS(SSL),而提到了TLS,我們又不得不提到一個讓人捉摸不透的東西:TLS證書。

關於證書的原理,這裏就不展開了,簡言之,就是服務器讓客戶端放心,我就是你要找的那個,不信你看看那誰誰給開的介紹信。

在日常使用或者開發中,我們有時會不可避免地需要分析診斷TLS證書,而分析證書呢,有一款非常不錯的開源工具你應該不會錯過:sslyze

這篇文章旨在提綱挈領地跟大家一起通過使用sslyze進行TLS證書分析診斷的結果,從而熟悉下證書診斷的點點滴滴的知識。證書相關的知識比較龐雜,說點點滴滴也有點寒酸,充其量只能是些皮毛,算是拋磚引玉吧。姑且先讓我們順着sslyze的思路,邊走邊聊吧。

1. 安裝及使用

sslyze是一個python項目,安裝使用比較容易:

pip install --upgrade sslyze

如果想使用它來進行對某個域名對應的證書進行診斷,比如說我想知道www.baidu.com這個域名對應的證書是不是合法。大家知道,證書是服務器傳給客戶端的,而在什麼時候傳的呢,那是在TLS握手的時候傳的,而我們知道TLS是建立在TCP之上的,要進行TLS握手,必須先有了TCP連接,而要進行TCP連接,必須知道五元組(源目地址、端口和協議),關於這個目的地址,就有文章可做了,萬一host這個證書是在不同的服務器上、對應於不同的ip呢?比如說,www.baidu.com這個域名對應了10個ip,我更新了證書了,但是我不確定某個服務器ip對應的證書是不是跟其他的一樣正確,那我可能需要對某個特定的ip進行診斷,讓sslyze告訴我,你去跟這個ip通信,拿到它傳給你的證書,看看是不是正確。這時,需要這麼辦:

sslyze --certinfo www.baidu.com{36.152.44.96}

其中,36.152.44.96是對應於www.baidu.com的一個ip。

至於其輸出是什麼樣,我們一會再說。

2. 輸出解析

我們通常使用sslyze時,可能會用到兩種輸出。一種是一般的命令行輸出,其優點是,簡潔、可讀性好。另外一種呢,是JSON輸出,這種輸出格式機器友好,便於編程解析,因此也不可或缺。

本來呢,兩種輸出常理之中應該僅僅是格式差異,結果應該是換湯不換藥吧。可是,sslyze的這兩種輸出內容還真是不一樣,而且差別還不小,雖然夠不上互補,但也足以讓初學者難於一一對應上。所以我們還得分別說道說道。

需要首先說明的是,我們以下的輸出是基於sslyze版本2.1.4,而openssl版本是2.8.3.

2.1 命令行文本輸出

在上文中,我們已經提及了這個命令,這裏重複下:

sslyze --certinfo www.baidu.com{36.152.44.96}

其輸出如下:

 1  AVAILABLE PLUGINS
 2  -----------------
 3 
 4   SessionRenegotiationPlugin
 5   OpenSslCipherSuitesPlugin
 6   FallbackScsvPlugin
 7   CertificateInfoPlugin
 8   HeartbleedPlugin
 9   SessionResumptionPlugin
10   EarlyDataPlugin
11   CompressionPlugin
12   OpenSslCcsInjectionPlugin
13   RobotPlugin
14   HttpHeadersPlugin
15 
16 
17 
18  CHECKING HOST(S) AVAILABILITY
19  -----------------------------
20 
21    www.baidu.com:443                       => 36.152.44.96
22 
23 
24 
25 
26  SCAN RESULTS FOR WWW.BAIDU.COM:443 - 36.152.44.96
27  -------------------------------------------------
28 
29  * Certificate Information:
30      Content
31        SHA1 Fingerprint:                  d1f6323db6f2ec81e7023690f49b2d91e0c3993a
32        Common Name:                       baidu.com
33        Issuer:                            GlobalSign Organization Validation CA - SHA256 - G2
34        Serial Number:                     13905183944940287882518820211
35        Not Before:                        2019-05-09 01:22:02
36        Not After:                         2020-06-25 05:31:02
37        Signature Algorithm:               sha256
38        Public Key Algorithm:              RSA
39        Key Size:                          2048
40        Exponent:                          65537 (0x10001)
41        DNS Subject Alternative Names:     ['baidu.com', 'click.hm.baidu.com', 'cm.pos.baidu.com', 'log.hm.baidu.com', 'update.pan.baidu.com', 'wn.pos.baidu.com', '*.91.com', '*.aipage.cn', '*.aipage.com', '*.apollo.auto', '*.baidu.com', '*.baidubce.com', '*.baiducontent.com', '*.baidupcs.com', '*.baidustatic.com', '*.baifae.com', '*.baifubao.com', '*.bce.baidu.com', '*.bcehost.com', '*.bdimg.com', '*.bdstatic.com', '*.bdtjrcv.com', '*.bj.baidubce.com', '*.chuanke.com', '*.dlnel.com', '*.dlnel.org', '*.dueros.baidu.com', '*.eyun.baidu.com', '*.fanyi.baidu.com', '*.gz.baidubce.com', '*.hao123.baidu.com', '*.hao123.com', '*.hao222.com', '*.im.baidu.com', '*.map.baidu.com', '*.mbd.baidu.com', '*.mipcdn.com', '*.news.baidu.com', '*.nuomi.com', '*.safe.baidu.com', '*.smartapps.cn', '*.ssl2.duapps.com', '*.su.baidu.com', '*.trustgo.com', '*.xueshu.baidu.com', 'apollo.auto', 'baifae.com', 'baifubao.com', 'dwz.cn', 'mct.y.nuomi.com', 'www.baidu.cn', 'www.baidu.com.cn']
42 
43      Trust
44        Hostname Validation:               OK - Certificate matches www.baidu.com
45        Android CA Store (9.0.0_r9):       OK - Certificate is trusted
46        Apple CA Store (iOS 13, iPadOS 13, macOS 10.15, watchOS 6, and tvOS 13):OK - Certificate is trusted
47        Java CA Store (jdk-13.0.2):        OK - Certificate is trusted
48        Mozilla CA Store (2019-11-28):     OK - Certificate is trusted
49        Windows CA Store (2019-11-10):     OK - Certificate is trusted
50        Symantec 2018 Deprecation:         WARNING: Certificate distrusted by Google and Mozilla on September 2018
51        Received Chain:                    baidu.com --> GlobalSign Organization Validation CA - SHA256 - G2
52        Verified Chain:                    baidu.com --> GlobalSign Organization Validation CA - SHA256 - G2 --> GlobalSign Root CA
53        Received Chain Contains Anchor:    OK - Anchor certificate not sent
54        Received Chain Order:              OK - Order is valid
55        Verified Chain contains SHA1:      OK - No SHA1-signed certificate in the verified certificate chain
56 
57      Extensions
58        OCSP Must-Staple:                  NOT SUPPORTED - Extension not found
59        Certificate Transparency:          WARNING - Only 2 SCTs included but Google recommends 3 or more
60 
61      OCSP Stapling
62                                           NOT SUPPORTED - Server did not send back an OCSP response
63 
64 
65  SCAN COMPLETED IN 0.85 S
66  ------------------------

1-14行,是sslyze自己可以使用的一些plugin,如果不打算自己enable或者編寫plugin的話,我們暫且先略過。

18-21行,表示當前診斷域名www.baidu.com對應的ip是36.152.44.96,這也沒有什麼可爭議的,因爲是我們預先指定的,假如我們不指定,這裏或許就有意義了,會給你看通過DNS解析出來的ip地址,即當前我們診斷的是哪個ip。

29行向下的Certificate Information,纔是我們想知道的東西,讓我們來一一查看。

  • Contents

位於輸出結果的30至41行,主要告訴我們關於證書本身的一些事情,我們要知道,所有的公開的證書都是由一個權威的機構給簽發的,這個機構叫CA(certificate authority),它是一個公開的第三方,是具有一些公信力的第三方機構。

大家知道,我們的系統或者瀏覽器在出廠的時候,就內置了一些CA,比如說我用的MacBook,剛到手就已經爲我內置了一系列世界上公認的一些CA了,這樣可以避免你從一些不安全的地方來獲取他們,因爲,這些CA是所有信任的原點,他們不安全,那麼所有的TLS就都不安全了。這些CA的作用就是來驗證,這些證書是不是自己簽發或者信任的。如果一個CA,比如說GlobalSign Organization Validation CA告訴你說,沒問題的,這個是我簽發的,你就放心好了。那你就可以相信它了。

既然內置了這麼些CA,我們跟服務端TLS通信前,收到了證書,怎麼知道找哪個CA來驗證呢?總不至於把所有的CA都驗證一遍吧?不至於,那樣實在太低效了,你收到的每個證書都會直接告訴你,你應該找誰去驗證,在哪裏告訴的呢?33行有個Issuer字段。我們這裏是GlobalSign Organization Validation CA - SHA256 - G2,告訴我們是GlobalSign的CA簽發的,SHA256簽名的,那後面的G2是什麼意思呢?"G"代表Generation,如果這個CA想換一個chain的話,那直接變成G2、G3就好了。

我們還可以看到這個證書只有在2019-05-09 01:22:02至2020-06-25 05:31:02期間纔是合法的,想要僞造出非法證書也很容易,只要把你的系統時間改到這個之外就可以了。公鑰是RSA的,簽名是SHA256的。

最有意思的是最下面那個DNS Subject Alternative Names,可以看到這麼多的域名使用着和"www.baidu.com"一樣的證書。 

  • Hostname Validation

這個是其實是openssl內置的一個基礎功能,目的是驗證證書裏說的hostname是不是跟你所請求的一致。比如你或者了一個證書A,是合法的證書,但是它不是baidu.com的證書,一下就被識破了,你不能用它來和baidu.com的服務器通信。

  • Android/Apple/Java/Mozilla CA Store

我們前文也說過,任何一個公開的平臺或者瀏覽器,它都必須提供一系列CA集合,用來方便絕大多數一般用戶安全連接網絡。這樣,每一個平臺自己的CA集合就或多或少地跟其他的平臺在這個CA集合上有了差異,這裏sslyze就模擬了這些系統或者瀏覽器的CA集合,來驗證假設用戶在這些平臺上,通過這些系統或者平臺自帶的CA集合,是不是得到證書被信任的結果。

  • Symantec 2018 Deprecation

我見過的每一個證書驗證在這項都會出現這麼一個WARNING,因此,可以斷定這項你就不要擔心了吧。其實,這一項涉及了一個非常狗血的故事,Symantec原本是一個比較大
的CA供應商,在2018年的時候,Google對Symantec簽發證書的方式已經非常不滿到忍無可忍了,於是乎,發佈了一個聲明,決定到2018年某個時間點,就在自己的瀏覽器上判定Symantec的證書都是不合法的,隨後得到了Mozilla的響應,然後Symantec就比較被動了,你簽發的證書已經遭到了兩大瀏覽器的抵制了嘛,然後無奈之下,只得把自己
的簽發證書這塊業務給賣掉了,表示從此金盆洗手,不玩這個了。你現在見到的Symantec證書已經是另外一個公司在運營的了,而且,你也不用擔心,因爲2018年早就過去了,原來那個Symantic簽發的被認定爲非法的證書要麼整改了要麼已經過期了,所以呢,任何健在的證書你都不用擔心這個問題啦。

  • Received/Verified Chain

要了解這兩個Chain,我們先得了解什麼是信任鏈(Trust Chain)。我們剛也提到過,這世間的著名的頂級CA也就那麼幾家,而這世間的證書可謂難以計數,如果每一個證書的申請和維護都由這幾家頂級CA來完成的話,頂級CA可真是煩透了。這時候,分治的思想就來了,頂級CA那是大咖啊,他認證了一些小弟,如果誰要找他,他會說大事找我行,小事就不要找我了,找我的小弟去,跟找我效果差不多。這裏他的這些小弟都是他給背書的,信用自然沒的說,你信任了頂級CA,也就自然信任了他的小弟。這些小弟也叫中間證書(Intermediate Certificate),提供了一個引導用戶到頂級CA的路徑,而且小弟可能還不止一級,小弟還可以信任小小弟,這就形成了一個鏈,這個鏈叫做“信任鏈”。

這具體是怎麼操作的呢?我們來看下圖:

用戶在訪問baidu.com的時候,首先通過DNS解析拿到某個服務器IP,連接到某個服務器,在TLS握手過程中,首先獲得baidu.com的證書,用戶一看它的Issuer,是GlobalSign Organization Validation CA - SHA256 - G2,而這也不是已知的頂級CA,於是又問服務器要GlobalSign Organization Validation CA - SHA256 - G2證書(實際是跟baidu.com證書一起發送給用戶的,這裏只是爲了讓大家容易理解一點),再看它的Issuer,一看是GlobalSign Root CA,這是他知道的一個頂級CA,那就到此爲止了,不必再麻煩服務器了。再回頭看下,我們剛纔接收到了幾次證書?一共是兩次,baidu.com -> GlobalSign Organization Validation CA - SHA256 - G2,兩次到達了頂級CA,這個鏈就是所謂的Received Chain。由此可見,服務器不光要保存baidu.com這種域名對應的證書,還要保存其中間證書,因爲用戶也需要從它這裏獲得。

證書都已經齊活了,那用來幹嘛呢?那自然是用來驗證了。首先還是驗證baidu.com的有效性,從它的Issuer字段知道,它是由GlobalSign Organization Validation CA - SHA256 - G2簽發的,那我們就拿到GlobalSign Organization Validation CA - SHA256 - G2證書,獲取它的公鑰,然後利用公鑰算法,來驗證baidu.com的簽名,由於公私鑰算法的嚴密性,簽名是非常難以僞造的,如果我們驗證出了簽名是正確的,就可以認爲該證書是GlobalSign Organization Validation CA - SHA256 - G2給簽發的。但是這個GlobalSign Organization Validation CA - SHA256 - G2是剛纔你服務器那裏獲得的,這不等於你自己證明你自己嗎,沒關係,你可以驗證它的Issuer,也就是GlobalSign Root CA,這個是頂級CA,本地有它的證書,那拿過來照着上面的做法來一通,就可以知道GlobalSign Organization Validation CA - SHA256 - G2是不是GlobalSign Root CA 給簽發的了,驗證通過了,那證明就是GlobalSign Root CA簽發了GlobalSign Organization Validation CA - SHA256 - G2,而GlobalSign Organization Validation CA - SHA256 - G2又簽發了baidu.com,從而證明你拿到的baidu.com是有效的。剛剛我們走完了一個鏈,就是baidu.com -> GlobalSign Organization Validation CA - SHA256 - G2 -> GlobalSign Root CA,爲了驗證而爲之的,所以就是Verifed Chain了。

以上過程比較簡化和粗糙,如果能夠說明白了,而且還不暈乎的話,那麼我們就來看看一個實際的而且更加詳實的證書解析結果吧。在本地運行如下openssl命令:

openssl s_client -showcerts -connect www.baidu.com:443

輸出結果如下:

 1 CONNECTED(00000006)
 2 depth=2 C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
 3 verify return:1
 4 depth=1 C = BE, O = GlobalSign nv-sa, CN = GlobalSign Organization Validation CA - SHA256 - G2
 5 verify return:1
 6 depth=0 C = CN, ST = beijing, L = beijing, OU = service operation department, O = "Beijing Baidu Netcom Science Technology Co., Ltd", CN = baidu.com
 7 verify return:1
 8 ---
 9 Certificate chain
10  0 s:/C=CN/ST=beijing/L=beijing/OU=service operation department/O=Beijing Baidu Netcom Science Technology Co., Ltd/CN=baidu.com
11    i:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Organization Validation CA - SHA256 - G2
12 -----BEGIN CERTIFICATE-----
13 MIIJrzCCCJegAwIBAgIMLO4ZPBiCeOo+Q3VzMA0GCSqGSIb3DQEBCwUAMGYxCzAJ
14 BgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTwwOgYDVQQDEzNH
15 // ... 省略若干行...
16 oZ0B5qslIww7JAJAWCT/NAKLlGEQaC+2gOPQX0oKpwLSwJg+HegCyCdxJrKoh7bb
17 nRBHS8ITYjTG0Dw5CTklj/6i9PP735snPfzQKOht3N0X0x8=
18 -----END CERTIFICATE-----
19  1 s:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Organization Validation CA - SHA256 - G2
20    i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
21 -----BEGIN CERTIFICATE-----
22 MIIEaTCCA1GgAwIBAgILBAAAAAABRE7wQkcwDQYJKoZIhvcNAQELBQAwVzELMAkG
23 A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
24 b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xNDAyMjAxMDAw
25 // ... 省略若干行...
26 K1pp74P1S8SqtCr4fKGxhZSM9AyHDPSsQPhZSZg=
27 -----END CERTIFICATE-----
28 ---
29 Server certificate
30 subject=/C=CN/ST=beijing/L=beijing/OU=service operation department/O=Beijing Baidu Netcom Science Technology Co., Ltd/CN=baidu.com
31 issuer=/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Organization Validation CA - SHA256 - G2
32 ---
33 No client certificate CA names sent
34 Server Temp Key: ECDH, P-256, 256 bits
35 ---
36 SSL handshake has read 4265 bytes and written 322 bytes
37 ---
38 New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
39 Server public key is 2048 bit
40 Secure Renegotiation IS supported
41 Compression: NONE
42 Expansion: NONE
43 No ALPN negotiated
44 SSL-Session:
45     Protocol  : TLSv1.2
46     Cipher    : ECDHE-RSA-AES128-GCM-SHA256
47     Session-ID: 42FD0DF68EDA274407EC33AD8B9E98177D10CBE8DA1F07E03F6E03A0CDB58FC3
48     Session-ID-ctx:
49     Master-Key: F863A3EB7527D0EC1F752C26CF8670749F7C02BFE451584E16CAAED22A414374DA5F06A24434CA1B7B69781D7C14AB7D
50     TLS session ticket:
51     0000 - b9 e4 f4 ab 7d 8a 32 7d-f3 56 1b 04 b6 62 89 f9   ....}.2}.V...b..
52     0010 - ff c0 b8 14 dd 2e 87 94-6c 16 c6 28 5a bd a1 e0   ........l..(Z...
53     0020 - ae c7 20 c8 7b c5 10 57-f5 6d 7f 40 a9 75 ed 7b   .. .{[email protected].{
54     0030 - cd 3d 3e 1b c0 c5 86 c7-24 55 ff d4 2c b2 58 e1   .=>.....$U..,.X.
55     0040 - 48 7f b9 e7 b5 c5 e9 0e-3b df 44 ce 5e 1c 03 9f   H.......;.D.^...
56     0050 - 92 a1 9a ec 93 d1 bd f3-f1 89 81 a7 d0 f4 ce 38   ...............8
57     0060 - 4d 87 17 99 d9 d4 eb 4c-46 75 8f e2 4b 62 03 18   M......LFu..Kb..
58     0070 - 63 86 83 e9 d6 54 0b ea-b8 ea bf 87 cc e6 4b c6   c....T........K.
59     0080 - 34 19 0f b0 25 2c a2 66-a4 5f 99 90 bd 61 00 74   4...%,.f._...a.t
60     0090 - 3e 45 f7 92 e9 2e f9 6c-12 c1 35 8e 4f 3c dd 7a   >E.....l..5.O<.z
61 
62     Start Time: 1585465282
63     Timeout   : 7200 (sec)
64     Verify return code: 0 (ok)
65 ---
66 closed

看看以上openssl輸出結果的第9行以下,Certificate chain那裏,可以看到我們這裏從服務器端接受到了兩個證書,我們應當注意到以下幾點:

  • 證書0的名字(Subject)是baidu.com(CN), 簽發者(Issuer)是GlobalSign Organization Validation CA - SHA256 - G2
  • 證書1的名字是證書0的簽發者,其簽發者是GlobalSign Root CA
  • 沒有收到GlobalSign Root CA的證書
  • Received Chain Contains Anchor

這裏所謂的包含Anchor,其實是服務器端傳遞給客戶端的證書中,包含了根證書。這是不允許的,如果包含了根證書,那會是怎麼樣,根證書是自簽名的,也就是它是可以自己驗證自己的,而且是用你服務器傳過來的驗證,那這還有什麼驗證的價值呢?所以,看到了這個,一定是證書出了問題了,告訴證書管理員,把Chain中的根證書給去掉,根證書客戶端那裏有的,用不着麻煩服務器。 

  •  Received Chain Order

如果理解了 Received/Verified Chain中所說的,那這裏就很容易理解了。就是告訴你接收到的Chain中的順序不對了。我們先不說不對的順序是什麼,我們先說說什麼是對的吧:

  • 首先是域名對應的證書
  • 其次是中間證書
  • 前一個證書的Issuer必然對應後一個證書的Subject
  • 最後一個證書的Issuer必然是某個Root CA

然後我們來探討一種不對的情況,就是,如果我服務器端處於某種目的,需要準備多個Certificate Path,即最終的Root CA是多個。假設以上baidu.com的例子,現在的Root CA是GlobalSign Root CA,假如服務器那邊還想爲本地沒有這個Root CA的用戶做點什麼,他想加一個比如說Baltimore CyberTrust Root,這樣用戶只要擁有兩個CA中的一個就會驗證成功。而我們知道中間證書的作用是形成一個Chain來連接域名證書和Root CA的,那麼這樣就會形成兩條路徑,可能接受到了兩個不同的中間證書,這樣是合理的,但是卻違背了我們以上說的那個被期望的順序了,即兩個中間證書中的前一個證書的Issuer不對應後一個的Subject,因而會被判定爲"Certificate chain out of order!".

  •  Verified Chain contains SHA1

以上我們已經知道,證書之間是通過“簽名”來構建這個信任鏈的。因而,“簽名”是這個信任鏈安全的核心,而“簽名”一個證書,則需要簽發者擁有一個絕密的只有自己才能知道的私鑰和一個公開的、用來驗證簽名正確性的私鑰,還需要一個單向哈希算法,這樣用自己的公鑰和需要簽名的內容通過這個哈希算法得出一個簽名,任何人可以通過公開的公鑰要驗證,從而確定這個證書是不是他簽發的。剛剛提到這個哈希算法的單向性是非常重要的,因爲,如果非常容易地通過簽名和公鑰來推算出這個私鑰的話,那就可以任意僞造證書了。相比較而言,SHA1就是這種哈希算法中比較弱的了,而SHA256等相對比較強,難以攻破。我們再來看這個檢查項,它表示在驗證證書的過程中,是否包含了SHA1來簽發的證書,如果有,證明這個信任鏈是不夠安全的。

  •  OCSP Must-Staple

要理解這個,我們首先要理解OCSP。OCSP即Online Certificate Status Protocol, 這個是用來幹嗎的呢,還得從歷史說起。話說,自有TLS證書的時候,就有了一個問題,就是萬一某個本來合法的證書泄露了(Leak),變得不安全了,這個證書的所有者,就是使用這個TLS證書來跟客戶端打交道的那些網站等服務器所有者,他們所要做的第一件事就是通知這個證書的簽發機構,幫我吊銷這個證書吧,免得不法分子正在冒充他跟客戶端通信。證書的簽發機構(CA)就會標記這個證書被吊銷了(Revoke)。客戶端怎麼知道哪些證書被吊銷了呢?這時,CA提供一個機制,就是定期把所有被他吊銷的證書打包,然後客戶端定期下載,當客戶端下次拿到一個證書後,就會跟這個吊銷的集合進行比對,來確認證書是否被吊銷。問題來了,定期下載,太頻繁吧,客戶端嫌麻煩,不頻繁吧,這容易漏掉某個剛剛被吊銷的,而且,被吊銷的證書每天有千千萬,這些證書原來對應的網站可能用戶絕大多數都訪問不到,這低效性可見一斑。怎麼辦呢?可能你已經想到改進措施了,就是用戶每次拿到一個證書後,自己到這個CA去驗證一下,看看有沒有被吊銷,這就形成了OCSP,這樣確實能夠避免了用戶下載過多沒有用的證書,也避免了因爲時效性問題導致的把被新吊銷的誤判。可是,這樣也不是沒有成本的,用戶每次TLS會話都需要訪問CA來次檢查,對用戶太低效,對CA服務器那邊也是壓力,而且用戶看了什麼網站都需要向CA彙報一次,那也就等於CA可以一直監控用戶的網絡行爲,這樣用戶也是不開心的。那這樣改進下,咱也不用客戶去檢查了,把這個負擔轉嫁給服務器吧,服務器每隔一段時間都去CA那邊報道下,讓他給像簽發證書一樣簽發一個證明,表示這個證書沒有過期,每次客戶端來訪問的時候,服務器就把這個證明連同證書一起發給客戶端,客戶端拿CA的公鑰輕鬆一驗證就知道真假,也不用去請求CA服務器了,服務器這邊也只要隔一段時間纔去CA請求一次這個證明就能保證用戶拿到的證書都不過期的,是不就是皆大歡喜。這裏的這個證明我們叫做Staple,這個TLS證書的擴展功能就是OCSP Must-Staple。用戶在TLS握手的時候,看到這個標記了,就知道服務器傳過來的證書中包含了staple,那客戶端驗一下就可以了。

  • Certificate Transparency 

所謂Certificate Transparency,其實就是一個開放標準用以限制或者要求CA不會亂簽發證書,特別是對於一個域名相關的證書進行亂簽發,比如一個CA給baidu.com簽發了證書,如果他再給另外一個組織簽發next.baidu.com,這可就亂套了,所以baidu.com的管理員需要有某種方法,來監控(或者某種意義上說是監督)這個CA,要按套路。爲了保證證書的透明度,證書界出了一個“正義聯盟”,它推出了一個Certificate Transparency Project,主要達成以下目的:

  1. 讓一個CA不可能或者說很難簽發一個域名下的證書而不被這個域名的管理員發現
  2. 提供一個審計和監控平臺,這樣域名管理員和CA就可以輕易地發現某個證書被錯誤地或者惡意地簽發了
  3. 方便地告訴用戶,某個域名被錯誤地或者惡意地使用了

它是如何保證工作的呢?這個項目的核心就是使用一個append-only log系統,來保存所有的證書記錄,每個證書在簽發的時候一定要向這個系統提交這個證書的記錄,所以每個證書籤發成功的時候返回一個記錄在證書中回執,就是Signed Certificate Timestamp (SCT),這是一個憑證,表示這個log系統已經接受了這個證書的信息了。

Google的Chrome作爲這方便的先鋒,被業界認可,他倡導了CA的一些規範,總結下來主要有如下幾點:

  1. Certificate Extension:證書中要包含SCT
  2. TLS Extension:SCT信息通過一個TLS擴展字段signed_certificate_timestamp包含在TLS握手中
  3. OCSP Stapling:CA必須支持域管理者使用OCSP Stapling

假如這個證書缺少其中一項或者幾項的功能,你或許會看到類似這樣的信息“WARNING - Only 2 SCTs included but Google recommends 3 or more”。

  • OCSP Stapling

這一項在上面OCSP Must-Staple中已經介紹過了,OCSP Must-Staple事實上是證書的一個擴展,而OCSP Stapling是服務器的一個功能,即是不是在客戶端向服務器發出stapled OCSP請求的時候給出相應的迴應。

2.2 JSON輸出

我們先前也提到過,JSON輸出便於代碼解析,因此在sslyze這個工具使用中場景甚至多餘命令行輸出。對應於上面的例子,這裏我們用JSON輸出一遍:

sslyze --certinfo --json_out=- www.baidu.com

其結果如下所示(注:這裏結果非常詳細,但也非常冗長,爲了不影響觀看,對某些內容做了摺疊,請大家注意行號):

 剔除一些一眼就能知道的內容,上面的輸出結果中,我們可以看到主要有certinfo和server_info兩塊內容,而其中server_info又都是server本身的一些信息或者再TLS握手中拿到的信息,與證書本身關聯不大,因而,我們還是把注意力集中在certinfo上吧。

  • leaf_certificate_has_must_staple_extension

 跟命令行輸出結果中“OCSP Must-Staple”對應,表示證書中是否含有OCSP must-staple擴展。

  • leaf_certificate_is_ev

我們能遇到的證書可以分爲三類,即Domain Validated (DV), Organization Validated (OV)和Extended Validated (EV),我們先對比下他們的差異:

    • DV:
      • 單個域名級別的認證
      • 便宜
    • OV:
      • CA在簽發這個證書的時候驗證公司信息
      • 安全性比DV高
      • 比DV稍貴
    • EV:
      • 比上面兩種安全性都高
      • 用戶鍵入瀏覽器時會顯示公司名,且顯示爲綠色(看瀏覽器)

對比了以上之後,不用我說了吧,EV是對用戶最好的,對服務提供商而言,除了貴,其他都好。

  • leaf_certificate_signed_certificate_timestamps_count

關於Signed Certificate Timestamp (SCT)上面已經介紹過了,這裏可以認爲跟上文所述的“Certificate Transparency”類似,表示含有多少個SCT檢查項。

  • leaf_certificate_subject_matches_hostname

即域名跟證書是否匹配,跟上文的“Hostname Validation”相類似。

  • ocsp_response/ocsp_response_is_trusted/ocsp_response_status

用戶要求服務器發送Stapled OCSP時,服務器的返回,以及本地驗證結果如何,具體道理在命令行輸出“OCSP Stapling”中我們提及過,他們是類似的。

  • path_validation_error_list/path_validation_result_list

 在命令行輸出分析中,我們也提及過,在不同的平臺上Root CA的集合可能不同,而從域名證書 -> 中間證書 -> Root CA 的路徑可能會有差別。“path_validation”實際就是模擬各個平臺或者系統對其驗證的路徑的遍歷結果,如果驗證失敗了,就會追加到“path_validation_error_list”中,如果成功了,自然會在“path_validation_result_list”中。

  • received_certificate_chain

關於“Received Chain”,我覺得上面已經囉囉嗦嗦一大堆了,在你覺得煩躁前我決定就此打住。需要看詳細的Received Chain,這裏提供了一個比較友好的方式,而不必用openssl了。

  • received_chain_contains_anchor_certificate

與命令行輸出中“Received Chain Contains Anchor”中的意思是一致的。

  • received_chain_has_valid_order

與命令行輸出中“Received Chain Order”類似。

  • verified_certificate_chain

選擇其中一個path進行驗證的結果,這一項可以看到上面所說的詳細的Certificate Chain。

  • verified_chain_has_legacy_symantec_anchor 

 與命令行輸出結果中“Received Chain Contains Anchor”類似,不過這裏有些許區別,它是檢查在verified chain,以確保在verified chain中不包含Symantec的root CA,因爲我們不希望這個verified chain通過驗證、而僅僅是通過Symantec的root CA讓它通過的。

  • verified_chain_has_sha1_signature

 與命令行輸出結果中“Verified Chain contains SHA1”一致。

3. 參考文獻

[1] https://docs.microsoft.com/en-us/windows/win32/seccrypto/certificate-chains

[2] https://blog.qualys.com/ssllabs/2017/09/26/google-and-mozilla-deprecating-existing-symantec-certificates

[3] https://cheapsslsecurity.com/p/what-is-ssl-certificate-chain/

[4] https://knowledge.digicert.com/solution/SO16297.html

[5] https://scotthelme.co.uk/ocsp-must-staple/

[6] https://www.globalsign.com/en/blog/what-is-certificate-transparency

[7] https://comodosslstore.com/resources/dv-vs-ov-vs-ev-ssl-which-certificates-are-good-for-site-security/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章