Web安全之JWT令牌安全与攻击防护详解
字数 1301 2025-11-10 15:23:17
Web安全之JWT令牌安全与攻击防护详解
一、JWT基本概念与结构
JWT(JSON Web Token)是一种开放标准,用于在各方之间安全传输信息作为JSON对象。它由三部分组成,通过点号分隔:
- Header(头部):包含令牌类型和签名算法(如HS256、RS256)
- Payload(载荷):包含声明(用户信息、过期时间等)
- Signature(签名):对前两部分的签名,用于验证完整性
示例结构:header.payload.signature
二、JWT的生成与验证流程
-
生成过程:
- 对Header进行Base64Url编码
- 对Payload进行Base64Url编码
- 使用指定算法对前两部分签名:Signature = algorithm(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
- 组合三部分形成完整JWT
-
验证过程:
- 拆分JWT获取三部分
- 重新计算签名(使用服务端密钥)
- 对比计算签名与JWT中的签名是否一致
- 验证过期时间等声明
三、常见JWT安全漏洞与攻击手法
-
算法混淆攻击:
- 原理:将算法改为"none",绕过签名验证
- 条件:服务端支持none算法
- 示例:修改header为{"alg":"none","typ":"JWT"}
-
密钥破解攻击:
- 原理:弱密钥可通过暴力破解
- 工具:hashcat、jwt-cracker等
- 防护:使用强密钥(长度≥256位)
-
签名验证绕过:
- 原理:服务端未严格验证签名
- 方式:删除签名部分、修改payload后重新组合
-
Kid参数注入:
- 原理:kid(Key ID)参数用于文件包含或SQL注入
- 示例:kid="../../../../etc/passwd"
四、JWT安全防护最佳实践
-
算法强制验证:
- 代码示例:
// 错误做法:直接使用客户端提供的算法 jwt.verify(token, secret); // 正确做法:明确指定算法 jwt.verify(token, secret, { algorithms: ['HS256'] }); -
密钥安全管理:
- 使用足够长度的随机密钥
- 定期轮换密钥
- 不同环境使用不同密钥
-
Payload安全配置:
- 设置合理的过期时间(exp)
- 验证颁发者(iss)和受众(aud)
- 使用随机jti(JWT ID)防止重放攻击
-
敏感信息保护:
- 不在Payload中存储密码等敏感信息
- 考虑使用JWE(JSON Web Encryption)进行加密
五、实际攻击案例演示
-
算法none攻击复现:
- 原始JWT:header.payload.signature
- 修改header:{"alg":"none","typ":"JWT"}
- 重新编码:base64(header) + "." + base64(payload) + "."
- 发送到服务端测试
-
Kid注入攻击防御:
- 安全代码示例:
const key = getKeyFromTrustedSource(kid); // 从可信源获取密钥 if (!isValidKid(kid)) { // 验证kid格式 throw new Error('Invalid key ID'); }
六、JWT安全开发检查清单
- □ 强制指定允许的算法白名单
- □ 验证签名完整性
- □ 检查所有声明(exp、nbf、iss等)
- □ 验证kid参数安全性
- □ 使用HTTPS传输
- □ 设置合理的令牌过期时间
- □ 实现安全的令牌刷新机制
- □ 记录JWT验证日志用于审计
通过以上分层讲解,可以从JWT基础原理到实际安全防护建立完整知识体系,帮助在开发和面试中全面掌握JWT安全问题。