网安系列【3】之深入理解内容安全策略(CSP)

文章目录

  • [一 CSP(内容安全策略)](#一 CSP(内容安全策略))
  • [二 CSP基础:如何实现内容安全策略](#二 CSP基础:如何实现内容安全策略)
    • [2.1 主要实现方式](#2.1 主要实现方式)
    • [2.2 基本指令解析](#2.2 基本指令解析)
  • [三 简单到复杂:CSP策略示例](#三 简单到复杂:CSP策略示例)
    • [3.1 示例1:最基本的CSP策略](#3.1 示例1:最基本的CSP策略)
    • [3.2 示例2:允许特定CDN资源](#3.2 示例2:允许特定CDN资源)
    • [3.3 示例3:更复杂的策略](#3.3 示例3:更复杂的策略)
  • [四 CSP进阶概念](#四 CSP进阶概念)
    • [4.1 非ce与哈希值](#4.1 非ce与哈希值)
    • [4.2 报告机制](#4.2 报告机制)
  • [五 CSP案例](#五 CSP案例)
    • [5.1 案例1:防止XSS攻击](#5.1 案例1:防止XSS攻击)
    • [5.2 案例2:第三方集成](#5.2 案例2:第三方集成)
    • [5.3 案例3:渐进式采用CSP](#5.3 案例3:渐进式采用CSP)
  • [六 CSP的局限性](#六 CSP的局限性)
  • [七 总结](#七 总结)

一 CSP(内容安全策略)

  • 内容安全策略(Content Security Policy,简称CSP)是一种重要的安全层,用于检测和减轻某些类型的前端攻击,包括跨站脚本(XSS)和数据注入攻击。它通过允许开发者创建可信内容来源的白名单,使浏览器只执行或渲染来自这些来源的资源。

在传统的前端开发中,浏览器会无条件地加载和执行任何来自页面内容的资源,这带来了严重的安全隐患:

  1. XSS攻击:恶意脚本被注入到网页中并在用户浏览器中执行
  2. 数据泄露:敏感数据被发送到恶意服务器
  3. 资源劫持:页面加载了被篡改的第三方资源
  • CSP像是为你的网站配备了一位严格的保安,只允许预先批准的"访客"(资源)进入。

二 CSP基础:如何实现内容安全策略

2.1 主要实现方式

  1. HTTP响应头 (推荐方式):

    http 复制代码
    Content-Security-Policy: default-src 'self'
  2. HTML meta标签

    html 复制代码
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'">
  • HTTP响应头中定义的CSP策略会完全覆盖meta标签中的策略。服务器发送的HTTP头在HTML文档开始解析前就已经被浏览器处理,CSP规范明确指出HTTP头是主要实施方式。

2.2 基本指令解析

CSP通过一系列指令来控制不同类型的资源:

  • default-src:默认策略,适用于未明确指定的大多数资源类型
  • script-src:控制JavaScript的来源
  • style-src:控制CSS样式表的来源
  • img-src:控制图片资源的来源
  • connect-src:控制XMLHttpRequest、WebSocket等连接的来源
  • font-src:控制网页字体的来源
  • object-src:控制<object><embed><applet>等插件
  • media-src:控制<audio><video>的来源
  • frame-src:控制iframe的来源(已废弃,改用child-srcframe-src

三 简单到复杂:CSP策略示例

3.1 示例1:最基本的CSP策略

  • 只允许加载同源的资源:
http 复制代码
Content-Security-Policy: default-src 'self'

这个策略表示:

  • 所有JavaScript、CSS、图片、字体等资源必须来自当前网站的域名
  • 不允许内联脚本和样式
  • 不允许eval()等动态代码执行

3.2 示例2:允许特定CDN资源

  • 允许来自自己域名和特定CDN的资源:
http 复制代码
Content-Security-Policy: 
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  style-src 'self' https://cdn.example.com;
  img-src 'self' https://images.example.com;
  font-src 'self' https://fonts.example.com;

3.3 示例3:更复杂的策略

  • 一个电商网站可能需要更复杂的策略:
http 复制代码
Content-Security-Policy: 
  default-src 'none';
  script-src 'self' https://ajax.googleapis.com https://cdnjs.cloudflare.com 'unsafe-inline' 'unsafe-eval';
  style-src 'self' https://fonts.googleapis.com 'unsafe-inline';
  img-src 'self' https://*.amazonaws.com data:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com;
  frame-src 'self' https://checkout.stripe.com;
  media-src 'self' https://videos.example.com;
  object-src 'none';

四 CSP进阶概念

4.1 非ce与哈希值

  • 为了在保持安全性的同时允许特定的内联脚本或样式,CSP提供了两种机制:
  1. nonce(一次性数字)

    html 复制代码
    <script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
      // 只有nonce匹配的脚本才会执行
    </script>
  • 对应的CSP头:

    http 复制代码
    Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
  1. 哈希值
    计算脚本内容的SHA256哈希:

    javascript 复制代码
    // 假设脚本内容是:alert('Hello, world.');
    // 计算其SHA256哈希得到:qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng=

    对应的CSP头:

    http 复制代码
    Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng='

4.2 报告机制

  • CSP提供了报告功能,可以收集策略违规行为而不实际阻止它们:
  1. 仅报告模式 (使用Content-Security-Policy-Report-Only头):

    http 复制代码
    Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report-endpoint
  2. 强制执行+报告模式

    http 复制代码
    Content-Security-Policy: default-src 'self'; report-uri /csp-report-endpoint

报告端点会收到类似以下的JSON数据:

json 复制代码
{
  "csp-report": {
    "document-uri": "https://example.com/page.html",
    "referrer": "https://example.com/",
    "violated-directive": "script-src 'self'",
    "effective-directive": "script-src",
    "original-policy": "script-src 'self'; report-uri /csp-report-endpoint",
    "disposition": "enforce",
    "blocked-uri": "https://malicious.example.com/malicious.js",
    "line-number": 10,
    "column-number": 20,
    "source-file": "https://example.com/page.html",
    "status-code": 200,
    "script-sample": "alert('XSS Attack!');"
  }
}

五 CSP案例

5.1 案例1:防止XSS攻击

问题场景:一个博客网站允许用户评论,但没有适当过滤输入,导致攻击者可以注入:

html 复制代码
<script>stealCookies();</script>

CSP解决方案

http 复制代码
Content-Security-Policy: 
  default-src 'self';
  script-src 'self';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data:;
  • 即使攻击者成功注入了恶意脚本,由于CSP禁止内联脚本执行,攻击将失败。

5.2 案例2:第三方集成

问题场景

一个电商网站需要集成:Stripe支付iframe、Google Analytics、来自CDN的jQuery和Bootstrap
CSP解决方案

http 复制代码
Content-Security-Policy: 
  default-src 'self';
  script-src 'self' https://ajax.googleapis.com https://cdnjs.cloudflare.com 'unsafe-eval';
  style-src 'self' https://cdnjs.cloudflare.com 'unsafe-inline';
  img-src 'self' https://*.stripe.com data:;
  connect-src 'self' https://api.stripe.com https://www.google-analytics.com;
  frame-src 'self' https://checkout.stripe.com;

5.3 案例3:渐进式采用CSP

  • 对于已有的大型网站,直接实施严格的CSP可能会破坏现有功能。可以采用渐进式方法:
  1. 首先使用报告模式

    http 复制代码
    Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report-endpoint
  2. 分析报告并调整策略

    • 识别哪些资源被阻止
    • 确定这些资源是否必要
    • 将合法的来源添加到白名单
  3. 逐步实施更严格的策略

    http 复制代码
    Content-Security-Policy: 
      default-src 'none';
      script-src 'self' 'nonce-{random}' 'strict-dynamic';
      style-src 'self' 'unsafe-inline';
      img-src 'self' data:;
      font-src 'self';
      connect-src 'self';
      frame-src 'none';
      report-uri /csp-report-endpoint

六 CSP的局限性

虽然CSP是强大的安全工具,但也有其局限性:

  1. 浏览器兼容性:虽然现代浏览器都支持CSP,但实现细节可能有所不同
  2. 配置复杂性:对于大型网站,制定和维护CSP策略可能很复杂
  3. 性能影响:浏览器需要解析和执行策略,可能对性能有轻微影响
  4. 误报问题:过于严格的策略可能阻止合法功能

七 总结

  • 内容安全策略是现代Web应用安全的重要组成部分。正确配置CSP,开发者可以显著降低XSS等前端攻击的风险。
  • 记住,没有"一刀切"的完美CSP策略,每个应用都需要根据其特定需求和安全考虑来定制策略。通过持续学习和实践,你将能够为你的Web应用构建强大的安全防线。