简单的 Python 脚本,用于检查假设的 JWT 漏洞。
假设存在一个使用 HS256 算法签名的 JWT 令牌的应用程序。示例如下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.zbgd5BNF1cqQ_prCEqIvBTjSxMS8bDLnJAE_wE-0Cxg
上述令牌可解码为以下数据:
{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
计算签名所使用的秘密密钥如下:
supersecret
用于计算签名的伪代码如下:
$alg = "sha256";
$data = "...";
$key = "supersecret";
hmac($alg, $data, $key);
但如果在头部中注入了意外的 "kid":0 字段呢?
{
"alg": "HS256",
"typ": "JWT",
"kid": 0
}
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
kid 字段是选择密钥的标准方式。 我的假设是,如果 kid 字段不是预期的,可能存在脆弱的实现,会将字符串 $key 的值当作数组处理:
hmac($alg, $data, $key[kid]);
结果就会使用 "s"($key[0])作为 HMAC 秘密。
injector.py 脚本接收原始 JWT 令牌, 在头部注入 "kid":0 字段, 并生成使用单字符秘密(ASCII 码:32-126 [{空格}, !, ", #, ..., x, y, z, {, |, }, ~])签名的令牌:
python3 injector.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.zbgd5BNF1cqQ_prCEqIvBTjSxMS8bDLnJAE_wE-0Cxg
结果将创建两个文件:tokens.txt 和 tokens_meta.txt。 tokens.txt 包含生成的令牌,可用作 Burp Intruder 的有效载荷列表。 如果任何令牌有效(意味着应用程序存在漏洞), 则可以使用 tokens_meta.txt 文件来检查生成该令牌所使用的算法和秘密。 tokens_meta.txt 文件包含以下数据:
token1:algorithm:secret
...
token{n}:algorithm:secret
请参阅 CHANGELOG。