如果 JWT 被盗怎么办?

What if JWT is stolen?

我正在尝试使用 JWT 为我的 RESTful API 实施无状态身份验证。

AFAIK,JWT 基本上是在 REST 调用期间作为 HTTP headers 传递的加密字符串。

但是如果有窃听者看到请求并窃取令牌怎么办?那么他就可以用我的身份伪造请求了?

实际上,此问题适用于所有 token-based 身份验证

如何预防?像 HTTPS 这样的安全通道?

我是一个处理身份验证的节点库的作者,express-stormpath,所以我会在这里提供一些信息。

首先,JWT 通常 加密。虽然有一种加密 JWT 的方法(参见:JWEs),但出于多种原因,这在实践中并不常见。

接下来,任何形式的身份验证(使用或不使用 JWT)都会受到中间人攻击 (man-in-the-middle) 攻击。当攻击者可以在您通过 Internet 发出请求时查看您的网络流量时,就会发生这些攻击。这是你的 ISP、NSA 等可以看到的

这就是 SSL 帮助防止的事情:通过加密来自您的计算机的网络流量 -> 某些服务器在进行身份验证时,监视您的网络流量的第三方无法看到您的令牌、密码或类似的东西,除非他们能够以某种方式获得服务器私有 SSL 密钥的副本(不太可能)。这就是 SSL 对于所有形式的身份验证都是强制性的原因。

但是,假设有人能够利用您的 SSL 并能够查看您的令牌:您问题的答案是,攻击者能够使用该令牌来冒充您并向您的服务器发出请求。

现在,这就是协议的用武之地。

JWT 只是身份验证令牌的一种标准。它们几乎可以用于任何事情。 JWT 有点酷的原因是您可以在其中嵌入额外的信息,并且您可以验证没有人弄乱它(签名)。

但是,JWT 本身与 'security' 无关。就所有意图和目的而言,JWT 或多或少与 API 密钥相同:只是用于对某处服务器进行身份验证的随机字符串。

使您的问题更有趣的是所使用的协议(很可能是 OAuth2)。

OAuth2 的工作方式是它旨在为客户提供临时令牌(如 JWT!)以仅在短时间内进行身份验证!

想法是,如果您的令牌被盗,攻击者只能在短时间内使用它。

使用 OAuth2,您必须经常 re-authenticate 通过提供您的 username/password 或 API 凭据然后取回令牌作为交换,您自己经常使用服务器。

因为这个过程时不时地发生,你的令牌会经常改变,让攻击者更难不断冒充你而不会遇到很大的麻烦。

希望对你有帮助^^

我知道这是一个老问题,但我想我可以在这里放下我的 0.50 美元,也许有人可以改进或提供一个论据来完全拒绝我的方法。 我通过 HTTPS (ofc) 在 RESTful API 中使用 JWT。

为此,您应该始终发出 short-lived 令牌(取决于大多数情况,在我的应用程序中,我实际上将 exp 声明设置为 30 分钟,并且 ttl 到 3 天,因此只要其 ttl 仍然有效且令牌尚未被 列入黑名单 )

,您就可以刷新此令牌

对于 authentication service,为了使令牌无效,我喜欢使用 in-memory 缓存层(redis 在我的例子中) 作为前面的 JWT blacklist/ban-list,具体取决于某些条件: (我知道它打破了 RESTful 的理念,但存储的文档实际上是 short-lived,因为我将剩余的 time-to-live -ttl 声明-列入黑名单-)

注意:黑名单令牌无法自动刷新

  • 如果 user.passworduser.email 已更新(需要密码确认),auth 服务 returns 刷新令牌并使(黑名单)以前的令牌无效,因此如果您客户端检测到用户的身份已被以某种方式泄露,您可以要求该用户更改其密码。 如果您不想为此使用黑名单,您可以(但我不鼓励您)验证针对 user.updated_at 字段的 iat(发布于)声明(如果 jwt.iat < user.updated_at 那么 JWT 无效)。
  • 用户故意退出。

最后你像大家一样正常验证令牌。

注意 2: 我建议为 jti 生成并使用 UUID 令牌,而不是使用令牌本身(真的很长)作为缓存的键宣称。这很好,我认为(不确定,因为它刚刚出现在我的脑海中)你也可以使用与 CSRF 令牌相同的 UUID,通过返回一个 secure / non-http-only cookie 并正确地使用 js 实现 X-XSRF-TOKEN header。这样您就可以避免为 CSRF 检查创建另一个令牌的计算工作。

抱歉来晚了一点,但也有类似的担忧,现在想就此做出一些贡献。

1) rdegges 补充了一个很好的观点,即 JWT 与 "security" 无关,只是验证是否有人搞砸了负载(签名); ssl 有助于防止违规行为。

2) 现在,如果 ssl 也以某种方式受到损害,任何窃听者都可以窃取我们的不记名令牌 (JWT) 并冒充真正的用户,下一步可以做的是,寻找 来自客户端的 JWT "proof of possession"

3) 现在,通过这种方法,JWT 的提交者拥有一个特定的 Proof-Of-Possession(POP) 密钥,接收者可以 cryptographically 确认请求是否来自同一真实用户或没有。

我为此参考了 Proof of Possesion 文章,并且对这个方法深信不疑。

如果能贡献点什么,我会很高兴。

干杯 (y)

我们不能只添加请求生成此 JWT 令牌的初始主机的 ip 作为声明的一部分吗?现在,当 JWT 被盗并从另一台机器使用时,当服务器验证此令牌时,我们可以验证请求的机器 ip 是否与作为声明一部分的那一组匹配。这将不匹配,因此令牌可以被拒绝。此外,如果用户尝试通过将自己的 ip 设置为令牌来操纵令牌,则令牌将被拒绝,因为令牌已更改。

为了解决令牌被盗的问题,您将每个 JWT 映射到有效 IP 列表。

例如,当用户使用特定 IP 登录时,您可以将该 IP 添加为该 JWT 的有效 IP,以及当您从另一个 IP(用户更改了互联网或JWT 被盗,或任何原因)您可以根据您的用例执行以下操作:

  1. 您可以向用户提供验证码以验证他是否是有效用户。如果他输入验证码,则将该 IP 添加到该 JWT 的有效列表中。
  2. 您可以注销用户并重新请求登录。
  3. 您可以提醒用户您的 IP 已更改或从其他位置请求。

建议是否可以改进。

客户端应使用用户密码的部分哈希来加密客户端向服务器发送http 消息的时间。这部分散列也应该在创建时用一些服务器密钥加密到令牌中。

服务器可以解密http请求时间并验证短时间延迟。

令牌将在每次请求时更改。