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

token 如何存放才能避免 csrf 攻击

  •  
  •   NoKey · 121 天前 · 2462 次点击
    这是一个创建于 121 天前的主题,其中的信息可能已经有所发展或是发生改变。
    放 cookie 中,但是后端不读 cookie
    所有请求需要前端把 token 放到 header 中一个参数下
    后端读 header 中的这个参数
    这样是不是就可以放置 csrf 攻击了呢?
    第三方直接通过服务链接带 cookie 过来,因为后端不读取,所以鉴权不通过
    13 条回复    2024-07-30 11:27:42 +08:00
    zzNucker
        1
    zzNucker  
       121 天前
    存 cookie, header, html 都可以
    ss098
        2
    ss098  
       121 天前
    你是不是在找 OAuth 2.0 Bearer token ?
    yinmin
        3
    yinmin  
       121 天前
    常见这 2 种方式吧:
    方式一:csrf token 放服务器的 session ,然后前端传 token (header 、post 参数、get 参数都可以)做对比
    方式二:csrf token 放 cookie 里(设置成 httponly 和 secure),然后前端传 token (header 、post 参数、get 参数都可以)做对比

    方式一的服务器 session 容易丢失,我是推荐方式二,可以做成无服务器状态模式。
    happyxhw101
        4
    happyxhw101  
       121 天前
    一般放在 header 里面可以防止 csrf 攻击,
    如果是放在 cookie 里面,那需要单独生成一个 csrf token ,前端用 js 把 csrf token 放在 header 里面,同时生成一个值是 csrf token 的 cookie ,后端收到请求比较 header 和 cookie 里面的值,这种也是常规手段,但也不能做到 100%
    Belmode
        6
    Belmode  
       121 天前
    我觉得 CSRF 无非是避免浏览器,在非法跨站请求携带默认参数时,导致的权限问题。那`认证信息`放哪都无所谓了,放 cookie 也可以,放本地存储也可以,提交的时候放 header 也行,放 cookie 也行。只要保证存储和使用时有标记不一样,并且服务端只认带这个标记的`认证信息`。

    楼上说的,Bearer Token 就是。`认证信息`存任何地方都行,但是放在请求头上时,Authorization: Bearer <token>。这样就确保,是自己站点的页面执行了 js 发送的请求,不是跨站请求。

    所以用 OAuth2.0 之类的认证方式,只要提交请求认证信息时做点不一样的操作,都不用特别考虑 CSRF 攻击,因为从机制上已经避免了。
    Belmode
        7
    Belmode  
       121 天前
    @Belmode OP 提问中的疑问的答案是肯定的。你那样操作,是可以避免 CSRF 攻击的。
    moon548834
        8
    moon548834  
       120 天前
    @Belmode 请教下为什么 token 放 cookie 里可以呢?我理解 header 是 ok 的
    用户 A 请求正常网站 C ,假设用户点了某个钓鱼网站 B ,那么 B->C 的过程不是会把 cookie 信息自动带上吗?

    或者说一个普通的 access_token 放到 cookie 面临的问题不能被一个也在 cookie 中的 csrf token 解决?
    forvvvv123
        9
    forvvvv123  
       120 天前
    @happyxhw101

    OP 用这个方法就行,最简单实用的,cookie 双重认证, 你所有的重要请求都在页面上用 js 发 post , 发的时候把 cookie 里面的 token 值带到请求上,放 post 参数、header 里都行;

    你后端收请求的时候:
    1. 先看 cookie 里面有没有 token ,没 token 就拒绝,然后 set-cookie 种个随机数 token ;
    2. 再看请求里面带没带和 cookie 一样的 token ,不一样就拒绝;

    对 csrf 的问题就解决了;


    网上有很多会结合 xss 和 csrf 考虑的,我个人认为这样复杂了,一般有了 xss 漏洞就不考虑 csrf 了,xss 能做的太多了;有 xss 的问题修 xss 的问题,讨论 csrf 都是要在没 xss 没钓鱼的情况下讨论,不然说不清;
    Belmode
        10
    Belmode  
       119 天前
    @moon548834 #8

    首先,我说以下一般实现,现在很多网站或者说产品,都没有专门设置 CSRF token 的,都不是通过这种手段来避免跨站攻击。
    在你例子中,用户从钓鱼网站 B 触发的网站 C 的请求,携带了 Cookie 到目标服务器,但是服务器是不会认可`此次请求已被授权的`,因为不是从网站 C 页面上发起的,所以网站 C 的 JS 没有执行,没有讲 Cookie 中的 token 部分提取出来,放到 Header 中,并拼上`Bearer`之类的符号,所以这次请求,就和用户第一次访问网站 C 一样,是安全的。

    这其中关键在于,网站 C 服务端,不认可从其他网页发起的 http 请求,只认可自己页面的,所以借助 Ouath2.0 令牌模式的机制,避免了 CSRF 。

    当然你自定义任何方式都可以,只要类似我#6 的说法。

    PS1: 理论上令牌可以放到任何位置,但是一般放到 localStorage 里,因为浏览器请求在没有 JS 处理的情况下,不会携带这些信息,有一定安全性。
    PS2: 我说的只是一种最简单的模型理论,实际上企业中,预防 CSRF 的手段特别多,因为用户信息和权限的校验步骤非常多,也非常复杂,不是那一种方式就能完成的,都是多种手段并用。
    PS3:V 站用了 CSRF token ,并且这个 token 有实效,过期了,页面都直接时效了,可以参考。
    moon548834
        11
    moon548834  
       118 天前
    "在你例子中,用户从钓鱼网站 B 触发的网站 C 的请求,携带了 Cookie 到目标服务器,但是服务器是不会认可`此次请求已被授权的`,因为不是从网站 C 页面上发起的"

    这个你说的是同源检查吧,如果 C 不做同源检查,那应该是认可的..

    ref: https://tech.meituan.com/2018/10/11/fe-security-csrf.html
    NoKey
        12
    NoKey  
    OP
       117 天前
    @moon548834 后端不仅仅通过 cookie 里面的 token 进行鉴权相关识别,是不是就没问题了,不用管是不是同源?
    moon548834
        13
    moon548834  
       114 天前
    @NoKey 应该是吧,总之我还是认为把 token 放 header 里是最佳实践
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1064 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 18:59 · PVG 02:59 · LAX 10:59 · JFK 13:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.