那些關於SSL/TLS的二三事(十一) — 關於憑證的維運

Carl
9 min readMay 24, 2018

--

前面已經對 SSL 的原理有了比較詳細的解說, 這篇開始要談的是實作的細節, 首先要談的是 SSL certificate 的開通. 談到開通, 會要解釋如何建立 certificate request, 如何讓 CA 幫你簽, 以及如何在你的網站或是 server 上安裝憑證, 讓其可透過 HTTPS 給外界存取, 當然, 也會稍微談一下如何撤銷憑證 (revoke).

Certificate request and signing

第一步驟, 網站的擁有者要先建立屬於自己的 private key. 這部分可以使用 openssl command 來完成, 指令如下:

$ openssl genrsa -out [name_of_your_key].key 4096

這個指令基本上會建立一個 .pem 格式, 4096 bit 的 RSA 金鑰, 其輸出檔案名稱就如 command 裡面所指定的名稱.

下一步是要去建立一個 certificate signing request (csr), 也是透過 openssl command 來完成, 指令如下:

$ openssl req -new -key [name_of_your_key].key -out [name_of_your_csr].csr

一旦你準備好了 CSR 檔案, 就可以來選擇 CA 了. 市場上的 CA 有很多, 通常會根據 CA 的名聲與價格等因素來選擇. 常見的有GoDaddy, GeoTrust, DigiCert等等. 當你決定好要找哪個 CA 後, 就到他們的網站並且把你的 CSR 傳上去即可.

收到 CSR 後, CA 會根據你的 domain 開始實行一系列的背景審核, 確認你是否是正確/合法的憑證擁有者. 當然, 前面也提到過, 這階段也會根據你所選擇的憑證等級而有不同的作業時間. 如 EV (Extended validation certificate) 可能就要花上10個工作天.

當 CA 完成了審核過程後, 就會簽核你的 CSR 然後把簽過的憑證寄還給你, 通常是一個 .crt 檔案. 詳細一點的說, CA 會根據憑證的資料區段來計算出 checksum, 並且以其 private key 對這段 checksum 進行加密, 然後把這段加密後的密文 (signature) 附加在原本的憑證後並且寄還給你. 這就是你要用來安裝在你的網站或是 load balancer/webserver 上的東西了.

那如果你不想要讓 CA 幫你簽呢? 譬如說你想要自己簽 (self signing). 對自簽來說, 最大的問題就是市場上的瀏覽器沒辦法驗證這些憑證除非你手動將自己的 public key 加到這些瀏覽器的 cert store 裡面. 不過自簽這種事通常也只會用在內部網路裡, 所以通常就是幫內部網路的客戶端安裝 public key 即可.

對於自簽, 一樣可以透過 openssl command 來達成, 指令如下:

$ openssl req -x509 -newkey rsa:4096 -keyout [name_of_your_key].key -out [name_of_your_crt].crt -days 365

記得該填的東西要填一填, 不然會生不出來.

跟CSR有關的安全考量

  • 使用夠長的 bit length 以預防大多數的攻擊: 以 RSA certificate 來說, 建議長度為 2048 或是更長. RSA 512 已經有被破解的紀錄了. 對 ECC 來說, 長度在 192 bits 或是更長會比較好.
  • 保護好你的 private keys: 確認你生成 private key 的時候是在一台安全且可信任的電腦上. 針對存取 private key 的動作進行權限控管, 當持有 private key 存取權限的員工離職後, 產生新的 private key.
  • 慎選你的 CA: 若你選擇了可靠的 CA — 如 SSL.com, 你可以相信你的私鑰跟 SSL 憑證將用於保護傳輸到你的 server 上的資料.
  • 選擇值得信賴的雜湊演算法: SHA2 或著是 SHA3 有比較好的碰撞抗性, MD5 與 SHA1 則都已經被證實會有碰撞出現.

部署你的憑證

一個網站的憑證通常都是跟其相應的私鑰一起被安裝的, 這部分可以安裝在 load balancer 或著是直接安裝在 web server 上. 反過來說, 要終止 SSL, 也可以在這兩個地方上進行.

對一些專業的網站來說, SSL 可能會被設置在 load balancer上, 這是因為瀏覽器是跟網站的 load balancer 進行 SSL handshake, 所以憑證就裝在這. 我們都知道, web server 通常都藏在 load balancer 後面, 在這種配置下, load balancer 跟 web server 之間的通訊基本上用明文就可以了, 因為它們之間的溝通都在內網裡面.

對於 load balancer 不支援 SSL 或是沒有 load balancer 的情況來講, SSL 就需要設置在 web server 這一層上了. 當然, 也有可能 load balancer 是用像 AWS Elastic Load Balancers 這種服務的話, 網站管理人可能會不想把自己的 private key 放到 AWS 上. 對於以上這些情況, 就必須將 SSL certificate 以及 private key 部署到每一個 web server 上了.

當談到將 SSL certificate 部署至 web server 上時, 你要知道怎麼樣去組態你的 web application 以便正確定位到機器上 certificate 以及 key store. 這部分就會根據不同的 application 而有不同的設置方式, 舉例來說, Apache 跟 Nginx 的設定方法可能就會如下圖所示:

大部分的 CA 也會說明如何根據不同的 application server 去組態 SSL 設定, 可以在其網站上找找.

安裝憑證時的安全考量

這些設定是對 load balancer 上的 SSL profile 或是 web server 的 SSL configuration 建議的更動. 主要適用於底層的函式庫功能如 handshake/record. OpenSSL 則是需要安裝在這些機器上的函式庫之一.

  • Cipher 的選擇: 不要使用 RC4, 因為對很多攻擊來說其是很脆弱的 (e.g. BEAST — Browser Exploit Against SSL/TLS).
  • 對 SSLV3, TLS1.0, TLS1.1 來說, AES 不應該被用於 CBC 模式下, 這會造成 BEAST 攻擊, 可以改成 AES + GCM 模式.
  • 禁用匯出 cipher suites 或是使用 null cipher suites, 以及使用 RC4/3DES 的 cipher suites. 對 TLS 1.1, 使用 AES256-SHA, TLS 1.2 則使用 AES256-GCM-SHA256
  • 可以的話, 用 TLS 1.2.

關於憑證的撤銷

儘管很罕見, 但有些時候我們必須要撤銷憑證, 理由可能有:

  • Key compromise: 意思就是說 CA 的 private key 被入侵或是出現內部洩漏的嫌疑, 如知道 private key 的離職員工洩漏了相關資訊. 不管是 key compromise 還是 CA compromise, 對網站來說都是惡意的一種行為.
  • 網站不需要這個憑證了: 意思就是說當初申請憑證的理由已經不存在了.
  • 想要更換當前的 CA, 這時候也需要撤銷.

那麼, 要如何撤銷憑證呢? 首先你需要把你的 certificate 加入 CRL (Certificate Revocation List). 這個列表是對網路上所有人公開的, 其網址通常存在於所有 SSL certificate 的 extension section 之中. 當你存取這個網址時, 就可以看到完整的撤銷列表, 當然這個列表是屬於特定 CA 的.

除了 CRL, 還有另一個替代方案稱為 OCSP (Online Certificate Status Protocol), 這是一種用來獲取 x.509 數位憑證之撤銷狀態的協定. OCSP 優於 CRL 的部分在於 CRL 會回傳給 client 整串 certificate 的列表; OCSP 則是只會回傳特定憑證個內容 (根據你查詢的序號). OSCP 通常是由 CA 來維護的, 你可以使用憑證的序號來查詢該憑證的撤銷狀態.

關於 SSL Errors

這邊會簡單紀錄一下比較常見的 SSL 錯誤訊息:

  • SSL_ERROR_NO_CERTIFICATE
    憑證或是憑證發行者在資料庫裡並不是被標註為可信任的
    Server 端沒有安裝金鑰
  • SSL_ERROR_WRONG_CERTIFICATE
    Client authentication failed: 金鑰資料庫裡的私鑰跟憑證資料庫裡的公鑰對不上
  • SSL_ERROR_UNSUPPORTED_VERSION
    某一端使用了不支援的安全協議版本
  • SSL_ERROR_BAD_CERT_DOMAIN
    請求的 domain name 無法跟 server 的憑證相匹配
  • SSL_ERROR_UNKNOWN_CIPHER_SUITE
    這很白話了
  • SSL_ERROR_UNKNOWN_CA_ALERT
    端點無法識別與信任發行此憑證的CA
  • SSL_ERROR_REVOKED_CERT_ALERT
    端點的憑證被撤銷了
  • PR_CONNECT_RESET_ERROR
    會寫這個是有故事的, 某次某組的人說, 他的https從國外分部打回國內的 application 打不通, 但從國內自己打 application 卻是通的. 某人這時候又說: “我當初有請 infra team 幫忙開通 https 了唷”. 經查明之後, 某人當初在申請表單上填寫的是 “http” 而不是 “https”, 而且 infra team 也沒有把關這件事, 就只是拿到什麼 key 什麼. 所以工作要細心呀~

References

--

--

Carl

Stand for something or you will fall for anything.