
在HTTP
里,一切都是明文傳輸的,流量在途中可隨心所欲的被控制。而在線使用的 WebApp,流量里既有通信數據,又有程序的界面和代碼,劫持簡直輕而易舉。
HTTPS
雖然不是絕對安全,但運營商要想劫持也不是這么簡單的事情。
下面我們來聊一聊HTTPS
如何做到防劫持。
SSL握手
先來看看HTTPS
建立連接的過程,相比HTTP
的三次握手,HTTPS
在三次握手之后多了SSL
握手。如下圖:

整個流程大概如下:
1.瀏覽器將自己支持的一套加密規則發送給網站。
2.網站部署了一組SSL秘鑰,分私鑰和秘鑰。
3.網站從瀏覽器的加密規則中選出一組加密算法與HASH算法,並將自己的身份信息(公鑰)以證書的形式發回給瀏覽器。證書里面包含了網站地址,加密公鑰,以及證書的頒發機構等信息。
4.獲得網站證書之后瀏覽器要做以下工作:
a) 驗證證書的合法性(頒發證書的機構是否合法,證書中包含的網站地址是否與正在訪問的地址一致等),如果證書受信任,則瀏覽器欄里面會顯示一個小鎖頭,否則會給出證書不受信的提示。
b) 如果證書受信任,或者是用戶接受了不受信的證書,瀏覽器會生成一串隨機數的密碼,並用證書中提供的公鑰加密。
c) 使用約定好的HASH計算握手消息,並使用生成的隨機數對消息進行加密。這個加密過程是非對稱加密,即公鑰加密,私鑰解密。私鑰只在網站服務器上存儲,其他人無法獲得這個私鑰,也就無法解密。可理解為公鑰是鎖,私鑰是鑰匙,客戶端將隨機數用公鑰鎖上,經過網絡傳輸到服務器,整個過程就算有人攔截了信息,由於沒有私鑰解鎖,也就無法解密。
過程如下圖:

5.將生成的所有信息發送給網站。
6.網站接收瀏覽器發來的數據之后,使用自己的私鑰將信息解密取出密碼,使用密碼解密瀏覽器發來的握手消息,並驗證HASH是否與瀏覽器發來的一致。
7.使用密碼加密一段握手消息,發送給瀏覽器。
8.瀏覽器解密並計算握手消息的HASH,如果與服務端發來的HASH一致,此時握手過程結束,之后所有的通信數據將由之前瀏覽器生成的隨機密碼並利用對稱加密算法進行加密。
這里瀏覽器與網站互相發送加密的握手消息並驗證,目的是為了保證雙方都獲得了一致的密碼,並且可以正常的加密解密數據,為后續真正數據的傳輸做一次測試。
備注:非對稱加密算法用於在握手過程中加密生成的密碼,對稱加密算法用於對真正傳輸的數據進行加密,而HASH算法用於驗證數據的完整性。由於瀏覽器生成的密碼是整個數據加密的關鍵,因此在傳輸的時候使用了非對稱加密算法對其加密。非對稱加密算法會生成公鑰和私鑰,公鑰只能用於加密數據,因此可以隨意傳輸,而網站的私鑰用於對數據進行解密,所以網站都會非常小心的保管自己的私鑰,防止泄漏。
如何防劫持
對於HTTP
請求來說,常見的劫持有DNS劫持和內容劫持。
舉個網上的例子,有人在知乎問過一個問題。
在瀏覽器輸入如下域名https:// www.zhihu.com那瀏覽器要打開這個網站,首先要解析域名www.zhihu.com,結果這個域名被黑客劫持到他的私人服務器1.2.3.4,結果我的瀏覽器和他 的私人服務器1.2.3.4建立SSL連接,他的服務器1.2.3.4也和www.zhihu.com建立SSL的連接,我收發的數據都通過他的服務器1.2.3.4中轉,也就是黑客的服務器1.2.3.4相當於一個https代理服務器,結果我收發的所有數據,他都能看到。可能這樣被劫持嗎?
這個黑客的攻擊就是通常說的中間人攻擊,跳轉1.2.3.4就是DNS劫持,DNS被劫持到一個非源端的IP上。我們根據上文SSL握手的流程來分析一下,這種可能性是否存在。
首先如果黑客要跟你的瀏覽器建立SSL連接,那么他需要有一個CA證書,而通常系統內置根證書都是大型機構的根證書,幾乎無法偽造。如果非要做一個只能是自簽名證書。

瀏覽器拿着對方的自簽名證書和系統證書進行校驗,結果一定是如下圖所示:

如果他要假冒其他機構頒發證書,因為沒有頒發機構的秘鑰,那么這個證書的指紋一定沒辦法對上,還是一樣會報警。

除非用戶自己主動導入一個自己信任的證書。

記住,不要隨便安裝受信任證書,否則HTTPS也幫不了你。我們平時為了調試HTTPS
請求,使用Charles/MitmProxy進行抓包,也需要在手機端導入一個證書,讓用戶選擇信任安裝,目的就是將Charles/MitmProxy作為中間人代理,如果沒有用戶信任安裝證書的過程,也同樣無法解析HTTPS的請求包。
還有人就說了,我可以讓用戶回落到HTTP
協議啊,中間人用HTTPS
跟服務器通信,然后用HTTP
跟客戶端通信——要知道大部分用戶在地址欄輸入URL時,並沒有指定協議的習慣,都是打www
開頭而不是打https://www
開頭,能用HTTPS
全是Web+Server上80端口301+Location到HTTPS
的功勞。
看起來似乎中間人充當了一個替換頁面里HTTPS
資源到HTTP
的反向代理,好像可行性還是很高。
但是只要利用HSTS(HTTP+Strict+Transport+Security,RFC6797)就可以解決這個問題。通過在HTTP+Header中加入Strict-Transport-Security的聲明,告訴瀏覽器在一定時間內必須通過HTTPS
協議訪問本域名下的資源。
這種情況下,只要用戶曾經在安全網絡環境下訪問過一次某站,中間人在指定時間內也無法讓其回落到HTTP
。
解決完DNS劫持,再看內容劫持就簡單多了。
你作為一個中間人,你沒有服務器私鑰A,是不能解密客戶端發送的內容的,如果你沒有客戶端自己生成的密鑰B,所以你也不能解密客戶端發過去的內容的。
總結:
1.CA證書保證了公鑰的可靠性。
2.服務端私鑰+公鑰的非對稱加解密保證了客戶端生成的隨機數傳輸安全,不會被中間人攔截獲取。But,非對稱加密對服務端開銷大。
3.所以利用隨機數的對稱加密保證后續通訊的安全性,也可以降低服務器的解密開銷。
4.HTTPS只針對傳輸內容進行加密,保證的是客戶端和網站之間的信息就算被攔截也無法破解。如果不是全站HTTPS,僅僅只是在登錄頁采用HTTPS,那些HTTP連接的頁面同樣是危險的,從HTTP->HTTPS跳轉依然可能被劫持。國內的部分銀行就是這樣,對安全性的考量還比不上百度,百度早就全站HTTPS了。
Charles

上文中提到利用Charles抓取HTTPS數據,看看下圖就知道了。
電腦端配置根證書


移動端的證書信任圖

如果你對Charles的自簽名證書選擇不信任,那么Charles也無法做到中間人解密。
整個過程:手機----》Charles ----》 服務器, Charles 即充當了服務端又充當了客戶端,才使得數據能夠正常的交互,在一次請求中數據被兩次加解密,一次是手機到Charles,一次是Charles到真正的服務端。這個過程中最重要的一環就是手機端安裝的根證書!