Specs 使用 Content-Security-Policy 防运营商劫持

阅读(767)

不只是防运营商劫持了,也防 XSS。

CSP 用于和浏览器约定一组规则,允许页面引入或执行的 js/css/网络请求/图片等外部资源。

有两种使用方式:

  1. 通过服务端配置输出 HTTP Header。如 Content-Security-Policy: script-src 'self'
  2. 通过页面 <meta> 元素声明,缺点在于不是所有规则都支持。如 <meta http-equiv="Content-Security-Policy" content="default-src http://kaifage.com; child-src 'none'; object-src 'none'">

格式

通用格式:

Content-Security-Policy: [内容类别1] [网址1] [网址2] [网址n]; [内容类别n] [网址n1] [网址n2]

内容类别分为以下几类:

  • base-uri : <base> 元素中的网址
  • child-src : 允许frame的网址
  • connect-src : XHR、WebSockets 和 EventSource 连接目标
  • font-src : 网页字体源
  • form-action : 用于列出可从 <form> 标记提交的有效端点。
  • frame-ancestors : 哪些页面可以嵌入本页,适用于 <frame>、<iframe>、<embed> 和 <applet> 标记。此指令不能在 <meta> 标记中使用,并仅适用于非 HTML 资源
  • img-src : 图像源
  • media-src : 视频/音频源
  • object-src : Flash 和其他插件
  • plugin-types : 可调用的插件种类
  • report-uri : 违反内容安全政策时浏览器向其发送报告的网址。此指令不能用于 标记
  • script-src : 允许的js脚本源
  • style-src : 样式源
  • upgrade-insecure-requests : 强制将 HTTP 更改为 HTTPS
  • worker-src : Level 3标准才有,限制worker源

如果不设定上述类别,则默认值为 *;可使用 default-src 指定默认值。

网址可以是协议、域名、端口或其组合。有几个内置的类别(使用时需加引号,否则会被作为服务器名称对待):

  • 'none' : 不执行任何匹配
  • 'self' : 与当前来源(不包含子域)匹配
  • 'unsafe-inline' : 允许使用内联 JavaScript 和 CSS
  • 'unsafe-eval' : 允许使用eval

使用内嵌脚本

对本文标题的场景,除了直接嵌入js脚本外,有可能直接嵌入一段包含完整代码的 <script>。

除了通过'unsafe-inline'暴力启用所有内嵌JS外,可以指定仅启用某一些。因内嵌的脚本不带有网址类的标记,所以需要先标记它。

标记方法1

<script nonce=EDNnf03nceIOfn39fn3e9h3sdfa>
  //Some inline code I cant remove yet, but need to asap.
</script>

然后将 nonce- 关键字 添加到 script-src 范围内。

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

标记方法2

对代码内容运算出哈希值,通过 sha256-哈希值 声明(chrome console也是采取哈希值对每段代码进行标识的):

Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

劫持上报

当发现违背以上规则的内容出现时,可通过 report-uri 上报到指定的 url,上报内容包含:

    {
  "csp-report": {
    "document-uri": "http://kaifage.com/about-us.html",
    "referrer": "http://evil.example.com/",
    "blocked-uri": "http://evil.example.com/evil.js",
    "violated-directive": "script-src 'self' https://apis.google.com",
    "original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
  }
}

实施步骤

在实施的网站中实施CSP,推荐采用下面两个步骤:

  1. 评估:评估需要使用哪些限制规则。开启仅上报功能:Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
  2. 正式启用。

兼容性

据 caniuse 的统计数据,IE基本不支持(Opera就不要玩了),IE11通过 X-Content-Security-Policy 对CSP1做了部分支持,其余浏览器均已支持。

当然了,哪天运营商直接修改页面输出的CSP策略就直接无敌了,还是早上HTTPS早省心。

Refer: