Specs 使用 Content-Security-Policy 防运营商劫持
阅读(1991)不只是防运营商劫持了,也防 XSS。
CSP 用于和浏览器约定一组规则,允许页面引入或执行的 js/css/网络请求/图片等外部资源。
有两种使用方式:
- 通过服务端配置输出 HTTP Header。如
Content-Security-Policy: script-src 'self'
- 通过页面 <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,推荐采用下面两个步骤:
- 评估:评估需要使用哪些限制规则。开启仅上报功能:
Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
- 正式启用。
兼容性
据 caniuse 的统计数据,IE基本不支持(Opera就不要玩了),IE11通过 X-Content-Security-Policy
对CSP1做了部分支持,其余浏览器均已支持。
当然了,哪天运营商直接修改页面输出的CSP策略就直接无敌了,还是早上HTTPS早省心。
Refer:
- 《Google 内容安全政策》https://developers.google.com/web/fundamentals/security/csp/?hl=zh-cn
- 《Caniuse 统计的兼容性》 https://www.caniuse.com/#search=csp
- 《W3C CSP1》 https://www.w3.org/TR/CSP1/
- 《W3C CSP2》 https://www.w3.org/TR/CSP2/
- 《W3C CSP3》 https://www.w3.org/TR/CSP3/