挖洞经验 | 篡改JWT实现账户劫持
字数 1553 2025-08-15 21:30:55
JWT安全漏洞分析与防御指南
1. JWT基础概念
1.1 什么是JWT
JSON Web Token (JWT) 是基于RFC 7519标准定义的,以JSON形式在网络应用间安全传递信息的一种紧凑而独立的方法,尤其适用于分布式站点的单点登录(SSO)场景。
1.2 JWT结构组成
JWT由三部分组成,各部分之间用点(.)分隔:
- Header(头部): 包含令牌类型和签名算法
- Payload(负载): 包含声明(claims),即要传输的数据
- Signature(签名): 用于验证消息在传输过程中未被篡改
格式示例:xxxxx.yyyyy.zzzzz
2. 漏洞发现与分析
2.1 漏洞背景
目标系统在邀请功能中使用JWT进行用户验证,但存在以下安全问题:
- JWT在客户端生成而非服务端
- 缺乏对JWT签名的有效验证
- 允许用户修改关键字段而不进行重新验证
2.2 攻击步骤详解
2.2.1 初始信息收集
- 攻击者使用自己的邮箱(attacker@attacker.com)发起邀请
- 系统发送包含JWT的确认链接到攻击者邮箱
- 使用工具(如jwt.io)解码JWT获取结构
2.2.2 管理员账户劫持
- 攻击者尝试邀请管理员邮箱(admin@company.com)
- 获取包含管理员相关信息的JWT响应
- 修改JWT中的关键字段:
- 将邀请人邮箱改为admin@company.com
- 修改用户ID为管理员ID
- 调整时间戳(created date)
- 重新编码生成新的JWT
- 使用篡改后的JWT进行身份验证和密码重置
2.2.3 普通用户密码重置
- 注册测试用户(Victim),获取其用户ID(如jyAzV7KhT)
- 使用攻击者邮箱发起密码重置请求
- 获取包含JWT的重置链接
- 修改JWT中的用户ID为Victim的ID
- 使用篡改后的JWT重置Victim账户密码
3. 漏洞根本原因
- 客户端生成JWT:目标系统错误地在客户端生成JWT,而非在服务端
- 缺乏签名验证:系统未正确验证JWT签名,允许篡改后的token通过验证
- 过度信任客户端数据:系统完全信任JWT中的声明而不进行二次验证
- 关键业务逻辑缺陷:密码重置流程设计不当,依赖可被篡改的客户端数据
4. 漏洞利用条件
- 需要知道目标用户的ID
- 系统使用客户端生成的JWT
- 系统不对JWT签名进行严格验证
- 系统允许通过JWT直接进行敏感操作(如密码重置)
5. 防御措施
5.1 安全开发实践
- 服务端生成JWT:所有JWT应在服务端生成,避免客户端篡改
- 严格签名验证:实现强制的签名验证机制
- 使用强密钥:采用足够强度的密钥进行签名
- 限制JWT有效期:设置合理的过期时间(exp claim)
5.2 业务逻辑加固
- 二次验证机制:对于敏感操作(如密码重置),应结合其他验证方式
- 关键字段绑定:将JWT中的用户ID与当前会话绑定验证
- 操作日志记录:记录所有关键操作的JWT使用情况
- 黑名单机制:对已使用的JWT进行标记,防止重复使用
5.3 技术实现建议
- 使用标准的JWT库而非自行实现
- 避免在URL中传输JWT(可能被记录),使用Authorization头
- 对不同的业务场景使用不同的签名密钥
- 定期轮换签名密钥
6. 测试与验证方法
- 篡改测试:尝试修改JWT各字段验证系统是否检测
- 签名测试:使用无效签名验证系统是否拒绝
- 过期测试:使用过期的JWT验证系统是否拒绝
- 重放测试:重复使用已使用的JWT验证系统是否检测
7. 相关资源
通过以上措施,可有效防御JWT篡改导致的账户劫持等安全问题。开发人员应始终遵循"不信任客户端数据"的原则,对关键操作实施多层验证机制。