別被自己的 CDN 背叛:來用 Subresource Integrity

Mozilla Firefox 開發者 (Developer) 版本 43 及其他主要瀏覽器,均協助控管第三方 JavaScript 載入並避免意外或惡意的修改作業。透過新的「Subresource Integrity」規格,網站則可納入 JavaScript 並在其遭到修改時隨即停止。有了此一技術,開發者可享受因「內容傳遞網路 (Content Delivery Network,CDN)」所提升的效能,而不需再擔心第三方傷害自己的網站。

CDN_2

圖片來源:http://www.cloudbus.org/

 

而且 Subresource Integrity 使用起來極為簡單:

整個概念就是在架設網頁之時,一併納入指令碼與其加密雜湊碼 (Cryptographic hash,例如 SHA-384)。接著瀏覽器即可下載指令碼,並針對已下載的檔案計算出雜湊。只有兩邊的雜湊吻合之後,才會執行指令碼。抗碰撞 (Collision resistant) 雜湊函式的安全屬性,可確保任一修改作業會形成完全不同的雜湊。如此不論是受允許的 CDN 或惡意管理者所進行的修改,均可讓網站所有者隨時得知消息並避免之。

另外必須注意的是,若要 Subresource Integrity 能順利運作,則 CDN 必須支援跨來源資源分享 (Cross-Origin Resource Sharing,CORS)。上述程式碼片段中的「crossorigin」屬性,將強制進行 CORS 所啟動的載入作業。匿名值 (Anonymous value) 即代表瀏覽器應該忽略任何使用者在該網站留下的 cookies 或驗證資料。如此可避免跨來源資料外洩 (Cross-origin data leaks),也能將網站請求縮減得更小。

Integrity 語法

你可能已經注意到,integrity 屬性並不僅僅包含雜湊值,也會納入摘要的雜湊演算法名稱。integrity 屬性的語法可允許相同 name-value 格式的多個 Token。如此可讓網站所有者指定不同強度的雜湊,以及可能藏在網址背後多個指令碼的值。這也有助於偵測瀏覽器版本 (Sniffing) 或內容協商 (Content negotiation)。

備援

為了達到最佳效能,使用者應該從 CDN 載入所有資源。如果無法查核 integrity,訪客就只會看到無法運作的網頁了。這時若要啟用備援系統,我們建議在自己的原始網域上再架設一份指令碼的副本。透過下列程式碼,即可恢復停止運作的網頁,並接著延伸之前的程式碼片段:

此程式碼將檢查是否已定義 jQuery,否則將插入一組指令碼標籤以載入相同來源版本的指令碼。

這裡必須注意,許多指令碼都會定期更新,不具備版號的指令碼尤為如此。如果你想讓由 CDN 載入的指令碼更安全,最好是附上特定版號,而不要只是在檔案名稱中加入「latest」而已。

用 HTTP 或 HTTPS?

Subresource Integrity 可用於 HTTP 與 HTTPS 上。如果你不只用純 HTTP 寫網頁,則瀏覽器還是可以辨別指令碼是否在 CDN 上遭到修改,但無法防堵正進行中的網路攻擊,因為他們可以僅從你的 HTML 中移除 Integrity 屬性。為了網站的完整,應使用 HTTPS 來達到 Web App 的一致性、完整性、可靠性。

樣式表 (Stylesheet) 支援

除了指令碼之外,我們另正努力新增支援其他 subresources。你也可針對 CSS 使用 Subresource Integrity。另可在 <link> 標籤上使用自己已知的 integrity 屬性!

立刻體驗 Subresource Integrity!

如果你想用範例測試瀏覽器的支援情形,或單純只是好玩,可先參閱 https://srihash.org/。如果你的 CDN 可支援 HTTPS,則此網站已經替你完成運算雜湊的所有基本工作與檢查。如 BootstrapCDN、CloudFlare、GitHub 等初期採用廠商已經完成相關實驗。
另外可在 MDN 上找到 Subresource Integrity 的其他說明文件。如果你想完整了解 Subresource Integrity 的細節,可參閱規格。

總的來說,當你在使用自己並未完整控制的 CDN 時,Subresource Integrity 讓你只要在自己的指令碼標籤裡新增幾組額外屬性,就能輕鬆讓網站達到更高的安全性。

 

 

原文連結:Do not let your CDN betray you: Use Subresource Integrity

 

 

您可能也會喜歡

目前找不到相關文章

對此文章發表回應

你的電子郵件位址並不會被公開。 必要欄位標記為 *