網頁程式開發人員適用的網站隔離功能

Mathias Bynens
Mathias Bynens

電腦版 Chrome 67 提供預設啟用網站隔離的新功能。這個 文章說明網站隔離的用意、重要性,以及網頁開發人員為何應該 注意哪些地方

什麼是網站隔離?

網際網路的用途是觀看貓咪影片、管理加密貨幣錢包等, 但你也不希望 fluffycats.example 存取你的珍貴加密貨幣!幸好 有了 Same-Origin,網站通常無法在瀏覽器中存取彼此的資料 政策。然而,惡意網站可能會試圖規避這項政策,以攻擊其他網站。 有時,某些瀏覽器程式碼會包含強制執行「同源政策」的安全性錯誤。 Chrome 團隊的目標是盡快修正錯誤。

網站隔離是 Chrome 的安全性功能,可提供額外的安全防護措施 這類攻擊較不容易可確保隨時將不同網站的網頁放在一起 轉換為不同程序,每項程序都會在沙箱中執行,限制該程序能執行的操作。 此外,這項功能還會禁止相關程序從其他網站接收特定類型的機密資料。身為 網站隔離功能的結果,讓惡意網站更難使用推測 例如 Spectre 等旁路攻擊,竊取其他網站中的資料。Chrome 團隊 額外的違規處置,網站隔離功能也能協助 自行處理規則

網站隔離功能有效讓不受信任的網站更難存取或竊取資訊 和其他網站上的帳戶資訊它針對不同類型的網路提供額外防護 例如安全性錯誤 近期的 Meltdown 和 Spectre 側邊頻道攻擊

如要進一步瞭解網站隔離,請參閱 Google 安全性網誌上的文章

跨來源讀取封鎖

即使將所有跨網站的網頁納入不同的程序,網頁仍可 和一些跨網站子資源,例如圖片和 JavaScript惡意網頁可能會利用 <img> 元素,載入含有機密資料的 JSON 檔案,例如銀行餘額:

<img src="https://your-bank.example/balance.json" />
<!-- Note: the attacker refused to add an `alt` attribute, for extra evil points. -->

如果沒有網站隔離,JSON 檔案的內容會新增到轉譯器的記憶體 處理時,轉譯器會注意到圖片格式無效,因此無法顯示 映像檔執行個體但攻擊者接著就能利用 Spectre 等弱點,以獲得可能讀取到的資訊 大型記憶體區塊

攻擊者還可以使用 <script> 來提交機密資料,而非使用 <img>, 記憶體:

<script src="https://your-bank.example/balance.json"></script>

跨來源讀取封鎖 (CORB) 是新的安全防護功能,可防止 balance.json 會根據其 MIME 類型輸入轉譯器程序記憶體的記憶體。

以下詳細說明 CORB 的運作方式。網站可透過伺服器要求兩種類型的資源:

  1. 資料資源,例如 HTML、XML 或 JSON 文件
  2. 媒體資源,例如圖片、JavaScript、CSS 或字型

網站可以從自身來源或其他來源接收資料資源 許可的 CORS 標頭 Access-Control-Allow-Origin: *。另一方面,媒體資源 來源,甚至沒有寬容限制的 CORS 標頭。

CORB 會阻止轉譯器程序接收跨來源資料資源 (即 HTML、XML 或 如果是:

  • 資源含有 X-Content-Type-Options: nosniff 標頭
  • CORS 未明確允許存取資源

如果跨來源資料資源未設定 X-Content-Type-Options: nosniff 標頭, CORB 會嘗試擷取回應內文,判斷其為 HTML、XML 或 JSON。這是 原因是某些網路伺服器設定錯誤,並以 text/html 格式提供圖片。

遭 CORB 政策封鎖的資料資源會在程序中顯示為空白, 該要求仍然會在背景執行。因此,惡意網頁有很長一段時間的 將跨網站資料提取至處理程序以進行竊取。

為了達到最佳安全性並且享有 CORB 的效益,建議您採取下列做法:

  • 請使用正確的 Content-Type 標頭標示回應。(舉例來說,HTML 資源 是以 text/html 的形式提供,JSON 資源具有 JSON MIME 類型,以及含有以下屬性的 XML 資源: XML MIME 類型)。
  • 使用 X-Content-Type-Options: nosniff 標頭選擇停用側錄功能。如果沒有這個標題 Chrome 會快速分析內容,嘗試確認類型正確無誤 允許回應 避免阻礙 JavaScript 檔案、 你最好自己做對的事,效果更好。

詳情請參閱 網頁程式開發人員適用的 CORB 文章CORB 詳細說明

網站開發人員為何應該重視網站隔離?

在大多數的情況下,網站隔離是瀏覽器幕後功能,並非直接 暴露在網頁程式開發人員的眼前。舉例來說,沒有網路的新 API 可供學習。一般而言 無論網站是否採用「網站隔離」功能,系統在執行網頁時都不應判斷網頁差異。

但有些例外狀況。啟用「網站隔離」功能後, 可能對網站造成影響的副作用。我們負責 已知網站隔離問題清單 下面會詳細說明這些最重要的影響。

系統不再同步全頁版面配置

使用「網站隔離」功能時,整頁版面配置將不再同步,因為 一個網頁現在可能會分散到多個程序這可能會影響網頁 版面配置變更就會立即反映至網頁上所有頁框

舉例來說,假設名為 fluffykittens.example 的網站透過 由 social-widget.example 代管的社交小工具:

<!-- https://fluffykittens.example/ -->
<iframe src="https://social-widget.example/" width="123"></iframe>
<script>
  const iframe = document.querySelector('iframe');
  iframe.width = 456;
  iframe.contentWindow.postMessage(
    // The message to send:
    'Meow!',
    // The target origin:
    'https://social-widget.example'
  );
</script>

社交小工具 <iframe> 的寬度先是 123 像素,但 FluffyKittens 頁面 會將寬度變更為 456 像素 (觸發版面配置),並傳送訊息至社交小工具 其中包含下列程式碼:

<!-- https://social-widget.example/ -->
<script>
  self.onmessage = () => {
    console.log(document.documentElement.clientWidth);
  };
</script>

每當社交小工具透過 postMessage API 收到訊息時,就會記錄 其根層級 <html> 元素

系統會記錄哪個寬度值?在啟用 Chrome 網站隔離功能之前,答案是 456。存取 document.documentElement.clientWidth 會強制執行版面配置,以往在 Chrome 之前即進行同步 已啟用網站隔離功能。不過,啟用網站隔離後,跨來源社交小工具就會 重新版面配置現在會在獨立程序中以非同步方式進行。因此,現在第一個問題 123,也就是舊的 width 值。

如果頁面變更跨來源 <iframe> 的大小,然後傳送 postMessage 至該網頁, 「網站隔離」影格在接收訊息時,可能還不知道新的大小。更多內容 一般而言,如果網頁會假設版面配置變更能立即全面生效,網頁可能就會損毀 不同的影格速率

在此特定範例中,更穩健的解決方案會在父項影格中設定 width 透過監聽 resize 事件來偵測 <iframe> 的變更。

卸載處理常式可能會更常逾時

頁框離開或關閉時,舊文件及內嵌的任何子頁框文件 都執行其 unload 處理常式。如果新的導覽程序在同一個轉譯器程序中執行 (例如 相同來源的導覽),舊文件的 unload 處理常式及其子頁框可對其執行 經過任意較長的時間,之後才允許執行新導覽。

addEventListener('unload', () => {
  doSomethingThatMightTakeALongTime();
});

在這種情況下,所有影格中的 unload 處理常式都非常可靠。

然而,即使沒有網站隔離功能,也會進行跨程序的某些主要頁框瀏覽,這會影響 卸載處理常式行為。舉例來說,如果您從 old.example 前往 new.example,只需輸入 網址列中的網址,new.example 的瀏覽方式將在新的程序中執行。卸載 old.example 及其子框架的處理常式會在背景的 old.example 程序中執行。 在 new.example 頁面顯示後,如未載入,舊的卸載處理常式就會終止 並列出特定逾時時間因為卸載處理常式可能未在逾時前完成, 卸載行為較不可靠

使用「網站隔離」功能後,所有跨網站瀏覽作業都會採用跨程序,因此 每個網站不會共用同一個程序。因此,上述情況適用於 更多情況,且 <iframe> 中的卸載處理常式通常具有背景和逾時行為 相同。

網站隔離所造成的另一個差異,是卸載處理常式的最新平行排序: 沒有網站隔離時,卸載處理常式會依跨影格嚴格由上而下的順序執行。但使用網站 隔離、卸載處理常式在不同程序中平行執行。

這些是啟用「網站隔離」功能的根本後果。Chrome 團隊正在努力解決 在可能的情況下,針對常見用途提高卸載處理常式的可靠性。我們也在 得知子框架卸載處理常式仍無法使用特定功能的錯誤,且 解決問題

卸載處理常式的一個重要案例,就是傳送工作階段結束的連線偵測 (ping)。一般而言,這通常會是 如下:

addEventListener('pagehide', () => {
  const image = new Image();
  img.src = '/end-of-session';
});
敬上

有這項變更時,建議您改用 navigator.sendBeacon,是更好的方法。 請改採以下做法:

addEventListener('pagehide', () => {
  navigator.sendBeacon('/end-of-session');
});

如果您需要進一步控管要求,可以使用 Fetch API 的 keepalive 選項:

addEventListener('pagehide', () => {
  fetch('/end-of-session', {keepalive: true});
});

結論

「網站隔離」功能會讓不受信任的網站更難存取或竊取您的 將每個網站都加入各自的處理程序,以便存取其他網站上的帳戶。因此,CORB 嘗試 將機密資料資源移出轉譯器程序。上述建議可確保 充分運用這些全新安全防護功能

感謝 Alex Moshchuk Charlie Reis Jason Miller Nasko Oskov Philip Walton Shubhie Panicker 湯瑪斯史坦納 閱讀本文的草稿版本並提供意見回饋。