您的位置:首页 > 其它

CSRF原理和防御

2017-04-01 02:26 225 查看
CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式。CSRF 攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执行在权限保护之下的操作。

攻击原理

比如,博客的后台存在一个添加文章的功能,为方便说明,假设它是个get请求,如/admin/add?title=标题&body=内容。要提交这个请求时,会判断用户是否已经登录,如果没登录则会自动跳转到登录页面,只有管理员有权限登录。所以,攻击者即使知道该请求路径,也过不了登录这关。但是攻击者可以在管理员不知情的情况下伪造请求。方法如下:

攻击者在自己的网站上包含如下的内容:

<img src="http://blog.example/admin/add?title=crsf&body=hack" />

然后将网址发给管理员,如果管理员登录后台的session还有效,那么当他访问包含上述内容页面时,就会自动向后台发送添加文章的请求,完成攻击者的目的。这个过程中,攻击者不需要拿到管理员的cookie就可以完成攻击。

需要注意的是,某些地方提到将Get改成Post来防御CSRF,实际上并没什么用,因为攻击者可以轻松的使用javascript来模拟post请求。

防御 CSRF 的几种策略

1.验证 HTTP Referer 字段

HTTP头中的Referer字段记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,而如果黑客要对其实施 CSRF 攻击,他一般只能在他自己的网站构造请求。因此,可以通过验证Referer值来防御CSRF 攻击。

2.使用验证码

关键操作页面加上验证码,后台收到请求后通过判断验证码可以防御CSRF。但这种方法对用户不太友好。

3.在请求地址中添加token并验证

CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于cookie中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有token或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。这种方法要比检查
Referer 要安全一些,token 可以在用户登陆后产生并放于session之中,然后在每次请求时把token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。

对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 
而对于 POST 请求来说,要在 form 的最后加上 <input type="hidden" name="csrftoken" value="tokenvalue"/>,这样就把token以参数的形式加入请求了。

4.在HTTP 头中自定义属性并验证

这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。

AngularJS提供的CSRF方案

AngularJS提供了对CSRF防御的支持,当cookie中存在名为XSRF-TOKEN的cookie时,会在POST/PUT/DELETE请求中带上名为X-XSRF-TOKEN的http header。(For Angular, it expects the cookie named XSRF-TOKEN and will do POST/PUT/DELETE requests with X-XSRF-TOKEN header.)

因此很容易就能采用上面的在HTTP头中带上token验证的方案来防御CSFR。

如果要修改默认的名称,可以设置下面两项:

$httpProvider.defaults.xsrfCookieName = 'csrftoken';

$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

参考:
https://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/ http://stackoverflow.com/questions/18156452/django-csrf-token-angularjs http://blog.ionic.io/angularjs-authentication/ http://www.jianshu.com/p/ea2acb01eb7f
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: