CSRF介绍
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
简单的说,就是利用游览器对用户的信任,比如,用户已经登录了ww.aaa.com,自然aaa这个网站就会将用户的登录状态session存在cookie中;
然后,aaa.com这个网页有一个对作品点赞的功能,点赞提交地址为aaa.com/api.like?id=777
;
这时,另外一个叫www.bbb.com的网站,放了这样一个元素,这样的话,一旦用户进入这个bbb.com页面,就会请求aaa.com这个网站的点赞接口,而且点赞的用户对象是888;
最后因为用户的登录信息尚未过期,那就等于给id为888这个作品点赞了,然而,用户并不知情。
防御方式
有两种方法:
- 后端判断referer是否合法(不推荐)
通过HTTP的referer可知道,用户是通过哪个网站发送这个请求的。但是referer的判断并不是好方法,有各种方式可以绕过的方法,具体可见 CSRF 花式绕过Referer技巧>> - 每次请求带上token
比如laravel,在后端模板渲染的时候会提供一个csrf的token,这样的话,不同域的网站是拿不到token的,所以也就防止了csrf了。
补充
使用iframe会引出一些不安全的问题,比如绕过referer验证,比如资源盗用等,所以,很多网站会设置X-Frame-Options
为 DENY
,这也是一个安全的补充点。
Q&A
问:既然请求静态资源都是get请求,那么要是后端把点赞接口改为post的方式也可以吧?
答:不可以。因为,bbb.com网站完全可以设置一个form表单,action为bbb.com,method为post,接着input的name为id,value为888,然后,script代码直接submit表单。为了页面不重定向,还可以在form外层加一个iframe。由于form表单其实是直接跳转,所以不存在跨域的问题。
总结
防止CSRF的最好方法还是带token吧~