內容安全政策 (CSP) 有助於確保網站擁有者信任網頁中載入的任何內容。CSP 可以減少跨網站指令碼攻擊 (XSS) 攻擊,因為攻擊者可以封鎖攻擊者插入的不安全指令碼。不過,如果 CSP 不夠嚴格,也可以輕鬆略過。詳情請參閱運用嚴格的內容安全政策 (CSP) 限制跨網站指令碼攻擊 (XSS)。Lighthouse 會收集主要文件強制執行的 CSP,並回報 CSP Evaluator (如果可以略過) 的問題。
![Lighthouse 報告警告,在強制執行模式下找不到 CSP。](https://cdn.statically.io/img/developer.chrome.com/static/docs/lighthouse/best-practices/csp-xss/image/lighthouse-report-warning-154b98c8f6e25.png?hl=zh-tw)
不可略過的 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 或雜湊的指令碼,並使用「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。中繼標記之前插入會略過 CSP。此外,CSP 中繼標記不支援 frame-ancestors
、sandbox
和報表功能。
確保 CSP 與舊版相容
並非所有瀏覽器都支援 CSP Nonce/Hash,因此建議將 unsafe-inline
新增為不符規定瀏覽器的備用選項。如果瀏覽器支援 Nonce/Hash,系統就會忽略 unsafe-inline
。
同樣地,所有瀏覽器都不支援 strict-dynamic
。建議您將許可清單設為所有不相容瀏覽器的備用清單。系統會������援 strict-dynamic
的瀏覽器中���略許可清單。
如何開發嚴格 CSP
以下範例說明如何搭配採用 Nonce 政策的嚴格 CSP。
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 Evaluator,檢查 CSP 是否有可能的略過項目。如要在不破壞現有網頁的情況下測試新的 CSP,請將 Content-Security-Policy-Report-Only
做為標頭名稱,在報表專用模式中定義 CSP。這會將 CSP 違規事項傳送到您使用 report-to
和 report-uri
設定的任何報表目的地,但不會實際強制執行 CSP。