內容安全策略(CSP)
內容安全策略(Content Security Policy, CSP) 是一個額外的安全層,用于幫助檢測和緩解某些類型的攻擊,包括跨站腳本(XSS)和數據注入攻擊。
你可以把它看作是一個白名單制度。你作為網站的管理員,服務器會返回一個特殊的 HTTP 頭(Content-Security-Policy)給瀏覽器:“這個網站只被允許執行來自以下來源的腳本、加載以下來源的圖片、連接以下來源的服務器……”,瀏覽器就會嚴格遵守這個規定,拒絕任何不在白名單上的內容。

簡而言之:服務器給瀏覽器一份關于安全的聲明,瀏覽器會按照聲明來執行。
它是如何保證安全的?
傳統的 XSS 防御(如我們上面代碼中的轉義和過濾)是在服務端進行操作,思路是“我把用戶輸入里的惡意代碼在服務器處理環節清理掉,再輸出給前端瀏覽器”。但這種方法可能存在漏洞,比如設計的過濾規則被繞過等。
CSP 的防御思路是在客戶端(瀏覽器端) 進行,它從根本上改變了瀏覽器的行為:
-
阻斷內聯腳本和樣式: 大多數 XSS 攻擊都依賴于將惡意代碼(如 < script >alert('xss') </script > 或 < img onerror="惡意代碼" >) 直接注入到 HTML 頁面中。CSP 默認禁止執行所有內聯 JavaScript(包括 < script > 塊和 HTML 事件處理程序如 onclick)和樣式,除非你顯式地允許它們(使用 'unsafe-inline' 或 nonce),這極大地增加了攻擊難度。
-
限制資源加載的來源: 即使攻擊者成功注入了標簽,比如 < script src="https://evil.com/hack.js" >,瀏覽器在收到 CSP 指令后,會檢查 src 中的域名 evil.com 是否在腳本加載的白名單中。如果不在,瀏覽器根本就不會去請求和加載這個惡意腳本。
-
禁止使用 eval() 等危險函數: CSP 默認會禁止使用像 eval()、setTimeout(string)、new Function(string) 這類可以執行字符串形式代碼的危險函數,因為它們經常被攻擊者利用。
如何實施 CSP?
通常通過在 Web 服務器的 HTTP 響應頭中添加 Content-Security-Policy 字段來實現。字段里需要配置通過一系列指令來定義策略,具體指令自己需要再查詢吧。
示例 1:一個嚴格且推薦的策略
Content-Security-Policy:
default-src 'self';
script-src 'self' https://cdn.jsdelivr.net; # 只允許同源和指定的 CDN 的腳本
style-src 'self' 'unsafe-inline'; # 允許內聯樣式(常見于框架)
img-src 'self' data:; # 允許同源和 data:URI 的圖片
object-src 'none'; # 完全禁止插件
report-uri /api/csp-report; # 發生違規時向這個地址報告
安全測試者如何繞過 CSP?
雖然 CSP 很強大,但配置不當的 CSP 仍然可能被繞過。安全測試者會檢查:
-
過于寬松的策略: 如果策略中包含 'unsafe-inline' 或 'unsafe-eval',或者白名單 (*),那么 CSP 提供的保護就大打折扣。
unsafe-inline——允許舊代碼或框架中的內聯腳本/樣式。unsafe-eval——允許eval函數。 -
允許 data: URI: 如果 script-src 包含了 data:,攻擊者可以注入 <script src="data:text/javascript,惡意代碼" > </script >。
-
允許通配符 *: 過于寬泛的來源。
-
JSONP 回調函數callback的利用:
若CSP依賴域名白名單(如 script-src https://trusted.com ),攻擊者可能通過以下方式繞過:
利用可信域名的JSONP接口注入惡意回調函數(如 https://trusted.com/api?callback=alert(1);// )
瀏覽器將收到服務器按照JSONP的規則,返回內容:alert(document.domain);//{"data": "some data from trusted.com Server"}; -
AngularJS 等框架的繞過: 在特定版本的 AngularJS 中,即使禁止了 unsafe-eval,也有其他方式可以執行代碼。
-
CSP 注入: 如果頁面本身允許用戶輸入某些內容并反射到 CSP 頭中(極其罕見但確實存在),攻擊者可能會注入一些指令來修改策略。
只能輔助,不可做主力
-
CSP無法替代輸入過濾;
若開發者完全依賴CSP而忽略輸入驗證(如未轉義用戶輸入),攻擊者仍可能通過DOM型XSS或繞過CSP的其他方式(如濫用JSONP接口)發起攻擊。 -
CSP只是作為縱深防御層;
- 第一層防御:輸入過濾與輸出編碼(如轉義 < 為 \<);
- 第二層防御:CSP限制腳本執行條件;
- 第三層防御:HttpOnly Cookie、CORS策略等。
-
在使用前,需要做嚴格的測試,有些前端框架并不能很好兼容CSP;
浙公網安備 33010602011771號