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包含三种类型的字段:
- 注册声明(Registered Claims):预定义的标准字段(如iss、exp、sub等)
- 公共声明(Public Claims):自定义的非敏感信息字段(如用户ID、角色等)
- 私有声明(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工作原理
基本工作流程
- 用户在客户端登录并将登录信息发送给服务器
- 服务器使用私钥对用户信息进行加密生成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。
攻击方法:
{
"alg": "none",
"typ": "JWT"
}
靶场示例:
- 靶场地址: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破解:
hashcat -a 0 -m 16500 <jwt> <wordlist>
靶场示例:
- 靶场地址: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命令:
docker run --rm -it portswigger/sig2n <token1> <token2>
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