許多Web開發者都知道SSL,但常見的情況是SSL沒有完整地部署或者沒有部署在它應該部署的地方。這篇關於何時及如何部署SSL的簡要指南,將幫助你避免大多數常見錯誤。
要點
- 如果你有任何機密資訊,或者你要進行使用者登陸,哪怕只是讓管理員登陸,你就應該部署HTTPS。風險並非只存在於理論上。
- 決不要部分部署HTTPS:請將它用於所有內容,否則你將面臨許多風險,比如session ID被攔截,其危害不亞於密碼被攔截。
- 如果你部署了HTTPS,請將任何普通的HTTP請求都重定向至HTTPS的URL,以強制所有的請求都通過HTTPS來處理。
- 啟用HTTP嚴格傳輸安全協議(HSTS)來進一步減少遭受攻擊的可能。
- 在你的cookies,比如session cookie上設定安全標記,確保它們不會經由普通的HTTP請求而洩露。
什麼是HTTPS?
HTTPS是將HTTP置於SSL/TLS之上,其效果是加密HTTP流量(traffic),包括請求的URL、結果頁面、cookies、媒體資源和其他通過HTTP傳輸的內容。企圖干擾HTTPS連線的人既無法監聽流量,也無法更改其內容。除了加密,遠端伺服器的身份也要進行驗證:畢竟,如果你都不知道另一端是誰,加密連線也就沒什麼用處了。這些措施將使攔截流量變得極其困難。雖然攻擊者仍有可能知道使用者正在訪問哪個網站,但他所能知道的也就僅限於此了。
何時及為什麼要部署HTTPS
只要你的網站有任何非公開資訊,你就應當部署HTTPS,包括那些需要登陸的網站——畢竟,如果資訊是公開的,根本就無需要求登陸。那些只有管理員才能登陸的網站,比如典型的Wordpress站點,也需要HTTPS。
部署HTTPS是必須的,因為如果沒有它,即使有人在被動監聽,也就是監聽而不操控網路流量,他也能順著HTTP傳輸讀取到密碼或認證令牌等機密資訊。
這種攻擊並非只存在於理論上。我自己(經過許可)就幹過幾次——在公共熱點(public hotspots)上這太容易做到了。公共熱點通常沒有使用任何WiFi加密,因此監聽所有流量只不過是小菜一碟。這種情況在酒吧、賓館、火車和其他公共場所非常普遍。換句話說,如果你的使用者某些時候從公共熱點訪問你的網站,而你又沒有使用HTTPS,那麼任何在公共熱點附近的人都可以監聽使用者所有的流量。這並不是監聽可能發生的唯一情況,但它確實很容易做到。
如果我只是在登陸頁面使用HTTPS呢?
別這麼幹。只在登陸頁面使用HTTPS固然可以防止使用者的密碼被竊取,但這只是問題的一部分。
首先,你的網站上使用HTTPS的部分越少,進行主動攔截就越容易:你的登陸連結可能指向一個HTTPS URL,但如果我在使用者點選之前就改變了連結,HTTPS就沒法幫到你了。部分使用HTTPS也將面臨被動攔截的風險。
驗證使用者名稱和密碼只是web上使用者身份驗證的一部分:我們還需要記住某個特定使用者已經過驗證和用於驗證的賬戶。最常見的辦法是使用session cookies,這通常意味著瀏覽器會將一個長的隨機字串,也就是session ID,儲存在一個cookie中,例如在PHP中可以使用PHPSESSID來實現。伺服器端的資料庫知道那個隨機字串對應某個特定的session,而那個session又對應著某個特定的已驗證使用者。如果我用某種方式得到了你的session ID,那麼當你登陸之後,我就獲得了你所有的許可權,這和我知道你的密碼沒什麼兩樣。
考慮到這一風險,session ID都非常長且隨機,並且它的生命期是有限的,這就意味著我沒法靠猜測來獲知它,因此session ID是足夠安全的。但是,由於cookie的運作方式,瀏覽器每次向網站發請求時都會包含cookie資訊。所以,即使已經登陸很久了,我請求的每個網頁,哪怕通常情況下是公開的網頁,也會導致我的session cookie被瀏覽器傳送出去。如果這時有人在監聽,他們依然可以篡改我的賬戶。
如果你僅僅把網站中涉及管理員的部分置於SSL的保護之下,同樣的情況也可能發生:當你登陸並隨後訪問非SSL的公開內容時,瀏覽器也會傳送session cookie。
簡而言之:由於允許訪問使用者賬戶的session cookie在每一次請求中都會被髮送,僅僅保障登陸頁面的安全是絕對不夠的。
我該如何正確地啟用HTTPS?
強制使用HTTPS
一些網站購買了SSL證照並將其配置到Web伺服器上,以為這就算完事兒了。但這只是表明你啟用了HTTPS選項,而使用者很可能不會注意到。為確保每個使用者都從HTTPS中受益,你應該將所有傳入的HTTP請求重定向至HTTPS。這意味著任何一個訪問你的網站的使用者都將自動切換到HTTPS,從那以後他們的資訊傳輸就安全了。
但上述做法還是留下了一個空子:當使用者第一次向你的網站傳送請求時,他們使用的是普通HTTP,而那時他們可能就已經在傳輸機密資訊了。上述做法還留下了一個“中間人攻擊”漏洞(man-in-the-middle hole)。
嚴格傳輸安全協議
為進一步加強控制,請啟用HTTP嚴格傳輸安全協議。這是一種可由伺服器傳送的特殊的頭資訊(header),它的含義是:在設定的時限內,你不能通過普通HTTP訪問網站,也不能在證照不可靠時通過HTTPS訪問網站。二級域名也可以選擇包含HSTS。
HSTS是一種簡單的伺服器頭資訊,且容易配置。但是要注意在時限結束之前無法撤銷設定,因此不要把時限設定得太長。你應該同時使用HSTS和HTTPS重定向,而不是用前者取代後者。
安全的cookies
Cookies,包括session cookie,有一個可選的安全標記。它大致的含義是:“不要用普通HTTP連線傳送這個cookie” 啟用這個安全標記,你的cookie就不會被瀏覽器的初始HTTP請求傳送出去,直到連線切換為HTTPS且不再會被監聽為止。
我可以只為已驗證使用者部署SSL嗎?
不可以。一旦你遵循了上述指南,當使用者發起普通HTTP連線時,你沒法知道他們是否經過了驗證。關鍵在於:除非使用者已經連上了SSL,否則他們不應該傳輸任何機密資訊,比如session cookie。
雖然我還能想出其他的辦法來解決這些安全問題,但它們可能會在某個環節上失效。如今SSL的成本已相當低,採用其他方案並不划算。
進一步閱讀
讀過這篇部落格,你可能還想看看“An appeal for security for the ordinary developer”、“But where is the decryption key?” 和“Proof of concept: arbitrary remote code execution through pickle-backed cookie-based sessions”這幾篇文章
想進一步瞭解怎樣正確設定加密和其他SSL選項,你可以看看Qualys Labs的SSL伺服器測試和最佳實踐文件、GitHub改進其SSL配置時的考量和Mozilla的TLS文件,不過Mozilla的TLS文件可能會嚇到新手。尚處於草案階段的Applied Crypto Hardening也不錯,它提供了直接可用的配置模板並詳細解釋了模板中所用選項的合理性。