这是 node-jws 库中签名验证绕过漏洞的概念验证。该漏洞允许攻击者在服务器从用户可控数据派生 HMAC 密钥时伪造有效的 JWT。
jws.createVerify() 函数在使用 HMAC 算法时,不会验证是否确实提供了密钥。如果你的应用程序根据 JWT 中的某些内容(如 kid 头)查找密钥,并且查找失败,那么你最终可能会使用空密钥进行验证。
攻击者可以利用这一点:
undefined,该值会被强制转换为空字符串攻击者现在可以冒充任何人或为自己授予管理员权限。
升级到 3.2.3+ 或 4.0.1+ 以修复此问题。
确保已安装 Bun,然后:
# 安装受影响版本
bun install [email protected]
# 运行利用程序
bun run exploit.js
你应该会看到输出显示一个伪造的管理员令牌被接受为有效。
PoC 模拟了一个服务器,它具有:
kid(密钥 ID)头查找密钥createVerify()攻击者创建一个 kid: "non-existent-key" 的 JWT,并使用空密钥签名。当服务器尝试查找此密钥时,获取到 undefined,将空字符串写入验证流,伪造的令牌通过验证。
# 升级到修补版本
bun install [email protected]
# 再次运行 - 现在应该失败
bun run exploit.js
使用修补版本,你将看到一个错误:secret must be a string or buffer or a KeyObject。该修复在继续之前验证 HMAC 操作是否具有正确的密钥。
如果你的代码类似于以下内容,你可能会受到影响:
const decoded = jws.decode(token);
const secret = lookupSecret(decoded.header.kid); // 可能返回 undefined!
const verifier = jws.createVerify({
algorithm: "HS256",
signature: token,
});
verifier.secret.write(secret); // 糟糕
verifier.secret.end();