渗透测试实战:JWT令牌篡改攻防全解析
那天下午三点,我们红队接到一个特殊任务——对公司的核心业务系统进行内部渗透测试。系统刚刚完成微服务架构改造,前端采用React框架,后端API全部基于JWT令牌进行身份验证。项目经理拍着胸脯保证:"这套安全体系绝对可靠,你们要是能找出漏洞,我请大家吃日料。"事实证明,那顿日料他请定了。
1. 突破口:API端点发现与初步分析
任何渗透测试都始于信息收集。我们首先使用公司配发的普通员工账号登录系统,同时打开Burp Suite抓包。在浏览用户个人中心时,Burp的Proxy历史记录里出现了这样的请求:
GET /api/v1/user/profile HTTP/1.1 Host: internal.corp.com Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwidXNlcm5hbWUiOiJqb2huLmRvZSIsInJvbGUiOiJlbXBsb3llZSIsImlhdCI6MTUxNjIzOTAyMn0.5mhBHQ6gQzY6f5Q7w7Q8w9e0rTspnH4kLmZuZ0Jjg5E这个JWT令牌引起了我们的注意。通过Burp的Decoder模块解码后,令牌结构清晰可见:
{ "alg": "HS256", "typ": "JWT" } { "sub": "1234567890", "username": "john.doe", "role": "employee", "iat": 1516239022 }关键发现:
- 使用HS256对称加密算法
- 包含明显的角色声明(role字段)
- 没有过期时间(exp字段)
- 签发时间(iat)显示令牌已使用超过6个月
提示:长期有效的JWT令牌是重大安全隐患,建议设置合理的过期时间(通常不超过1小时)
2. JWT令牌篡改实验
发现JWT的结构缺陷后,我们开始测试篡改可能性。首先尝试最简单的重放攻击:
- 使用原始令牌访问管理员接口
/api/v1/admin/users - 返回403 Forbidden(符合预期)
- 修改role字段为"admin"后重放请求
- 仍然返回403(因为签名验证失败)
接下来尝试破解签名密钥。由于系统使用HS256算法,我们需要获取或暴力破解签名密钥。通过以下步骤最终获取了密钥:
# 使用hashcat进行暴力破解 hashcat -m 16500 jwt.txt rockyou.txt -O破解参数对比表:
| 参数 | 初始值 | 优化值 |
|---|---|---|
| 字典 | rockyou.txt | 公司名+常见密码组合 |
| 线程数 | 默认 | 最大 |
| 尝试次数 | 约100万/分钟 | 约300万/分钟 |
8小时后,我们成功获取了签名密钥"Company@2023"。这个弱密钥直接导致了整个安全体系的崩塌。
3. 权限提升实战
有了签名密钥,我们可以任意构造有效令牌。以下是生成管理员令牌的Python代码示例:
import jwt secret = "Company@2023" payload = { "sub": "1234567890", "username": "john.doe", "role": "admin", "iat": 1516239022 } token = jwt.encode(payload, secret, algorithm="HS256") print(token)使用新生成的令牌,我们成功实现了:
- 查看所有用户信息
- 修改系统配置
- 访问财务敏感数据
- 创建具有管理员权限的新用户
攻击路径总结:
- 发现长期有效的JWT令牌
- 识别弱加密算法(HS256)
- 暴力破解签名密钥
- 构造高权限令牌
- 完全控制系统
4. 防御方案设计与实施
完成渗透后,我们立即与开发团队合作修复漏洞。以下是实施的多层防御措施:
技术控制措施:
| 层级 | 措施 | 实施细节 |
|---|---|---|
| 令牌设计 | 使用RS256非对称加密 | 私钥签名,公钥验证 |
| 生命周期 | 短期有效+刷新机制 | 访问令牌15分钟过期 |
| 内容安全 | 移除敏感声明 | 只保留必要字段 |
| 密钥管理 | 定期轮换密钥 | 每季度更换一次 |
开发流程改进:
- 在CI/CD管道中加入JWT安全扫描
- 对密钥进行强度检测
- 实施自动化令牌撤销机制
- 定期红蓝对抗演练
注意:防御措施需要根据业务场景平衡安全性与用户体验,过度安全可能影响系统可用性
5. 深度防御:超越基础配置
真正的安全需要纵深防御体系。我们进一步实施了这些增强措施:
监控与响应:
- 实时分析JWT使用模式
- 异常令牌使用告警(如权限突变)
- 自动阻断可疑请求
架构级防护:
# 示例:JWT验证中间件增强版 def verify_jwt_middleware(request): token = extract_token(request) try: payload = jwt.decode(token, PUBLIC_KEY, algorithms=["RS256"]) if payload.get('role') == 'admin': log_admin_access(request.ip) verify_second_factor(request) return payload except jwt.ExpiredSignatureError: abort(401, "Token expired") except jwt.InvalidTokenError: abort(403, "Invalid token")人员培训重点:
- 安全编码规范
- 威胁建模方法
- 应急响应流程
- 安全设计模式
那次渗透测试后,公司全面升级了身份认证体系。最让我意外的是,开发团队主动要求每月进行一次安全演练——那顿日料花的真值。