如果JWT被盗怎么办?

smw*_*dia 170 authentication access-token jwt

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

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

但是,如果有一个窃听者看到了请求并窃取了令牌呢?那么他能用我的身份伪造请求吗?

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

怎么预防?像HTTPS这样的安全渠道?

rde*_*ges 257

我是一个节点库的作者,它在很大程度上处理身份验证,表达stormpath,所以我会在这里提供一些信息.

首先,JWT通常加密.虽然有一种方法可以加密JWT(参见:JWE),但由于许多原因,这在实践中并不常见.

接下来,任何形式的身份验证(使用JWT或不使用JWT)都会受到MitM攻击(中间人)攻击.当您通过互联网发出请求时,攻击者可以查看您的网络流量,就会发生这些攻击.这是您的ISP可以看到的,NSA等.

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

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

现在,这是协议的来源.

JWT只是身份验证令牌的一个标准.它们可以用于几乎任何东西.JWT很酷的原因是你可以在其中嵌入额外的信息,你可以验证没有人搞乱它(签名).

但是,JWT本身与"安全"无关.对于所有意图和目的,JWT与API密钥或多或少相同:只是随机字符串,用于在某处对某个服务器进行身份验证.

是什么让你的问题更有趣,是使用的协议(很可能是OAuth2).

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

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

使用OAuth2时,您必须经常通过提供用户名/密码或API凭据,然后以交换方式获取令牌来重新对服务器进行身份验证.

因为这个过程经常发生,所以你的令牌会经常变化,让攻击者更加难以不经常冒犯你.

希望这有助于^^

  • 输入单个响应时间太长.如果你想了解更多,我已经就这个问题进行了详细的讨论.您可以在线查看我的幻灯片:https://speakerdeck.com/rdegges/jwts-suck-and-are-stupid (5认同)
  • 作者不对.您可以使用不同的设计模式来使令牌无效.但总的来说:使用JWT进行任何类型的身份验证都是个坏主意.使用具有嵌入内部的会话构思的会话cookie更加高效,该会话构思是以加密方式签名的. (4认同)
  • 下一篇文章的作者认为,JWT的一个缺点是,从被盗的JWT中恢复的唯一方法是生成一个新的密钥对并有效地注销所有用户。鉴于会话ID存储在数据库中,该网站只能删除受影响用户的会话并将其注销所有设备。我不确定OAuth2如何适合这里的图片,或者它是否有助于减轻呈现的缺点。https://medium.com/@rahulgolwalkar/pros-and-cons-in-using-jwt-json-web-tokens-196ac6d41fb4 (3认同)
  • 从理论上讲,不可能防止令牌被盗。我们能做的最好的事情就是检测到发生了这种情况,然后尽快撤消会话。最好的检测方法是使用旋转刷新令牌(如RFC 6819所建议)。这是一个详细解释此问题的博客:https://supertokens.io/blog/the-best-way-to-securely-manage-user-sessions (2认同)

Fro*_*dor 26

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

为了实现这个目标,你应该总是发行短期令牌(取决于大多数情况,在我的应用程序中,我实际上将exp声明设置为30分钟,并且ttl为3天,所以只要它ttl仍然可以刷新此令牌有效且令牌未被列入黑名单)

对于authentication service,为了使令牌无效,我喜欢使用内存缓存层(在我的情况下为redis)作为JWT blacklist/ ban-list在前面,取决于一些标准:(我知道它打破了RESTful哲学,但存储的文件是真的很短暂,因为我将剩余的生存时间列入黑名单 - ttl索赔- )

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

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

最后,您通常会像每个人一样验证令牌.

注2:我建议为声明生成和使用UUID令牌,而不是使用令牌本身(实际上很长)作为缓存的密钥jti.哪个好,我想(不确定,因为它只是出现在我的脑海中)你可以使用同样的UUID作为CSRF令牌,通过返回一个secure/ non-http-onlycookie并X-XSRF-TOKEN使用js 正确实现头.这样您就可以避免为CSRF检查创建另一个令牌的计算工作.

  • 贡献你的想法永远不会太晚.感谢您的回复. (7认同)
  • 能便宜到什么程度?首先,如果你仍然在服务器端存储任何东西,你就不能享受 JWT 声称的“可扩展性”好处,因为在做任何事情之前,所有应用程序服务器都需要与一个中央黑名单服务器进行对话。如果因为快过期只需要存储1k个黑名单,可以对session做同样的操作,因此只需要存储1k个session。 (7认同)
  • 我喜欢这种方法。实际上,您不必检查每个请求的黑名单,只需检查在JWT过期(可以从令牌本身读取)之后直到TTL期间发生的请求。在“标准”用例中,最多应该在给定令牌的生存期内发生一次。刷新后,您可能会拒绝以后的任何刷新请求。谢谢@Frondor (3认同)
  • 如果您在服务器上存储了一个需要检查每个请求的黑名单,那么为什么不简单地使用普通的旧会话呢? (2认同)

aRv*_*Rvi 10

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

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

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

在上述用例中,您还可以使用有效期为 5 分钟的缓存,而不是每次都进行检查。

建议是否可以改进。


yan*_*nky 6

抱歉,在此方面晚了一点,但有类似的担忧,现在想在同一点上有所作为。

1)rdegges补充了一个很好的观点,即JWT与“安全性”无关,并且仅验证是否有人弄乱了有效载荷(签名);ssl有助于防止违规。

2)现在,如果ssl也以某种方式受到威胁,任何窃听者都可以窃取我们的不记名令牌(JWT)并冒充真正的用户,下一步可以做的是,从客户端寻求JWT 的“拥有证明”

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

为此,我提到了所有权证明一文,并对方法深信不疑。

如果能够做出任何贡献,我将很高兴。

欢呼声(y)


小智 5

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

  • 这是一种可能的解决方案,但对于防火墙后面的客户端来说,通常是从地址池中选取 IP 地址,并且该地址可以随时更改。 (3认同)
  • 如果有转发代理怎么办?或者用户每次连接时都使用VPN。不值得接近。 (3认同)
  • 移动用户也是一个问题。我的移动IP每天都会变化很多次。 (3认同)