許多網頁應用程式需要顯示由使用者控管的內容。這些作業可以是使用者上傳的圖片 (例如個人資料相片) 簡單,也可以像使用者自行控管的 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-origin
和Cross-Origin-Embedder-Policy: require-corp
以啟用跨來源隔離功能。
- 在獨立子網域提供使用者內容 (例如 Google 會使用
方法 2:提供活躍使用者內容
即使採用傳統沙箱網域做法的弱點,也可以安全提供有效內容 (例如 HTML 或 SVG 圖片)。
最簡單的做法是利用 Content-Security-Policy: sandbox
標頭,讓瀏覽器隔離回應。雖然目前並非所有網路瀏覽器都實作沙箱文件的程序隔離,但持續修正瀏覽器程序模型,可能會改善沙箱內容與嵌入應用程式間的區隔。如果 SpectreJS 和轉譯器遭駭的攻擊不在您的威脅模型範圍內,那麼使用 CSP 沙箱或許已經足夠解決方案。
Google 開發了一個解決方案,可透過翻新沙箱網域的概念,完全隔離不受信任的活動內容。核心概念是:
- 建立已新增至公開後置字元清單的沙箱網域。舉例來說,只要在 PSL 中新增
exampleusercontent.com
,就能確保foo.exampleusercontent.com
和bar.exampleusercontent.com
是跨網站的做法,因此能完全隔離開來。 - 符合
*.exampleusercontent.com/shim
的網址都會轉送至靜態填充碼檔案。這個填充碼檔案包含簡短的 HTML 和 JavaScript 程式碼片段,可監聽message
事件處理常式並轉譯其接收的所有內容。 - 為使用這項功能,產品會建立對
$RANDOM_VALUE.exampleusercontent.com/shim
的 iframe 或彈出式視窗,並使用postMessage
將不受信任的內容傳送至填充碼進行轉譯。 - 實際顯示的內容會轉換為 Blob,並在沙箱 iframe 中顯示。
相較於傳統沙箱網域做法,這可以確保所有內容都完全隔離在不重複的網站上。而且主要應用程式交易可擷取顯示的資料,因此不再需要使用功能網址。
結論
只要搭配使用這兩項解決方案,就能從 googleusercontent.com
等傳統沙箱網域,改用與第三方 Cookie 封鎖功能相容的安全解決方案。Google 已遷移多項產品來使用這些解決方案,明年也安排了更多遷移計畫。