在新型網頁應用程式中安全地代管使用者資料

David Dworken
David Dworken

許多網頁應用程式需要顯示由使用者控管的內容。這些作業可以是使用者上傳的圖片 (例如個人資料相片) 簡單,也可以像使用者自行控管的 HTML 一樣複雜 (例如網頁開發教學課程)。要做到這點並不容易,因此我們致力找出簡單、安全的解決方案,適用於多數類型的網頁應用程式。

用來隔離不受信任內容的傳統解決方案

如要安全提供使用者控管的內容,傳統解決方案必須使用所謂的沙箱網域。基本概念是,如果應用程式的主網域為 example.com,您可以在 exampleusercontent.com 上提供所有不受信任的內容。由於這兩個網域是跨網站網域,因此 exampleusercontent.com 中的任何惡意內容都不會影響 example.com
能夠安全地提供所有不受信任的內容,包括圖片、下載內容和 HTML。雖然看起來不需要使用這項功能或下載圖片,但這麼做能避免內容深入分析的風險 (在舊版瀏覽器中更是如此)。
沙箱網域業界廣泛使用,而且成效很長。但有兩個主要缺點:

  • 應用程式通常需要限制單一使用者的內容存取權,因此必須執行驗證和授權作業。沙箱網域刻意不與主應用程式網域共用 Cookie,因此安全就非常困難。如要支援驗證功能,網站必須依賴「功能網址」,或是為沙箱網域另外設定驗證 Cookie。在現代網路中,第二種方法尤其容易發生問題,因為許多瀏覽器會預設限制跨網站 Cookie。
  • 雖然使用者內容與主要網站隔離,並未獨立於其他使用者內容。這會造成惡意使用者內容攻擊沙箱網域上的其他資料(例如,透過讀取同來源資料)的風險。

同樣值得注意的是,由於資源已明確區隔在獨立網域中,因此沙箱網域有助於降低網路釣魚風險。

提供使用者內容的現代化解決方案

網路技術不斷演進,現在可透過更便捷且更安全的方式,提供不受信任的內容。做法有很多種,因此我們會列出 Google 目前廣泛採用的解決方案。

方法 1:提供不活躍的使用者內容

如果網站只需提供不活躍的使用者內容 (例如非 HTML 或 JavaScript 的內容,例如圖片及下載),則不需獨立的沙箱網域,系統現在就可以安全地執行這項作業。以下說明兩個重要步驟:

  • 一律將 Content-Type 標頭設為所有瀏覽器支援的已知 MIME 類型,且保證不提供主動內容 (有疑問時,application/octet-stream 會是安全的選擇)。
  • 此外,請務必設定以下回應標頭,確保瀏覽器完全隔離回應。
回應標頭 Purpose

X-Content-Type-Options: nosniff

防止內容探查

Content-Disposition: attachment; filename="download"

觸發下載而非轉譯

Content-Security-Policy: sandbox

沙箱環境保護內容,如同在個別網域提供內容一樣

Content-Security-Policy: default-src ‘none'

停用 JavaScript 執行功能 (並納入任何子資源)

Cross-Origin-Resource-Policy: same-site

避免將網頁納入跨網站

這種標頭組合可確保回應僅由應用程式載入為子資源,或讓使用者以檔案形式下載。此外,標頭可透過 CSP 沙箱標頭和 default-src 限制提供多層防護,避免瀏覽器發生錯誤。整體而言,上述設定可極度放心,以這種方式處理的回應無法植入或隔離安全漏洞。

縱深防禦

雖然上述解決方案代表對 XSS 而言大致足夠,但您仍可採用一些額外的強化措施,以提供額外的安全防護:

  • 設定 X-Content-Security-Policy: sandbox 標頭以與 IE11 相容。
  • 設定 Content-Security-Policy: frame-ancestors 'none' 標頭禁止嵌入端點。
  • 透過以下方式,在隔離子網域上沙箱使用者內容:
    • 在獨立子網域提供使用者內容 (例如 Google 會使用 product.usercontent.google.com 等網域)。
    • 設定 Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp 以啟用跨來源隔離功能。

方法 2:提供活躍使用者內容

即使採用傳統沙箱網域做法的弱點,也可以安全提供有效內容 (例如 HTML 或 SVG 圖片)。
最簡單的做法是利用 Content-Security-Policy: sandbox 標頭,讓瀏覽器隔離回應。雖然目前並非所有網路瀏覽器都實作沙箱文件的程序隔離,但持續修正瀏覽器程序模型,可能會改善沙箱內容與嵌入應用程式間的區隔。如果 SpectreJS轉譯器遭駭的攻擊不在您的威脅模型範圍內,那麼使用 CSP 沙箱或許已經足夠解決方案。
Google 開發了一個解決方案,可透過翻新沙箱網域的概念,完全隔離不受信任的活動內容。核心概念是:

  • 建立已新增至公開後置字元清單的沙箱網域。舉例來說,只要在 PSL 中新增 exampleusercontent.com,就能確保 foo.exampleusercontent.combar.exampleusercontent.com 是跨網站的做法,因此能完全隔離開來。
  • 符合 *.exampleusercontent.com/shim 的網址都會轉送至靜態填充碼檔案。這個填充碼檔案包含簡短的 HTML 和 JavaScript 程式碼片段,可監聽 message 事件處理常式並轉譯其接收的所有內容。
  • 為使用這項功能,產品會建立對 $RANDOM_VALUE.exampleusercontent.com/shim 的 iframe 或彈出式視窗,並使用 postMessage 將不受信任的內容傳送至填充碼進行轉譯。
  • 實際顯示的內容會轉換為 Blob,並在沙箱 iframe 中顯示。

相較於傳統沙箱網域做法,這可以確保所有內容都完全隔離在不重複的網站上。而且主要應用程式交易可擷取顯示的資料,因此不再需要使用功能網址。

結論

只要搭配使用這兩項解決方案,就能從 googleusercontent.com 等傳統沙箱網域,改用與第三方 Cookie 封鎖功能相容的安全解決方案。Google 已遷移多項產品來使用這些解決方案,明年也安排了更多遷移計畫。