私人網路存取權:推出預檢

Titouan Rigoudy
Titouan Rigoudy
Yifan Luo
Yifan Luo

更新

  • 2022 年 7 月 7 日:更新目前狀態,並新增 IP 位址空間定義。
  • 2022 年 4 月 27 日:宣布更新的時間表。
  • 2022 年 3 月 7 日:在 Chrome 98 中發現問題後,我們宣布將回溯。

簡介

Chrome 將淘汰「私人網路存取權」(PNA) 規格,不再允許從公開網站直接存取私人網路端點。

Chrome 會在任何子資源的私人網路要求之前,開始傳送 CORS 預檢要求,要求取得目標伺服器的明確權限。這項預先檢查要求會攜帶新的標頭 Access-Control-Request-Private-Network: true,而回應必須攜帶對應的標頭 Access-Control-Allow-Private-Network: true

目的是保護使用者免於遭受跨網站偽造要求 (CSRF) 攻擊,鎖定私人網路上的路由器和其他裝置。這些攻擊影響了數十萬名使用者,讓攻擊者將他們重新導向至惡意伺服器。

推出計畫

Chrome 將分兩階段推出這項變更,讓網站有時間注意到變更,並據此做出調整。

  1. 在 Chrome 104 中:

    • Chrome 實驗會在私人網路子資源要求之前傳送預檢要求。
    • 預檢失敗只會在開發人員工具中顯示警告,而不影響私人網路要求。
    • Chrome 會收集相容性資料,並聯絡受影響最大的網站。
    • 我們預期這項功能將與現有網站廣泛相容。
  2. 最快在 Chrome 113 中:

    • 只有在相容性資料顯示變更足夠安全,且我們在必要時直接與開發人員聯絡的情況下,才會開始這項作業。
    • Chrome 會強制執行預檢要求必須成功,否則會讓要求失敗。
    • 淘汰前測試版會在同一時間開始,讓受此階段影響的網站申請延長期限。試用期至少為 6 個月。

什麼是私人網路存取權 (PNA)

私人網路存取權 (舊稱 CORS-RFC1918) 會限制網站傳送要求至私人網路上的伺服器的能力。

Chrome 已實作部分規格:自 Chrome 96 起,只有安全內容才能提出私人網路要求。詳情請參閱先前的網誌文章

此規範也擴充了跨來源資源共享 (CORS) 通訊協定,因此網站現在必須先向私人網路上的伺服器明確要求授權,才能傳送任意要求。

PNA 如何分類 IP 位址及識別私人網路

IP 位址分為三個 IP 位址空間: - public - private - local

本機 IP 位址空間包含 IP 位址,這些 IP 位址可能是 RFC1122 的第 3.2.1.3 節所定義的 IPv4 迴轉式位址 (127.0.0.0/8),或是 RFC4291 的第 2.5.3 節所定義的 IPv6 迴轉式位址 (::1/128)。

私人 IP 位址空間包含僅在目前網路內有意義的 IP 位址,包括 RFC1918 中定義的 10.0.0.0/8172.16.0.0/12192.168.0.0/16RFC3927 中定義的連結本機位址 169.254.0.0/16RFC4193 中定義的獨特本機 IPv6 單播位址 fc00::/7RFC4291 的第 2.5.6 節中定義的連結本機 IPv6 單播位址 fe80::/10,以及 IPv4 對應 IPv6 位址,其中對應的 IPv4 位址本身為私人位址。

公開 IP 位址空間包含所有未提及的其他位址。

本地 IP 位址的私密程度高於私人 IP 位址,而私人 IP 位址的私密程度高於公開 IP 位址。

當可用性較高的網路向可用性較低的網路傳送要求時,要求就會是私密的。
私人網路存取 (CORS-RFC1918) 中的公開、私人、本機網路關係

詳情請參閱需要的意見回饋:私人網路 (RFC1918) 的 CORS

預檢要求

背景

預檢要求是 跨來源資源共享 (CORS) 標準引進的機制,可在向目標網站傳送可能產生副作用的 HTTP 要求前,先向該網站要求權限。這可確保目標伺服器瞭解 CORS 通訊協定,並大幅降低 CSRF 攻擊的風險。

權限要求會以 OPTIONS HTTP 要求的形式傳送,並附上特定的 CORS 要求標頭,說明即將傳送的 HTTP 要求。回應必須附帶特定的 CORS 回應標頭,明確同意即將提出的要求。

代表 CORS 預檢的序列圖。系統會將 OPTIONS HTTP 要求傳送至目標,並傳回 200 OK。接著傳送 CORS 要求標頭,並傳回 CORS 回應標頭

私人網路存取權的新功能

在預先檢查要求中引入一組新的要求和回應標頭:

  • 在所有 PNA 預檢要求中設定 Access-Control-Request-Private-Network: true
  • 必須在所有 PNA 預先飛行回應中設定 Access-Control-Allow-Private-Network: true

系統會針對所有私人網路要求傳送 PNA 的預先驗證要求,不論要求方法和模式為何。這些資訊會在 cors 模式、no-cors 和所有其他模式中,提前傳送給要求。這是因為所有私人網路要求都可能用於 CSRF 攻擊,無論要求模式為何,以及回應內容是否會提供給發起端。

如果目標 IP 位址比發起端更私密,則也會針對同源要求傳送 PNA 的預先檢查要求。這與一般 CORS 不同,因為預檢要求僅適用於跨來源要求。針對相同來源的要求發出預先檢查要求,可防範DNS 重新綁定攻擊。

範例

可觀察的行為取決於要求的模式

No-CORS 模式

假設 https://foo.example/index.html 嵌入 <img src="https://bar.example/cat.gif" alt="dancing cat"/>,而 bar.example 會解析為 192.168.1.1,這是根據 RFC 1918 的私人 IP 位址。

Chrome 會先傳送預檢要求:

HTTP/1.1 OPTIONS /cat.gif
Origin: https://foo.example
Access-Control-Request-Private-Network: true

如要讓這項要求成功,伺服器必須傳回以下內容:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Private-Network: true

接著,Chrome 會傳送實際要求:

HTTP/1.1 GET /cat.gif
...

伺服器可以正常回應。

CORS 模式

假設 https://foo.example/index.html 執行下列程式碼:

await fetch('https://bar.example/delete-everything', {
  method: 'PUT',
  credentials: 'include',
})

再次說明 bar.example 解析為 192.168.1.1

Chrome 會先傳送預檢要求:

HTTP/1.1 OPTIONS /delete-everything
Origin: https://foo.example
Access-Control-Request-Method: PUT
Access-Control-Request-Credentials: true
Access-Control-Request-Private-Network: true

如要讓這項要求成功,伺服器必須傳回以下內容:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Credentials: true
Access-Control-Allow-Private-Network: true

接著,Chrome 會傳送實際要求:

HTTP/1.1 PUT /delete-everything
Origin: https://foo.example

伺服器可根據一般 CORS 規則回應的下列值:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://foo.example

如何判斷網站是否受到影響

自 Chrome 104 起,如果偵測到私人網路要求,系統會先傳送預檢要求。如果這項預先檢查要求失敗,系統仍會傳送最終要求,但 DevTools 問題面板會顯示警告。

開發人員工具「Issues」面板中顯示的失敗的預先檢查要求警告。這項資訊指出:
   請確保私人網路要求只會傳送至允許這類要求的資源,並提供特定要求的詳細資料,以及列出的受影響資源。

您也可以在網路面板中查看及診斷受影響的預檢要求:

在開發人員工具網路面板中,針對 localhost 的預檢要求失敗,會顯示 501 狀態。

如果您的要求會在沒有私人網路存取規則的情況下觸發一般 CORS 預檢,則網路面板中可能會顯示兩個預檢,而第一個預檢永遠顯示失敗。這是已知錯誤,您可以放心忽略。

在開發人員工具「網路」面板中,預檢要求在成功執行前出現錯誤。

如要查看強制執行預檢成功時會發生的情況,請從 Chrome 98 開始傳送下列指令列引數

--enable-features=PrivateNetworkAccessRespectPreflightResults

任何失敗的預先檢查要求都會導致擷取失敗。這麼做可讓您測試網站在推出計畫的第二階段後是否正常運作。您可以使用上述的開發人員工具面板,以與警告相同的方式診斷錯誤。

網站受到影響時的處理方式

這項異動在 Chrome 104 版中推出時,應該不會遺漏任何網站。不過,我們強烈建議您更新受影響的要求路徑,確保網站能正常運作。

我們提供兩種解決方案:

  1. 在伺服器端處理預檢要求
  2. 透過企業政策停用 PNA 檢查

在伺服器端處理預檢要求

更新所有受影響擷取的目標伺服器,以便處理 PNA 預先飛行檢查要求。首先,請在受影響的路徑上實作標準 CORS 預先檢查要求的支援功能。然後新增兩個新回應標頭的支援功能。

當伺服器收到預檢要求 (含有 CORS 標頭的 OPTIONS 要求) 時,伺服器應檢查 Access-Control-Request-Private-Network: true 標頭是否存在。如果要求中有這個標頭,伺服器應檢查 Origin 標頭、要求路徑及其他相關資訊 (例如 Access-Control-Request-Headers),確保要求安全無虞。通常,您應允許存取受控單一來源。

伺服器決定允許要求後,應以必要的 CORS 標頭和新的 PNA 標頭回應 204 No Content (或 200 OK)。這些標頭包括 Access-Control-Allow-OriginAccess-Control-Allow-Private-Network: true,以及其他必要的標頭。

如要瞭解具體情況,請參閱範例

使用企業政策停用私人網路存取權檢查

如果您對使用者擁有管理控制權,可以使用下列任一政策停用私人網路存取權檢查:

如需更多資訊,請參閱「瞭解 Chrome 政策管理」。

提供意見

如果您代管的網站位於私人網路內,且會要求公用網路發出要求,Chrome 團隊對相關意見和用途有興趣。請前往 crbug.com 向 Chromium 提交問題,並將元件設為 Blink>SecurityFeature>CORS>PrivateNetworkAccess

後續步驟

接下來,Chrome 將擴大私人網路存取權檢查,涵蓋網頁工作站:專用工作站、共用工作站和服務工作站。我們暫時預計在 Chrome 107 開始顯示警告。

接著,Chrome 會將私人網路存取權檢查擴大至涵蓋導覽,包括 iframe 和彈出式視窗。我們暫時預計在 Chrome 108 開始顯示警告。

在這兩種情況下,我們將謹慎地採取類似的階段推出方式,讓網頁程式開發人員有時間調整和預估相容性風險。

特別銘謝

Unsplash 上透過 Mark Olsen 新增封面相片。