签名的好坏取决于验证器

一个 的签名使其声明可信,但前提是验证它的代码正确地这样做。大多数 JWT 漏洞并非密码学中的缺陷;它们是可被诱使接受本应拒绝令牌的验证器。以下是重要的那些,以及防止它们的检查。

信任令牌自身的算法

  • alg: none JWT 规范定义了一个无签名的“未受保护”令牌,以 {"alg":"none"} 声明。一个遵从它的验证器将接受一个带有伪造声明和空签名的令牌。一个正确的验证器绝不会把 none 视为对一个本应被签名令牌的有效值。
  • 算法混淆()。RS256 中,令牌由一个私钥签名并用公钥验证。如果一个验证器从令牌读取算法,而攻击者把头部改为 HS256,验证器可能尝试用公钥作为密钥来验证一个 ,而这个值攻击者也持有。伪造的令牌于是通过。

两者唯一的防御相同:由验证器决定可接受的算法,而非令牌。 在你的验证调用中固定预期的算法(或一个简短的允许列表),并拒绝其他任何算法。

跳过声明

一个有效签名证明令牌已被签发且未被篡改。它并不证明该令牌是给你的仍然有效。一个正确的验证器还会检查:

  • exp(过期)nbf(不早于):拒绝已过期或尚未生效的令牌,并允许一个小的时钟漂移容差。
  • aud(受众):确认该令牌是为此服务而设的。为服务 A 签发的令牌不应被服务 B 接受。
  • iss(签发者):确认它来自你信任的签发者,并从该签发者而非从令牌中推导验证密钥。

省略这些,正是一个被盗或误投的令牌最终在其不应被接受之处被接受的方式。

较小的陷阱

  • HMAC 密钥。 一个用简短或可猜测密钥签名的 HS256 令牌,可被离线暴力破解直到找到一个匹配的签名。请使用一个长的随机密钥。
  • 处理 kid kid 头部选择一个密钥;把它视为不受信任的输入(它曾被用于注入),且只从你信任的签发者的 JWKS 获取密钥。
  • 把解码与验证混为一谈。 在不检查签名和时间的情况下读取一个令牌的声明并非验证。只对一个完全验证过的令牌采取行动。

简短版

固定算法、验证 expaudiss、使用强密钥,并且绝不把解码与验证混为一谈。JWT 工具 会解码一个令牌,以清晰的语言显示其声明与过期,并对你粘贴的一个密钥验证一个 HMAC 签名,全部在你的浏览器中,令牌和密钥绝不会被发送。