JWT

Environment: Kali CTFHub

Tools: BurpSuite jwt_tool


1.0 JWT基础

1.1 什么是JWT?

定义:

JWT (JSON Web Token) 是一个开放标准, 定义了一种紧凑且自包含的方式, 用于在各方之间以 JSON 对象的形式安全传输信息. 令牌本身包含了所有必要的用户信息, 服务端无需额外存储会话状态

特点:

  • 紧凑: 体积小, 适合通过URL, POST 参数, HTTP Header 传递
  • 自包含: 携带用户ID, 角色等关键信息, 减少数据库查询
  • 跨域: 天然支持跨域认证, 适合微服务和前后端分离架构

核心应用场景

场景 说明
认证 用户登录后, 后续请求携带 JWT 即可访问受保护资源
信息交换 使用公钥/私钥对签名, 确保发送方身份可信

1.2 JWT 与 Session的区别(为什么需要 JWT?)

传统 Session 认证问题:

  • 服务端需要存储 Session, 分布式环境下需共享存储(如Redis), 增加复杂度
  • 存在单点故障风险
  • 扩展性受限, 新增服务实例需同步认证状态

JWT 的无状态优势:

详见 特点


1.3 JWT 核心结构

一个完整的 JWT 由三部分组成, 用点号分隔 '.'

01 Header (头部)

描述 JWT 的元数据, 是一个 Base64Url 编码的 JSON对象

1
2
3
{
"alg": "HS256", // 签名算法
"typ": "JWT" // 令牌

alg 字段指定签名算法, typ 固定为JWT


02 Payload (荷载)

JWT 的主体内容, 包含需要传递的声明

注册声明(Registered Claims) – 预定义的标准字段

声明 全称 含义
iss Issuer 签发者
exp Expiration Time 过期时间(必须使用Unix时间戳)
sub Subject 主题(通常为用户ID)
aud Audience 受众
nbf Not Before 在此时间之前不可用
iat Issued At 签发时间
jti JWT ID JWT 唯一标识

公共声明(Public Claims) : 自定义字段, 用于传递非敏感信息, 如用户ID, 角色.

私有声明(Private Claims): 双方约定的自定义信息.

重点: Payload 仅 Base64 编码, 不是加密, 任何能拿到Token的人都可解码读取内容.


03 SIgnature (签名)

对 Header 和 Payload 进行签名, 用于验证令牌的完整性和真实性.

HS256 对称签名

1
2
3
4
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)

两种主流签名算法对比:

算法 类型 特点 场景
HS256 对称加密 同一密钥签名和验证, 密钥不能泄露 单一服务端内部使用
RS256 非对称加密 私钥签名, 公钥认证 分布式系统, 第三方验证

1.4 JWT 工作原理

以下 JWT 验证流程图解

流程:

  1. 用户登录: 客户端向服务端发送用户名和密码
  2. 服务器验证: 验证凭据是否正确
  3. 生成 JWT: 使用密钥签名, 编码用户信息(如 ID, Role) 和过期时间
  4. 返回客户端: 将 JWT 返回给客户端
  5. 客户端存储: 通常存储在localStorage或 Cookie中
  6. 携带 JWT 请求: 后续请求在Authorization: Bearer <JWT>Header中携带
  7. 服务器验证: 验证签名和有效期, 通过则允许访问

2.0 JWT 常见漏洞与攻击手法

  • alg: none 攻击

    将 Header 中的alg改为none, 并删除签名. 部分有缺陷的库会直接接受未签名的Token

    • 影响: 完全绕过身份验证, 可伪造任意用户身份

    • 利用: jwt_tool -X a

  • 算法混淆攻击(RS256 → HS256)

    利用非对称加密 (RS256) 和对称加密 (HS256) 的差异, 攻击者获取公钥后, 将其作为 HMAC 的 “密钥” 伪造Token

    原理: 服务端期望 RS256 验证, 但攻击者将算法改为 HS256, 用公钥作为对称密钥签名.

  • 弱密钥爆破

    如果 JWT 使用 HS256 且密钥太弱 , 可用社工字典暴力破解.

  • kid 参数注入

    kid (Key ID) 用于指示服务器使用哪把密钥验证, 若输入过滤不严, 可进行:

    • 路径遍历: ../../dev/null (使服务器使用空密钥)
    • SQL注入: 操纵密钥查询逻辑
  • jku (JWK Set URL) 注入

    jku 告诉服务器去哪里获取公钥, 若服务器未校验该URL, 攻击者可将其指向自己控制的服务器, 用自己生成的密钥伪造Token

  • 信息泄露

    Payload 仅 Base64 编码, 不是加密, 攻击者可轻易解码读取其中的敏感信息


2.1 JWT 漏洞实战

靶场: CTFHub 链接

01 敏感信息泄露

  • 靶场打开后随意输入用户名和密码

  • 获取Token

    • 浏览器开发者工具
    • BurpSuite抓包(本文演示)

    可见是标准的三段式结构 → JWT

  • JWT 解码

    • jwt.io (网页解码)
    • Python
    • jwt_tool(本文演示)
    1
    uv run jwt_too1.py <JWT>

    通过 FL 和 AG 的拼接值即可过关


02 无签名

  • 靶场打开后随意输入用户名和密码

  • 获取Token

  • BurpSuite插件 JWT Editor

    Attack → ‘none’ Signing Algorithm == (手工)”alg”: “none” && 删除JWT第三段SIgnature值

    最终 JWT 格式应为: base64(header).base64(payload).


03 弱密钥

本例采用john增量暴力破解

  • 打开靶场后输入随机用户名和密码

  • 获取登录后的数据包, 找到Token字段

    1
    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IjEiLCJwYXNzd29yZCI6IjEiLCJyb2xlIjoiZ3Vlc3QifQ.XjHFAfHxEoWOhPL1nlGO1zXqwsWHZb9hhZ7Njx31yGU
  • 将Token保存为jwt.txt

  • 使用john

    1
    john --format=HMAC-SHA256 --incremental=Lowernum jwt.txt

    成功破解

  • 伪造新Token并修改权限

    1
    uv run jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IjEiLCJwYXNzd29yZCI6IjEiLCJyb2xlIjoiZ3Vlc3QifQ.XjHFAfHxEoWOhPL1nlGO1zXqwsWHZb9hhZ7Njx31yGU -S hs256 -p "eilh" -I -pc role -pv admin

  • Token提交

    BurpSuite开启拦截抓包, 替换伪造Token, 得到flag


04 修改签名算法

漏洞原理:

服务端使用RS256: 私钥签名, 公钥验证, 但服务端并未写死验证算法, 读取alg字段, 可以将RS256, 修改为HS256, 通过公钥文件当HMAC‑HS256对称密钥校验签名.