JWT 常见测试点
字数 2405 2025-11-21 12:10:37

JWT 安全测试全面指南

一、JWT 基础与工作流程

1.1 JWT 基本结构

JWT(JSON Web Token)由三部分组成,以点号分隔:

  • Header:包含令牌类型和签名算法
  • Payload:包含声明(用户信息、权限等)
  • Signature:对前两部分的签名,用于验证完整性

1.2 JWT 工作流程

  1. 用户认证:客户端提交账号密码到认证服务器(HTTPS)
  2. 令牌生成:服务器验证通过后,使用密钥生成签名后的JWT
  3. 令牌返回:JWT返回给客户端存储
  4. API访问:客户端在请求头中携带JWT访问受保护资源
  5. 服务器验证:服务器解析并验证JWT签名
  6. 授权处理:验证成功后读取Payload中的用户信息进行授权

二、JWT 安全漏洞类型与测试方法

2.1 未验证签名绕过

漏洞原理:服务端未对JWT签名进行验证,直接信任Payload内容

测试步骤

  1. 使用正常账号登录系统,捕获JWT令牌
  2. 解析Payload,识别用户标识字段(如account、unionid)
  3. 修改Payload中的用户标识为其他合法用户
  4. 保持原有签名或使用相同算法重新签名
  5. 使用伪造的JWT访问API接口

漏洞验证:成功访问目标用户数据即存在漏洞

修复方案

  • 严格验证JWT签名有效性
  • 身份信息应以数据库或会话验证为准
  • 实施服务端资源访问身份匹配校验

2.2 有缺陷的签名验证绕过

漏洞原理:服务端错误处理alg=none情况,跳过签名验证

测试步骤

  1. 正常登录获取JWT令牌
  2. 将Header中的alg参数修改为"none"
  3. 修改Payload中的用户身份为管理员
  4. 移除签名部分(或保留空签名)
  5. 使用修改后的令牌访问权限接口

漏洞代码示例

alg = decodeHeader(token).alg
if (alg == 'none') {
    // 错误:跳过签名验证
    payload = decodePayload(token)
}

修复方案

  • 拒绝接受alg=none的令牌
  • 严格校验JWT签名,仅接受配置的算法
  • 使用正确的密钥对,不允许客户端推测密钥

2.3 弱签名密钥绕过

漏洞原理:使用弱密钥或常见密钥进行HS256签名,易被爆破

测试方法

  1. 获取正常JWT令牌(HS256算法)
  2. 使用工具爆破签名密钥(如jwt_tool.py)
  3. 使用爆破出的密钥伪造管理员令牌
  4. 替换原令牌访问管理功能

常用爆破密钥:secret、key、password等弱密钥

修复方案

  • 使用高强度随机密钥(≥32字节)
  • 采用非对称签名算法(RS256)
  • 定期更换签名密钥

2.4 JWT头部注入绕过

2.4.1 JWK头部注入

漏洞原理:服务端信任header中的jwk参数,使用攻击者公钥验证

测试步骤

  1. 生成RSA密钥对
  2. 在JWT头部添加jwk字段,包含公钥信息
  3. 使用私钥对修改后的令牌签名
  4. 服务端使用注入的公钥验证通过

修复方案

  • 禁止解析JWT header中的jwk字段
  • 固定使用服务器配置的验证密钥

2.4.2 JKU头部注入

漏洞原理:服务端从指定URL加载公钥进行验证

测试步骤

  1. 在可控服务器托管包含公钥的JWK集合文件
  2. 修改JWT头部jku字段指向该URL
  3. 使用对应私钥签名伪造令牌
  4. 服务端从指定URL加载公钥验证

修复方案

  • 禁用jku头部或实施严格白名单
  • 固定使用本地配置的公钥源

2.5 KID标头路径遍历

漏洞原理:KID参数存在路径遍历漏洞,可读取系统文件

测试方法

  1. 修改KID参数为路径遍历形式(如../../../etc/passwd)
  2. 服务端尝试读取指定文件作为密钥
  3. 利用文件读取失败的回退机制绕过验证

修复方案

  • 严格校验KID参数格式
  • 禁止路径遍历字符
  • 密钥文件不存储在Web可访问目录

2.6 算法混淆攻击

漏洞原理:利用服务器算法验证缺陷,将非对称算法误用为对称算法

测试方法

方法一:公钥作为对称密钥

  1. 获取服务器RS256公钥
  2. 将公钥Base64编码作为HS256的对称密钥
  3. 修改alg为HS256,使用公钥签名伪造令牌

方法二:令牌派生公钥(无密钥暴露)

  1. 收集多个服务器签名的JWT令牌
  2. 使用工具(如jwt_forgery.py)逆向推导公钥
  3. 利用推导的公钥进行算法混淆攻击

修复方案

  • 强制指定验证算法,不依赖header参数
  • 验证密钥类型与算法匹配性
  • 使用标准算法和足够长度的密钥

2.7 敏感信息泄露

漏洞原理:JWT Payload或Header中包含敏感信息

测试方法

  1. Base64解码JWT各部分
  2. 检查是否包含密码、密钥等敏感数据
  3. 利用泄露信息进行进一步攻击

常见泄露点

  • 用户密码或密钥
  • 内部系统信息
  • 加密密钥或种子

修复方案

  • 实施令牌版本控制(token_version)
  • 验证时检查令牌版本与数据库一致性
  • 避免在JWT中存储敏感信息

三、JWT安全最佳实践

3.1 签名验证规范

  • 始终验证JWT签名有效性
  • 拒绝alg=none的令牌
  • 使用强密码学算法(RS256优于HS256)

3.2 密钥管理

  • 使用高强度随机生成密钥
  • 定期更换签名密钥
  • 安全存储私钥,避免泄露

3.3 头部参数处理

  • 禁用不可信的头部参数(jwk、jku、x5u)
  • 严格校验KID参数格式和范围
  • 实施公钥源白名单机制

3.4 令牌生命周期管理

  • 设置合理的令牌过期时间
  • 实现令牌撤销机制
  • 使用令牌版本控制防止重放

3.5 安全开发实践

  • 使用经过验证的JWT库
  • 实施完整的错误处理机制
  • 定期进行安全审计和渗透测试

四、测试工具推荐

4.1 常用测试工具

  • jwt_tool.py:JWT漏洞测试和密钥爆破
  • Burp Suite JWT插件:Burp集成测试功能
  • jwt.io:在线JWT解码和验证

4.2 自定义测试脚本

开发自定义测试脚本针对特定实现进行深度测试,重点关注算法验证、密钥管理和头部处理等关键环节。

通过系统化的测试方法和严格的安全实践,可以有效发现和修复JWT实现中的安全漏洞,确保身份验证机制的安全性。

JWT 安全测试全面指南 一、JWT 基础与工作流程 1.1 JWT 基本结构 JWT(JSON Web Token)由三部分组成,以点号分隔: Header :包含令牌类型和签名算法 Payload :包含声明(用户信息、权限等) Signature :对前两部分的签名,用于验证完整性 1.2 JWT 工作流程 用户认证 :客户端提交账号密码到认证服务器(HTTPS) 令牌生成 :服务器验证通过后,使用密钥生成签名后的JWT 令牌返回 :JWT返回给客户端存储 API访问 :客户端在请求头中携带JWT访问受保护资源 服务器验证 :服务器解析并验证JWT签名 授权处理 :验证成功后读取Payload中的用户信息进行授权 二、JWT 安全漏洞类型与测试方法 2.1 未验证签名绕过 漏洞原理 :服务端未对JWT签名进行验证,直接信任Payload内容 测试步骤 : 使用正常账号登录系统,捕获JWT令牌 解析Payload,识别用户标识字段(如account、unionid) 修改Payload中的用户标识为其他合法用户 保持原有签名或使用相同算法重新签名 使用伪造的JWT访问API接口 漏洞验证 :成功访问目标用户数据即存在漏洞 修复方案 : 严格验证JWT签名有效性 身份信息应以数据库或会话验证为准 实施服务端资源访问身份匹配校验 2.2 有缺陷的签名验证绕过 漏洞原理 :服务端错误处理alg=none情况,跳过签名验证 测试步骤 : 正常登录获取JWT令牌 将Header中的alg参数修改为"none" 修改Payload中的用户身份为管理员 移除签名部分(或保留空签名) 使用修改后的令牌访问权限接口 漏洞代码示例 : 修复方案 : 拒绝接受alg=none的令牌 严格校验JWT签名,仅接受配置的算法 使用正确的密钥对,不允许客户端推测密钥 2.3 弱签名密钥绕过 漏洞原理 :使用弱密钥或常见密钥进行HS256签名,易被爆破 测试方法 : 获取正常JWT令牌(HS256算法) 使用工具爆破签名密钥(如jwt_ tool.py) 使用爆破出的密钥伪造管理员令牌 替换原令牌访问管理功能 常用爆破密钥 :secret、key、password等弱密钥 修复方案 : 使用高强度随机密钥(≥32字节) 采用非对称签名算法(RS256) 定期更换签名密钥 2.4 JWT头部注入绕过 2.4.1 JWK头部注入 漏洞原理 :服务端信任header中的jwk参数,使用攻击者公钥验证 测试步骤 : 生成RSA密钥对 在JWT头部添加jwk字段,包含公钥信息 使用私钥对修改后的令牌签名 服务端使用注入的公钥验证通过 修复方案 : 禁止解析JWT header中的jwk字段 固定使用服务器配置的验证密钥 2.4.2 JKU头部注入 漏洞原理 :服务端从指定URL加载公钥进行验证 测试步骤 : 在可控服务器托管包含公钥的JWK集合文件 修改JWT头部jku字段指向该URL 使用对应私钥签名伪造令牌 服务端从指定URL加载公钥验证 修复方案 : 禁用jku头部或实施严格白名单 固定使用本地配置的公钥源 2.5 KID标头路径遍历 漏洞原理 :KID参数存在路径遍历漏洞,可读取系统文件 测试方法 : 修改KID参数为路径遍历形式(如../../../etc/passwd) 服务端尝试读取指定文件作为密钥 利用文件读取失败的回退机制绕过验证 修复方案 : 严格校验KID参数格式 禁止路径遍历字符 密钥文件不存储在Web可访问目录 2.6 算法混淆攻击 漏洞原理 :利用服务器算法验证缺陷,将非对称算法误用为对称算法 测试方法 : 方法一:公钥作为对称密钥 获取服务器RS256公钥 将公钥Base64编码作为HS256的对称密钥 修改alg为HS256,使用公钥签名伪造令牌 方法二:令牌派生公钥(无密钥暴露) 收集多个服务器签名的JWT令牌 使用工具(如jwt_ forgery.py)逆向推导公钥 利用推导的公钥进行算法混淆攻击 修复方案 : 强制指定验证算法,不依赖header参数 验证密钥类型与算法匹配性 使用标准算法和足够长度的密钥 2.7 敏感信息泄露 漏洞原理 :JWT Payload或Header中包含敏感信息 测试方法 : Base64解码JWT各部分 检查是否包含密码、密钥等敏感数据 利用泄露信息进行进一步攻击 常见泄露点 : 用户密码或密钥 内部系统信息 加密密钥或种子 修复方案 : 实施令牌版本控制(token_ version) 验证时检查令牌版本与数据库一致性 避免在JWT中存储敏感信息 三、JWT安全最佳实践 3.1 签名验证规范 始终验证JWT签名有效性 拒绝alg=none的令牌 使用强密码学算法(RS256优于HS256) 3.2 密钥管理 使用高强度随机生成密钥 定期更换签名密钥 安全存储私钥,避免泄露 3.3 头部参数处理 禁用不可信的头部参数(jwk、jku、x5u) 严格校验KID参数格式和范围 实施公钥源白名单机制 3.4 令牌生命周期管理 设置合理的令牌过期时间 实现令牌撤销机制 使用令牌版本控制防止重放 3.5 安全开发实践 使用经过验证的JWT库 实施完整的错误处理机制 定期进行安全审计和渗透测试 四、测试工具推荐 4.1 常用测试工具 jwt_ tool.py :JWT漏洞测试和密钥爆破 Burp Suite JWT插件 :Burp集成测试功能 jwt.io :在线JWT解码和验证 4.2 自定义测试脚本 开发自定义测试脚本针对特定实现进行深度测试,重点关注算法验证、密钥管理和头部处理等关键环节。 通过系统化的测试方法和严格的安全实践,可以有效发现和修复JWT实现中的安全漏洞,确保身份验证机制的安全性。