前后端分离的项目, API 接口如何防止重放攻击 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lemayi
V2EX    问与答

前后端分离的项目, API 接口如何防止重放攻击

  •  
  •   lemayi 2017-07-29 15:21:23 +08:00 20572 次点击
    这是一个创建于 3028 天前的主题,其中的信息可能已经有所发展或是发生改变。
    当前的项目是前后端分离的,用了 laravel 的 jwt 做 token 验证。
    看过很多文档都说用时间戳 timestamp 和 nonstr 来做。
    但是客户端的时间戳没办法保证和服务器的一致。
    每个用户的可能时区都不一样。没办法通过传递时间戳参数来验证是否过期。
    如果只用 nonstr,如果设置 1 天清除一次。那么一天后重放也是可以的。
    所以想请教下怎么来处理这个问题呢?
    19 条回复    2017-07-30 11:25:54 +08:00
    shoaly
        1
    shoaly  
       2017-07-29 16:10:49 +08:00
    客户端传给服务器
    ?nOnstr=md5(时间戳 +随机数+ 特定字符串)&time=时间戳&random=随机数

    服务器端:
    验证 md5(用客户端传入的时间戳+ 随机数+特定字符串) 与 nonstr 对比 验证是否是客户端的请求, 然后将这个 nonstr 存入缓存当中, 同一个 nonstr 如果已经存在, 则为重放攻击
    shoaly
        2
    shoaly  
       2017-07-29 16:11:42 +08:00
    补充 1 天之后的重放, ..时间戳能对比出来啊.... 客户端确实和服务器端时间不一致, 但是 差不了几秒.
    retanoj
        3
    retanoj  
       2017-07-29 16:16:38 +08:00 via Android
    为什么时间戳无法保证和服务器一致? 难道不是在用格林尼治时间吗? timestamp 加签名应该可以解决重放了
    des
        4
    des  
       2017-07-29 16:31:03 +08:00
    时间差?就不能请求获得服务器时间,然后基于这个时间戳校正吗,如果出错就先获取一次时间戳再请求一次。

    总不能客户端的一分钟被人偷走一秒吧?
    nealv2ex
        5
    nealv2ex  
       2017-07-29 16:39:50 +08:00
    单纯的放重放来说 ,全不用不管与服务器的差值,只看时间戳就可以,时间是线性增大,不会变小,如果不变或者变小了,就有问题。

    收到请求,校验时间戳必须比上一次 这个 session 的提交的时间戳大。

    比如
    第一次是 0,第二次 1 在过滤重放攻击这个条件下,这 2 个值都是合法的。
    ho121
        6
    ho121  
       2017-07-29 16:53:24 +08:00
    @nealv2ex 改时间怎么办?
    danielmiao
        7
    danielmiao  
       2017-07-29 17:02:28 +08:00   1
    令牌桶,客户端请求的时候判断超过 x 分钟,更新令牌;
    然后旧令牌的失效时间为,更新令牌的时间+[0.2, 1] * x,以保证正常的并发请求;

    简单的说就是动态发放令牌,有效令牌为当前发放和有效期内的旧令牌,最好使用 cookie,保证对页面的无侵入
    danielmiao
        8
    danielmiao  
       2017-07-29 17:03:22 +08:00
    @nealv2ex 这个方案有个问题就是 ajax 并发请求的时候,后发先置的问题
    paradoxs
        9
    paradoxs  
       2017-07-29 17:11:37 +08:00
    参照 google authy 的验证机制, 把随机数发生器内置在前端就行了。
    nealv2ex
        10
    nealv2ex  
       2017-07-29 17:42:35 +08:00
    @ho121 改时间,就不是 *重放* 攻击了。

    @danielmiao 这里只解决 *重放*,后发先至是其他问题。

    不过请思考一下,后发的请求已经到了,那么是不是说,

    客户端取消了先发的请求,要不然哪里来的后发请求,

    那么我只处理后发的请求,不处理先发的请求应该是合理的。
    lemayi
        11
    lemayi  
    OP
       2017-07-29 18:15:37 +08:00
    感谢各位的解答!非常感谢!
    @nealv2ex 的回答,之前我也有考虑。但是确实会有并发,后发先至的问题。既然是并发,先发,后发的请求都肯定是合理。如果参考你的处理的方式,肯定就排除掉了正常的请求。

    @shoaly @des @retanoj 因为是前后端分离的 web 项目。js 生成的时间戳应该是本地时间。所以这个时间是很有可能和服务器不一致的。跨时区,篡改等。我之前做过测试。在服务器端放个含时间 js 的 html。然后去请求。确实打印出来的时间是我本地的时间。我电脑改了。显示的时间也改变了。其实我问的问题,主要就是纠结于此。如果是在后端的程序请求 api 那就没这个问题。我可以让客户端设置成和服务器端的一致。

    @danielmiao 的方式令我思路大开。因为当前用的是 jwt 的 token。那么我可以让前端,每 30 分钟就去重新刷新获取新的 token。然后配置每次请求用 nonstr 来防止重发。记录 30 分钟内的 nonstr 集合。不在这个集合里面就是正常请求。这样即使过了 30 分钟,发起重放。实际上我的 token 已经变了。就没这个问题了。也不会有时间戳一致的问题了。
    plantain
        12
    plantain  
       2017-07-29 18:23:42 +08:00
    标准方法难道不是 https ?
    des
        13
    des  
       2017-07-29 18:42:03 +08:00 via Android
    @lemayi 一开始以为是客户端,web 的话上 https 啊,不然重放都是小问题
    motian
        14
    motian  
       2017-07-29 18:50:26 +08:00 via iPhone
    时间戳本身是跟时区无关的,你在东八区和零时区,不同的是日期时间,时间戳是一致的,客户端和服务端的时间差问题可以进行定期的时间校准。
    retanoj
        15
    retanoj  
       2017-07-29 22:27:26 +08:00 via Android   1
    不过 lz,jwt 里有个字段是标识请求仅一次有效的啊,好像是 iat ?可以参考一下
    whileFalse
        16
    whileFalse  
       2017-07-29 22:29:40 +08:00 via iPhone
    你要防止的是啥?中间人重放的话上 https 就行
    lianz
        17
    lianz  
       2017-07-29 22:34:42 +08:00
    timestamp=int(timestamp()/30),这样服务器客户端时间误差 30 秒内就可以满足条件。

    当然请求签名是一定要做的,不然一切白费。
    voocel
        18
    voocel  
       2017-07-29 22:45:25 +08:00 via iPhone
    请问用的是哪个 jwt 包
    lemayi
        19
    lemayi  
    OP
       2017-07-30 11:25:54 +08:00
    @voocel "tymon/jwt-auth": "^1.0@dev"
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4848 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 09:45 PVG 17:45 LAX 01:45 JFK 04:45
    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