電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

摘要:本文嘗試一步步還原HTTPS的設計原理過程,以理解為什麼HTTPS最終會是這副模樣。但是這並不代表HTTPS的真實設計過程。在閱讀本文時,你可以嘗試放下已有的對HTTPS的理解,這樣更利於"還原"過程。

一、序

疫情當下,口罩難搶啊,沒有口罩的我不能出門。在 52 破解上看到了一個口罩查詢餘量的軟件。

軟件類似這樣子:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

我用這軟件蹲點搶來好久,也沒搶到。於是我尋思著,能不能把這個軟件的口罩消息來源給搞到。由於是一枚菜雞 web 狗,俺也不會逆向。通過 wireshark 來抓請求看看他到底是咋弄的。

看他軟件上的提示,是每隔 5s 就請求一次數據。由於 wireshark 抓包的數據是抓這個網卡的全部流量,分析起來比較多。打開 wireshark,抓了一會包就停了沒必要太久。不然會很多其他的流量請求。

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

可以看到居多數給 27.124.36.8 這個 IP 發包,我日還是 https,這可咋整。沒有密鑰咋解密呢。嗯,雖然解不開數據包,不知道他以什麼樣子的參數去發送,但是我們能看到服務器的證書信息

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

發現了一個 app.tonystark.io

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

僅僅是找到了服務器的地址,具體的口罩信息的請求方式,我們還是不知道。


二、HTTPS原理學習

https 與 http 相比,僅僅多了一層的 tls:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

為什麼要加入這一層tls安全層呢?

是因為最初的 HTTP 存在下面三個問題:

· 數據在裸奔。數據以明文的方式傳播

· 無法驗證通信雙方的身份

· 無法防止數據被篡改


我們先不了聊HTTP,HTTPS,我們繼續從一個聊天軟件說起,我們要實現A能發一個hello消息給B:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

如果我們要實現這個聊天軟件,本文只考慮安全性問題,要實現

A發給B的hello消息包,即使被中間人攔截到了,也無法得知消息的內容

如何做到真正的安全?

這個問題,很多人馬上就想到了各種加密算法,什麼對稱加密、非對稱加密、DES、RSA、XX、噼裡啪啦~

而我想說,加密算法只是解決方案,我們首先要做的是理解我們的問題域——什麼是安全?

我個人的理解是:

A與B通信的內容,有且只有A和B有能力看到通信的真正內容

好,問題域已經定義好了(現實中當然不止這一種定義)。對於解決方案,很容易就想到了對消息進行加密。

題外話,但是隻有這一種方法嗎?我看未必,說不定在將來會出現一種物質打破當前世界的通信假設,實現真正意義上的保密。

對於A與B這樣的簡單通信模型,我們很容易做出選擇:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

這就是對稱加密算法,其中圖中的密鑰S同時扮演加密和解密的角色。具體細節不是本文範疇。

只要這個密鑰S不公開給第三者,同時密鑰S足夠安全,我們就解決了我們一開始所定問題域了。因為世界上有且只有A與B知道如何加密和解密他們之間的消息。

但是,在WWW環境下,我們的Web服務器的通信模型沒有這麼簡單:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

如果服務器端對所有的客戶端通信都使用同樣的對稱加密算法,無異於沒有加密。那怎麼辦呢?即能使用對稱加密算法,又不公開密鑰?請讀者思考21秒鐘。

答案是:Web服務器與每個客戶端使用不同的對稱加密算法:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

如何確定對稱加密算法

慢著,另一個問題來了,我們的服務器端怎麼告訴客戶端該使用哪種對稱加密算法?

當然是通過協商。

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

但是,你協商的過程是沒有加密的,還是會被中間人攔截。那我們再對這個協商過程進行對稱加密就好了,那你對協商過程加密的加密還是沒有加密,怎麼辦?再加密不就好了……好吧,進行雞生蛋蛋生雞的問題了。

如何對協商過程進行加密

新問題來了,如何對協商過程進行加密?密碼學領域中,有一種稱為"非對稱加密"的加密算法,特點是私鑰加密後的密文,只要是公鑰,都可以解密,但是公鑰加密後的密文,只有私鑰可以解密。私鑰只有一個人有,而公鑰可以發給所有的人。

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

雖然服務器端向A、B……的方向還是不安全的,但是至少A、B向服務器端方向是安全的。

好了,如何協商加密算法的問題,我們解決了:使用非對稱加密算法進行對稱加密算法協商過程。

這下,你明白為什麼HTTPS同時需要對稱加密算法和非對稱加密算法了吧?

協商什麼加密算法

要達到Web服務器針對每個客戶端使用不同的對稱加密算法,同時,我們也不能讓第三者知道這個對稱加密算法是什麼,怎麼辦?

使用隨機數,就是使用隨機數來生成對稱加密算法。這樣就可以做到服務器和客戶端每次交互都是新的加密算法、只有在交互的那一該才確定加密算法。

這下,你明白為什麼HTTPS協議握手階段會有這麼多的隨機數了吧。

如何得到公鑰?

細心的人可能已經注意到瞭如果使用非對稱加密算法,我們的客戶端A,B需要一開始就持有公鑰,要不沒法開展加密行為啊。

這下,我們又遇到新問題了,如何讓A、B客戶端安全地得到公鑰?

我能想到的方案只有這些:

方案1. 服務器端將公鑰發送給每一個客戶端

方案2. 服務器端將公鑰放到一個遠程服務器,客戶端可以請求得到

我們選擇方案1,因為方案2又多了一次請求,還要另外處理公鑰的放置問題。

公鑰被調包了怎麼辦?又是一個雞生蛋蛋生雞問題?

但是方案1有個問題:如果服務器端發送公鑰給客戶端時,被中間人調包了,怎麼辦?

我畫了張圖方便理解:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

顯然,讓每個客戶端的每個瀏覽器默認保存所有網站的公鑰是不現實的。

使用第三方機構的公鑰解決雞生蛋蛋生雞問題

公鑰被調包的問題出現,是因為我們的客戶端無法分辨返回公鑰的人到底是中間人,還是真的服務器。這其實就是密碼學中提的身份驗證問題。

如果讓你來解決,你怎麼解決?如果你瞭解過HTTPS,會知道使用數字證書來解決。但是你想過證書的本質是什麼麼?請放下你對HTTPS已有的知識,自己嘗試找到解決方案。

我是這樣解決的。既然服務器需要將公鑰傳給客戶端,這個過程本身是不安全,那麼我們為什麼不對這個過程本身再加密一次?可是,你是使用對稱加密,還是非對稱加密?這下好了,我感覺又進了雞生蛋蛋生雞問題了。

問題的難點是如果我們選擇直接將公鑰傳遞給客戶端的方案,我們始終無法解決公鑰傳遞被中間人調包的問題。

所以,我們不能直接將服務器的公鑰傳遞給客戶端,而是第三方機構使用它的私鑰對我們的公鑰進行加密後,再傳給客戶端。客戶端再使用第三方機構的公鑰進行解密。

下圖就是我們設計的第一版"數字證書",證書中只有服務器交給第三方機構的公鑰,而且這個公鑰被第三方機構的私鑰加密了:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

如果能解密,就說明這個公鑰沒有被中間人調包。因為如果中間人使用自己的私鑰加密後的東西傳給客戶端,客戶端是無法使用第三方的公鑰進行解密的。

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

話到此,我以為解決問題了。但是現實中HTTPS,還有一個數字簽名的概念,我沒法理解它的設計理由。

原來,我漏掉了一個場景:第三方機構不可能只給你一家公司製作證書,它也可能會給中間人這樣有壞心思的公司發放證書。這樣的,中間人就有機會對你的證書進行調包,客戶端在這種情況下是無法分辨出是接收的是你的證書,還是中間人的。因為不論中間人,還是你的證書,都能使用第三方機構的公鑰進行解密。像下面這樣:

第三方機構向多家公司頒發證書的情況:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

客戶端能解密同一家第三機構頒發的所有證書:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

最終導致其它持有同一家第三方機構證書的中間人可以進行調包:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

數字簽名,解決同一機構頒發的不同證書被篡改問題

要解決這個問題,我們首先要想清楚一個問題,辨別同一機構下不同證書的這個職責,我們應該放在哪?

只能放到客戶端了。意思是,客戶端在拿到證書後,自己就有能力分辨證書是否被篡改了。如何才能有這個能力呢?

我們從現實中找靈感。比如你是HR,你手上拿到候選人的學歷證書,證書上寫了持證人,頒發機構,頒發時間等等,同時證書上,還寫有一個最重要的:證書編號!我們怎麼鑑別這張證書是的真偽呢?只要拿著這個證書編號上相關機構去查,如果證書上的持證人與現實的這個候選人一致,同時證書編號也能對應上,那麼就說明這個證書是真實的。

我們的客戶端能不能採用這個機制呢?像這樣:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

可是,這個"第三方機構"到底是在哪呢?是一個遠端服務?不可能吧?如果是個遠端服務,整個交互都會慢了。所以,這個第三方機構的驗證功能只能放在客戶端的本地了。

客戶端本地怎麼驗證證書呢?

客戶端本地怎麼驗證證書呢?答案是證書本身就已經告訴客戶端怎麼驗證證書的真偽。

也就是證書上寫著如何根據證書的內容生成證書編號。客戶端拿到證書後根據證書上的方法自己生成一個證書編號,如果生成的證書編號與證書上的證書編號相同,那麼說明這個證書是真實的。

同時,為避免證書編號本身又被調包,所以使用第三方的私鑰進行加密。

這地方有些抽象,我們來個圖幫助理解:

證書的製作如圖所示。證書中的"編號生成方法MD5"就是告訴客戶端:你使用MD5對證書的內容求值就可以得到一個證書編號。

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

當客戶端拿到證書後,開始對證書中的內容進行驗證,如果客戶端計算出來的證書編號與證書中的證書編號相同,則驗證通過:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

但是第三方機構的公鑰怎麼跑到了客戶端的機器中呢?世界上這麼多機器。

其實呢,現實中,瀏覽器和操作系統都會維護一個權威的第三方機構列表(包括它們的公鑰)。因為客戶端接收到的證書中會寫有頒發機構,客戶端就根據這個頒發機構的值在本地找相應的公鑰。

題外話:如果瀏覽器和操作系統這道防線被破了,就沒辦法。想想當年自己裝過的非常規XP系統,都害怕。

說到這裡,想必大家已經知道上文所說的,證書就是HTTPS中數字證書,證書編號就是數字簽名,而第三方機構就是指數字證書籤發機構(CA)。

CA如何頒發數字證書給服務器端的?

當我聽到這個問題時,我誤以為,我們的SERVER需要髮網絡請求到CA部門的服務器來拿這個證書。 到底是我理解能力問題,還是。。

其實,問題應該是CA如何頒發給我們的網站管理員,而我們的管理員又如何將這個數字證書放到我們的服務器上。

我們如何向CA申請呢?每個CA機構都大同小異,我在網上找了一個:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

拿到證書後,我們就可以將證書配置到自己的服務器上了。那麼如何配置?這是具體細節了,留給大家google了。

也許我們需要整理一下思路

我們通過推算的方式嘗試還原HTTPS的設計過程。這樣,我們也就明白了為什麼HTTPS比HTTP多那麼多次的交互,為什麼HTTPS的性能會差,以及找到HTTPS的性能優化點。

而上面一大堆工作都是為了讓客戶端與服務器端安全地協商出一個對稱加密算法。這就是HTTPS中的SSL/TLS協議主要乾的活。剩下的就是通信時雙方使用這個對稱加密算法進行加密解密。

以下是一張HTTPS協議的真實交互圖(從網上copy的,忘了從哪了,如果侵權麻煩告知):

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

能不能用一句話總結HTTPS?

答案是不能,因為HTTPS本身實在太複雜。但是我還是嘗試使用一段話來總結HTTPS:

HTTPS要使客戶端與服務器端的通信過程得到安全保證,必須使用的對稱加密算法,但是協商對稱加密算法的過程,需要使用非對稱加密算法來保證安全,然而直接使用非對稱加密的過程本身也不安全,會有中間人篡改公鑰的可能性,所以客戶端與服務器不直接使用公鑰,而是使用數字證書籤發機構頒發的證書來保證非對稱加密過程本身的安全。這樣通過這些機制協商出一個對稱加密算法,就此雙方使用該算法進行加密解密。從而解決了客戶端與服務器端之間的通信安全問題。

三、怎麼才能夠對流量進行解密?

網上搜索大多都是兩種解法,一種是導入 RSA 私鑰進入 wireshark。第二種是配置 SSLKEYLOGFILE。

1、導入 RSA 私鑰進入 wireshark

實現過程:

使用 fiddler 的中間人代理技術拿到含有私鑰的服務器證書。

· 打開 fiddler 並啟用 https 代理服務

· 用配置了 fiddler 代理的瀏覽器訪問百度

· 運行 "certmgr.msc"打開證書管理器

· 從 Personal/Certificates 目錄下找到 *.baidu.com 的證書,右鍵所有任務-導出

2、取出證書中的私鑰

使用 openssl 取出私鑰。

1) 將 pfx 證書轉為 pem 證書

命令行:

1. openssl pkcs12 -in 證書路徑> -nodes -out <輸出的pem證書路徑(.pem)>

2) 從 pem 證書中取出私鑰

命令行:

1. openssl rsa -in 證書路徑>

-out <輸出的私鑰文件路徑(.key)>

3) 點擊編輯——>首選項——>協議——>SSL(有的版本只有 TLS),導入 RSA key:


導入服務器證書:

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

點擊 ok 後,Wireshark 會對捕獲的報文進行解密:

這種方法僅僅對於使用 RSA 的密鑰交換有用,在知曉了 RSA 密鑰,就可以導入 wireshark 來解密流量。但是目前大多數的 HTTPS 網站都是採用 DH 密鑰交換。在此說明一下 RSA 和 DH 的區別。先看這個兩個的過程。

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

ssl_handshake_rsa:

· Client Hello,包含協議版本、客戶端 random、密碼套件列表

· Server Hello,服務器"hello"消息包含服務器隨機、服務器選擇的密碼套件和服務器的證書

· Client Key Exchange Client 驗證證書後,客戶端創建一個隨機的 pre-master secret。並使用公鑰加密發送 之後服務器收到加密的 pre-master secret 會使用私鑰進行解密。所以,我們知道私鑰,就可以導入 wireshark ,解出 pre-master secret 來解密流量。

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

ssl_handshake_diffie_hellman:

· Client Hello,包含協議版本、客戶端 random、密碼套件列表

· Server Hello,服務器"hello"消息包含服務器隨機、服務器選擇的密碼套件和服務器的證書

· Server Key Exchange 緊跟著 Server Hello,為了啟動 DH 交換,服務器會發送 Diffie-Hellman 參數和簽名

· Client Key Exchange 客戶端會驗證服務器的證書。然後會向服務器發送 DH 參數。

注:整個過程不存在密鑰的交換,客戶端服務端可以通過 DH 參數來計算 pre-master secret。

對於這種情況,由於 Premaster Secret 無需交換,中間人就算有私鑰也無法獲得 Premaster Secret 和 Master Secret。也就是說 Wireshark 無法通過配置 RSA Private Key 的方式解密「使用 ECDHE 進行密鑰交換」的加密流量。

第二種 SSLKEYLOGFILE

在系統環境變量加入SSLKEYLOGFILE這個變量,並選擇導出目錄

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

Firefox 和 Chrome 都會在系統環境變量存在 SSLKEYLOGFILE 文件路徑時,將每個 HTTPS 連接產生的 Premaster Secret 或 Master Secret 存下來。有了這個文件,Wireshark 就可以輕鬆解密 HTTPS 流量

然後打開 wireshark,ctrl+shift+P 在 Protocols 選擇 TLS 協議,並導入即可

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

即可解除加密

電腦網絡:疫情期間,沒想到搶個口罩,搶懂了HTTPS網絡協議原來

總結

為了搶個口罩也是不容易,硬生生的把 HTTPS 原理給整明白了,學無止境,希望對大家有所幫助。


分享到:


相關文章: