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

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 是安全的選擇)。
  • 此外,請一律設定下列回應標頭,以確保瀏覽器能完全隔離回應。
回應標頭 目的

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 事件處理常式,並轉譯其接收的所有內容。
  • 如要使用這項功能,產品會建立 iframe 或彈出式視窗至 $RANDOM_VALUE.exampleusercontent.com/shim,並使用 postMessage 將不受信任的內容傳送至填充碼進行算繪。
  • 轉譯的內容會轉換成 Blob,並在沙箱的 iframe 中轉譯。

與傳統的沙箱網域方法相較,這個方式能確保所有內容都能在一個專屬網站上完全隔離。此外,由於主要應用程式會擷取要轉譯的資料,因此不再需要使用功能網址。

結論

這兩個解決方案搭配使用,能讓您從 googleusercontent.com 等傳統版沙箱網域,遷出更安全且與第三方 Cookie 封鎖功能相容的解決方案。Google 已經為許多產品改用這些解決方案,並預計明年展開更多遷移作業。