我们首先统一一下口径:
站点A:被攻击的网站
站点B:伪造请求的网站
一般网站的防御方法是:
判断请求中的token和cookie中的token是否相同,相同则表示请求发起者和会话用户是同一个人。
这种防御方法可行的原因是:
站点B无法获取到站点A的cookie,所以无法在请求中添加token。
但,我们假设站点B知道站点A的某个页面表单里有隐藏的token字段,那么,站点B在自己的页面中写一个隐藏的iframe去请求这个页面。(这里有一个问题,iframe会创建新的会话吗?但不管会不会,都有如下可能)
- iframe不会生成新的会话。那么对于用户而言,假设用户在访问站点A后没有关闭站点又去访问了站点B,那么站点B中的iframe和站点A属于同一个会话,也就是说他们的token相同。这个时候站点B通过预先写好的脚本去获取到iframe中的token,然后在伪造的请求中加入这个token,能否成功?
- iframe会生成新的会话。那也就是说站点B的iframe中的token和站点A的token值是不相同的,但是可以使用以下方法去伪造请求:站点B不是直接在页面中添加伪造请求,而是在iframe里去添加伪造请求,由于iframe中是站点A的会话,所以请求会带着站点A的cookie一起发出去,由于iframe和站点A共用一套cookie(因为同域),所以就成功盗用了用户的身份。这种方法可行吗?
---------- 补充 -----------
经过验证,iframe并不会产生新的会话,而是会沿用未关闭的站点A的会话。
也就是说,iframe中表单的token字段已经可见,关键在于脚本是否能够获取到(跨域获取iframe中的内容)。
我想你对csrf是不是有一些误会。。。
首先,iframe跨域嵌套基本是不可行的,这点你可以试试各大网站,你用iframe嵌套它们,并尝试获取iframe中的内容,会被拒绝。
然后,csrf的攻击无需获取cookie(它的原理是攻击网站B构建一个a网站的请求,冒充是a网站,然后就成功的让浏览器带上了cookie-所以,哪怕是http only也无法阻止,从而身份校验成功-当然,这里你应该也能看到,最简单的判断referer字段就可以防御了,不过鉴于客户端是不可信的,所以一般不建议仅仅只校验referer)
再说下,目前的csrf防御的一种通用方案是:请求加token(注意,不是cookie作为token,而是主动在header请求里加一个token字段)
这样,只要你无法获取实际的token,就无法伪造,所以相对安全系数更高。