內容安全策略 (CSP) 的實現
Content-Security-Policy HTTP 標頭提供了對網站可載入程式碼及其允許執行的操作的精細控制。
問題
本文主要關注的焦點是跨站指令碼 (XSS) 攻擊。這些攻擊通常是由於缺乏對網站資源載入來源的控制和意識所致。隨著網站變得越來越龐大和複雜,並且越來越依賴 JavaScript 庫等第三方資源,這一問題也變得更難管理。
CSP 還可以幫助修復其他問題,這些問題將在其他文章中介紹
解決方案
實現 嚴格 CSP 是利用 CSP 緩解 XSS 漏洞的最佳方法。它使用基於 nonce 或 hash 的獲取指令,以確保只有包含正確 nonce 或 hash 的指令碼和/或樣式才能執行。駭客插入的 JavaScript 將無法執行。
嚴格 CSP 還
- 停用不安全的 內聯 JavaScript 的使用,這意味著內聯 事件處理程式屬性(如
onclick)的用法。這可以防止不正確轉義的使用者輸入被 Web 瀏覽器解釋為 JavaScript。 - 停用 有風險的 API 呼叫(如
eval())的使用,這是script-src指令的另一個效果。 - 透過
object-src 'none'停用所有物件嵌入。 - 透過
base-uri 'none';停用<base>元素的用法來設定基本 URI。
與基於位置的策略(也稱為允許列表策略,即您指定指令碼可以從哪些域執行)相比,嚴格 CSP 更受青睞。這是因為允許列表策略最終經常允許不安全的域,這違背了擁有 CSP 的初衷,而且它們可能變得非常龐大和難以管理,特別是如果您試圖允許需要大量第三方指令碼才能正常執行的服務。
實施 CSP 的步驟
實施嚴格 CSP,然後開始精確定位因該策略而載入失敗的資源,並採取措施來解決這些問題。
注意: 在使用 Content-Security-Policy 標頭實施任何實際的 CSP 之前,建議您先使用 Content-Security-Policy-Report-Only HTTP 標頭進行測試;請參閱下方的 報告模式 CSP。
- 決定是使用 nonces 還是 hashes。如果您可以動態生成內容,則應使用 nonces;如果您需要提供靜態內容,則應使用 hashes。
- 按照 解決方案 部分的概述實施嚴格 CSP。確保您想要執行的外部和內部指令碼(透過
<script>元素包含)在伺服器上已將其正確的 nonce 插入到nonce屬性中。如果您改用 hashes,則外部指令碼應將正確的 hash 插入到integrity屬性中。 - 如果允許的指令碼繼續載入第三方指令碼,這些指令碼將無法載入,因為它們沒有所需的 nonce 或 hash。透過新增
strict-dynamic指令來解決此問題,該指令使第一個指令碼載入的指令碼具有相同的信任級別,而無需顯式提供 nonce 或 hash。 - 重構嚴格 CSP 所不允許的模式,例如內聯事件處理程式和
eval()。例如,將內聯事件處理程式替換為指令碼內的addEventListener()呼叫。 - 除非網站需要嵌入能力,否則應使用
object-src 'none'停用其執行。 - 如果您無法刪除
eval()的用法,可以將unsafe-eval關鍵字新增到您的嚴格 CSP 中以允許它們,儘管這會大大削弱 CSP 的安全性。 - 如果您無法刪除事件處理程式屬性,可以將
unsafe-hashes關鍵字新增到您的嚴格 CSP 中以允許它們。這在一定程度上不安全,但比允許所有內聯 JavaScript 安全得多。
如果您無法使嚴格 CSP 生效,基於允許列表的 CSP 比沒有 CSP 要好得多,像 default-src https: 這樣的 CSP 仍然提供了一些保護,停用了不安全的內聯/eval(),並且只允許透過 HTTPS 載入資源(影像、字型、指令碼等)。
警告: 如果可能,請避免在 CSP 中包含不安全的來源。例如:
unsafe-inline.script-src、object-src或default-src中的data:URI。- 過於寬泛的來源或表單提交目標。
如果您無法使用 Content-Security-Policy 標頭,頁面可以改用 <meta http-equiv="Content-Security-Policy" content="…"> 元素。這應該是文件 <head> 中的第一個 <meta> 元素。
報告模式 CSP
在使用 Content-Security-Policy 標頭實施任何實際的 CSP 之前,建議您先使用 Content-Security-Policy-Report-Only HTTP 標頭進行測試。這使您能夠檢視使用該策略是否會發生任何違規行為。
網站應使用 report-to 和 report-uri 報告指令。這些指令會導致瀏覽器將關於 CSP 違規的 JSON 報告 POST 到端點(在 report-to 的情況下,在 Reporting-Endpoints 標頭中指定)。這使得 CSP 違規能夠被快速捕獲和修復。
注意: report-to 指令比已棄用的 report-uri 指令更受推薦。但是,兩者仍然是必需的,因為 report-to 尚未獲得完整的跨瀏覽器支援。