← 返回文章列表

什麼是CSP(Content Security Policy)?能做到什麼事情?

目錄

什麼是 CSP?

Content Security Policy(CSP)是一種 HTTP 回應標頭,用於告訴瀏覽器哪些外部資源可以載入到網頁中。這是一種多層式資安防禦機制,能有效防止跨網站指令碼攻擊(XSS)、點擊劫持(Clickjacking)和其他程式碼注入攻擊。

CSP 由網站伺服器透過 HTTP 標頭或 HTML 的 <meta> 標籤傳遞給瀏覽器,瀏覽器則會根據這些規則決定是否允許載入各類資源。

為什麼需要 CSP?

傳統的網站安全主要依賴伺服器端驗證,但攻擊者仍有辦法繞過這些防護。CSP 的核心價值在於:

  • 防止 XSS 攻擊:限制指令碼來源,阻止未授權的 JavaScript 執行
  • 防止資料外洩:控制 AJAX、Fetch、WebSocket 等連線的目標網域
  • 防止點擊劫持:透過 frame-ancestors 防止網站被嵌入惡意網頁
  • 減少 Mixed Content 問題:確保所有資源都透過 HTTPS 載入

CSP 如何運作?

CSP 的運作方式很直觀:伺服器傳送一個包含政策規則的 HTTP 標頭,瀏覽器則會解析這些規則並據此過濾內容。當瀏覽器遇到違反 CSP 的情況時,會在控制台產生警告(預設模式)或完全阻擋資源(強制模式)。

基本的 CSP 語法如下:

Content-Security-Policy: directive1 source1; directive2 source2

例如:

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'

CSP 指令詳解

主要指令

指令說明
default-src預設來源策略,用於未指定指令的資源類型
script-src控制 JavaScript 檔案的來源
style-src控制 CSS 樣式表的來源
img-src控制圖片資源的來源
font-src控制字體檔案的來源
connect-src控制 AJAX、Fetch、WebSocket 的連線目標
media-src控制音訊和視訊資源的來源
object-src控制 <object>、<embed>、<applet> 等外掛程式
frame-src控制 <iframe> 和 <frame> 的來源(舊版為 child-src)
frame-ancestors指定哪些網頁可以嵌入當前頁面(用於防止點擊劫持)
form-action限制表單提交的目標網域
base-uri控制 <base> 標籤的 URL
upgrade-insecure-requests自動將 HTTP 請求升級為 HTTPS

特殊關鍵字

  • 'self':允許來自同源的資源
  • 'none':禁止所有來源
  • 'unsafe-inline':允許內聯指令碼或樣式(不安全)
  • 'unsafe-eval':允許 eval() 等動態程式碼執行(不安全)
  • 'nonce-xxx':只允許具有特定隨機數的內聯指令碼
  • 'hash-xxx':只允許特定雜湊值的內聯指令碼

常見設定範例

基本嚴格模式

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'

允許 CDN 資源

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com https://ajax.googleapis.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https://*.cloudflare.com; font-src 'self' https://fonts.gstatic.com

允許 Google Analytics

Content-Security-Policy: default-src 'self'; script-src 'self' https://www.google-analytics.com https://www.googletagmanager.com; connect-src 'self' https://www.google-analytics.com

只允許 HTTPS

Content-Security-Policy: default-src 'self'; upgrade-insecure-requests

CSP 與 X-Frame-Options 差異

很多人會問:CSP 的 frame-ancestors 和傳統的 X-Frame-Options 有什麼不同?

特性CSP frame-ancestorsX-Frame-Options
語法彈性支援多個來源、萬用字元、CORS只支援 DENY、SAMEORIGIN、ALLOW-FROM
多網域設定可同時允許多個網域僅支援單一網域(ALLOW-FROM 支援度低)
瀏覽器支援現代瀏覽器全面支援舊版瀏覽器支援度有限
回退機制無瀏覽器支援時會靜默失效部分瀏覽器會忽略
功能性可控制 iframe 嵌入還能控制其他資源僅能防止點擊劫持

差異說明

X-Frame-Options 是早期的解決方案,語法簡單但彈性不足。例如:

X-Frame-Options: DENYX-Frame-Options: SAMEORIGINX-Frame-Options: ALLOW-FROM https://example.com

CSP frame-ancestors 是更現代的解決方案:

Content-Security-Policy: frame-ancestors 'self' https://trusted-site.com https://cdn.example.com

實際上,CSP frame-ancestors 是設計用來取代 X-Frame-Options 的。如果您需要同時支援舊版瀏覽器,可以兩者都設置;但在現代環境中,建議使用 CSP frame-ancestors。

多來源設定實作

在實際應用中,網站通常需要從多個來源載入資源。CSP 支援多種方式來設定多個來源:

方式一:直接列出多個網域

Content-Security-Policy: script-src 'self' https://cdn.example.com https://ajax.googleapis.com https://www.googletagmanager.com

方式二:使用萬用字元

Content-Security-Policy: img-src 'self' https://*.cloudflare.com https://*.akamai.com

萬用字元可以匹配子網域,例如 *.example.com 會允許 cdn.example.comapi.example.com 等。

方式三:使用資料 URI

Content-Security-Policy: img-src 'self' data: https://example.com

data: 允許以 Base64 編碼的內聯圖片。

方式四:結合多個條件

Content-Security-Policy:   default-src 'self';  script-src 'self' 'nonce-abc123' https://cdn.example.com;  style-src 'self' 'self' https://fonts.googleapis.com;  img-src 'self' data: https://*.cloudflare.com;  frame-ancestors 'self' https://trusted-partner.com;

方式五:使用 report-uri 監控違規

Content-Security-Policy: default-src 'self'; report-uri https://example.com/csp-report

當發生 CSP 違規時,瀏覽器會自動將詳細資料 POST 到指定的 URL,方便開發者監控和調整政策。

結論

CSP 是現代網站安全不可或缺的一環。透過正確設定 CSP 標頭,您可以大幅降低 XSS、點擊劫持等攻擊的風險。

建議的實作步驟:

  1. 先以 Content-Security-Policy-Report-Only 測試,收集違規報告
  2. 逐步放寬政策,確保功能正常運作
  3. 最終切換為強制模式 Content-Security-Policy
  4. 定期檢視報告,調整政策以因應網站變更

記住:CSP 的核心原則是「預設拒絕,只開放必要來源」。越嚴格的政策,安全性越高,但需要更仔細地規劃每個例外情況。