[Security] SSL—HTTPS 背後功臣

Security 資訊安全系列文第三篇 🤓

上一篇講到 SSH (Secure Shell),一種加密連線方式,確保我們對遠端伺服器發送指令時,能夠不被竊聽或是竄改命令。本篇一鼓作氣,來介紹與 SSH (縮寫)只有一字之差的 SSL–Secure Sockets Layer。它們不僅名字相似,功能/目的也滿接近的。對了,這是 Security 資訊安全系列文第三篇!

本篇文章會從 SSL 基礎概念談起,介紹 SSL 背後原理、相關名詞介紹(包含 TLS, CA, chain of trust, OpenSSL)、 OpenSSL 實際操作、與 SSL 憑證種類。開始吧!

SSL: Secure Sockets Layer

當我們瀏覽網頁時,我們都有個好習慣:先檢查網址列的開頭是不是有個 🔒鎖的圖案。

這個鎖代表什麼?代表你現在連線到的網站是安全可信任的。更準確的說,這個鎖的記號代表你與這個網站是使用安全的 HTTPS (HTTP Secure) 連線,而不是使用不安全的 HTTP protocol。連線後,只有瀏覽器本人跟網站能夠解讀雙方之間傳遞的資料,就算其他人想要從中攔截(比如說你的使用者帳號密碼),也沒辦法。

HTTPS 背後的 protocol,就是 SSL。

SSL 加密步驟

SSL 讓瀏覽器(所謂的 client)要連到一個遠端網站(所謂的 server)之前,先要求這個網站提供身分認證,跟這個網站約定暗號(交換鑰匙),打好交情(建立加密的 session),才會心甘情願地跟這個網站連線。可以分成六個步驟:

  1. 瀏覽器對想要連線的網站送出連線請求,同時要求網站驗證自己。
  2. 網站將自己的 SSL 數位憑證 (SSL certificate) 回傳給 client,裡面包含了網站的 public key。
  3. 瀏覽器驗證網站回傳的的 root certificate,透過 chain of trust 機制 確認這個證明文件是否可以被信認,同時也確認這個憑證是否過期。
  4. 當認證通過,瀏覽器會用網站的 public key 建立一個 symmetric session key
  5. 網站用自己的 private key 解讀 session key,並且回傳一個確認訊息,開始一個被 SSL 保護的 session。
  6. 這個 session key 會被用來加密所有之後瀏覽器與網站之間傳送的資料。

下面來介紹一些 SSL 相關名詞。

TLS: Transport Layer Security Protocol

上一篇文中有稍微提到 TLS 的歷史,簡而言之,由於 SSL 已經不再安全(POODLEDROWN 是兩個曾經發生過的著名攻擊),所以現在已經被 TLS protocol 取代。慣性使然,當我們說 SSL(比如說 SSL 憑證)時,大部分情況其實是在說 TLS。

CA: Certificate Authority

數位憑證認證機構,簡稱 CA,是負責發放與管理數位憑證 (certificate)的單位。前面提到進行 SSL 連線的前置作業是 server 要提供數位憑證讓瀏覽器驗證,但瀏覽器要怎麼驗證?它會去看這個憑證是不是被一個它相信的 CA 簽署的。如果是,那瀏覽器就相信這個 server 可以信任,如果不是,那瀏覽器就再看這個 CA 有沒有它自己的 certificate,如果有,而這個 certificate 是被一個瀏覽器信任的 CA 簽的,那就放行,如果沒有,就再往下找。如果一路找下去,找不到可以信任的 CA,就失敗。

假設今天世界上有甲乙丙三家 CA。CA 丙簽了 CA 乙的憑證,而 CA 乙簽了 CA 甲的憑證。瀏覽器小明想連線到網站 A,而小明只知道 CA 丙。連線前,網站 A 傳了它的 certificate 們給小明。小明先看第一張,眉頭一皺,發現 A 的憑證是不認識的 CA 甲簽的,往下翻,看到 CA 乙簽了甲的憑證,但小明也不認識乙,所以繼續往下翻,下一張是乙的憑證,是 CA 丙簽署的—bingo! 於是網站 A 順利與小明建立連線。

所以 CA 其實很像保證人的角色,它向瀏覽器保證一個網域的合法性,讓想要連線的那一方確保自己的連線對象是安全的。

Chain of Trust

這樣一層一層檢查 certificate,直到找到信任的 CA 的機制,叫做 chain of trust。你可能會疑惑,為什麼不直接讓所有 server 都帶著 CA 丙簽的 certificate 就好了?為什麼還需要經過這麼多層?主要原因是安全。如果今天壞人 B 找到一個破解 CA 甲的方法,可以偽造甲的簽名,這個漏洞一旦被發現,所有被甲簽過的憑證就都沒有意義了,那些網域必須要重新找 CA 來擔保自己的合法性。

使用 chain of trust 的好處是,它可以降低 root CA(chain of trust 的源頭 CA,就是例子中的 CA 丙)被暴露的風險。不過這也代表,要成為一個 root CA,安全防護必須要做到謹慎再謹慎,不然如果 root CA 的私鑰被攻破了,後果不堪設想。

OpenSSL

SSL/TLS 是 protocol,而 OpenSSL 就是一個開源的實作(SSH 與 OpenSSH 也是同樣的關係)。

捲起袖子玩一玩

如果你的電腦是 Unix 系列的,很大的機率是系統已經裝好 OpenSSL 了。如果是 Windows 系統,也可以直接去網站下載最新的版本。

$openssl version
LibreSSL 2.6.5

可以先打開終端機,試試 version 指令,如果有回傳版本給你,就代表你的電腦已經有 OpenSSL 了。

$openssl help(或是任何 OpenSSL 不認得的指令...)就可以看到 OpenSSL 提供的指令包。

其中 s_client 是一個挺實用的工具,讓我們診斷與測試 SSL 的安全連線。下面示範測試 jennycodes.me 網站的 SSL 狀態。

$openssl s_client -connect jennycodes.me:443 -servername jennycodes.me

CONNECTED(00000005)
depth=2 C = IE, O = Baltimore, OU = CyberTrust, CN = Baltimore CyberTrust Root
verify return:1
depth=1 C = US, ST = CA, L = San Francisco, O = "CloudFlare, Inc.", CN = CloudFlare Inc ECC CA-2
verify return:1
depth=0 C = US, ST = CA, L = San Francisco, O = "CloudFlare, Inc.", CN = sni.cloudflaressl.com
verify return:1
---
Certificate chain
 0 s:/C=US/ST=CA/L=San Francisco/O=CloudFlare, Inc./CN=sni.cloudflaressl.com
   i:/C=US/ST=CA/L=San Francisco/O=CloudFlare, Inc./CN=CloudFlare Inc ECC CA-2
 1 s:/C=US/ST=CA/L=San Francisco/O=CloudFlare, Inc./CN=CloudFlare Inc ECC CA-2
   i:/C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root
---
Server certificate
-----BEGIN CERTIFICATE-----
(略)
-----END CERTIFICATE-----
subject=/C=US/ST=CA/L=San Francisco/O=CloudFlare, Inc./CN=sni.cloudflaressl.com
issuer=/C=US/ST=CA/L=San Francisco/O=CloudFlare, Inc./CN=CloudFlare Inc ECC CA-2
---
No client certificate CA names sent
Server Temp Key: ECDH, X25519, 253 bits
---
SSL handshake has read 2642 bytes and written 307 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-ECDSA-CHACHA20-POLY1305
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-ECDSA-CHACHA20-POLY1305
    Session-ID: 5FEF2BA2A72483061BEB18C92222BBC507A1A95749AE67094F2863D537B7C600
    (略)
    Verify return code: 0 (ok)
---
closed

結果長這樣。解釋一下,我目前用的 SSL 是直接從 CloudFlare (CDN 伺服器)設定,不影響效用,但是 certificate 不會看到 jennycodes.me 的字樣。從上面一路看下來,certificate chain 的部分可以看到 openssl client 經過兩步 chain of trust 就認證了 jennycodes.me 網域(CloudFlare Inc ECC CA-2 -> Baltimore CyberTrust Root),緊接著的是 server certificate 內容,再下面可以注意的是 SSL-Session 下的 protocol 是用 TLSv1.2,而不是 SSL。

如果加上 -state 指令,變成:

$openssl s_client -connect jennycodes.me:443 -servername jennycodes.me -state

就會看到前面出現這段

SSL_connect:before/connect initialization                                                                               
SSL_connect:SSLv3 write client hello A
SSL_connect:SSLv3 read server hello A
depth=2 C = IE, O = Baltimore, OU = CyberTrust, CN = Baltimore CyberTrust Root
verify return:1
depth=1 C = US, ST = CA, L = San Francisco, O = "CloudFlare, Inc.", CN = CloudFlare Inc ECC CA-2
verify return:1
depth=0 C = US, ST = CA, L = San Francisco, O = "CloudFlare, Inc.", CN = sni.cloudflaressl.com
verify return:1
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server key exchange A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:SSLv3 read server session ticket A
SSL_connect:SSLv3 read finished A

可以看到連線前的握手過程,逐步確認 SSL 連線的步驟是否正確,滿好玩的。

再來,上面的指令只會顯示最前面那張 certificate 內容(也就是 server certificate)。如果想要看到所有的 certificate ,可以加上 -showcerts

$openssl s_client -connect jennycodes.me:443 -servername jennycodes.me -showcerts

就可以拿到包含 root certificate 的所有憑證了。

光是 s_client 就有很多指令可以用了,這邊送上 s_client 的 man page,請好奇的人自行欣賞。

SSL 憑證種類

依照安全層級(validation level)分類的話,SSL 憑證可以分成三種:Domain Validated (DV), Organization Validated (OV), Extended Validation (EV)。以下分別介紹:

Domain Validated SSL Certificates (DV)

SSL 中安全層級:低
費用:低

CA 認證時,單純確認這個組織是否真的擁有這個網域(通常使用 email 確認)。

從上面的那三張 certificate 名稱中就已經可以看到該組織用的是哪一種 SSL certificate 了。拿 PicCollage 當例子,中間的那張 Sectigo RSA Domain Validation Secure Server CA 代表 PicCollage 使用的是 DV certificate。下面的 Details 欄位也可以看到 subject 就只有單純顯示 common name 這個資訊。

Organization Validated SSL Certificates (OV)

SSL 中安全層級:中
費用:中

CA 除了確認該組織是否擁有這個網域之外,也會聯絡並稍微調查該組織,確認該組織是可信的。發放的憑證中會有該組織的相關資訊,像是名字與位置。

跟 DV 比起來,OV 可以看到的訊息就更多,像是地區與組織名稱。

Extended Validation SSL Certificates

SSL 中安全層級:高
費用:高

CA 除了該組織的網域所有權、組織基本資料、實體位置,還會驗證該組織的法律地位。這種證書需要組織提供文件與耐心 (?) 來等待審核通過。

EV 比起 OV 又多了一些資訊,像是 business category 與 serial number。同樣可以從上面的 certificate issuer 看到這是 EV 等級的 SSL 憑證。

若是依照網域/子網域數(number of secured domains/subdomains)分類,則 SSL 憑證也可以分成Wildcard, Multi-Domain (MDC), Unified Communications (UCC) 三種。這邊比較直觀,就不細講啦。

後話

最近我們的 Android team 遇到一個問題:有兩台 Samsung 的測試手機不知道為什麼一直無法連到 PicCollage 伺服器拿資料,錯誤訊息顯示是因為 SSL 無法認證。有趣的是只有這兩台 Samsung 手機出事,如果是 SSL 憑證的問題應該是所有手機都會被影響。我們試了一些不同方法,後來參考這裡這裡將 server certificate 掛在 Android 程式碼中,直接承認這張 certificate 的合法性。可以動了,卻不是根本性的解法。

後來,找到了原因:這兩台 Samsung 裝置的系統時間被改過了(改到了很久以後的未來),而我們的 SSL 最近剛要過期,所以系統認為我們的 SSL 憑證早就已經過期了...

也是因為如此,這篇文章才會這麼早出現(本來想先寫其他更有趣的主題)(SSL 對不起),為了追這個 bug,順手查了一些相關資料,想想其實乾脆再順手一點,就把 SSL 寫出來了。

下回預告

最近在研究 Ruby on Rails 的效能與記憶體,新年之前不知道有沒有辦法再出一篇。如果沒有的話,新年快樂!


  • Find me at