在 REST API 中使用客户端随机数防止重新提交和重放攻击

信息安全 休息 api 随机数
2021-08-16 17:24:55

我有一个 REST API 后端,它具有 HTTPS(和阻止 HTTP)并使用 JWT 作为身份验证机制。客户端是 iOS/Android 应用程序。我想通过使用客户端随机数来为关键 API 添加一层保护,以防止(大部分)重新提交(由于网络/UI 不良而无意中调用相同的 API 两次)和(可能)重放攻击。目前的详细情况如下。

(所有 REST 调用都通过 HTTPS)

  1. 客户端使用用户名和密码进行 API 调用,以从服务器端交换 JWT。
  2. 客户端使用获得的 JWT(HTTP 标头)并随后对服务器进行 API 调用。
  3. 后端服务器检查 JWT 并执行请求。

当前的问题是,任何可以拦截 HTTP 包的人都可以重放 API 调用。此外,在网络不好的情况下,客户端可以按两次提交/确认按钮,然后重新提交请求。

我的建议如下:

  1. 客户端使用用户名和密码进行 API 调用,以从服务器端交换 JWT。
  2. 客户端使用获得的 JWT + 客户端生成的 nonce 并随后对后端服务器进行 API 调用。
  3. 后端服务器首先检查 JWT,然后检查 nonce。假设我们有一个类似 Redis 的带有 TTL 的 kv 存储。
  4. 如果 Redis 中存在 nonce,我们将拒绝该请求。如果不是,我们接受请求并在 Redis 中使用一些预定义的 TTL(比如 1 小时?)设置 nonce,以便拒绝重播。

我不得不承认我对安全知之甚少。我想知道这个提议是否合法?还是我错过了一些重要的事情?如果我的想法没问题,生成随机数的最佳算法是什么?在将它与 Redis 进行比较之前,服务器端是否需要以某种方式“解码”随机数以查看它是否符合协议?

2个回答

客户端随机数存在三个困难:

  • 客户端如何知道何时生成新的 nonce?(什么动作构成了一个新的请求,以便为它生成一个新的随机数?)

  • 服务器如何知道什么是有效的随机数?假设的攻击者提供的 4gb blob 可以是随机数吗?

  • 服务器如何知道要保留多少随机数以及保留多长时间?

服务器提供的 nonce 有两个好处:

  • 让客户做的更少
  • 服务器知道接下来会发生什么

服务器不必保留所有 nonce 的记录,只记录当前的 nonce,并且可以在第一个有效请求到达时将其删除。一个新的随机数可以随响应一起发送。

此模型强制执行一个请求中的交互模型。如果需要多个并发请求,服务器可以生成一个 nonce 块,但挑战再次是客户端需要一个模型来区分唯一请求,确保每个用户操作不会导致从中提取新的 nonce当地的游泳池。这个困难应该建议以这样一种方式构建应用程序,即一次只有一个 nonce-required 请求正在运行。

(所有 REST 调用都是通过 HTTPS)

然后,您已经受到保护,免受重放攻击。