内容安全策略(CSP)详解
字数 2096 2025-11-12 03:30:54

内容安全策略(CSP)详解

1. 什么是内容安全策略(CSP)?

内容安全策略是一种通过HTTP响应头(Content-Security-Policy)或HTML元标签(<meta>)定义的网络安全机制,用于限制网页中可以加载或执行的资源(如脚本、样式、图片等),从而减少跨站脚本攻击(XSS)和数据注入攻击的风险。

核心思想:通过白名单机制,明确告诉浏览器哪些来源的资源是可信的,禁止加载或执行非白名单内的资源。


2. 为什么需要CSP?

以XSS攻击为例:攻击者通过注入恶意脚本(如<script>alert('XSS')</script>)到网页中,浏览器无法区分脚本是否合法,会直接执行。CSP通过以下方式防御:

  • 禁止内联脚本(如<script>标签或事件处理函数onclick),除非显式允许。
  • 限制外部资源(如JS文件、CSS、图片)只能从特定域名加载。

3. CSP的配置语法

CSP策略由多个指令组成,每个指令对应一类资源。常见指令包括:

  • default-src:默认策略(适用于未单独指定的资源类型)。
  • script-src:控制JavaScript的加载与执行。
  • style-src:控制CSS样式表。
  • img-src:控制图片资源。
  • connect-src:控制Ajax请求、WebSocket等连接。
  • font-src:控制字体文件。
  • frame-src:控制嵌入的框架(如<iframe>)。

示例策略

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; img-src *;  
  • default-src 'self':默认只允许同源资源。
  • script-src 'self' https://trusted.cdn.com:脚本仅允许同源或trusted.cdn.com
  • img-src *:图片允许从任何域名加载。

4. CSP指令的取值规则

每个指令的值由来源表达式组成,常见取值包括:

  • 'self':仅允许同源资源。
  • 'none':禁止所有资源。
  • 'unsafe-inline':允许内联脚本或样式(降低安全性)。
  • 'unsafe-eval':允许动态代码执行(如eval())。
  • https::允许所有HTTPS域名。
  • 具体域名(如https://example.com)。
  • 哈希值(如'sha256-abc123...'):匹配特定内联脚本的哈希。
  • 随机数(nonce,如'nonce-xyz'):匹配带有nonce属性的脚本。

5. 逐步配置CSP的策略

步骤1:分析现有资源依赖

检查页面需要加载的所有资源(JS、CSS、图片等),记录其来源。例如:

  • 脚本:同源脚本、jQuery(CDN)、Google Analytics。
  • 图片:同源图片、第三方图片服务(如https://img.example.com)。

步骤2:制定初步策略

假设页面结构如下:

<script src="/js/local.js"></script>  
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/jquery.min.js"></script>  
<img src="https://img.example.com/logo.png">  

初步CSP策略:

Content-Security-Policy:  
  script-src 'self' https://cdn.jsdelivr.net;  
  img-src 'self' https://img.example.com;  
  default-src 'self';  

步骤3:处理内联脚本和样式

如果页面存在内联脚本(如<script>alert('test')</script>),CSP默认会阻止。解决方案:

  1. 避免内联代码:将脚本移到外部文件。
  2. 使用nonce(推荐):
    • 生成随机数(如nonce="rAnDoM123")添加到脚本标签:
      <script nonce="rAnDoM123">alert('Allowed')</script>  
      
    • CSP头中包含相同的nonce:
      Content-Security-Policy: script-src 'nonce-rAnDoM123';  
      
  3. 使用哈希
    • 计算内联脚本的SHA256哈希值:
      echo -n "alert('Allowed')" | openssl dgst -sha256 -binary | openssl base64  
      
    • 将哈希值加入策略:
      Content-Security-Policy: script-src 'sha256-abc123...';  
      

步骤4:处理动态代码执行

如果页面使用eval()new Function(),需添加'unsafe-eval'(但应尽量避免):

Content-Security-Policy: script-src 'self' 'unsafe-eval';  

6. 报告模式与调试

部署CSP前,可先启用报告模式,让浏览器报告违规行为但不阻止:

  • 使用Content-Security-Policy-Report-Only头:
    Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report-endpoint;  
    
  • 浏览器会将违规信息以JSON格式POST到report-uri指定的端点,用于分析需调整的策略。

7. 进阶优化

  • 严格动态(Strict Dynamic):
    通过'strict-dynamic'允许由可信脚本动态加载的依赖,适用于现代模块化应用。
  • 帧祖先限制
    使用frame-ancestors 'self'防止点击劫持,替代旧的X-Frame-Options头。
  • 升级请求
    通过upgrade-insecure-requests自动将HTTP资源转换为HTTPS。

8. 常见问题与绕过案例

  • JSONP绕过:如果白名单包含允许JSONP的域名,攻击者可能通过JSONP回调执行恶意代码。
  • 重定向绕过:若白名单域名存在开放重定向漏洞,可能被利用加载恶意资源。
  • 策略注入:若CSP头部分内容由用户输入控制,可能导致策略被篡改(如添加unsafe-inline)。

总结

CSP是防御XSS和数据注入的关键工具,但需根据实际资源依赖精细配置。最佳实践包括:

  1. 最小化白名单范围。
  2. 优先使用nonce或哈希替代unsafe-inline
  3. 通过报告模式逐步调试。
  4. 定期审计策略,避免遗留漏洞。
内容安全策略(CSP)详解 1. 什么是内容安全策略(CSP)? 内容安全策略 是一种通过HTTP响应头( Content-Security-Policy )或HTML元标签( <meta> )定义的网络安全机制,用于限制网页中可以加载或执行的资源(如脚本、样式、图片等),从而减少跨站脚本攻击(XSS)和数据注入攻击的风险。 核心思想 :通过白名单机制,明确告诉浏览器哪些来源的资源是可信的,禁止加载或执行非白名单内的资源。 2. 为什么需要CSP? 以XSS攻击为例:攻击者通过注入恶意脚本(如 <script>alert('XSS')</script> )到网页中,浏览器无法区分脚本是否合法,会直接执行。CSP通过以下方式防御: 禁止内联脚本 (如 <script> 标签或事件处理函数 onclick ),除非显式允许。 限制外部资源 (如JS文件、CSS、图片)只能从特定域名加载。 3. CSP的配置语法 CSP策略由多个 指令 组成,每个指令对应一类资源。常见指令包括: default-src :默认策略(适用于未单独指定的资源类型)。 script-src :控制JavaScript的加载与执行。 style-src :控制CSS样式表。 img-src :控制图片资源。 connect-src :控制Ajax请求、WebSocket等连接。 font-src :控制字体文件。 frame-src :控制嵌入的框架(如 <iframe> )。 示例策略 : default-src 'self' :默认只允许同源资源。 script-src 'self' https://trusted.cdn.com :脚本仅允许同源或 trusted.cdn.com 。 img-src * :图片允许从任何域名加载。 4. CSP指令的取值规则 每个指令的值由 来源表达式 组成,常见取值包括: 'self' :仅允许同源资源。 'none' :禁止所有资源。 'unsafe-inline' :允许内联脚本或样式(降低安全性)。 'unsafe-eval' :允许动态代码执行(如 eval() )。 https: :允许所有HTTPS域名。 具体域名(如 https://example.com )。 哈希值(如 'sha256-abc123...' ):匹配特定内联脚本的哈希。 随机数( nonce ,如 'nonce-xyz' ):匹配带有 nonce 属性的脚本。 5. 逐步配置CSP的策略 步骤1:分析现有资源依赖 检查页面需要加载的所有资源(JS、CSS、图片等),记录其来源。例如: 脚本:同源脚本、jQuery(CDN)、Google Analytics。 图片:同源图片、第三方图片服务(如 https://img.example.com )。 步骤2:制定初步策略 假设页面结构如下: 初步CSP策略: 步骤3:处理内联脚本和样式 如果页面存在内联脚本(如 <script>alert('test')</script> ),CSP默认会阻止。解决方案: 避免内联代码 :将脚本移到外部文件。 使用nonce (推荐): 生成随机数(如 nonce="rAnDoM123" )添加到脚本标签: CSP头中包含相同的nonce: 使用哈希 : 计算内联脚本的SHA256哈希值: 将哈希值加入策略: 步骤4:处理动态代码执行 如果页面使用 eval() 或 new Function() ,需添加 'unsafe-eval' (但应尽量避免): 6. 报告模式与调试 部署CSP前,可先启用 报告模式 ,让浏览器报告违规行为但不阻止: 使用 Content-Security-Policy-Report-Only 头: 浏览器会将违规信息以JSON格式POST到 report-uri 指定的端点,用于分析需调整的策略。 7. 进阶优化 严格动态 (Strict Dynamic): 通过 'strict-dynamic' 允许由可信脚本动态加载的依赖,适用于现代模块化应用。 帧祖先限制 : 使用 frame-ancestors 'self' 防止点击劫持,替代旧的 X-Frame-Options 头。 升级请求 : 通过 upgrade-insecure-requests 自动将HTTP资源转换为HTTPS。 8. 常见问题与绕过案例 JSONP绕过 :如果白名单包含允许JSONP的域名,攻击者可能通过JSONP回调执行恶意代码。 重定向绕过 :若白名单域名存在开放重定向漏洞,可能被利用加载恶意资源。 策略注入 :若CSP头部分内容由用户输入控制,可能导致策略被篡改(如添加 unsafe-inline )。 总结 CSP是防御XSS和数据注入的关键工具,但需根据实际资源依赖精细配置。最佳实践包括: 最小化白名单范围。 优先使用 nonce 或哈希替代 unsafe-inline 。 通过报告模式逐步调试。 定期审计策略,避免遗留漏洞。