內容安全政策 (CSP) 有助於確保網頁載入的所有內容都獲得網站管理員的信任。CSP 可阻擋攻擊者注入的不安全指令碼,因此有助於減輕跨網站指令碼 (XSS) 攻擊的影響。不過,如果 CSP 不夠嚴格,很容易就會遭到規避。詳情請參閱「透過嚴格的內容安全政策 (CSP) 降低跨網站指令碼 (XSS) 的風險」。Lighthouse 會收集主要文件上強制執行的 CSP,並在可略過 CSP 時,回報 CSP 評估工具的問題。
不可略過的 CSP 的必要做法
請實施下列做法,確保 CSP 無法遭到略過。如果 CSP 可供略過,Lighthouse 會發出嚴重警告。
CSP 指定 XSS
如要針對 XSS 進行防範,CSP 應包含 script-src
、object-src
和 base-uri
指令。CSP 也應沒有語法錯誤。
script-src
和 object-src
分別可保護網頁免受不安全指令碼和不安全外掛程式的侵害。或者,您也可以使用 default-src
設定廣泛政策,取代許多指令,包括 script-src
和 object-src
。
base-uri
可防止未經授權的 <base>
標記遭到插入,這類標記可用於將所有相對網址 (例如指令碼) 重新導向至攻擊者控制的網域。
CSP 會使用 Nonce 或 Hash 避免繞過許可清單
為 script-src
設定許可清單的 CSP 會假設來自信任網域的所有回應都是安全的,且可做為指令碼執行。不過,這項假設不適用於現代應用程式;有些常見的良性模式 (例如公開 JSONP 介面和代管 AngularJS 程式庫的副本) 會讓攻擊者逃避 CSP 的限制。
實際上,雖然應用程式作者可能不會察覺,但攻擊者可以利用 XSS 錯誤規避大部分 script-src
許可清單,且這些清單對指令碼注入的防護效果不大。相較之下,以 Nonce 和雜湊為基礎的做法不會有這些問題,也更容易採用及維護更安全的政策。
舉例來說,以下程式碼會使用在信任網域中代管的 JSONP 端點,插入攻擊者控管的指令碼:
CSP:
script-src https://trusted.example.com
HTML:
<script src="https://trusted.example.com/path/jsonp?callback=alert(document.domain)//"></script>
為避免遭到規避,CSP 應個別允許使用 Nonce 或 Hash 的指令碼,並使用「strict-dynamic」而非許可清單。
安全 CSP 的其他建議
請實施下列做法,提升安全性和相容性。如果 CSP 未遵循其中一個建議,Lighthouse 就會發出中度嚴重警告。
設定 CSP 回報功能
設定回報目的地有助於監控任何中斷情形。您可以使用 report-uri
或 report-to
指令設定回報目的地。report-to
目前並未獲得所有新式瀏覽器的支援,因此建議同時使用這兩種屬性,或只使用 report-uri
。
如果任何內容違反 CSP,瀏覽器就會將報告傳送至設定的目的地。請確認您已在這個目的地設定應用程式,以便處理這些報表。
在 HTTP 標頭中定義 CSP
您可以在中繼標記中定義 CSP,如下所示:
<meta http-equiv="Content-Security-Policy" content="script-src 'none'">
不過,如果可以,請在 HTTP 回應標頭中定義 CSP。在 Meta 標記之前插入內容會略過 CSP。此外,中繼標記 CSP 不支援 frame-ancestors
、sandbox
和回報。
確保 CSP 可回溯相容
並非所有瀏覽器都支援 CSP nonce/hash,因此建議為不相容的瀏覽器新增 unsafe-inline
做為備用方案。如果瀏覽器支援 Nonce/Hash,就會忽略 unsafe-inline
。
同樣地,並非所有瀏覽器都支援 strict-dynamic
。建議您為所有不相容的瀏覽器設定許可清單做為備用方案。在支援 strict-dynamic
的瀏覽器中,系統會忽略許可清單。
如何開發嚴格 CSP
以下是使用嚴格 CSP 搭配以 Nonce 為基礎的政策的範例。
CSP:
script-src 'nonce-random123' 'strict-dynamic' 'unsafe-inline' https:;
object-src 'none';
base-uri 'none';
report-uri https://reporting.example.com;
HTML:
<script nonce="random123" src="https://trusted.example.com/trusted_script.js"></script>
random123
是每次載入網頁時,伺服器端產生的任何 Base64 字串。unsafe-inline
和 https:
會因 Nonce 和 strict-dynamic
而遭新式瀏覽器忽略。如要進一步瞭解如何採用嚴格 CSP,請參閱 嚴格 CSP 指南。
您可以使用 Lighthouse 和 CSP 評估工具,檢查 CSP 是否有潛在的規避問題。如果您想測試新的 CSP,但又不想冒著破壞現有網頁的風險,請使用 Content-Security-Policy-Report-Only
做為標頭名稱,在「僅報表」模式下定義 CSP。這項操作會將 CSP 違規事項傳送至您使用 report-to
和 report-uri
所設定的任何回報目的地,但不會實際強制執行 CSP。