使用 HTTPS 和 HTTP 嚴格傳輸安全性,讓惡意中間人無法得逞

Mike West

考量到大量個人資料會透過網際網路流通,我們不能輕易忽視加密功能,也不能輕易忽視現代瀏覽器提供多種機制,可確保使用者資料在傳輸期間的安全性:安全性 Cookie嚴格傳輸安全性是其中最重要的兩種機制。這類服務可讓您無縫保護使用者,將他們的連線升級為 HTTPS,並保證使用者資料絕不會以明文傳送。

重要性請考慮以下情況:

透過未加密的 HTTP 連線傳送網頁,就好比將未密封的信封交給街上第一個看起來像是往郵局方向走的路人。運氣好的話,她可能會親自將包裹送到目的地,或者將包裹交給下一個她看到的、朝正確方向前進的人。對方也可能會採取相同做法,以此類推。

這個臨時鏈結中的大多數陌生人都值得信賴,絕不會偷看或修改你的公開信。不過,信件轉交次數越多,擁有完整信件存取權的人數就會越多。最後,信件的收件者很可能會收到郵件中的某物,但這是否與你一開始交付的相同物品,則是未知數。或許你應該將信封密封起來…

中間人

無論好壞,網際網路的廣大範圍都仰賴陌生人的可信度。伺服器並未直接連線,而是在龐大的電話遊戲中,將要求和回應從路由器傳遞到其他路由器。

您可以使用 traceroute 查看這些跳躍點的運作情形。從我的電腦到 HTML5Rocks 的路徑如下所示:

$ traceroute html5rocks.com
traceroute to html5rocks.com (173.194.71.102), 30 hops max, 60 byte packets
 1  router1-lon.linode.com (212.111.33.229)  0.453 ms
 2  212.111.33.233 (212.111.33.233)  1.067 ms
 3  217.20.44.194 (217.20.44.194)  0.704 ms
 4  google1.lonap.net (193.203.5.136)  0.804 ms
 5  209.85.255.76 (209.85.255.76)  0.925 ms
 6  209.85.253.94 (209.85.253.94)  1.226 ms
 7  209.85.240.28 (209.85.240.28)  48.714 ms
 8  216.239.47.12 (216.239.47.12)  22.575 ms
 9  209.85.241.193 (209.85.241.193)  36.033 ms
10  72.14.233.180 (72.14.233.180)  43.222 ms
11  72.14.233.170 (72.14.233.170)  43.242 ms
12  *
13  lb-in-f102.1e100.net (173.194.71.102)  44.523 ms

13 個跳躍點其實還不錯。不過,如果我透過 HTTP 傳送要求,則每個中繼路由器都會完全存取我的要求和伺服器回應。所有資料都會以未加密的明文形式傳輸,而任何中介服務都可能會充當「中間人」,讀取我的資料,甚至在傳輸過程中竄改資料。

更糟的是,這種攔截行為幾乎無法偵測。惡意修改的 HTTP 回應看起來就像有效的回應,因為沒有任何機制可確保收到的資料與傳送的資料「完全一致」。如果有人決定為了好笑而將我的網路搞得天翻地覆,那麼我大概就沒什麼好辦法了。

這是安全的通訊管道嗎?

從明文 HTTP 切換至安全的 HTTPS 連線,可提供最佳的中間人防護機制。HTTPS 連線會在傳送任何資料前,將整個管道端對端加密,因此您和目的地之間的機器無法讀取或修改傳輸中的資料。

Chrome 的網址列會提供許多有關連線狀態的詳細資訊。
Chrome 的網址列會提供許多有關連線狀態的詳細資料。

HTTPS 提供的安全性根源於公開和私密加密編譯金鑰的概念。詳細討論這些細節 (很高興) 已超出本文的範圍,但核心前提相當簡單:使用特定公開金鑰加密的資料「只能」使用相應的私密金鑰解密。當瀏覽器啟動 HTTPS 握手以建立安全通道時,伺服器會提供憑證,讓瀏覽器取得所有必要資訊,藉此驗證其身分,並檢查伺服器是否持有適當的私密金鑰。從此時起,所有通訊都會以加密方式進行,以證明要求已傳送至已驗證的伺服器,並從該伺服器接收回應。

因此,HTTPS 可讓您確保自己與認為的伺服器進行通訊,且沒有其他人會在網路上收聽或修改位元。這類加密技術是網路安全的必要條件。如果應用程式目前並未透過 HTTPS 提供,就可能遭到攻擊。修正問題。Ars Technica 提供一篇很棒的指南,可讓您免費取得及安裝憑證,建議您參閱相關技術細節。設定會因供應商和伺服器而異,但憑證要求程序在所有地方都相同。

預設採用安全設定

申請及安裝憑證後,請務必確保使用者能從您的努力中受惠:透過 HTTP 重新導向的魔法,將現有使用者透明地遷移至 HTTPS 連線,並確保「僅」透過安全連線傳送 Cookie

請這邊走

當使用者造訪 http://example.com/ 時,請傳送含有適當 Location 標頭的 301 Moved Permanently 回應,將使用者重新導向至 https://example.com/

$ curl -I http://mkw.st/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.3.7
...
Keep-Alive: timeout=20
Location: https://mkw.st/

您可以在 Apache 或 Nginx 等伺服器中輕鬆設定這類重新導向。舉例來說,從 http://example.com/ 重新導向至 https://example.com/ 的 Nginx 設定如下所示:

server {
    listen [YOUR IP ADDRESS HERE]:80;
    server_name example.com www.example.com;
    location "/" {
        rewrite ^(.*) https://www.example.com$1 permanent;
    }
}

透過 Cookie,我們可以透過無狀態 HTTP 通訊協定,為使用者提供流暢的登入體驗。儲存在 Cookie 中的資料 (包括工作階段 ID 等敏感資訊) 會隨每個要求一併傳送,讓伺服器瞭解目前回應的使用者。確認使用者透過 HTTPS 連線至網站後,我們也應確保儲存在 Cookie 中的機密資料只會透過安全連線傳輸,絕不會以明文傳送。

設定 Cookie 通常會涉及類似以下的 HTTP 標頭:

set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT

您可以透過附加單一關鍵字,指示瀏覽器限制 Cookie 的使用方式,以保護工作階段:

Set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT; secure

使用「secure」關鍵字設定的 Cookie 一律不會透過 HTTP 傳送。

關閉已開啟的視窗

透明重新導向至 HTTPS 的意思是,使用者在您的網站上瀏覽時,大多數時間都會使用安全連線。不過,這會讓攻擊者有小小的機會可趁虛實:初始的 HTTP 連線會完全開放,容易遭受 SSL 剝離和相關攻擊。由於中間人可完全存取初始 HTTP 要求,因此可充當您與伺服器之間的 Proxy,無論伺服器的意圖為何,都會讓您維持在不安全的 HTTP 連線。

您可以要求瀏覽器強制執行 HTTP 嚴格傳輸安全性 (HSTS),藉此降低這類攻擊的風險。傳送 Strict-Transport-Security HTTP 標頭可指示瀏覽器在用戶端中執行 HTTP 到 HTTPS 的重新導向,而無需觸及網路 (這對效能也非常有幫助;最佳要求是您不必提出的要求):

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

支援此標頭的瀏覽器 (目前為 Firefox、Chrome 和 Opera:caniuse 有詳細資料) 會註明這個特定網站已要求僅限 HTTPS 存取權,也就是說,無論使用者如何造訪網站,都會透過 HTTPS 存取。即使她在瀏覽器中輸入 http://example.com/,最終仍會使用 HTTPS,而不會建立 HTTP 連線。更棒的是,如果瀏覽器偵測到無效憑證 (可能會嘗試偽造伺服器的 ID),使用者就無法透過 HTTP 繼續操作;這表示使用者只能選擇使用 HTTPS 或不使用,非常實用。

瀏覽器會在 max-age 秒 (在本例中約為一個月) 後讓伺服器的 HSTS 狀態到期;請將此值設為合理的數字。

您也可以在標頭中加入 includeSubDomains 指示詞,確保來源的所有子網域都受到保護:

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

安全前進

HTTPS 是唯一可確保您傳送的資料完整傳送至預期收件者的唯一方法。您應該立即為網站和應用程式設定安全連線。這項程序相當簡單,有助於保護客戶資料安全。建立加密通道後,無論使用者如何造訪您的網站,您都應透過傳送 301 HTTP 回應,將使用者透明地重新導向至這個安全連線。接著,請在設定 Cookie 時加入 secure 關鍵字,確保所有使用者的機密工作階段資訊「僅」使用該安全連線。完成所有這些步驟後,請確保使用者不會意外離開巴士:透過傳送 Strict-Transport-Security 標頭,確保瀏覽器正確執行,以保護使用者。

設定 HTTPS 的程序非常簡單,而且對網站和使用者有極大助益。這麼做絕對值得。

資源

  • StartSSL 提供免費的網域驗證憑證。免費就是好。當然,您也可以升級至更高級別的驗證服務,價格合理。
  • SSL 伺服器測試:為伺服器設定 HTTPS 後,請透過 SSL Labs 的伺服器測試,確認設定是否正確。您會收到詳細的報告,瞭解是否已順利上線。
  • 如想進一步瞭解設定伺服器的細節,不妨參考 Ars Technica 近期發表的文章「Securing your Web Server with SSL/TLS」
  • HTTP 嚴格傳輸安全性規格 (RFC6797) 值得您略讀,瞭解可能需要的 Strict-Transport-Security 標頭所有技術資訊。
  • 當您確實瞭解自己的操作方式後,下一個可能的步驟就是宣傳您的網站只能透過特定一組憑證存取。IETF 正在進行一些工作,讓您可以透過 Public-Key-Pins 標頭執行這項操作。雖然目前仍處於初期階段,但很有趣,值得持續關注。