【網絡安全系列】你的連線不是私人連線?由中間人攻擊說起

Ivan Wong
2021-09-26

「你的連線不是私人連線」?這個或許是其中一個最多人遇過,但又不明所以的警告了。不少人往往會被它嚇怕,以為將要前往的是惡意網站,馬上按上一頁離去。不過,有時候又會有人告訴你,直接按「繼續前往」就是了 (一般是公司或學校的內聯網)。究竟這個警告說的是什麼?忽略它又會否引起資安問題?其實這個警告牽涉的正是安全傳輸中的一大難題 —— 中間人攻擊 (Man-in-the-middle attack)。安全傳輸系列的第一章,將會由基礎的密鑰交換說起,講解什麼是中間人攻擊。
如何安全地交換密鑰?
交換密鑰是安全通信中很重要的一環。如果 A 要把加密的信息傳給 B,那 A 和 B 都需要有同樣的密鑰,反之亦然;而且還要確保第三者不會得悉此密鑰。預先面對面交換密鑰,固然是最安全的辦法 (假設沒有人竊聽)。但其實很多時候,通訊雙方是不認識的,而他們第一次溝通便是通過非面對面的方式進行。既然如此,A、B 雙方必須要在不安全的通信渠道下交換密鑰,而又能夠讓密鑰保密。要達到這個目的,就需要用到迪菲-赫爾曼密鑰交換 (Diffie–Hellman key exchange,下稱 D-H) 。D-H 是現今絕大部份密鑰交換協定的基礎,由 Bailey Whitfield Diffie 和 Martin Edward Hellman 於 1976 年發表,而他們亦因而獲得 2015 年的圖靈獎。
不過在解釋 D-H 之前,先要重温一下簡單的初中數學。首先是模除 (Modulo),簡單來說就是計算出一個數除以另一個數的餘數。給予兩個正整數
希望大家都記得這些初中數學吧,基本上 D-H 是個很簡單的協定,只需要知道以上這些就足以理解了。那讓我舉一個例子講解 D-H 吧。現在有三個人,Alice、Bob 和 Charlie。Alice 和 Bob 只能通過不安全的通信渠道

Figure 1: Alice 和 Bob 在不安全的通信渠道上進行 D-H,期間被 Charlie 竊聽
我們按照 Figure 1 走一次 D-H 的過程:
- Alice 和 Bob 先選取兩個可以公開的數字,
和 , 這個數字可以不安全的通信渠道下交換,所以 Charlie 也會知道 - 接著,Alice 和 Bob 分別選取一個秘密的數字,Alice 選取
,而 Bob 選取 ,而他們並不會告知對方所選取的數字。 - Alice 和 Bob 利用
和 ,分別運算出 和 ,接著通過 傳送給對方。這時,Charlie 能夠得知的,分別是 , , 及 ,但當中並不包含密鑰。 - 最後,Alice 利用獲得的
算出 ,而 Bob 則算出 。
通過我們前段提及過的兩個 properties,我們可以得出:
- Alice 算出了
- Bob 算出了
看到了吧,盡管 Alice 不知道
有些讀者可能會問,為什麼要加上 modulo 運算呢?這是為了保護
D-H 的漏洞,中間人攻擊
盡管 D-H 看起來很安全,但它有一個致命的弱點,就是無法在交換密鑰時認證雙方的身份,導致竊聽者能夠透過中間人攻擊 (Man-in-the-middle attack,下稱 MITM) 獲得訊息明文。我們用同一個例子,講解 MITM 吧。

Figure 2: Charlie 通過中間人攻擊,取得 Alice 和 Bob 通訊的明文信息,卻沒有被發現,成功瞞天過海
我們從上面的第二步開始,此時 Charlie 已選取一個秘密數字
- Charlie 截取 Alice 發出的
,並向 Bob 發出 ,表示自己就是 Alice - Charlie 截取 Bob 發出的
,並向 Alice 發出 ,表示自己就是 Bob - Alice 和 Bob 也被騙了,分別算出了
和 ,並以為這就是正確交換的密鑰,Charlie 也算出了 和 - 通訊開始,Charlie 截取 Alice 發出的訊息
,通過 解密,得到了明文 "hello",並重新以 加密成 ,發給 Bob
如果是 Bob 發出訊息,Charlie 也同樣先解密,再重新加密發給 Alice 便可以了。總括而言,Alice 和 Bob 都被 Charlie 欺騙,以為 Charlie 是對方,並分別與 Charlie 進行了兩個不同的 D-H。 此後,Charlie 只需要繼續偽裝即可。由於 Alice 和 Bob 仍然會收到對方發出的訊息,他們並不會發現被 Charlie 竊聽了。
「你的連線不是私人連線」?說的就是中間人攻擊了
說回本文的主題,「你的連線不是私人連線」這個警告,其實就是告訴你,連線有機會受到中間人攻擊。假設你現在用瀏覽器打開 Facebook,卻發現這個警告,就代表瀏覽器無法驗證和你通訊的另一方,是否真的是 Facebook 的伺服器。為了阻止中間人攻擊,所有使用加密協定的伺服器,都會安裝一個憑證,用於證明自己的身份。這個憑證需要通過第三方簽署確認,證明伺服器的擁有者與宣示的身份相符。

Figure 3: Facebook 現在使用的憑證,便是由 DigiCert 這個第三方機構簽署的
如果出現「你的連線不是私人連線」這個警告,那就代表你的瀏覽器無法通過憑證驗證伺服器的身份。常見的原因不外乎有:
- 憑證有效日期已過
- 憑證簽署人身份不明 (並非由 DigiCert 這些可信的機構所簽署,例如自行簽發的憑證,這也是進入公司或學校的內聯網出現此警告的常見原因了)
- 憑證宣告錯誤 (e.g. 宣告自己是 Facebook,但用的卻是 Google 的憑證)
關於加密連線的身分認證,其實還有很多東西可以探討,例如決定了什麼第三方機構簽署人是可信的「公開金鑰基礎建設」(Public Key Infrastructure,簡稱:PKI),以及它的對手,去中心化的身分認證協定 PGP (Pretty Good Privacy)。筆者未來會再寫幾篇文章,講解一下它們啊。

@spectre
I am a software engineer, familiar with programming languages such as Go, Typescript and C++. Right now has been working as a DevOps engineer, so I'm also studying some DevOps things, mostly related to AWS and Kubernetes.
我是一名軟件工程師,比較熟悉 Go、Typescript 及 C++。目前的職位是 DevOps 工程師,所以也在學習一些 DevOps 知識,請大家多多指教!