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

请教一下关于 nonce 防重放

  •  1
     
  •   matepi · 170 天前 · 2657 次点击
    这是一个创建于 170 天前的主题,其中的信息可能已经有所发展或是发生改变。
    有一点没想明白,如果针对客户端是 web 页面的情况,那么 nonce 的生成算法,就一般都是在 web 端的 js 代码中了。

    这样相当于 nonce 的生成过程,仍然是对客户端暴露的,只要重放人有能力进行客户端 js 的分析与模拟运行,那不是 nonce 就失效了么?
    第 1 条附言  ·  170 天前
    具体的需求是:

    一个系统具有多个较复杂的幂等查询功能,内部用户使用。
    但发现内部用户太多使用自动化手段、模拟正常用户登录,反复调用幂等查询,造成查询所占资源紧张。
    尤其是内部正常用户之间还会借用多账号等手段,增加自动化并发能力。
    希望通过一些手段控制,这些用户自动化重复调用、消耗系统资源的情况。

    现在大家对 nonce 的解释听下来,恐怕这个需求、并不是一个可以通过 nonce 防重放解决的需求?
    第 2 条附言  ·  170 天前
    总结一下从楼里从大家这边学到的:

    nonce 防重放,要注意的,并不能解决正常用户重复自动化请求的问题。
    而是解决 mitm 等过程中,被截获请求后,以“简单”低成本,重复用户请求的情况。

    我所上述问题场景,个人理解还是有一些常见性的,现在看来
    不是防重放,和反爬有些关联又不相同,是不是应该定义一种新的场景、还是说有这样的场景轮子了呢?

    防自动化?优雅请求?用户配额限流?

    其中又需要具备的是什么技术
    限流;
    用户配额管理;
    对 WEB 日志等进行聚类分析等以发现自动化操作、并联动用户封禁/配额动态调整
    ……等等?

    有没有针对这样的,听上去是防重放、又有区别于防重放的场景,已有的轮子了呢?
    31 条回复    2023-11-09 11:36:12 +08:00
    LonnyWong
        1
    LonnyWong  
       170 天前   ❤️ 2
    防重放不是说防用户重复请求,一般是防别人在网络上抓到你的包,然后重放。
    举个例子,你向 A 转账 10 元,并不是说你不能再向 A 转 10 元。防的是 A 把你的包抓了,不断地转 10 元。
    error451
        2
    error451  
       170 天前
    一个 nonce 只能够请求一次,你抓到了 nonce 再一次请求是不可能成功的啊, 怎么可能进行重放攻击?
    你是不是混淆了 nonce ? nonce 不是 token 啊 , 不需要任何算法, 你自己手输入一个随机字符串也可以啊。没有人会对 nonce 校验,单纯的放一个列表里就行了。
    一个算法就做一件事情,nonce 就只防止重放攻击,其他的安全措施需要用其他的算法,别混淆。
    jinliming2
        3
    jinliming2  
       170 天前 via iPhone
    即便是 web 页面,nonce 也是服务端下发的哇?
    matepi
        4
    matepi  
    OP
       170 天前
    @LonnyWong 理解了。但这样也是假设在这个“别人”并没有对服务端客户端深度分析的情况下吧。如果这个“别人”是有心人,分析了这个 nonce 整体的交互和生成过程。那应该也是仍然可以实现重放的?

    又,如果要防用户的重复请求呢?尤其是查询类,没有类似金额控制类的情况呢。
    killerv
        5
    killerv  
       170 天前
    有点记不太清楚了,nonce 应该是服务端发放的,随机的保证一段时间内不重复就行,这个只能用一次,客户端生成 nonce ,服务端也不认啊
    matepi
        6
    matepi  
    OP
       170 天前
    @jinliming2 这意思是,nonce 是随着用户前一次请求,由服务器端返回客户端的,并在下一次请求中再带上服务端么?我看的理解还以为是都是客户端完全随机生成 uuid 或者带点 timestamp 之类的客户端算法生成?

    如果是服务器端生成,那对于分布式化的服务端,一是要搞个中心存储节点来存了吧?二是,这样会禁止掉在客户端开启多个 web 页面,并行操作的可能?
    retNu1l
        7
    retNu1l  
       170 天前
    nonce 随机生成的,没有啥算法,没有签名情况下你随便改个字母都大概率命中不了重复校验。另外一般会对 once 同请求参数一起签名一下,增加逆向客户端及抓包篡改难度。
    tool2d
        8
    tool2d  
       170 天前   ❤️ 1
    一般都是服务器返回的,你访问一下这个:

    https://acme-v02.api.letsencrypt.org/acme/new-nonce

    返回的头有 replay-nonce ,每次都会变,正常情况下客户端是无法生成的。

    那些能生成的,都是野路子。
    LonnyWong
        9
    LonnyWong  
       170 天前
    @matepi nonce 是完全随机的,一次性的,知道怎么生成也没用。你说的别人分析交互过程,不是防重放,是防假冒,要用其他手段来解决。

    防重复请求,一般在请求前生成一个唯一的 ID ,后台要根据这个 ID 去重,前端要确保同一个请求的 ID 相同且全局唯一。
    tool2d
        10
    tool2d  
       170 天前
    单纯客户端生成的,基于 timestamp 的签名,那种叫 Signature-Algorithm: HMACSHA256

    我尝试过想破解,但是是一个 APP ,并不是 web js 代码,难度就挺大的。
    matepi
        11
    matepi  
    OP
       170 天前
    @retNu1l 这个签名如果是客户端做的,不是一样会能被搞掉的么?尤其 web 页面情况,js 代码都很好模拟的情况下
    matepi
        12
    matepi  
    OP
       170 天前
    @LonnyWong “一般在请求前生成一个唯一的 ID ”这个何时、何侧、以何种算法生成的呢?按我之前理解是客户端,现在听大家的意思的理解,应该是在前一次请求、由服务器端、按服务器端内的算法生成的?

    “前端要确保同一个请求的 ID 相同且全局唯一。”我的理解,客户端前端只是把服务器端前一次下发的内容,在本次再带上服务器端的简单逻辑?客户端前端应该没有啥确保保证的能力吧。

    但如果是“在前一次请求、由服务器端、按服务器端内的算法生成的”;“并在本次再带上服务器”的逻辑的话,似乎这个逻辑就会限制了用户开多个 web 页面并行做请求的能力?
    vultr
        13
    vultr  
       170 天前
    @matepi 8 楼 @tool2d 说的才是对的,nonce 得服务器返回才是安全的。
    tool2d
        14
    tool2d  
       170 天前
    @matepi "似乎这个逻辑就会限制了用户开多个 web 页面并行做请求的能力?"

    前端有个幂等属性,关键 POST 操作肯定不能并行请求。

    如果是 GET ,那随便并行。
    matepi
        15
    matepi  
    OP
       170 天前
    @tool2d 返回头的返回情况,如果一个正常用户,在前一个正常请求还没有完成、返回头还没有带回客户端的情况下,就并行进行第二次正常请求,这种情况怎么办呢?或是 ajax 异步请求提交并发交易、或是直接保留原页面以右键在新页面中打开的方式提交交易呢
    matepi
        16
    matepi  
    OP
       170 天前
    @tool2d ……现在的需求就是要控制幂等交易(大开销查询)的正常用户但其做的模拟幂等交易。随便放行并不行啊……
    potatowish
        17
    potatowish  
       170 天前 via iPhone
    客户端前端从服务端获取 nonce ,不管是通过接口返回还是返回头的方式,有心人都能获取新的 nonce
    LonnyWong
        18
    LonnyWong  
       170 天前
    @matepi 简单的 UUID 就可以,按需求定制适用的方案。
    zliea
        19
    zliea  
       170 天前
    防重放其实主要还是 timestamp ,nonce 只是加入随机,增加难度而已。
    cylx3124
        20
    cylx3124  
       170 天前
    nonce 只是前后端签名验证的一部分, 一般通过 nonce + 时间戳 + 验签, 可以做到反爬虫和防止针对同一请求的重放。

    nonce + 时间戳 + 验签的方式, 只能增加伪造请求的难度, 不能完全杜绝伪造请求。因为不管是浏览器还是 app 端, nonce 获取和验签代码都是在客户端本地运行的, 有能力的人一定能破解你的 nonce 和 验签算法。

    B 站 app 就是典型的例子 https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/misc/sign/APP.md

    只有在后端做好风控、参数和业务逻辑的各种校验,才能真正做到接口的安全(服务器被攻击除外)。
    dyllen
        21
    dyllen  
       170 天前
    @matepi 你是为了防止页面数据重复提交?这个随机字符串是服务器下发的,是直接渲染在页面里面的。
    szandy6
        22
    szandy6  
       170 天前
    nonce 又不是加密算法生成的,它就是一个随机串,不存在暴漏问题。
    你可以理解为 nonce 保证只能请求一次,服务器会短暂保存请求过的 nonce ,下次再有人用这个 nonce ,就会被认为是重放。
    matepi
        23
    matepi  
    OP
       170 天前
    @cylx3124 我的理解,风控、参数和逻辑校验,其实还是不能解决、正常用户的大开销的幂等查询类请求?类似于 DDoS 的请求行为?最终只能给用户上配额之类的?

    但配额也是有问题的,如果自动化查询者具备了很多用户账号,实际上还是能够挤占正常用户的额度?
    cylx3124
        24
    cylx3124  
       170 天前
    @matepi

    这种需求如果有专业的风控团队,可以扔给风控团队去做,没有的话就只能根据 手机号、用户 id ,设备 id 、ip 等不同维度在服务端实现拦截了。

    真正的反爬虫是一种很难实现的目标,因为任何一种反爬虫的方法都可能被爬虫工程师找到绕过的办法。
    justplaymore
        25
    justplaymore  
       170 天前
    nonce 是用来保证明文的不可预测性。

    当明文非常容易预测时:
    举例:
    请求 1 明文 money=10 ,签名 abc 。
    请求 2 明文 money=10 ,签名 abc 。
    请求 3 明文 money=10 ,签名 abc 。
    这 3 个请求的明文是相同的,非常好预测,没有随机性,那么攻击者收集足够多的请求样本后,就知道明文和密文的直接对应关系了,就可以得到一个明文和密文的字典了,类比彩虹表。

    当在明文中加上了 nonce ,保证不可预测性
    举例:
    请求 1 明文 money=10&nonce=q1w2e3r4 签名 1234
    请求 2 明文 money=10&nonce=5t4r3e2w1 签名 4567
    请求 3 明文 money=10&nonce=5t6y7u8i9 签名 6787
    虽然这 3 个请求中都是 10 元,但是明文不同,导致签名也不同,攻击者无法通过收集的样本,分析出明文 10 元和签名的关系。

    我是从不可预测性来解释 nonce 的作用,和具体的技术实现没有关系,和前端还是后端实现没有关系。
    proxytoworld
        26
    proxytoworld  
       170 天前
    nonce 是防 mitm 的,至于你说的限制,得在服务端进行限流
    justplaymore
        27
    justplaymore  
       170 天前
    一个系统具有多个较复杂的幂等查询功能,内部用户使用。
    但发现内部用户太多使用自动化手段、模拟正常用户登录,反复调用幂等查询,造成查询所占资源紧张。
    尤其是内部正常用户之间还会借用多账号等手段,增加自动化并发能力。
    希望通过一些手段控制,这些用户自动化重复调用、消耗系统资源的情况。

    看了你的需求,这不是 nonce 能解决的场景。
    对用调用量过多的情况,可以使用接口调用限流来控制,降低自动化调用的效率。
    对于复杂查询,可以从查询缓存,异步计算角度去考虑。
    opengps
        28
    opengps  
       170 天前
    后端幂等性当然得靠后端进行,办法也非常简单,就是第一次有效执行结果的缓存重发就行了
    justplaymore
        29
    justplaymore  
       170 天前   ❤️ 5
    lz 的提问方式是典型的 xy 问题。

    对于 X-Y Problem 的意思如下:

    1 )有人想解决问题 X
    2 )他觉得 Y 可能是解决 X 问题的方法
    3 )但是他不知道 Y 应该怎么做
    4 )于是他去问别人 Y 应该怎么做?

    简而言之,没有去问怎么解决问题 X ,而是去问解决方案 Y 应该怎么去实现和操作。于是乎:

    1 )热心的人们帮助并告诉这个人 Y 应该怎么搞,但是大家都觉得 Y 这个方案有点怪异。
    2 )在经过大量地讨论和浪费了大量的时间后,热心的人终于明白了原始的问题 X 是怎么一回事。
    3 )于是大家都发现,Y 根本就不是用来解决 X 的合适的方案。

    X-Y Problem 最大的严重的问题就是:在一个根本错误的方向上浪费他人大量的时间和精力!
    moya
        30
    moya  
       170 天前
    nonce 防止 XSS 攻击
    gxm44
        31
    gxm44  
       170 天前
    nonce 服务端下发,而且 js 无法读取到
    moya
        32
    moya  
       170 天前
    @moya 看错忽略,以为说的是 script 标签
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1087 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 23:16 · PVG 07:16 · LAX 16:16 · JFK 19:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.