更新:我已经完成了对此问题的研究,并发布了一篇冗长的博客文章,解释了我的发现:The Unspoken Vulnerability of JWTs。我解释了使用JWT进行本地身份验证的重大举措是如何遗漏一个关键细节:必须保护签名密钥。我还解释说,除非你愿意竭尽全力保护密钥,否则你最好通过Oauth委派身份验证或使用传统的会话ID。
我已经看到很多关于JSON Web令牌安全性的讨论 - 重放,撤销,数据透明,令牌指定alg,令牌加密,XSS,CSRF - 但我没有看到任何对风险的评估依赖签名密钥。
如果某人违反了服务器并获得了JWT签名密钥,我认为此人此后可以使用该密钥伪造未过期的JWT并秘密获取访问权限。当然,服务器可以在每个请求上查找每个JWT以确认其有效性,但服务器完全使用JWT,因此他们不必这样做。服务器可以确认IP地址,但是如果JWT不可信,那还涉及查找,显然这样做会妨碍可靠的移动访问。
将此与基于会话ID的服务器违规进行对比。如果此服务器是散列密码,则攻击者必须在每个用户到期之前单独使用会话ID。如果服务器仅存储会话ID的哈希值,则攻击者必须写入服务器以确保访问。无论如何,似乎攻击者的优势不大。
我找到了一种使用JWT而没有这种缺点的架构。反向代理位于外部不可信客户端和内部微服务后端集合described here by Nordic APIs之间。客户端从授权服务器获取不透明令牌,并使用该令牌与服务器应用程序通信以获取所有请求。对于每个请求,代理将不透明令牌转换为JWT并缓存它们的关联。外部世界从未提供JWT,限制了窃取密钥造成的损害(因为代理进入认证服务器以确认不透明的令牌)。但是,此方法需要解除引用每个客户端令牌,就像会话ID需要按请求解除引用一样,从而消除了JWT对客户端请求的好处。在这种情况下,JWT只允许服务在他们自己之间传递用户数据而不必完全相互信任 - 但我仍然试图理解该方法的价值。
我的担忧似乎仅适用于不受信任的客户使用JWT作为身份验证令牌。然而,JWT被许多备受瞩目的API使用,包括Google API。我错过了什么?服务器漏洞可能很少只读?有没有办法减轻风险?
答案 0 :(得分:4)
我相信你正在以错误的方式思考这个问题。不要误会我的意思,你考虑安全性是很好的,但是你在服务器端检查事物的方式接近它的方式,添加额外的检查来破坏无状态会话的目标等等,似乎是一条单行道,走向你自己的理智。
总结两种标准方法:
JWT是无会话状态对象,由服务端密钥保存MAC。
传统会话标识符存储在内存或数据库服务器端,正如您所说的那样,经常进行哈希处理以防止会被泄露的会话被劫持。
攻击者通常难以实现写访问权限。原因是数据库数据通常是通过SQL injection漏洞从目标系统中提取的。这几乎总是提供对数据的读访问,但是使用这种技术插入数据更加困难,尽管并非不可能(某些漏洞实际上导致了对目标机器的完全root访问)。
如果您有一个允许在使用JWT时允许访问密钥的漏洞,或者在使用会话标识符时允许写入数据库表的漏洞,则游戏结束 - 您的用户会话可能被劫持,您将受到攻击。
因此,更多必然会造成损害,这一切都取决于漏洞的深度。
仔细检查您的JWT键的安全性是否符合您的风险偏好:
减轻影响的方法是任何网络应用程序的良好实践:
这些将帮助您评估真正的风险所在。这非常集中于应用程序的某个特定方面,因为这会导致忽略其他人,这可能会给您的业务模型带来更高的风险。 JWT并不危险,并且没有比系统中其他组件更多的风险,但是如果您选择使用它们,则应确保正确使用它们。无论您是否适用于您的应用程序的特定环境,并且在一般意义上难以评估,所以我希望我的答案能够指导您朝着正确的方向前进。
答案 1 :(得分:0)
当攻击者能够在基于JWT的系统中获取签名密钥时,这意味着他能够访问服务器后端本身。在那种情况下,所有希望都会消失。与此相比,当同一攻击在基于会话的系统中成功时,攻击者将能够拦截对后端的用户名/密码身份验证请求,和/或自己生成会话ID,和/或更改验证会话所需的验证例程id和/或修改会话ID指向的数据。用于缓解此问题的任何安全机制也适用于会话系统和JWT系统。