V2EX 的 csrfToken 设计缺陷及修正 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
autoxbc
V2EX    程序员

V2EX 的 csrfToken 设计缺陷及修正

  •  
  •   autoxbc 2017-08-15 06:14:35 +08:00 6122 次点击
    这是一个创建于 3049 天前的主题,其中的信息可能已经有所发展或是发生改变。
    关于跨域请求伪造攻击,十八摸这个文章写的简单易懂
    https://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/

    打开本站每一个话题页面都有一个独立 csrfToken,并在那些写数据的处理函数中附带这个 token。

    但是这个设计有个问题,就是 token 会快速过期。比如打开 A 话题页面,然后打开 B 话题页面,回到 A 页面,给某个人发送感谢,一定会失败,但是 thankReply 函数没有正确处理返回数据,会显示感谢发送成功。

    同样的问题会出现在 感谢回复,感谢主题,给主题投票,忽略主题,收藏主题,删除通知。

    在遵循 csrfToken 设计初衷的情况下,可以有一些修正方法。

    网站方面:
    1. 每个页面中使用 localStorage 存储 csrfToken,对所有写数据的请求,放弃硬编码 token,也不读取全局变量,而是从 localStorage 中读取,此时网站的所有打开页面共享一个最新的 token,失效问题解决。

    2. 因为写数据相比读数据是个低频行为,所以可以设立单独的 updateToken 方法,每次写数据操作,先 ajax 一个 token,服务器根据用户当前是否合法登录,决定是否返回有效 token。获取到 token 后,附加到写数据函数中。

    用户方面:
    V 站的各种设计,其实累积了一些问题,好像长期没有修正。作为用户,可以自己动手改良体验。
    1. 对应上面的方法 1,自己写脚本 localStorage.csrfToken = csrfToken,然后写几个函数封装上面的 6 个系统函数,然后埋到对应位置。

    2. 对应上面的方法 2,自己写 updateToken 方法,ajax 最新的 token,然后写几个函数封装上面的 6 个系统函数,然后埋到对应位置。

    方法 2 的好处是,如果 token 的过期时间较短,即使 localStorage.csrfToken = csrfToken,对于那些打开较长时间的页面(一天没看完的主题,第二天接着看),也可能面临过期问题。每次更新就没有问题。

    各位发布了 V2EX 增强脚本的同学,如果看到了这个帖子,可以考虑加进这个特性。
    19 条回复    2017-08-15 18:18:45 +08:00
    binux
        1
    binux  
       2017-08-15 06:30:21 +08:00 via Android
    然而 V2EX 现在的 csrf 不需要 js
    zjsxwc
        2
    zjsxwc  
       2017-08-15 06:33:55 +08:00 via Android
    我觉得如果不考虑 ie6 这种老浏览器,其实上 https 与校验 referer 就能防御 csrf,没必要用 csrf token。
    wenzhoou
        3
    wenzhoou  
       2017-08-15 07:56:01 +08:00 via Android
    5 年前的帖子。有错误啊。referer 主流的浏览器都能禁止的。referer 伪造比较容易,这条路我认为走不通。token 才是正确解决方式。楼主说 local storage,那不是特意把本来隐藏起来的东西,公开给所有人看吗?这样真的好吗?
    caomu
        4
    caomu  
       2017-08-15 08:35:35 +08:00 via Android   1
    v 站的 csrf 很有毒,而且 ajax 还照样返回正常。。。强迫我每次 ajax 操作都要手动刷新一次看结果,然后现在我都不后台多开帖子了,看完一个后退再看另一个。。。真希望能改进一下。。。
    zjsxwc
        5
    zjsxwc  
       2017-08-15 08:40:37 +08:00
    @wenzhoou

    如果有用户会去折腾浏览器主动禁止 referer,那么我认为这是水平很高的用户了,那么他能够为他的行为负责。
    zjsxwc
        6
    zjsxwc  
       2017-08-15 08:53:09 +08:00
    @autoxbc
    >> 2. 因为写数据相比读数据是个低频行为,所以可以设立单独的 updateToken 方法,每次写数据操作,先 ajax 一个 token,服务器根据用户当前是否合法登录,决定是否返回有效 token。获取到 token 后,附加到写数据函数中。



    你如果一定要使用 csrftoken,那么必须每个页面都是独立的 token,如果像你说的提供一个获取最新 csrftoken 的接口,来实现共用一个最新的 csrftoken 的话,你这个获取 csrftoken 的接口本身就有问题了,如何保证不被恶意跨域获取最新 csrftoken 呢?于是这种 csrftoken 方式就完全没有意义了。
    honeycomb
        7
    honeycomb  
       2017-08-15 09:58:17 +08:00 via Android
    @zjsxwc 我们一般会增大 referer 的粒度,或是不信任的情况下完全禁用 referer,以及 url 上的如 utm 的尾巴。
    毕竟网站不需要知道用户从哪里来,或是要去哪里。
    keakon
        8
    keakon  
       2017-08-15 10:18:14 +08:00   2
    印象中 V2EX 应该是用 Tornado 实现的,默认的 csrfToken 是保存在 cookie 中的,服务端并不保存,而是检查 POST 的数据是否和 cookie 中一致。至于每个页面都更新 csrfToken,则不是 Tornado 干的。
    cgb1021
        9
    cgb1021  
       2017-08-15 10:32:36 +08:00
    2 young 2 simple
    vjnjc
        10
    vjnjc  
       2017-08-15 10:56:16 +08:00
    没有还原你说的发送感谢失败。。。。
    autoxbc
        11
    autoxbc  
    OP
       2017-08-15 13:09:49 +08:00
    @wenzhoou #3
    localStorage 只有所属网站和用户可以访问,不会公开给第三方
    autoxbc
        12
    autoxbc  
    OP
       2017-08-15 13:17:50 +08:00
    @zjsxwc #6
    token 捆绑到用户而不是页面,第三方跨域取的 token 不是用户的 token,诱骗用户做取 token 的动作,得到的数据第三方也拿不到。可以仔细读帖子中的介绍文章。
    autoxbc
        13
    autoxbc  
    OP
       2017-08-15 13:42:28 +08:00
    @keakon #8 这个部分可能没用框架的内置实现,自己写的有副作用
    autoxbc
        14
    autoxbc  
    OP
       2017-08-15 13:48:10 +08:00
    @vjnjc #10 我这可以重复还原,并且按照方案 1 写了修正,修完就好了

    其他人的反馈,可以看这个帖子
    t/382609
    wenzhoou
        15
    wenzhoou  
       2017-08-15 14:02:55 +08:00 via Android
    @autoxbc 感谢指正。
    neilwong
        16
    neilwong  
       2017-08-15 17:36:59 +08:00
    我在想会不会有 xss+csrf 的混合型攻击,先 xss 获取到 csrfToken,再在自己页面上伪造提交,可能需要钓鱼链接支持才能实现吧
    ctsed
        17
    ctsed  
       2017-08-15 18:12:52 +08:00 via Android   1
    其实只考虑防 csrf,token 复用也没事
    ctsed
        18
    ctsed  
       2017-08-15 18:16:04 +08:00 via Android
    @neilwong 如果有 xss,还在乎 csrf ?
    autoxbc
        19
    autoxbc  
    OP
       2017-08-15 18:18:45 +08:00
    @neilwong #16
    好像 xss 危害更高,如果 xss 已经成功,可以直接在目标页面提交攻击,不再需要 csrf token。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1396 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 16:39 PVG 00:39 LAX 08:39 JFK 11:39
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86