三種解密 HTTPS 流量的方法介紹

Jerry Qu發表於2016-04-04

Web 安全是一項系統工程,任何細微疏忽都可能導致整個安全壁壘土崩瓦解。拿 HTTPS 來說,它的「內容加密、資料完整性、身份認證」三大安全保證,也會受到非法根證書、服務端配置錯誤、SSL 庫漏洞、私鑰被盜等等風險的影響。很多同學認為只要訪問的網站地址前有一把小綠鎖就絕對安全,其實不然。本文通過介紹三種最常規的 HTTPS 流量解密方法及原理,淺談一下 HTTPS 的安全風險。

三種解密 HTTPS 流量的方法介紹

Man-in-the-middle

Man-in-the-middle(中間人,簡稱為 MITM),能夠與網路通訊兩端分別建立連線,交換其收到的資料,使得通訊兩端都認為自己直接與對方對話,事實上整個會話都被中間人所控制。簡而言之,在真正的服務端看來,中間人是客戶端;而真正的客戶端會認為中間人是服務端。

實現中間人攻擊有各種各樣的手段,這裡不展開討論。一些常見的 HTTP/HTTPS 抓包除錯工具,都是通過建立本地 Proxy 服務,再修改瀏覽器 Proxy 設定來達到攔截流量的目的,他們的工作原理與中間人攻擊一致。我用過的這一類工具有:FiddlerCharles 和 whistle。我在「HTTP 代理原理及實現(一)」一文中介紹的 HTTP 普通代理,扮演的就是 HTTP 中間人角色。

本文主要討論 HTTPS 中間人,簡單示意如下:

Server <---> Local Proxy <---> Browser
         ^                 ^
       HTTPS(1)          HTTPS(2)

上述 HTTPS(1) 連線,是中間人冒充客戶端,與服務端建立的連線,由於 HTTPS 服務端一般不認證客戶端身份,這一步通常沒有問題。而對於 HTTPS(2) 連線來說,中間人想要冒充服務端,必須擁有對應域名的證書私鑰,而攻擊者要拿到私鑰,只能通過這些手段:

  1. 去網站伺服器上拿;
  2. 從 CA 處簽發證書;
  3. 自己簽發證書。

要防範前兩點,需要網站做好各個方面的安全防護,從主機安全到網站安全(避免私鑰被盜),從域名解析安全到域名郵箱安全(避免攻擊者重簽證書)。而攻擊者自己簽發的證書,無法通過系統內建根證書的驗證,預設無法用於中間人攻擊。

對於 Fiddler 這一類除錯工具來說,能夠解密 HTTPS 流量的關鍵在於他們會往系統受信任的根證書列表匯入自己的證書,這樣他們的自簽證書就能被瀏覽器信任。進入 Fiddler 設定中的「HTTPS」Tab,勾選相關功能後,就可以順利解密和修改 HTTPS 流量。這時在瀏覽器中可以看到這樣的證書鏈:

三種解密 HTTPS 流量的方法介紹

RSA Private Key

我在「使用 Wireshark 除錯 HTTP/2 流量」這篇文章中寫到:Wireshark 的抓包原理是直接讀取並分析網路卡資料,要想讓它解密 HTTPS 流量,有兩個辦法:

  1. 如果你擁有 HTTPS 網站的加密私鑰,可以用來解密這個網站的加密流量;
  2. 某些瀏覽器支援將 TLS 會話中使用的對稱金鑰儲存在外部檔案中,可供 Wireshark 加密使用。

那篇文章介紹了第二種方案,本文簡單介紹第一種。

開啟 Wireshark 的 SSL 協議設定,參考下圖,把 IP、埠、協議和證書私鑰都配上(私鑰必須存為 PEM 格式):

三種解密 HTTPS 流量的方法介紹

然後訪問私鑰對應的網站,可以看到流量已被解密:

三種解密 HTTPS 流量的方法介紹

截圖中的加密資料是以 HTTP/1 傳輸的,這種方式能解密 HTTP/2 流量嗎?結論是:不能!具體原因下面慢慢分析。

我們知道,TLS 握手階段需要進行金鑰交換和服務端認證這兩個重要的操作,金鑰交換是為了在不安全資料通道中產生一個只有通訊雙方知道的共享金鑰 Premaster Secret,進而生成 Master Secret 以及後續對稱加密 Session Key 和 MAC Key。而客戶端進行服務端認證的目的是確保連線到擁有網站私鑰的合法伺服器。

最常見的金鑰交換方式是 RSA,下面這張圖清晰的描述了這個過程:

三種解密 HTTPS 流量的方法介紹

Client Random 和 Server Random 明文傳輸,中間人可以直接檢視。客戶端生成 Premaster Secret 後,用服務端證書公鑰加密後傳送,如果服務端擁有對應的私鑰,就可以成功解密得到 Premaster Secret。這時,客戶端和服務端擁有相同的 Client Random、Server Random 和 Premaster Secret,可以各自算出相同的後續所需 Key。

可以看到,這種方式合併了金鑰交換和服務端認證兩個步驟,如果服務端能解密 Premaster Secret,也就意味著服務端擁有正確的私鑰。中間人沒有私鑰,無法得到 Premaster Secret,也就無法解密後續流量。

對於 Wireshark 來說,配置某個網站的私鑰後,能解密這個網站「使用 RSA 進行金鑰交換」的加密流量就很容易理解了。

顯然,RSA 金鑰交換有一個很大的問題:沒有前向安全性(Forward Secrecy)。這意味著攻擊者可以把監聽到的加密流量先存起來,後續一旦拿到了私鑰,之前所有流量都可以成功解密。

實際上,目前大部分 HTTPS 流量用的都是 ECDHE 金鑰交換。ECDHE 是使用橢圓曲線(ECC)的 DH(Diffie-Hellman)演算法。下圖是 DH 金鑰交換過程:

三種解密 HTTPS 流量的方法介紹

上圖中的 Server DH Parameter 是用證書私鑰簽名的,客戶端使用證書公鑰就可以驗證服務端合法性。相比 RSA 金鑰交換,DH 由傳遞 Premaster Scret 變成了傳遞 DH 演算法所需的 Parameter,然後雙方各自算出 Premaster Secret。

對於這種情況,由於 Premaster Secret 無需交換,中間人就算有私鑰也無法獲得 Premaster Secret 和 Master Secret。也就是說 Wireshark 無法通過配置 RSA Private Key 的方式解密「使用 ECDHE 進行金鑰交換」的加密流量。當然,使用 ECDHE 後,雖然中間人拿到私鑰也無法解密之前的流量,但他可以實施 MITM 攻擊來解密之後的流量,所以私鑰還是要保管好。

相比 RSA 既可以用於金鑰交換,又可以用於數字簽名;ECC 這邊就分得比較清楚了:ECDHE 用於金鑰交換,ECDSA 用於數字簽名。也就是目前金鑰交換 + 簽名有三種主流選擇:

  • RSA 金鑰交換、RSA 數字簽名;
  • ECDHE 金鑰交換、RSA 數字簽名;
  • ECDHE 金鑰交換、ECDSA 數字簽名;

以下是使用這三種金鑰交換方式的網站在 Chrome 中的截圖:

三種解密 HTTPS 流量的方法介紹

HTTP/2 中只能使用 TLSv1.2+,還禁用了幾百種 CipherSuite(詳見:TLS 1.2 Cipher Suite Black List)。實際上,HTTP/2 允許使用的 CipherSuite 必須採用具有前向安全性的金鑰交換演算法,不允許使用 RSA 金鑰交換。這也是為什麼 RSA Private Key 無法解密 HTTP/2 加密流量。

SSLKEYLOGFILE

Firefox 和 Chrome 都會在系統環境變數存在 SSLKEYLOGFILE 檔案路徑時,將每個 HTTPS 連線產生的 Premaster Secret 或 Master Secret 存下來。有了這個檔案,Wireshark 就可以輕鬆解密 HTTPS 流量,即使是使用了 ECDHE 這種具有前向安全性的金鑰交換,如下圖:

三種解密 HTTPS 流量的方法介紹

這種方案的詳細介紹請參考「使用 Wireshark 除錯 HTTP/2 流量」這篇文章。

SSLKEYLOGFILE 檔案記錄的是 HTTPS 資料傳輸中最重要的加密資訊,如果不是出於除錯目的,一般也沒人會主動配置這個環境變數,所以這個方案基本不會對 HTTPS 安全性產生影響。

總結

Fiddler 這類工具通過往系統匯入根證書來實現 HTTPS 流量解密,充當中間人角色。要防範真正的 HTTPS 中間人攻擊,網站方需要保管好自己的證書私鑰和域名認證資訊,為了防範不良 CA 非法向第三方簽發自己的網站證書,還要儘可能啟用 Certificate Transparency、HTTP Public Key Pinning 等策略;使用者方不要隨便信任來歷不明的證書,更不要隨意匯入證書到根證書列表,還要養成經常檢查常用網站證書鏈的習慣。

RSA 金鑰交換沒有前向安全性,這意味著一旦私鑰洩漏,之前所有加密流量都可以解開。為此,網站方需要啟用使用 ECDHE 作為金鑰交換的 CipherSuite,或者直接使用 ECC 證書;使用者方需要棄用不支援 ECDHE 的古董作業系統及瀏覽器。

對於瀏覽器而言,HTTPS 毫無祕密,通過瀏覽器生成的 SSLKEYLOGFILE 檔案,Wireshark 可以輕鬆解密 HTTPS 流量。另外,如果瀏覽器被安裝惡意擴充套件,即使訪問安全的 HTTPS 網站,提交的資料一樣可以被截獲。這種客戶端被攻擊者控制引發的安全問題,無法通過 HTTPS 來解決。

相關文章