您现在的位置是:网站首页 > 使用 CSP(内容安全策略)防范 XSS文章详情

使用 CSP(内容安全策略)防范 XSS

XSS(跨站脚本攻击)是前端安全中最常见的威胁之一,攻击者通过注入恶意脚本窃取用户数据或破坏页面功能。CSP(内容安全策略)作为一种声明式机制,通过限制资源加载和执行来源,能有效降低XSS风险。以下是具体实现方法和实践细节。

CSP 的核心机制

CSP 通过 HTTP 响应头或 <meta> 标签定义资源加载规则,浏览器会强制执行这些策略。其核心逻辑是白名单机制,只有明确允许的来源才会被加载。例如:

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com

这条策略表示:

  • 默认所有资源只能从当前域名加载('self'
  • 脚本仅允许来自当前域名和 https://trusted.cdn.com

关键指令详解

脚本控制指令

script-src 是最关键的指令,用于控制 JavaScript 执行来源:

  • 'none' 完全禁止脚本
  • 'unsafe-inline' 允许内联脚本(会削弱防护)
  • 'unsafe-eval' 允许 eval() 等动态执行
  • 哈希值或随机数可精确放行特定内联脚本

示例:允许特定内联脚本执行

<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
  console.log("这个脚本会被执行");
</script>

对应 CSP 头:

Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'

其他资源指令

  • style-src:控制 CSS 加载
  • img-src:限制图片来源
  • connect-src:限制 XHR/fetch 请求目标
  • frame-src:控制 iframe 嵌入
  • font-src:字体文件来源控制

防御 XSS 的具体实践

场景 1:彻底禁用内联脚本

最严格的策略配置:

Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'

效果:

  • 禁止所有内联脚本和事件处理器(如 onclick="alert(1)"
  • 禁止动态代码执行(如 eval()
  • 阻止非当前域的脚本加载

场景 2:渐进式迁移方案

对于遗留系统难以立即移除内联脚本的情况:

  1. 先启用报告模式:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
  1. 根据报告逐步修复问题
  2. 最终切换为强制执行模式

场景 3:第三方库集成

允许特定 CDN 的 React/Vue 等库:

Content-Security-Policy: 
  script-src 'self' https://unpkg.com/react@18/umd/react.production.min.js;
  style-src 'self' 'unsafe-inline'

注意:现代框架通常需要 'unsafe-inline' 因其可能生成内联样式

高级防护技巧

随机数(Nonce)实现

每次页面请求生成唯一随机数:

// 服务器端生成
const nonce = crypto.randomBytes(16).toString('base64');
res.setHeader('Content-Security-Policy', `script-src 'nonce-${nonce}'`);

哈希(Hash)控制

对必须的内联脚本计算 SHA 哈希:

<script>alert('Allowed script');</script>

生成策略:

Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng='

严格动态(Strict-Dynamic)

现代 CSP 3.0 特性:

Content-Security-Policy: script-src 'nonce-abc123' 'strict-dynamic'

允许通过可信脚本动态加载的脚本执行

常见问题解决方案

问题 1:Google Analytics 被阻止

解决方案:

script-src 'self' https://www.google-analytics.com;
connect-src 'self' https://www.google-analytics.com

问题 2:Webpack 开发模式

开发环境特殊配置:

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

问题 3:社交媒体插件

Twitter/Facebook 插件需要:

script-src 'self' https://platform.twitter.com https://connect.facebook.net;
frame-src https://platform.twitter.com https://www.facebook.com

监控与报告

违规报告配置

Content-Security-Policy: 
  default-src 'self';
  report-uri https://your-api.com/csp-report;
  report-to csp-endpoint

报告示例(JSON 格式):

{
  "csp-report": {
    "document-uri": "https://example.com/login",
    "violated-directive": "script-src 'self'",
    "blocked-uri": "https://evil.com/xss.js",
    "line-number": 15
  }
}

实时监控方案

  1. 将报告发送至 SIEM 系统(如 Splunk)
  2. 设置阈值告警(如 1 小时内超过 50 次违规)
  3. 分析攻击模式并调整策略

CSP 的局限性

  1. 不防护 DOM 型 XSS:通过 location.hash 等 DOM 操作的攻击需要其他措施
  2. 配置复杂性:过度严格可能破坏正常功能
  3. 浏览器兼容性:部分旧版本浏览器支持不完整

补充方案示例(DOM XSS 防护):

// 净化用户输入
function sanitize(input) {
  const div = document.createElement('div');
  div.textContent = input;
  return div.innerHTML;
}

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步