JWT介绍及其安全性分析
字数 2292 2025-08-18 11:39:08

JSON Web Token (JWT) 安全详解

0x00 JWT 简介

JSON Web Token (JWT) 是一种紧凑的、URL安全的表示方式,用于在双方之间传输声明。JWT 中的声明被编码为 JSON 对象,用作 JSON Web Signature (JWS) 结构的有效载荷或 JSON Web Encryption (JWE) 结构的明文。

JWT 由三部分组成:

  • Header (头部)
  • Payload (有效载荷)
  • Signature (签名)

这三个部分使用 BASE64URL 算法编码(与 BASE64 相似,但 + 替换为 -/ 替换为 _,且去掉 = 填充)。

示例 JWT 结构:

eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxNjYwNDYiLCJleHAiOjE1NzI4Mzk4NTZ9.aAwuJZBuG2zKBJ04QQ36FvLP-9PesiO30j9VCDDgKR0

解码后:

// header
{
  "alg": "HS256"
}
// payload
{
  "iss": "166046",
  "exp": 1572839856
}
// VERIFY SIGNATURE
HMACSHA256(
  base64UrlEncode(header)
  base64UrlEncode(payload),
  111
)

0x01 JWT 的安全问题

1. 缺乏机密性

JWT 的有效载荷可以轻松解码,如果需要保密数据,应使用 JWE (JSON Web Encryption)。

2. 潜在授权绕过

攻击者可能修改有效载荷并绕过授权检查。虽然签名机制可以防止篡改,但实现不当会导致漏洞。

0x02 JWT 攻击方法

攻击方法一:修改签名算法

攻击步骤:

  1. 获取一个已签名的 JWT
  2. 修改标头为 {"alg":"none"}
  3. 发送给服务器(可带或不带签名)

漏洞原因:JWT 规范中 "none" 算法是合规的,但许多库错误地接受了这种无签名的令牌。

相关漏洞:

攻击方法二:删除签名

攻击步骤:

  1. 获取一个使用 HS256/HS512 等算法签名的 JWT
  2. 删除整个签名部分
  3. 发送给服务器

漏洞原因:某些库在签名缺失时仍会解码并验证令牌。

案例:

攻击方法三:插入错误信息

攻击步骤:

  1. 修改有效载荷
  2. 服务器返回错误信息可能包含敏感信息(如预期签名)

漏洞原因:服务器配置不当,在错误信息中泄露敏感数据。

案例:

攻击方法四:破解 HMAC 密钥

攻击步骤:

  1. 获取一个 JWT 令牌
  2. 使用暴力破解/字典攻击破解 HMAC 密钥

工具:

安全要求:根据 RFC,HMAC 密钥长度应至少与哈希输出相同(HS256 需要 256 位密钥)。

攻击方法五:利用签名方法混淆

攻击步骤(针对 RSA 算法):

  1. 获取服务器的公钥
  2. 修改标头为 HS256 但使用 RSA 公钥作为 HMAC 密钥
  3. 服务器使用公钥验证 HMAC 签名

漏洞原因:服务器未强制使用特定签名算法,允许攻击者指定算法。

案例:

攻击方法六:信任攻击者密钥

攻击步骤:

  1. 攻击者在令牌中嵌入自己的公钥
  2. 服务器使用攻击者提供的公钥验证签名

案例:

攻击方法七:恢复私钥

针对 JWE 加密的漏洞:

  • ECDH-ES 算法实现问题:Adobe 报告
  • AES-GCM 模式漏洞:研究论文
  • RSA 使用 PKCS1v1.5 填充的已知问题

攻击方法八:上下文相同令牌

漏洞原因:多个服务器使用相同签名密钥,一旦泄露可生成任意有效令牌。

解决方案:使用 iss (签发者) 和 aud (受众) 声明限制令牌使用范围。

攻击方法九:重放 JWT

攻击步骤:

  1. 获取一个有效令牌(如用于 DELETE 操作)
  2. 在令牌过期后重新使用

解决方案:使用 jti (JWT ID) 和 exp (过期时间) 声明,并确保正确实现。

案例:

攻击方法十:定时攻击签名

攻击原理:通过测量签名验证响应时间差异,逐步破解签名。

研究显示:在实验室条件下,每秒 55,000 请求可在 22 小时内破解签名。

防御措施:使用恒定时间比较算法验证签名。

0x03 JWT 安全最佳实践

设计与实现

  1. 明确需求:确定需要 JWS 还是 JWE,选择合适的算法
  2. 强制使用特定签名算法,不允许客户端指定
  3. 区分 verify()decode() 功能
  4. 关闭调试模式,防止信息泄露

密钥管理

  1. 使用足够强度的密钥(HS256 至少 256 位)
  2. 密钥不在代码中硬编码,安全存储
  3. 制定密钥泄露应急方案
  4. 生产与测试环境使用不同密钥

签名验证

  1. 拒绝 "none" 算法
  2. 拒绝缺失签名的令牌
  3. 检查 JWE 使用的加密算法是否安全
  4. 使用恒定时间算法比较签名

令牌管理

  1. 不在 URL 中传递令牌(防止日志记录)
  2. 设置合理的短有效期(exp 声明)
  3. 实现令牌吊销机制
  4. 使用 issaud 声明限制使用范围
  5. 检查 jti 唯一性防止重放

库安全

  1. 定期检查使用的 JWT 库漏洞
  2. 及时更新到安全版本
  3. 监控新发现的漏洞

0x04 JWT 替代方案

PASETO (Platform-Agnostic Security Tokens)

PASETO 旨在解决 JWT 的设计缺陷,提供更安全的替代方案。

特点:

  • 更简单的设计
  • 强制使用安全算法
  • "none" 算法等危险选项

资源:

0x05 参考资料

  1. JSON Web Token 最佳实践
  2. JWT 手册
  3. JWT 漏洞讨论
  4. Java JWT 速查表 (OWASP)
  5. JWT 会话安全问题
JSON Web Token (JWT) 安全详解 0x00 JWT 简介 JSON Web Token (JWT) 是一种紧凑的、URL安全的表示方式,用于在双方之间传输声明。JWT 中的声明被编码为 JSON 对象,用作 JSON Web Signature (JWS) 结构的有效载荷或 JSON Web Encryption (JWE) 结构的明文。 JWT 由三部分组成: Header (头部) Payload (有效载荷) Signature (签名) 这三个部分使用 BASE64URL 算法编码(与 BASE64 相似,但 + 替换为 - , / 替换为 _ ,且去掉 = 填充)。 示例 JWT 结构: 解码后: 0x01 JWT 的安全问题 1. 缺乏机密性 JWT 的有效载荷可以轻松解码,如果需要保密数据,应使用 JWE (JSON Web Encryption)。 2. 潜在授权绕过 攻击者可能修改有效载荷并绕过授权检查。虽然签名机制可以防止篡改,但实现不当会导致漏洞。 0x02 JWT 攻击方法 攻击方法一:修改签名算法 攻击步骤: 获取一个已签名的 JWT 修改标头为 {"alg":"none"} 发送给服务器(可带或不带签名) 漏洞原因:JWT 规范中 "none" 算法是合规的,但许多库错误地接受了这种无签名的令牌。 相关漏洞: CVE-2018-1000531 Auth0 漏洞报告 攻击方法二:删除签名 攻击步骤: 获取一个使用 HS256/HS512 等算法签名的 JWT 删除整个签名部分 发送给服务器 漏洞原因:某些库在签名缺失时仍会解码并验证令牌。 案例: FusionAuth 漏洞 攻击方法三:插入错误信息 攻击步骤: 修改有效载荷 服务器返回错误信息可能包含敏感信息(如预期签名) 漏洞原因:服务器配置不当,在错误信息中泄露敏感数据。 案例: Auth0 CVE-2019-7644 jwt-dotnet 漏洞 攻击方法四:破解 HMAC 密钥 攻击步骤: 获取一个 JWT 令牌 使用暴力破解/字典攻击破解 HMAC 密钥 工具: hashcat -m 16500 jwt.txt -a 3 -w 3 ?a?a?a?a?a?a c-jwt-cracker 安全要求:根据 RFC,HMAC 密钥长度应至少与哈希输出相同(HS256 需要 256 位密钥)。 攻击方法五:利用签名方法混淆 攻击步骤(针对 RSA 算法): 获取服务器的公钥 修改标头为 HS256 但使用 RSA 公钥作为 HMAC 密钥 服务器使用公钥验证 HMAC 签名 漏洞原因:服务器未强制使用特定签名算法,允许攻击者指定算法。 案例: CVE-2016-10555 jwt-simple 漏洞 攻击方法六:信任攻击者密钥 攻击步骤: 攻击者在令牌中嵌入自己的公钥 服务器使用攻击者提供的公钥验证签名 案例: CVE-2018-0114 Go-jose 漏洞 攻击方法七:恢复私钥 针对 JWE 加密的漏洞: ECDH-ES 算法实现问题: Adobe 报告 AES-GCM 模式漏洞: 研究论文 RSA 使用 PKCS1v1.5 填充的已知问题 攻击方法八:上下文相同令牌 漏洞原因:多个服务器使用相同签名密钥,一旦泄露可生成任意有效令牌。 解决方案:使用 iss (签发者) 和 aud (受众) 声明限制令牌使用范围。 攻击方法九:重放 JWT 攻击步骤: 获取一个有效令牌(如用于 DELETE 操作) 在令牌过期后重新使用 解决方案:使用 jti (JWT ID) 和 exp (过期时间) 声明,并确保正确实现。 案例: jwt-dotnet 漏洞 攻击方法十:定时攻击签名 攻击原理:通过测量签名验证响应时间差异,逐步破解签名。 研究显示:在实验室条件下,每秒 55,000 请求可在 22 小时内破解签名。 防御措施:使用恒定时间比较算法验证签名。 0x03 JWT 安全最佳实践 设计与实现 明确需求:确定需要 JWS 还是 JWE,选择合适的算法 强制使用特定签名算法,不允许客户端指定 区分 verify() 和 decode() 功能 关闭调试模式,防止信息泄露 密钥管理 使用足够强度的密钥(HS256 至少 256 位) 密钥不在代码中硬编码,安全存储 制定密钥泄露应急方案 生产与测试环境使用不同密钥 签名验证 拒绝 "none" 算法 拒绝缺失签名的令牌 检查 JWE 使用的加密算法是否安全 使用恒定时间算法比较签名 令牌管理 不在 URL 中传递令牌(防止日志记录) 设置合理的短有效期( exp 声明) 实现令牌吊销机制 使用 iss 和 aud 声明限制使用范围 检查 jti 唯一性防止重放 库安全 定期检查使用的 JWT 库漏洞 及时更新到安全版本 监控新发现的漏洞 0x04 JWT 替代方案 PASETO (Platform-Agnostic Security Tokens) PASETO 旨在解决 JWT 的设计缺陷,提供更安全的替代方案。 特点: 更简单的设计 强制使用安全算法 无 "none" 算法等危险选项 资源: PASETO 官网 PASETO 详细介绍 0x05 参考资料 JSON Web Token 最佳实践 JWT 手册 JWT 漏洞讨论 Java JWT 速查表 (OWASP) JWT 会话安全问题