关于 csrf 漏洞和攻击的原理,以及在yii2 fecshop 中的应用分析

技术分享 · Fecmall · 于 5年前 发布 · 3537 次阅读

csrf是什么

CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

上面的说法是比较官方的解释,下面进行通俗的说法:

身边比较常见的,譬如,让你登陆了网站账户(地址为:www.a.com) ,然后别人给你发了一个连接www.b.com/xxxx ,如果你点击了,那么你的账户里面的积分,或者其他的一些东西可能被操作。

原因为:你登陆了A网站,那么浏览器中有网站A的cookie,如果在B网站中写一个form提交表单,提交的post地址为网站A,js设置访问网站B表单自动提交,如果你在登陆网站A账户后点击B网站的这个url,就会提交表单,因为浏览器中有A网站的cookie,那么这个提交表单就会提交成功,譬如转账操作,这显然不是用户想要在A网站执行的操作,而被隐藏执行了

总体来说,csrf攻击的前提是,用户得先登陆网站A的账户,这样才有权限操作各种操作, 然后利用各种诱导让用户点击B网站的触发页面,跨站请求伪造,然后就可以执行相关的操作,因此csrf漏洞的触发是有条件的,这也就是很多xx链接不要点击的原因,但是,如果网站做了csrf的防范,点击了也不会有问题的

<input class="thiscsrf" type="hidden" value="-pJu7CfqMcpScHBs6vTyAyyylKUEOG_25ufQZi89oUKU1xaaXahY8jovHB2Zlb5lTtPd0kgPIamgrKo1bUnAHQ==" name="_csrf">

因为网站会在表单中加入一个csrf 选项,A站的信息提交用户信息的同时,也要带上这个csrf选项,提交了服务端,服务端会验证csrf,合法后才会通过,因此对于B网站提交过来的表单,是没有csrf的,因此请求会拒绝

那么问题来了B网站是否有其他途径获取A网站的csrf信息?有的!!因为js的ajax可以访问远程获取远程的信息,进行执行,不过值的庆幸的是,js ajax默认是不允许跨域的,如果跨域需要服务端通过cors开启,因此默认情况下是没有问题的,但是!!!如果php端加入了

header('Access-Control-Allow-Origin: *');

尤其是vue 这种前后端分离,还是基于浏览器的方式,有一些开发者为了方便,会这样设置,这样设置,在csrf漏洞范畴中是很危险的,这样B网站可以通过ajax访问A网站的内容(因为允许所有网站跨域ajax访问),然后解析出来csrf的信息,然后加入到表单中提交,还是会发起csrf攻击,csrf验证将会通过,因此线上环境不要这样设置,只将vue端的域名填写进去即可。

关于fecshop vue端的cors设置:http://www.fecshop.com/topic/1547

关于Yii2 csrf 防范的代码分析,这个文章分析的很好,可以参看这个:https://www.cnblogs.com/HKUI/p/6068453.html

共收到 6 条回复
Fecmall#15年前 0 个赞

因为csrf的触发有一些条件,需要登陆用户点击跨站的链接才能触发,因此小站经常忽略这个。

fecshop近期将会把csrf的漏洞补齐

                                                  2018-11-26
Fecmall#25年前 0 个赞

出处:https://security.stackexchange.com/questions/115794/should-i-use-csrf-protection-for-get-requests

google翻译文字如下:

由于同源政策,只有状态变更操作才需要CSRF保护。该政策规定:

Web浏览器允许第一个Web页面中包含的脚本访问第二个Web页面中的数据,但前提是两个Web页面具有相同的源。

因此,CSRF攻击将无法访问它请求的数据,因为它是跨站点(即CSRF中的CS)请求,并且由同源策略禁止。所以非法数据访问不是CSRF的问题。

由于CSRF攻击可以执行命令但无法查看其结果,因此它被迫盲目行动。例如,CSRF攻击可以告诉您的浏览器请求您的银行帐户余额,但无法看到该余额。这显然是一种毫无意义的攻击(除非您尝试DDoS银行服务器或其他东西)。但是,例如,如果CSRF攻击告诉您的浏览器指示您的银行将资金从您的帐户转移到攻击者的帐户,那么这并非毫无意义。攻击脚本无法访问传输的成功或失败页面。幸运的是,对于攻击者来说,他们不需要查看银行的回复,他们只想在他们的帐户中存钱。

由于只有状态变化的操作可能成为CSRF攻击的目标,因此只有他们需要CSRF防御。

因此对于查看数据的get请求是不需要加csrf的,但是对于一些delete操作也使用get请求,就需要更改请求方式了。

Fecmall#35年前 0 个赞

对于appserver,这类web api,是从request header中读取access-token,和session cookie的原理不一样,因此是不能跨站进行csrf攻击的

https://github.com/fecshop/yii2_fecshop/blob/master/yii/filters/auth/QueryParamAuth.php#L27

https://github.com/fecshop/yii2_fecshop/blob/master/services/Customer.php#L666

因此fecshop的appserver入口是没有csrf漏洞的

资料参考:https://www.bbsmax.com/A/xl563yX0dr/ https://www.web-tinker.com/article/20857.html

successgo#45年前 0 个赞

讲解的很清楚明白,十分有用。

Fecmall#55年前 0 个赞

为了一次性解决csrf漏洞问题,又回头查阅了资料,以及yii2的实现

这次升级后,xss和csrf就都没问题了

之前纠结一个问题:

我自己的网站为A,伪造站为B

如果产品页面我做full page cache(整页缓存),那么动态数据需要异步加载,产品页面存在加入购物车操作post请求,需要csrf参数,但是csrf是不能缓存的,因此必须通过ajax异步加载过来,那么我使用ajax异步加载的csrf信息,B站是否可以通过ajax加载过来?然后放到form表单中伪造,在fecshop的产品页面你会发现有一个get的ajax请求,因为get请求默认是可以跨站的,譬如图片的加载, 那么js是否可以读取呢?看了这篇文章放心了:https://security.stackexchange.com/questions/115794/should-i-use-csrf-protection-for-get-requests

As a CSRF attack can execute commands but can't see their results, it is forced to act blindly. 

另外我也测试了,ajax跨站get请求,通过浏览器的debug工具可以查看到内容的确是加载了,但是浏览器js无法读取内容

Fecmall#65年前 0 个赞

因此对于网站中涉及到数据库更新操作的update,add,delete操作,不要使用get请求,而必须需要使用post请求,原因解析:

1.get请求默认是可以跨站请求的,譬如图片加载

2.很多时候为了方便,我们会将一些删除操作使用get请求,譬如后台数据列表,删除某条数据,直接用a标签,然后加上删除的url,然后将要删除的id写到url请求里面,直接get请求,写起来很方便,譬如:http://wwww.xxx.com/custom/article/delete?id=33,然后使用get请求,这个只有登陆用户才能访问,因此会认为是安全, 但是这会留下csrf漏洞, 如果你登陆了后台账户,别人给你发了封邮件,里面有一个假的图片,为: <img src="http://wwww.xxx.com/custom/article/delete?id=33">,那么打开邮箱的时候,你的后台的这一条数据就会被删除,因为浏览器里面有cookie,因此有执行权限。

3.因此涉及到数据库改动的要用post请求

4.对于get请求,仅仅是查询,不会涉及到数据库操作,因此被加载了也不会存在更新操作

5.get请求,就像上面img src加载的方式,浏览器为了安全,js默认是不能读取内容的,虽然浏览器加载了get的内容。

6.当然,post请求也可以被攻击,在form表单里面,需要加上csrf参数,譬如:

<input class="thiscsrf" type="hidden" value="-pJu7CfqMcpScHBs6vTyAyyylKUEOG_25ufQZi89oUKU1xaaXahY8jovHB2Zlb5lTtPd0kgPIamgrKo1bUnAHQ==" name="_csrf">

然后在服务端做csrf验证,就可以防范csrf了。

添加回复 (需要登录)
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册
Your Site Analytics