如果JWT被偷了怎么办?

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

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

但是如果有一个窃听者看到了请求和窃取令牌呢?然后他就能用我的身份伪造申请了?

实际上,这个关注点适用于所有基于令牌的身份验证

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

60785 次浏览

我是一个节点库的作者,它相当深入地处理身份验证,express-stormpath,所以我将在这里补充一些信息。

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

接下来,任何形式的身份验证(是否使用jwt)都可能受到MitM攻击(中间人)的攻击。当攻击者在你通过互联网发出请求时可以查看你的网络流量时,就会发生这些攻击。这是你的ISP可以看到的,美国国家安全局,等等。

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

然而,让我们说,有人能够利用您的SSL并能够查看您的令牌:您问题的答案是是的,攻击者能够使用该令牌来模拟您并向您的服务器发出请求。

这就是协议的用武之地。

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

然而,jwt本身与“安全性”无关。从所有意图和目的来看,jwt或多或少与API密钥相同:只是用于对某个服务器进行身份验证的随机字符串。

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

OAuth2的工作方式是为客户端提供临时令牌(如jwt !),仅用于短时间的身份验证!

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

使用OAuth2,您必须经常通过提供您的用户名/密码或API凭据来重新验证自己,然后以交换的方式获得令牌。

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

希望这有助于^^

我知道这是一个老问题,但我认为我可以在这里放弃我的0.5美元,也许有人可以改进或提供一个完全拒绝我的方法的论点。 我正在使用jwt在HTTPS (ofc)上的RESTful API

要做到这一点,你应该总是发出短暂的令牌(取决于大多数情况,在我的应用程序中,我实际上将exp声明设置为30分钟,ttl设置为3天,所以只要它的ttl仍然有效,令牌还没有列入黑名单,你就可以刷新这个令牌)

对于authentication service,为了使令牌无效,我喜欢使用内存中的缓存层(在我的例子中是复述,)作为前面的JWT blacklist/ban-list,这取决于一些标准: (我知道这违反了RESTful哲学,但存储的文档确实是短暂的,因为我将它们的剩余生存时间列入黑名单- __abc0 claim-)

注意:黑名单令牌不能自动刷新

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

最后,像所有人一样,正常地验证令牌。

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

对不起,我来晚了一点,但我有类似的担忧,现在想在同样的问题上贡献一些东西。

1) rdegges增加了一个很好的观点,即JWT与“安全”无关,只是验证,如果有人搞砸了有效负载与否(签名);SSL有助于防止入侵。

2)现在,如果ssl也以某种方式受到损害,任何窃听者都可以窃取我们的持有者令牌(JWT)并模拟真正的用户,下一个可以做的步骤是,从客户端寻找JWT的“管有证明”

3)现在,使用这种方法,JWT的演示者拥有一个特定的所有权证明(POP)密钥,接收方可以密码地确认请求是否来自同一真实用户。

我参考了管有证明的文章,并相信这种方法。

如果能有所贡献,我将非常高兴。

干杯(y)

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

为了处理令牌被盗用的问题,您将每个JWT映射为有效ip列表。

例如,当用户登录一个特定的IP时,当你可以添加该IP为该JWT的有效IP时,当你从另一个IP(用户改变了互联网或JWT被盗,或任何原因)得到这个JWT的请求时,你可以根据你的用例做以下事情:

  1. 将CSRF令牌与用户令牌映射,如果它被窃取,那么它的CSRF令牌将不匹配,因为您可以使该用户令牌无效。
  2. 您可以向用户提供验证码,以验证他是否是有效用户。如果他输入验证码,然后将该IP添加到该JWT的有效列表中。
  3. 您可以注销该用户,然后重新请求登录。
  4. 您可以提醒用户您的IP已更改或从不同的位置请求。

建议是否可以改进。

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

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

令牌将改变每个请求。

一旦令牌被盗,游戏就结束了。 然而,有一种方法可以使使用被盗令牌变得更加困难

检查https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html#token-sidejacking作为参考。

基本上,您可以创建一个x字节长的十六进制指纹,将其原始值存储在令牌哈希中,例如使用SHA-512,并将哈希指纹放在httponly安全cookie中。

现在,您不仅需要验证令牌的签名和过期日期,还需要验证cookie的存在,并确保原始指纹值匹配。