JWT 原理与漏洞深度解析及攻防实战
字数 1654 2025-08-29 08:30:24

JWT 原理与漏洞深度解析及攻防实战

一、JWT 原理详解

1. JWT 结构

JWT (JSON Web Token) 由三部分组成,以 . 分隔:

  • Header:声明算法(alg)和类型(typ),例如:

    {
      "alg": "HS256",
      "typ": "JWT"
    }
    
  • Payload:存储用户身份和权限信息,例如:

    {
      "sub": "1234567890",
      "name": "John Doe",
      "admin": true
    }
    
  • Signature:对Header和Payload的签名,防止篡改。

签名生成逻辑 (以HS256为例):

signature = HMACSHA256(
  base64UrlEncode(header) + "." + 
  base64UrlEncode(payload), 
  secret_key
)

最终 Token 格式:

base64(Header).base64(Payload).base64(Signature)

2. JWT 工作流程

  1. 用户登录:客户端发送凭证(如用户名/密码)
  2. 服务端生成 JWT:验证成功后返回签名的 Token
  3. 客户端存储:通常存储在 Cookie 或 LocalStorage
  4. 后续请求:客户端携带 Token,服务端验证签名和有效期

二、JWT 漏洞场景深度剖析

1. 敏感信息泄露

漏洞原理

JWT 的 Payload 仅通过 Base64 编码,未加密。若开发者将敏感数据(如密码、密钥、手机号)存入 Payload,攻击者可轻易解码获取信息。

实际案例

某电商平台将用户地址和手机号明文存入 JWT,攻击者通过解码 Token 获取用户隐私数据。

代码示例(错误 vs 正确)

# 错误:明文存储手机号
payload = {"user": "admin", "phone": "13800138000"}

# 正确:仅存储必要标识
payload = {"user_id": "a3f8b", "role": "user"}  # 使用无意义 UUID 替代敏感字段

利用方式

使用浏览器开发者工具或在线解码工具(如 jwt.io)直接读取 Payload:

echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwaG9uZSI6IjEzODAwMTM4MDAwIn0" | base64 -d
# 输出:{"phone":"13800138000"}

防御方案

  • 最小化 Payload 内容,避免存储敏感数据
  • 对必要敏感字段加密(如AES)后再存入 Payload

2. 接受任意签名(alg: none 攻击)

漏洞原理

当服务端未强制校验签名算法时,攻击者可篡改 Header 的 algnone,绕过签名验证。

攻击步骤

  1. 截获合法 Token: header.payload.signature
  2. 修改 Header 为 {"alg":"none","typ":"JWT"}
  3. 删除 Signature,构造新 Token: malicious_header.payload.
  4. 发送给服务端,若验证通过则攻击成功

代码示例(服务端漏洞代码)

# 错误:未限制算法类型
def decode_token(token):
    return jwt.decode(token, key="secret", algorithms=None)  # 允许所有算法

利用工具

使用 Burp Suite 的 Repeater 模块修改请求头,或手动生成 Token:

import base64
header = base64.urlsafe_b64encode(b'{"alg":"none","typ":"JWT"}').decode().strip("=")
payload = base64.urlsafe_b64encode(b'{"user":"admin"}').decode().strip("=")
fake_token = f"{header}.{payload}."

防御方案

  • 强制指定允许的算法列表
  • 拒绝 alg: none 的 Token
  • 示例安全代码:
    jwt.decode(token, key="secret", algorithms=["HS256"])  # 明确指定算法
    

3. 弱密钥攻击

漏洞原理

当使用弱密钥(如"secret"、"123456")时,攻击者可暴力破解签名密钥。

实际案例

某系统使用默认密钥"secret",攻击者通过字典攻击获取密钥后伪造任意 Token。

利用工具

  • hashcat: hashcat -m 16500 jwt.txt wordlist.txt
  • jwt_tool: python3 jwt_tool.py -C -t <token> -d wordlist.txt

防御方案

  • 使用强随机密钥(至少32字节)
  • 定期轮换密钥
  • 使用非对称加密算法(如RS256)

4. 签名验证缺失

漏洞原理

服务端未验证 Token 签名,仅解码 Payload 就信任其内容。

代码示例(漏洞代码)

# 错误:未验证签名
def get_user(token):
    payload = jwt.decode(token, verify=False)  # 关闭验证
    return payload.get("user")

防御方案

  • 始终验证签名
  • 示例安全代码:
    jwt.decode(token, key="secret", algorithms=["HS256"], verify=True)
    

三、JWT 安全最佳实践

  1. 最小化 Payload:仅存储必要标识信息
  2. 强制算法验证:明确指定允许的算法列表
  3. 使用强密钥:避免默认或弱密钥
  4. 设置合理有效期:使用 exp 声明过期时间
  5. HTTPS 传输:防止 Token 被窃听
  6. 安全存储:避免 XSS 导致 Token 泄露
  7. 黑名单机制:对已注销 Token 进行管理

四、JWT 安全配置示例

安全生成 Token (Python)

import jwt
import datetime

# 使用强密钥
SECRET_KEY = "a_very_long_and_random_secret_key_here"

def create_token(user_id):
    payload = {
        "user_id": user_id,  # 仅存储必要标识
        "exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1),  # 1小时后过期
        "iat": datetime.datetime.utcnow()  # 签发时间
    }
    return jwt.encode(payload, SECRET_KEY, algorithm="HS256")

安全验证 Token (Python)

def verify_token(token):
    try:
        # 明确指定算法,强制验证签名和过期时间
        payload = jwt.decode(
            token, 
            SECRET_KEY, 
            algorithms=["HS256"],
            options={"verify_exp": True}
        )
        return payload
    except jwt.ExpiredSignatureError:
        raise Exception("Token expired")
    except jwt.InvalidTokenError:
        raise Exception("Invalid token")

五、总结

JWT 是一种强大的身份验证机制,但错误实现会导致严重安全漏洞。开发者必须:

  1. 理解 JWT 的工作原理
  2. 识别常见漏洞模式
  3. 实施安全最佳实践
  4. 定期审计现有实现

通过正确配置和安全编码,可以充分发挥 JWT 的优势,同时避免潜在的安全风险。

JWT 原理与漏洞深度解析及攻防实战 一、JWT 原理详解 1. JWT 结构 JWT (JSON Web Token) 由三部分组成,以 . 分隔: Header :声明算法( alg )和类型( typ ),例如: Payload :存储用户身份和权限信息,例如: Signature :对Header和Payload的签名,防止篡改。 签名生成逻辑 (以HS256为例): 最终 Token 格式: 2. JWT 工作流程 用户登录 :客户端发送凭证(如用户名/密码) 服务端生成 JWT :验证成功后返回签名的 Token 客户端存储 :通常存储在 Cookie 或 LocalStorage 后续请求 :客户端携带 Token,服务端验证签名和有效期 二、JWT 漏洞场景深度剖析 1. 敏感信息泄露 漏洞原理 JWT 的 Payload 仅通过 Base64 编码, 未加密 。若开发者将敏感数据(如密码、密钥、手机号)存入 Payload,攻击者可轻易解码获取信息。 实际案例 某电商平台将用户地址和手机号明文存入 JWT,攻击者通过解码 Token 获取用户隐私数据。 代码示例(错误 vs 正确) 利用方式 使用浏览器开发者工具或在线解码工具(如 jwt.io)直接读取 Payload: 防御方案 最小化 Payload 内容,避免存储敏感数据 对必要敏感字段加密(如AES)后再存入 Payload 2. 接受任意签名(alg: none 攻击) 漏洞原理 当服务端未强制校验签名算法时,攻击者可篡改 Header 的 alg 为 none ,绕过签名验证。 攻击步骤 截获合法 Token: header.payload.signature 修改 Header 为 {"alg":"none","typ":"JWT"} 删除 Signature,构造新 Token: malicious_header.payload. 发送给服务端,若验证通过则攻击成功 代码示例(服务端漏洞代码) 利用工具 使用 Burp Suite 的 Repeater 模块修改请求头,或手动生成 Token: 防御方案 强制指定允许的算法列表 拒绝 alg: none 的 Token 示例安全代码: 3. 弱密钥攻击 漏洞原理 当使用弱密钥(如"secret"、"123456")时,攻击者可暴力破解签名密钥。 实际案例 某系统使用默认密钥"secret",攻击者通过字典攻击获取密钥后伪造任意 Token。 利用工具 hashcat: hashcat -m 16500 jwt.txt wordlist.txt jwt_ tool: python3 jwt_tool.py -C -t <token> -d wordlist.txt 防御方案 使用强随机密钥(至少32字节) 定期轮换密钥 使用非对称加密算法(如RS256) 4. 签名验证缺失 漏洞原理 服务端未验证 Token 签名,仅解码 Payload 就信任其内容。 代码示例(漏洞代码) 防御方案 始终验证签名 示例安全代码: 三、JWT 安全最佳实践 最小化 Payload :仅存储必要标识信息 强制算法验证 :明确指定允许的算法列表 使用强密钥 :避免默认或弱密钥 设置合理有效期 :使用 exp 声明过期时间 HTTPS 传输 :防止 Token 被窃听 安全存储 :避免 XSS 导致 Token 泄露 黑名单机制 :对已注销 Token 进行管理 四、JWT 安全配置示例 安全生成 Token (Python) 安全验证 Token (Python) 五、总结 JWT 是一种强大的身份验证机制,但错误实现会导致严重安全漏洞。开发者必须: 理解 JWT 的工作原理 识别常见漏洞模式 实施安全最佳实践 定期审计现有实现 通过正确配置和安全编码,可以充分发挥 JWT 的优势,同时避免潜在的安全风险。