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

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) 中的公開、私人、本機網路關係

如需瞭解詳情,請參閱「私人網路的 CORS (RFC1918):歡迎提供意見回饋」。

預檢要求

背景

預檢要求是 跨來源資源共享 (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 重新綁定攻擊。

範例

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

無 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」面板中出現失敗的預先檢查要求警告。這項資訊指出:
   請確保私人網路要求只會傳送至允許的資源,並提供特定要求的詳細資料,以及列出的受影響資源。

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

在 DevTools 網路面板中,針對 localhost 的失敗預先檢查要求會顯示 501 狀態。

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

在 DevTools 網路面板中,預檢要求在成功執行前出現偽造的失敗。

如要查看強制執行預先檢查成功的結果,請從 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 開始顯示警告。

無論是哪種情況,我們都會謹慎地以類似的階段性方式推出,讓網頁開發人員有時間調整並評估相容性風險。

特別銘謝

封面相片來源:Mark OlsenUnsplash 網站上提供。