Content Security Policy 安全性與實用性平衡指南
前言
Content Security Policy 是一個額外的安全層,用於檢測和減輕特定類型的攻擊,包括跨站腳本 (XSS) 和數據注入等。通過仔細配置 CSP,可以大幅降低網站被攻擊的風險。
本指南旨在提供一個實務上的 CSP 配置方案,在確保網站安全性的同時,也顧及開發效率與維護性。此配置適用於大多數企業級網站專案,並提供與資安稽核單位溝通的建議。
基本配置方法
1. 透過 HTTP Header 設定
1 | Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://trusted-cdn.com; style-src 'self' 'unsafe-inline' https://trusted-cdn.com; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.example.com; |
2. 透過 Meta 標籤設定
1 | <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://trusted-cdn.com;"> |
常用指令說明
- default-src: 作為其他資源載入的預設值
- script-src: 控制 JavaScript 來源
- style-src: 控制 CSS 來源
- img-src: 控制圖片來源
- font-src: 控制字型來源
- connect-src: 控制 AJAX、WebSocket 等連接
- frame-src: 控制框架來源
- media-src: 控制音頻和視頻來源
常見配置值
- 'self': 只允許來自同源的內容
- 'unsafe-inline': 允許內聯腳本/樣式
- 'unsafe-eval': 允許 eval() 等動態程式碼執行
- 'nonce-{random}': 使用隨機數驗證腳本
- 'strict-dynamic': 允許受信任腳本動態載入其他腳本
- https:: 允許任何 HTTPS 來源
- data:: 允許 data: URI 格式
分階段實施建議
第一階段:監控模式
1 | Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report-endpoint; |
第二階段:基本限制
1 | Content-Security-Policy: default-src 'self' https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' https:; connect-src 'self' https:; |
第三階段:強化安全性
1 | Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{random}' https://trusted-cdn.com; style-src 'self' 'nonce-{random}' https://trusted-cdn.com; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.example.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; |
常見問題處理
內聯腳本/樣式被阻擋
- 使用 nonce 屬性
- 將程式碼移至外部文件
- 暫時使用 'unsafe-inline'
第三方資源載入失敗
- 檢查並添加所需的域名到對應的指令中
- 使用 report-uri 監控被阻擋的請求
動態生成的內容被阻擋
- 考慮使用 'unsafe-eval'
- 重構程式碼避免使用 eval()
- 使用 Worker 執行動態程式碼
最佳實踐
- 從寬鬆的策略開始,逐步收緊
- 使用 report-uri 監控違規情況
- 避免使用 'unsafe-inline' 和 'unsafe-eval'
- 明確列出所有需要的外部資源
- 定期審查和更新策略
- 使用 HTTPS 確保策略的有效性
建議配置範本
基礎版本(適用於一般網站)
1 | Content-Security-Policy: |
加強版本(適用於金流相關功能)
1 | Content-Security-Policy: |
配置說明與理由
1. 為何允許 'unsafe-inline'?
在某些情況下允許 'unsafe-inline' 是必要的:
- 現代前端框架(如 Vue、React)需要注入動態樣式
- 第三方服務整合(如 Google Analytics)常需要內聯腳本
- 提高開發效率和降低維護成本
2. 安全性補償措施
即使使用了 'unsafe-inline',我們仍實施以下安全措施:
嚴格的域名白名單
- 明確列出所有允許的外部資源來源
- 禁止使用萬用字元(*)作為域名
強制 HTTPS
- 使用 upgrade-insecure-requests
- 阻擋所有混合內容
框架保護
- 設定 frame-ancestors 為 'none' 防止點擊劫持
- 限制表單提交目標
資源完整性驗證
1
2
3<script src="https://example.com/script.js"
integrity="sha384-{hash}"
crossorigin="anonymous"></script>
分層安全策略
1. 網站分區管理
- 一般頁面:使用基礎版本配置
- 後台管理:使用加強版本配置
- 金流相關:使用最嚴格配置
2. 監控與報告
1 | Content-Security-Policy-Report-Only: |
3. 漸進式實施
- 先使用 Report-Only 模式收集資料
- 分析違規報告,調整配置
- 逐步實施正式政策
與資安稽核單位溝通要點
1. 安全性證明
- 我們的配置參考了 OWASP 的建議
- 採用了分層安全策略
- 實施了完整的監控機制
- 定期進行安全檢測
2. 產業實務參考
- Facebook、Google 等大型網站也採用類似配置
- 這是業界普遍採用的平衡方案
3. 風險評估報告範例
1 | 安全性評估報告 |
實施建議
1. 開發環境配置
1 | // vue.config.js / webpack.config.js |
2. 生產環境配置
1 | // 後端 Node.js 範例 |
常見問題處理
1. 第三方服務整合
- 確認所有需要的域名
- 添加到相應的指令中
- 使用資源完整性驗證
2. 舊版瀏覽器相容性
- 提供後備方案
- 使用特性檢測
- 漸進式增強
總結
CSP 的配置需要在安全性和實用性之間取得平衡。我們的方案:
- 符合業界標準
- 採用分層安全策略
- 實施持續監控
- 提供完整的風險緩解措施
這樣的配置既保障了網站安全,又確保了系統的可用性與可維護性。
本部落格所有文章除特別聲明外,均採用CC BY-NC-SA 4.0 授權協議。轉載請註明來源 kyosora 筆記!
評論
