前言
现在介绍一个全新的、有效的安全防御策略来减轻这种风险,这就是内容安全策略(ContentSecurity Policy,CSP)。之前安全开发人员会制作一个安全沙箱,也就是白名单,来限制可以访问的域。XSS跨站脚本攻击,通过虚假内容和诱骗点击来绕过同源策略。这是一个很大的问题,如果攻击者成功注入代码,有相当多的用户数据会被泄漏。XSS攻击在这里我不做详细介绍,之前的博客已经介绍过请查看之前文章。
CSP是什么
CSP定义了Content-Security-PolicyHTTP头来允许你创建一个可信来源的白名单,使得浏览器只执行和渲染来自这些来源的资源,而不是盲目信任服务器提供的所有内容。即使攻击者可以找到漏洞来注入脚本,但是因为来源不包含在白名单里,因此将不会被执行。且默认配置下不允许执行内联代码(< script >块内容,内联事件,内联样式),以及禁止执行eval() , newFunction() , setTimeout([string], …) 和setInterval([string], …) 。
因此要使用CSP技术保护自己的网站,开发者就不得不花费大量时间分离内联的JavaScript代码和做一些调整。例子如下:
重写前:
<script>
function doAmazingThings() {
alert('YOU AM AMAZING!');
}
</script>
<button onclick='doAmazingThings();'>Am I amazing?</button>
重写后:
<script src='amazing.js'></script>
<button id='amazing'>Am I amazing?</button>
// amazing.js
/*function doAmazingThings() {
alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentReady', function () {
document.getElementById('amazing')
.addEventListener('click', doAmazingThings);
});*/
setTimeout重写前:
setTimeout(“document.querySelector(‘a’).style.display = ‘none’;”, 10);
setTimeout重写后:
setTimeout(function () { document.querySelector(‘a’).style.display = ‘none’; }, 10);
无论是否使用CSP,以上的代码其实有更大的优点。内联JavaScript完全混合了结构和行为,你不应该这么做。另外外联资源更容易进行浏览器缓存,开发者更容易理解,并且便于编译和压缩。如果采用外联代码,你会写出更好的代码。
内联样式需要以同样的方式进行处理,无论是style属性还是style标签都需要提取到外部样式表中。这样可以防止各式各样神奇的数据泄漏方式。
如果你必须要有内联脚本和样式,可以为script-src or style-src属性设定’unsafe-inline值。但是不要这样做,禁止内联脚本是CSP提供的最大安全保证,同时禁止内联样式可以让你的应用变得更加安全和健壮。这是一个权衡,但是非常值得。
兼容Chrome 16+和Firefox 4+的浏览器上可用,并且它在IE10上预计会获得有限的支持。Safari目前还不支持,但是WebKit每晚构建版已经可用,所以预计Safari将会在下面的迭代中提供支持。
CSP知乎案例分析
知乎是国内少有使用CSP工具的网站。可以看到下图加入Content-Security-Policy,是在Response Headers里面,服务器返回到浏览器的。
Content-Security-Policy:default-src ; img-src data: blob:; frame-src ‘self’ .zhihu.com getpocket.com note.youdao.com read.amazon.cn; script-src ‘self’ .zhihu.com .google-analytics.com res.wx.qq.com ‘unsafe-eval’; style-src ‘self’ .zhihu.com ‘unsafe-inline’; connect-src * wss:;
解说:
- default-src : 默认运行任何域文件
- img-src:运行各种图片
- frame-src:支持本域和*.zhihu.com getpocket.com note.youdao.com read.amazon.cn
- script-src:支持本域和内联 .zhihu.com .google-analytics.com res.wx.qq.com
- style-src:支持本域和内联合 *.zhihu.com
- connect-src:支持wss连接类型
—————
CSP语法
只允许本域:
Content-Security-Policy: default-src ‘self’
限制不同类型的文件规定域:
Content-Security-Policy: default-src ‘self’; img-src ; object-src media1.example.com media2.example.com .cdn.example.com; script-src trustedscripts.example.com
运行内联脚本和样式:
Content-Security-Policy: default-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’
指令 | 作用 |
---|---|
default-src | 默认设置。 |
content-src | 限制连接的类型(例如XHR、WebSockets和EventSource) |
font-src | 控制网络字体的来源。 |
content-src | 限制连接的类型(例如XHR、WebSockets和EventSource) |
frame-src | 列出了可以嵌入的frame的来源。 |
img-src | 定义了可加载图像的来源。 |
media-src | 限制视频和音频的来源。 |
object-src | 限制Flash和其他插件的来源。 |
style-src | 类似于Script-src,只是作用于css文件。 |
sandbox | 对请求的资源启用sandbox(类似于iframe的sandbox属性)。 |
report-uri | 告诉浏览器如果请求的资源不被策略允许时,往哪个地址提交日志信息。特别的:如果只想让浏览器汇报日志,而不阻止任何内容。可以改用Content-Security-Policy-Report-Only响应头。 |
参数 | 示例 | 作用 |
---|---|---|
* | img-src * | 允许任何内容。 |
none | img-src ‘none’ | 不允许任何内容。 |
self | img-src ‘self’ | 允许来自相同来源的内容(相同的协议、域名和端口)。 |
data | img-src data | 允许data:协议(例如base64编码的图片)。 |
www.a.com | img-src img.a.com | 允许加载指定域名的资源。 |
*.a.com | img-src *.a.com | 允许加载a.com任何子域的资源。 |
https://img.com | img-src https://img.com | 允许加载img.com的https资源(协议需匹配)。 |
https: | img-src https: | 允许加载https资源。 |
unsafe-inline | script-src ‘unsafe-inline’ | 允许加载inline资源(例如常见的style属性,onclick,inline js和inline css等等)。 |
unsafe-eval | script-src ‘unsafe-eval’ | 允许加载动态js代码,例如eval()。 |
通过csp收集入侵信息
这样配置收集不匹配的信息,发送到report-uri里面。
Content-Security-Policy-Report-Only: script-src ‘self’; report-uri http://test/
这样,如果页面上有inline的JS,依然会执行,只是浏览器会向指定地址发送一个post请求,包含这样的信息:
{“csp-report”:{“document-uri”:”http://test/test.php“,”referrer”:”“,”violated-directive”:”script-src ‘self’”,”original-policy”:”script-src ‘self’; report-uri http://test/“,”blocked-uri”:”“}}
nigix例子
通过add_header添加到response header里面。
add_header Content-Security-Policy “default-src ; img-src data: blob:; frame-src ‘self’ ; script-src ‘self’ ‘unsafe-inline’; style-src ‘self’ ‘unsafe-inline’”;
—————
总结
充分了解CSP安全策略的语法和指令,并最大程度的合理的去利用和部署这些策略,努力把安全策略发挥到极致,使其最终把危害降低到最低。
CSP并不能消除内容注入攻击,但可以有效的检测并缓解跨站攻击和内容注入攻击带来的危害。
CSP不是做为防御内容注入(如XSS)的第一道防线而设计,而最适合部署在纵深防御体系中。
编辑工具
在线CSP编写,可以协助和帮助网站管理员编写出适合自己站点的CSP。
http://cspisawesome.com/