关于JWT的攻击利用

一、JWT简介

JWT(JSON Web Token)是一种用于身份认证和授权的开放标准,它通过在网络应用间传递被加密的JSON数据来安全地传输信息使得身份验证和授权变得更加简单和安全。
JWT的常见用途包括在身份验证流程中生成令牌,将用户信息传递给Web应用程序,以及在不同的服务之间进行身份验证和授权。由于JWT是自包含的,不需要在服务器端存储会话信息,因此它们适用于分布式系统和微服务架构。

二、基本结构

JWT(JSON Web Token)的结构由三部分组成,分别是Header、Payload和Signature。如下图所示:
在这里插入图片描述

1、Header(头部)

Header包含了JWT使用的算法和类型等元数据信息,通常使用JSON对象表示并使用Base64编码,Header中包含两个字段:alg和typ
Header示例:

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

alg(Algorithm):指定用于对JWT进行签名的加密算法,常见的有HMAC、RSA和ECDSA等算法。在这里,使用了HS256,它代表HMAC SHA-256算法,一种常见的对称加密算法。
typ(Type):指定令牌的类型,通常设置为"JWT"表示这是一个JSON Web Token。

2、Payload(载荷)

Payload包含了JWT的主要信息,通常使用JSON对象表示并使用Base64编码,Payload中包含三个类型的字段:注册声明、公共声明和私有声明

  • 公共声明(Public Claims):这些声明用于共享信息,但它们应该是在被定义时以公开方式可用的,以避免冲突。例如:用户ID、角色等
  • 私有声明(Private Claims):这些声明是由用户定义的,用于在双方之间共享信息。例如密码、信用卡号等
  • 注册声明(Registered Claims):预定义的标准字段,包含了一些JWT的元数据信息,例如iss(发行者)、sub(主题)、exp(过期时间)等。

Payload示例:

{
  "sub": "1234567890",
  "name": "MP-Fly",
  "iat": 1516239022
}

在这个示例中,JWT的载荷部分是一个JSON对象,包含了一些声明(claims):
sub(Subject):表示令牌的主题,通常是用户的唯一标识符,如用户ID。
name:包含有关用户的姓名信息。
iat(Issued At):指定令牌的签发时间,以 UNIX 时间戳表示。

3、Signature(签名)

Signature是用于验证令牌的完整性和真实性。它使用头部中指定的加密算法(如HMAC SHA256或RSA)对头部和载荷部分进行签名,以确保它们在传输过程中未被篡改。Signature的生成方式通常是将Header和Payload连接起来然后使用指定算法对其进行签名,最终将签名结果与Header和Payload一起组成JWT,Signature的生成和验证需要使用相同的密钥。

Signature示例:

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

这个示例使用HMAC SHA-256算法生成JWT的签名,其中:
base64UrlEncode(header) 表示对JWT头部的Base64 URL编码。
base64UrlEncode(payload) 表示对JWT载荷的Base64 URL编码。
secret 是用于生成签名的密钥。
生成的签名(Signature)示例(使用假设的密钥):
!23QweAsd
最终将Header、Payload和Signature连接起来用句点(.)分隔就形成了一个完整的JWT,下面是一个示例JWT,其中第一部分是Header,第二部分是Payload,第三部分是Signature。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ik1QLUZseSIsImlhdCI6MTUxNjIzOTAyMn0.cQ37gZ5oVgE6SGb6L9roV_QSqyKSGcW1Q_3Xr4-73Ec

注意JWT 中的每一部分都是经过Base64编码的,但并不是加密的,因此JWT中的信息是可以被解密的。

三、JWT工作原理

1、生成令牌

  • (1)创建头部(Header):首先,选择一个加密算法(例如HS256或RS256),并将其与令牌类型(通常是"JWT")组成头部。头部通常以JSON格式表示,并使用Base64 URL编码。

  • (2)创建载荷(Payload):在载荷中,包含声明(claims)信息,这些声明可以是注册声明、私有声明或公共声明。注册声明包括标准字段如iss(发行者)、sub(主题)、exp(过期时间)等,而私有声明用于应用程序特定信息。载荷也以JSON格式表示,并使用Base64 URL编码。

  • (3)生成签名(Signature):签名由将头部和载荷组合在一起,并使用密钥进行签名的过程生成。

  • (4)合并三部分:将头部、载荷和签名用点号分隔并组合成一个JWT字符串。

2、传输令牌

  • (1)发送令牌:将生成的JWT发送给需要访问信息的一方,通常通过HTTP标头进行传输。令牌可以放在请求的授权标头中(Bearer Token)
  • (2)接收令牌:接收方接收到JWT后,将其分成头部、载荷和签名三个部分。

3、验证令牌

  • (1)验证签名: 接收方使用相同的密钥和算法对头部和负载进行签名,并比较生成的签名与JWT中的签名是否匹配。如果匹配,令牌有效。

  • (2)验证声明:接收方还需验证载荷中的声明,例如检查令牌是否过期(通过比较"exp"声明与当前时间)以及其他声明来确保授权和身份验证操作的有效性。

  • (3)令牌有效性: 如果签名验证通过且声明有效,则令牌有效;否则,拒绝令牌并执行相应的安全措施。

四、java实现JWT签名验证

使用JWT库要在Maven或Gradle中添加依赖,在Maven中,可以将以下依赖添加到pom.xml文件中:

 <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>java-jwt</artifactId>
        <version>3.5.0</version>
 </dependency>

JWT签名和验证的示例代码:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;

public class JWTExample {

    private static final String SECRET_KEY = "my_secret_key";

    public static void main(String[] args) {
        // 构建 JWT
        String jwtToken = Jwts.builder()
                .setSubject("1234567890")
                .claim("name", "John Doe")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1 hour
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();

        // 验证 JWT
        try {
            // 分离 Header, Payload 和 Signature
            String[] jwtParts = jwtToken.split("\\.");
            String header = jwtParts[0];
            String payload = jwtParts[1];
            String signature = jwtParts[2];

            // 验证签名
            String expectedSignature = Jwts.parser()
                    .setSigningKey(SECRET_KEY)
                    .parseClaimsJws(jwtToken)
                    .getSignature();
            if (!signature.equals(expectedSignature)) {
                throw new RuntimeException("Invalid JWT signature");
            }

            // 验证 Payload 中的信息
            Claims claims = Jwts.parser()
                    .setSigningKey(SECRET_KEY)
                    .parseClaimsJws(jwtToken)
                    .getBody();
            System.out.println("Valid JWT");
        } catch (Exception e) {
            System.out.println("Invalid JWT: " + e.getMessage());
        }
    }
}

在上面的示例代码中使用jwt库进行JWT的签名和验证,首先构建了一个JWT,然后将其分离为Header、Payload和Signature三部分,使用parseClaimsJws函数对JWT进行解析和验证,从而获取其中的Payload中的信息并进行验证,最后如果解析和验证成功,则说明JWT是有效的,否则说明JWT是无效的,在实际应用中应该将SECRET_KEY替换为应用程序的密钥。

五、JWT攻击利用

1、伪造令牌

靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-unverified-signature
在这里插入图片描述
在这里插入图片描述
账号密码为wiener/peter,点击登录进行抓包
在这里插入图片描述
在这里插入图片描述
可以看到session是JWT形式,直接解密.
在这里插入图片描述
将payload部分sub用户改成administrator,然后编码一下替换原版的payload部分,
在这里插入图片描述
替换掉之前的payload
在这里插入图片描述
要完成题目的要求访问/admin路径在这里插入图片描述
有两个删除用户的接口,进行删除操作
在这里插入图片描述
在这里插入图片描述
删除成功,这道题就是我们利用JWT可以被解密的特性,伪造了administrator用户的JWT,实现从普通用户到administrator权限的一个越权操作。

2、签名用none

靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-flawed-signature-verification
在这里插入图片描述
还是一样的要求,要删除carlos用户,和上一题一样的操作,先登录
在这里插入图片描述
登录之后,替换payload发现返回401报错
在这里插入图片描述
这一题首先去解密一下JWT的第一部分即header部分
在这里插入图片描述
将alg至为none再进行编码替换
在这里插入图片描述
此时再替换header,并将SIGNATURE签名去掉,只留下header和payload部分(header中替换alg为none,payload中替换winer为administraor),保留结尾的点.
在这里插入图片描述
这时可以访问删除用户的接口
在这里插入图片描述
在这里插入图片描述
成功通关,这一关是利用了如果"alg"字段设为"none",则标识不签名,这样一来任何token都是有效的,攻击者可以通过将alg字段设置为"none"来伪造他们想要的任何token,接着便可以使用伪造的token冒充任意用户登陆网站

3、弱密钥爆破

在这里插入图片描述
还是一样登录进去,获取jwt
在这里插入图片描述
在这里插入图片描述
这里使用了弱密钥,这时候就可以通过爆破弱密钥来进行攻击,获取弱密钥和加密算法后,就能进行伪造签名。
在这里插入图片描述
获取到密钥后,打开https://jwt.io/重新生成一个jwt
修改前
在这里插入图片描述
在左侧填入原始的jwt,随后在右侧,修改账号为administrator,在右侧下面填入秘钥,然后就会在左边生成新的对应的jwt。修改后,复制左侧的jwt然后进行替换到数据包。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
完成!

五、漏洞利用工具

1、jwt.io
https://jwt.io/:一个在线工具,可以解析和调试 JWT,帮助开发者查看 JWT 的内容和签名算法,识别常见问题。

2、jwt_tool:
https://github.com/ticarpi/jwt_tool:用于分析、生成和攻击 JWT 的工具,支持算法混淆攻击等多种手段。

3、jwtcrack:
https://github.com/Sjord/jwtcrack:字典枚举破解 HS256, HS384 或 HS512 加密算法的JWT

### 使用 Burp Suite 进行 JWT 爆破攻击的最佳实践 #### 准备工作 安装并启用 JWT4B 插件,该插件提供了实时操作 JWT 的能力以及内置的自动化攻击功能[^1]。通过此插件可以直接在 Burp Suite 中处理 JSON Web Token (JWT),而不需要切换到其他工具。 #### 配置环境 确保已将目标应用程序流量代理至 Burp Suite,并且可以正常捕获包含 JWT 的请求。对于需要爆破的情况,重点在于获取有效的签名验证绕过方法或找到正确的加密密钥。 #### 执行爆破攻击 利用 JWT4B 提供的功能来执行密钥爆破: - **选择合适的攻击模式**:根据实际情况决定采用何种方式进行攻击。如果怀疑存在弱密钥,则可以选择暴力破解;如果是特定场景下的漏洞(比如 `alg` 字段被错误设置),则应针对性地调整策略。 - **准备字典文件**:创建一个可能作为私钥使用的字符串列表用于尝试匹配真实的密钥。这通常是一个文本文件,每行代表一个猜测值。 - **启动爆破过程** - 在 Burp Suite 内部加载待测的 JWT。 - 设置好相应的选项,特别是指明要用来测试的不同密钥候选者的位置[--kf 参数指定字典](此处为说明而非引用)[^3]。 ```bash # 假设命令行为如下形式(实际操作是在图形界面上完成) ./jwt_tool -s <your.jwt.token> --kf /path/to/keyfile.txt ``` 当遇到成功的密钥时,程序将会给出提示 "found key"。 #### 注意事项 - 测试过程中务必遵循合法合规的原则,在授权范围内开展渗透测试活动; - 对于任何敏感数据的操作都要谨慎行事,防止意外泄露事件的发生; - 记录下所有的实验步骤以便后续复查和报告撰写。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

F1y`

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值