JWT渗透姿势一篇通
字数 4070 2025-08-20 18:17:47

JWT渗透测试全面指南

文章前言

企业内部产品应用广泛使用JWT作为用户身份认证方式,本文汇总了JWT相关的各种安全问题,包括新发现的安全问题以及之前遗留的部分JWT安全问题,形成一篇完整的JWT安全指南。

JWT基础概念

基本定义

JWT(JSON Web Token)是一种用于身份认证和授权的开放标准,它通过在网络应用间传递被加密的JSON数据来安全地传输信息。对于渗透测试人员而言,JWT可能是非常吸引人的攻击途径,因为它们可能隐藏着特权升级、信息泄露、SQL注入、XSS、SSRF、RCE、LFI等漏洞的利用途径。

相关术语

  • JWS:Signed JWT,签名过的JWT
  • JWK:JWT的密钥,也就是常说的SECRET
  • JWE:Encrypted JWT,部分payload经过加密的JWT
  • JKU:JWT Header中的一个字段,内容是一个URI,用于指定验证令牌秘钥的服务器
  • X5U:JWT Header中的一个字段,指向一组X509公共证书的URL
  • X.509标准:公钥证书的格式标准,是TLS/SSL等众多Internet协议的基础

JWT基本结构

JWT由三部分组成:Header、Payload和Signature。

Header

Header包含JWT使用的算法和类型等元数据信息,通常使用JSON对象表示并使用Base64编码。主要字段:

  • alg:指定使用的加密算法(如HMAC、RSA、ECDSA等)
  • typ:指定JWT的类型(通常为JWT)

示例:

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload

Payload包含JWT的主要信息,通常使用JSON对象表示并使用Base64编码。Payload包含三种类型的字段:

  1. 注册声明(Registered Claims):预定义的标准字段(如iss、exp、sub等)
  2. 公共声明(Public Claims):自定义的非敏感信息字段(如用户ID、角色等)
  3. 私有声明(Private Claims):自定义的敏感信息字段(如密码、信用卡号等)

示例:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

Signature

Signature是使用指定算法对Header和Payload进行签名生成的,用于验证JWT的完整性和真实性。生成方式通常是将Header和Payload连接起来然后使用指定算法进行签名。

示例签名生成:

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

完整JWT示例

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

JWT工作原理

基本工作流程

  1. 用户在客户端登录并将登录信息发送给服务器
  2. 服务器使用私钥对用户信息进行加密生成JWT并发送给客户端
  3. 客户端将JWT存储在本地,每次请求时携带JWT进行认证
  4. 服务器使用公钥对JWT进行解密和验证
  5. 服务器处理请求并返回响应

JKU工作原理

  1. 用户携带JWS(带有签名的JWT)访问应用
  2. 应用程序解码JWS得到JKU字段
  3. 应用根据JKU访问返回JWK的服务器
  4. 应用程序得到JWK
  5. 使用JWK验证用户JWS
  6. 验证通过则正常响应

JWT漏洞攻防

1. 签名未校验

漏洞原理:开发人员混淆了验证令牌的方法和解码令牌的方法,只将传入的令牌传递给decode()方法,导致应用程序不验证签名。

靶场示例

  • 靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-unverified-signature
  • 攻击步骤:
    1. 登录普通用户账户
    2. 捕获JWT令牌
    3. 修改payload中的sub为"administrator"
    4. 重新发送请求获取管理员权限

2. 签名算法设置为None

漏洞原理:JWT支持将alg字段设为"None",表示不签名。如果服务器未关闭此功能,攻击者可伪造任意token。

攻击方法

{
  "alg": "none",
  "typ": "JWT"
}

靶场示例

  • 靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-flawed-signature-verification
  • 攻击步骤:
    1. 捕获普通用户JWT
    2. 修改alg为"none"
    3. 修改payload中的sub为"administrator"
    4. 移除签名部分
    5. 发送修改后的JWT获取管理员权限

3. 密钥暴力猜解

漏洞原理:使用弱密钥或默认密钥,容易被暴力破解。

公开密钥列表
https://github.com/wallarm/jwt-secrets/blob/master/jwt.secrets.list

使用Hashcat破解

hashcat -a 0 -m 16500 <jwt> <wordlist>

靶场示例

  • 靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-weak-signing-key
  • 攻击步骤:
    1. 使用字典暴力破解密钥
    2. 发现密钥为"secret1"
    3. 使用该密钥生成管理员权限的JWT
    4. 获取管理员权限

4. JWT头部注入

4.1 JWK参数注入

漏洞原理:服务器使用jwk参数中嵌入的键值验证签名,而非使用有限的公钥白名单。

靶场示例

  • 靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jwk-header-injection
  • 攻击步骤:
    1. 使用BurpSuite的JWT Editor生成新的RSA密钥
    2. 修改JWT,在header中添加jwk参数嵌入公钥
    3. 修改payload中的sub为"administrator"
    4. 使用私钥签名
    5. 发送修改后的JWT获取管理员权限

4.2 JKU参数注入

漏洞原理:服务器使用jku参数引用的JWK集验证签名,而非受信任的域。

靶场示例

  • 靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jku-header-injection
  • 攻击步骤:
    1. 生成新的RSA密钥
    2. 将公钥作为JWK上传到exploit服务器
    3. 修改JWT的jku指向exploit服务器
    4. 修改kid匹配JWK中的kid
    5. 修改payload中的sub为"administrator"
    6. 发送修改后的JWT获取管理员权限

4.3 KID参数路径遍历

漏洞原理:kid参数易受目录遍历攻击,可迫使服务器使用任意文件作为验证密钥。

靶场示例

  • 靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-kid-header-path-traversal
  • 攻击步骤:
    1. 生成对称密钥,k值设为"AA=="(null)
    2. 修改JWT的kid为"../../dev/null"
    3. 修改alg为"HS256"
    4. 修改payload中的sub为"administrator"
    5. 使用对称密钥签名
    6. 发送修改后的JWT获取管理员权限

5. 算法混淆攻击

漏洞原理:迫使服务器使用不同于预期的算法验证JWT签名,如使用HS256而非RS256。

靶场示例

  • 靶场地址:https://portswigger.net/web-security/jwt/algorithm-confusion/lab-jwt-authentication-bypass-via-algorithm-confusion
  • 攻击步骤:
    1. 从/jwks.json获取服务器公钥
    2. 将公钥转换为PEM格式并Base64编码
    3. 创建对称密钥,k值为编码后的公钥
    4. 修改JWT的alg为"HS256"
    5. 修改payload中的sub为"administrator"
    6. 使用对称密钥签名
    7. 发送修改后的JWT获取管理员权限

6. 令牌派生公钥

使用工具

  • 工具地址:https://github.com/silentsignal/rsa_sign2n
  • 使用Docker命令:
    docker run --rm -it portswigger/sig2n <token1> <token2>
    

7. 敏感信息泄露

漏洞原理:JWT payload可能包含敏感信息,如密码等。

示例

  1. 获取JWT并Base64解码payload
  2. 发现包含password字段(可能是MD5哈希)
  3. 破解MD5哈希获取明文密码
  4. 使用获取的凭据登录

8. 密钥硬编码

风险

  • 密钥容易被发现和窃取
  • 难以进行密钥轮换和管理
  • 可能导致多个应用共享同一密钥

9. 会话续期问题

9.1 无限使用

  • 过期的JWT仍可继续使用

9.2 Token刷新缺陷

  • 续期逻辑错误导致新旧token一致

9.3 N个新Token生成

  • 在续期期间可无限制生成多个有效JWT

工具集合

1. jwt_tool

项目地址
https://github.com/ticarpi/jwt_tool

主要功能

  • 检查令牌有效性
  • 测试已知漏洞
  • 扫描配置错误
  • Fuzz声明值
  • 测试密钥有效性
  • 高速字典攻击
  • 时间戳篡改
  • 密钥生成和重建
  • 伪造新令牌

2. MyJWT

功能

  • 修改JWT
  • None漏洞利用
  • RSA/HMAC混淆
  • 密钥暴力破解
  • kid注入
  • Jku绕过
  • X5u绕过

3. 辅助脚本

脚本地址
https://gist.github.com/imparabl3/efcf4a991244b9f8f99ac39a7c8cfe6f

功能

  • 利用CRLF漏洞

参考链接

  1. JWT secrets list: https://github.com/wallarm/jwt-secrets/blob/master/jwt.secrets.list
  2. PortSwigger JWT labs: https://portswigger.net/web-security/jwt/
  3. rsa_sign2n: https://github.com/silentsignal/rsa_sign2n
JWT渗透测试全面指南 文章前言 企业内部产品应用广泛使用JWT作为用户身份认证方式,本文汇总了JWT相关的各种安全问题,包括新发现的安全问题以及之前遗留的部分JWT安全问题,形成一篇完整的JWT安全指南。 JWT基础概念 基本定义 JWT(JSON Web Token)是一种用于身份认证和授权的开放标准,它通过在网络应用间传递被加密的JSON数据来安全地传输信息。对于渗透测试人员而言,JWT可能是非常吸引人的攻击途径,因为它们可能隐藏着特权升级、信息泄露、SQL注入、XSS、SSRF、RCE、LFI等漏洞的利用途径。 相关术语 JWS :Signed JWT,签名过的JWT JWK :JWT的密钥,也就是常说的SECRET JWE :Encrypted JWT,部分payload经过加密的JWT JKU :JWT Header中的一个字段,内容是一个URI,用于指定验证令牌秘钥的服务器 X5U :JWT Header中的一个字段,指向一组X509公共证书的URL X.509标准 :公钥证书的格式标准,是TLS/SSL等众多Internet协议的基础 JWT基本结构 JWT由三部分组成:Header、Payload和Signature。 Header Header包含JWT使用的算法和类型等元数据信息,通常使用JSON对象表示并使用Base64编码。主要字段: alg :指定使用的加密算法(如HMAC、RSA、ECDSA等) typ :指定JWT的类型(通常为JWT) 示例: Payload Payload包含JWT的主要信息,通常使用JSON对象表示并使用Base64编码。Payload包含三种类型的字段: 注册声明(Registered Claims) :预定义的标准字段(如iss、exp、sub等) 公共声明(Public Claims) :自定义的非敏感信息字段(如用户ID、角色等) 私有声明(Private Claims) :自定义的敏感信息字段(如密码、信用卡号等) 示例: Signature Signature是使用指定算法对Header和Payload进行签名生成的,用于验证JWT的完整性和真实性。生成方式通常是将Header和Payload连接起来然后使用指定算法进行签名。 示例签名生成: 完整JWT示例 JWT工作原理 基本工作流程 用户在客户端登录并将登录信息发送给服务器 服务器使用私钥对用户信息进行加密生成JWT并发送给客户端 客户端将JWT存储在本地,每次请求时携带JWT进行认证 服务器使用公钥对JWT进行解密和验证 服务器处理请求并返回响应 JKU工作原理 用户携带JWS(带有签名的JWT)访问应用 应用程序解码JWS得到JKU字段 应用根据JKU访问返回JWK的服务器 应用程序得到JWK 使用JWK验证用户JWS 验证通过则正常响应 JWT漏洞攻防 1. 签名未校验 漏洞原理 :开发人员混淆了验证令牌的方法和解码令牌的方法,只将传入的令牌传递给decode()方法,导致应用程序不验证签名。 靶场示例 : 靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-unverified-signature 攻击步骤: 登录普通用户账户 捕获JWT令牌 修改payload中的sub为"administrator" 重新发送请求获取管理员权限 2. 签名算法设置为None 漏洞原理 :JWT支持将alg字段设为"None",表示不签名。如果服务器未关闭此功能,攻击者可伪造任意token。 攻击方法 : 靶场示例 : 靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-flawed-signature-verification 攻击步骤: 捕获普通用户JWT 修改alg为"none" 修改payload中的sub为"administrator" 移除签名部分 发送修改后的JWT获取管理员权限 3. 密钥暴力猜解 漏洞原理 :使用弱密钥或默认密钥,容易被暴力破解。 公开密钥列表 : https://github.com/wallarm/jwt-secrets/blob/master/jwt.secrets.list 使用Hashcat破解 : 靶场示例 : 靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-weak-signing-key 攻击步骤: 使用字典暴力破解密钥 发现密钥为"secret1" 使用该密钥生成管理员权限的JWT 获取管理员权限 4. JWT头部注入 4.1 JWK参数注入 漏洞原理 :服务器使用jwk参数中嵌入的键值验证签名,而非使用有限的公钥白名单。 靶场示例 : 靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jwk-header-injection 攻击步骤: 使用BurpSuite的JWT Editor生成新的RSA密钥 修改JWT,在header中添加jwk参数嵌入公钥 修改payload中的sub为"administrator" 使用私钥签名 发送修改后的JWT获取管理员权限 4.2 JKU参数注入 漏洞原理 :服务器使用jku参数引用的JWK集验证签名,而非受信任的域。 靶场示例 : 靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jku-header-injection 攻击步骤: 生成新的RSA密钥 将公钥作为JWK上传到exploit服务器 修改JWT的jku指向exploit服务器 修改kid匹配JWK中的kid 修改payload中的sub为"administrator" 发送修改后的JWT获取管理员权限 4.3 KID参数路径遍历 漏洞原理 :kid参数易受目录遍历攻击,可迫使服务器使用任意文件作为验证密钥。 靶场示例 : 靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-kid-header-path-traversal 攻击步骤: 生成对称密钥,k值设为"AA=="(null) 修改JWT的kid为"../../dev/null" 修改alg为"HS256" 修改payload中的sub为"administrator" 使用对称密钥签名 发送修改后的JWT获取管理员权限 5. 算法混淆攻击 漏洞原理 :迫使服务器使用不同于预期的算法验证JWT签名,如使用HS256而非RS256。 靶场示例 : 靶场地址:https://portswigger.net/web-security/jwt/algorithm-confusion/lab-jwt-authentication-bypass-via-algorithm-confusion 攻击步骤: 从/jwks.json获取服务器公钥 将公钥转换为PEM格式并Base64编码 创建对称密钥,k值为编码后的公钥 修改JWT的alg为"HS256" 修改payload中的sub为"administrator" 使用对称密钥签名 发送修改后的JWT获取管理员权限 6. 令牌派生公钥 使用工具 : 工具地址:https://github.com/silentsignal/rsa_ sign2n 使用Docker命令: 7. 敏感信息泄露 漏洞原理 :JWT payload可能包含敏感信息,如密码等。 示例 : 获取JWT并Base64解码payload 发现包含password字段(可能是MD5哈希) 破解MD5哈希获取明文密码 使用获取的凭据登录 8. 密钥硬编码 风险 : 密钥容易被发现和窃取 难以进行密钥轮换和管理 可能导致多个应用共享同一密钥 9. 会话续期问题 9.1 无限使用 过期的JWT仍可继续使用 9.2 Token刷新缺陷 续期逻辑错误导致新旧token一致 9.3 N个新Token生成 在续期期间可无限制生成多个有效JWT 工具集合 1. jwt_ tool 项目地址 : https://github.com/ticarpi/jwt_ tool 主要功能 : 检查令牌有效性 测试已知漏洞 扫描配置错误 Fuzz声明值 测试密钥有效性 高速字典攻击 时间戳篡改 密钥生成和重建 伪造新令牌 2. MyJWT 功能 : 修改JWT None漏洞利用 RSA/HMAC混淆 密钥暴力破解 kid注入 Jku绕过 X5u绕过 3. 辅助脚本 脚本地址 : https://gist.github.com/imparabl3/efcf4a991244b9f8f99ac39a7c8cfe6f 功能 : 利用CRLF漏洞 参考链接 JWT secrets list: https://github.com/wallarm/jwt-secrets/blob/master/jwt.secrets.list PortSwigger JWT labs: https://portswigger.net/web-security/jwt/ rsa_ sign2n: https://github.com/silentsignal/rsa_ sign2n