3. JWT 常见伪造攻击类型

JWT(JSON Web Token)作为无状态认证的主流方案,其安全性高度依赖实现方的签名验证逻辑与密钥管理。攻击者利用实现缺陷或配置疏漏,可绕过签名校验、伪造任意身份。本章系统梳理四种最常见的 JWT 伪造攻击类型,并给出对应的检测与防御要点。

3.1 攻击类型总览

攻击类型 核心原理 利用条件 危害等级
alg=none 攻击 将 JWT 头部 alg 字段设为 none,使服务端跳过签名验证 服务端未强制校验 alg 白名单 严重
弱密钥爆破 使用常见弱密钥字典对 HS256 等对称签名进行暴力破解 密钥强度不足(如 secret、123456) 高
密钥泄露 攻击者通过源码泄露、配置暴露、日志打印等方式获取签名密钥 密钥存储不当或 CI/CD 流程泄露 严重
算法混淆攻击 将头部 alg 从 RS256(非对称)改为 HS256(对称),用公钥作为 HMAC 密钥伪造签名 服务端未区分公钥/私钥用途,且允许算法切换 严重
安全基线: 所有 JWT 服务端必须实现 alg 白名单校验,禁止接受 none 算法,并严格区分对称与非对称算法的密钥使用场景。

3.2 alg=none 攻击

这是最基础的 JWT 伪造手法。攻击者将 JWT 头部中的 alg 字段修改为 none,并移除签名部分,使 token 变为 header.payload.(尾部带点但无签名)。若服务端未对 alg 做白名单校验,则会直接信任该 token 的 payload 内容。

攻击示例:
// 原始合法 JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJyb2xlIjoiYWRtaW4ifQ.signature

// 伪造后的 JWT(alg=none)
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VyIjoiYWRtaW4iLCJyb2xlIjoiYWRtaW4ifQ.

检测要点:

  • 服务端必须维护一个允许的 alg 白名单(如 ["HS256", "RS256"]),拒绝 none 及未注册算法。
  • 在 JWT 解析库中,禁用自动降级到 none 的行为(如 Java 的 jjwt 需设置 .setAllowedClockSkew() 并显式指定算法)。
  • 使用 require(alg) 或类似方法强制要求签名算法必须存在且合法。

3.3 弱密钥爆破

当 JWT 使用对称签名算法(如 HS256、HS384、HS512)时,密钥强度直接决定安全性。攻击者收集到一个合法 JWT 后,可使用 hashcat、jwt-cracker 等工具对签名进行离线字典爆破。常见弱密钥包括 secret、password、123456、jwt_secret 等。

风险提示: 对称签名密钥必须满足以下要求:
  • 长度 ≥ 256 位(32 字节)
  • 使用密码学安全的随机数生成器(如 /dev/urandom)
  • 禁止硬编码在代码或配置文件中
  • 定期轮换(建议 ≤ 90 天)

检测与防御:

  • 在开发环境使用 jwt-cracker 或 hashcat -m 16500 对测试密钥进行爆破验证,确保密钥强度达标。
  • 生产环境部署密钥强度扫描工具,定期检查 JWT 密钥是否出现在公开泄露的密码库中。
  • 优先使用非对称算法(RS256/ES256),即使公钥泄露也不会导致签名伪造。

3.4 密钥泄露

密钥泄露往往源于管理疏漏而非算法缺陷。常见泄露途径包括:

泄露途径 典型场景 检测方法
源码仓库泄露 密钥硬编码在 .env 或配置文件中,随代码提交到 Git 使用 git-secrets、truffleHog 扫描历史提交
日志打印 调试日志中输出 JWT 签名密钥或完整 token 日志脱敏规则检查,禁止打印密钥字段
CI/CD 环境变量 构建流水线中明文传递密钥,被日志或工件捕获 使用密钥管理服务(KMS/Vault)注入密钥
反向代理/网关 Nginx 或 API 网关配置中暴露 JWT 密钥 定期审计网关配置文件权限
最佳实践: 密钥应存储在专用的密钥管理服务(如 AWS KMS、HashiCorp Vault、Azure Key Vault)中,运行时通过 API 获取,禁止以文件或环境变量形式持久化。

3.5 算法混淆攻击

算法混淆攻击(Algorithm Confusion Attack)利用了 JWT 库对公钥/私钥用途的区分缺陷。攻击者将 JWT 头部 alg 从 RS256(非对称,使用私钥签名、公钥验证)改为 HS256(对称,使用同一密钥签名和验证)。若服务端使用公钥作为 HMAC 的验证密钥,攻击者即可用公开的公钥伪造任意 JWT。

攻击流程:
1. 获取服务端公钥(通常通过 /.well-known/jwks.json 或硬编码)
2. 构造恶意 payload(如 {"user":"admin","role":"admin"})
3. 将头部 alg 改为 "HS256"
4. 使用公钥字符串作为 HMAC 密钥,对 header.payload 进行签名
5. 将伪造的 JWT 发送给服务端
6. 服务端使用公钥作为 HS256 密钥验证签名 → 验证通过

检测与防御:

  • 服务端必须根据 alg 字段选择对应的密钥类型:非对称算法使用公钥验证,对称算法使用独立密钥。
  • 实现 alg 白名单时,禁止同时允许对称和非对称算法混用(如同时允许 HS256 和 RS256)。
  • 使用 JWT 库的 setSigningKey() 方法时,明确指定密钥用途(如 setPublicKey() 与 setSecretKey() 分开)。
  • 在服务端验证逻辑中,检查 alg 是否与预期算法一致,不一致则直接拒绝。
JWT 四种伪造攻击类型对比 alg=none 攻击 弱密钥爆破 密钥泄露 算法混淆攻击 JWT 服务端签名验证逻辑 绕过签名校验 / 伪造身份 各攻击类型对应的防御措施 ● alg=none:强制 alg 白名单,拒绝 none 算法 ● 弱密钥爆破:使用 ≥256 位随机密钥,优先非对称算法 ● 密钥泄露:密钥管理服务(KMS/Vault),禁止硬编码 ● 算法混淆:区分公钥/私钥用途,禁止对称与非对称混用 核心原则:服务端必须主动校验算法类型与密钥用途,不依赖客户端提供的 alg 字段

3.6 攻击检测与错误码断言

在后端安全合规中,针对 JWT 伪造攻击应定义明确的错误码与断言规则,确保攻击行为可被记录、告警和阻断。

错误码 含义 触发条件 建议 HTTP 状态码
JWT_ALG_NONE 检测到 alg=none 攻击 JWT 头部 alg 为 none 或未在白名单中 401 Unauthorized
JWT_WEAK_KEY 检测到弱密钥签名 签名验证通过但密钥强度低于安全基线 401 Unauthorized
JWT_KEY_LEAK 密钥疑似泄露 同一密钥在短时间内被多个不同来源使用 500 Internal Server Error
JWT_ALG_CONFUSION 检测到算法混淆攻击 alg 与密钥类型不匹配(如 RS256 使用对称密钥验证) 401 Unauthorized
JWT_SIGNATURE_INVALID 签名验证失败(通用) 签名不匹配或 token 被篡改 401 Unauthorized
合规断言要求:
  • 所有 JWT 验证失败必须记录结构化日志,包含 token 头部、payload 摘要、来源 IP、时间戳。
  • 对于 JWT_ALG_NONE 和 JWT_ALG_CONFUSION 错误,应触发安全告警并临时封禁来源 IP(建议 5 分钟)。
  • 错误码必须在 API 响应体中返回,禁止仅返回 HTTP 状态码而不提供错误原因。
JWT 验证与安全错误码断言流程 接收 JWT Token 解析 Header 获取 alg alg 白名单校验 签名验证 JWT_ALG_NONE 身份认证通过 JWT_SIGNATURE_INVALID JWT_ALG_CONFUSION 所有错误码必须在响应体中返回,并触发结构化日志记录与安全告警

3.7 本章小结

JWT 伪造攻击的核心在于服务端对 alg 字段和密钥用途的验证缺失。四种攻击类型中,alg=none 和 算法混淆 属于实现缺陷,弱密钥爆破 和 密钥泄露 属于密钥管理问题。后端架构师应在 JWT 验证中间件中实现以下安全基线:

  • 强制 alg 白名单,拒绝 none 及未注册算法。
  • 区分对称与非对称算法的密钥验证逻辑,禁止混用。
  • 密钥强度 ≥ 256 位,使用 KMS 管理,定期轮换。
  • 定义标准错误码(如 JWT_ALG_NONE、JWT_ALG_CONFUSION),在响应体中返回并记录安全日志。
下一阶段: 第 4 章将深入讲解 JWT 签名验证的代码实现细节,包括 Java(jjwt)、Python(PyJWT)、Node.js(jsonwebtoken)等主流库的安全配置示例。