首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  程序员

V2EX 的 csrfToken 设计缺陷及修正

  •  
  •   autoxbc · 2017-08-15 06:14:35 +08:00 · 4580 次点击
    这是一个创建于 819 天前的主题,其中的信息可能已经有所发展或是发生改变。
    关于跨域请求伪造攻击,十八摸这个文章写的简单易懂
    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
        1
    binux   2017-08-15 06:30:21 +08:00 via Android
    然而 V2EX 现在的 csrf 不需要 js
        2
    zjsxwc   2017-08-15 06:33:55 +08:00 via Android
    我觉得如果不考虑 ie6 这种老浏览器,其实上 https 与校验 referer 就能防御 csrf,没必要用 csrf token。
        3
    wenzhoou   2017-08-15 07:56:01 +08:00 via Android
    5 年前的帖子。有错误啊。referer 主流的浏览器都能禁止的。referer 伪造比较容易,这条路我认为走不通。token 才是正确解决方式。楼主说 local storage,那不是特意把本来隐藏起来的东西,公开给所有人看吗?这样真的好吗?
        4
    caomu   2017-08-15 08:35:35 +08:00 via Android   ♥ 1
    v 站的 csrf 很有毒,而且 ajax 还照样返回正常。。。强迫我每次 ajax 操作都要手动刷新一次看结果,然后现在我都不后台多开帖子了,看完一个后退再看另一个。。。真希望能改进一下。。。
        5
    zjsxwc   2017-08-15 08:40:37 +08:00
    @wenzhoou

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



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

    其他人的反馈,可以看这个帖子
    https://www.v2ex.com/t/382609
        15
    wenzhoou   2017-08-15 14:02:55 +08:00 via Android
    @autoxbc 感谢指正。
        16
    neilwong   2017-08-15 17:36:59 +08:00
    我在想会不会有 xss+csrf 的混合型攻击,先 xss 获取到 csrfToken,再在自己页面上伪造提交,可能需要钓鱼链接支持才能实现吧
        17
    ctsed   2017-08-15 18:12:52 +08:00 via Android   ♥ 1
    其实只考虑防 csrf,token 复用也没事
        18
    ctsed   2017-08-15 18:16:04 +08:00 via Android
    @neilwong 如果有 xss,还在乎 csrf ?
        19
    autoxbc   2017-08-15 18:18:45 +08:00
    @neilwong #16
    好像 xss 危害更高,如果 xss 已经成功,可以直接在目标页面提交攻击,不再需要 csrf token。
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   4245 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 23ms · UTC 02:45 · PVG 10:45 · LAX 18:45 · JFK 21:45
    ♥ Do have faith in what you're doing.