渗透测试--JWT攻防(一)
字数 1515 2025-08-10 09:43:39

JWT攻防教学文档

一、JWT简介

JSON Web Token (JWT) 是一种用于安全地在不同实体之间传递信息的开放标准(RFC 7519),主要用于身份验证和授权领域。

主要特点:

  • 自包含:不需要在服务器端存储会话信息
  • 适用于分布式系统和微服务架构
  • 在网络应用程序和服务之间传递声明(claims)信息

二、JWT结构

JWT由三部分组成,使用点号(.)分隔:

Header.Payload.Signature

1. Header (头部)

  • 包含令牌元信息,如加密算法
  • Base64编码但未加密
  • 主要字段:
    • alg (Algorithm):指定签名算法,如HS256(HMAC SHA-256)
    • typ (Type):令牌类型,通常为"JWT"

示例:

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

2. Payload (载荷)

包含三类声明(claims):

  1. 注册声明(Registered claims):预定义标准声明
    • iss (issuer):发行者
    • sub (subject):主题(通常为用户ID)
    • exp (expiration time):过期时间
    • iat (issued at):签发时间
  2. 私有声明(Private claims):用户自定义
  3. 公共声明(Public claims):应公开定义的声明

示例:

{
  "sub": "1234567890",
  "name": "toboshuse",
  "iat": 1697790142
}

3. Signature (签名)

用于验证令牌完整性和真实性,生成方式:

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

三、JWT工作原理

生成令牌流程:

  1. 创建头部(Header),选择加密算法
  2. 创建载荷(Payload),包含声明信息
  3. 生成签名(Signature),使用密钥和算法
  4. 组合三部分形成完整JWT

验证令牌流程:

  1. 接收方拆分JWT为三部分
  2. 使用相同算法和密钥重新计算签名
  3. 比较新签名与原始签名
  4. 验证声明(如检查过期时间)

四、Java中的JWT实现

Maven依赖:

<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.9.1</version>
</dependency>

示例代码:

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

public class JwtExample {
    private static final String SECRET_KEY = "mySecretKey";
    
    // 创建JWT
    private static String createJWT(String subject, String name) {
        return Jwts.builder()
            .setSubject(subject)
            .claim("name", name)
            .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
            .compact();
    }
    
    // 验证JWT
    private static Claims parseJWT(String jwt) {
        try {
            return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(jwt)
                .getBody();
        } catch (Exception e) {
            return null;
        }
    }
}

五、JWT攻击手法

攻击1:伪造令牌

原理:利用JWT可被解密的特性,修改Payload部分提升权限

步骤

  1. 获取正常JWT令牌
  2. 解码Payload部分
  3. 修改关键字段(如将sub改为"administrator")
  4. 重新编码Payload
  5. 替换原Payload部分

防御

  • 使用强密钥
  • 验证签名有效性
  • 不信任客户端提供的令牌

攻击2:签名算法设为None

原理:当alg设为"None"时,服务器可能不验证签名

步骤

  1. 修改Header部分,将alg改为"None"
  2. 移除Signature部分
  3. 修改Payload提升权限
  4. 发送伪造的JWT

防御

  • 生产环境禁用"None"算法
  • 严格验证签名算法
  • 拒绝没有签名的JWT

六、实战演练

靶场1:未验证签名的JWT

  1. 登录获取普通用户JWT
  2. 解码Payload,修改sub为"administrator"
  3. 重新编码并替换原Payload
  4. 使用伪造JWT访问/admin路径

靶场2:有缺陷的签名验证

  1. 登录获取JWT
  2. 修改Header将alg设为"None"
  3. 移除Signature部分
  4. 修改Payload提升权限
  5. 使用伪造JWT访问特权接口

七、安全建议

  1. 密钥管理

    • 使用强密钥(足够长度和复杂度)
    • 定期轮换密钥
    • 不要硬编码密钥
  2. 算法选择

    • 避免使用"None"算法
    • 优先使用RS256而非HS256(非对称优于对称)
    • 明确指定允许的算法列表
  3. 声明验证

    • 验证所有关键声明(iss, sub, exp等)
    • 检查令牌有效期
    • 验证发行者(iss)是否可信
  4. 传输安全

    • 使用HTTPS传输JWT
    • 避免在URL中传递JWT
    • 考虑使用HttpOnly和Secure标志的Cookie
  5. 其他

    • 实现令牌撤销机制
    • 限制令牌有效期
    • 监控异常令牌使用
JWT攻防教学文档 一、JWT简介 JSON Web Token (JWT) 是一种用于安全地在不同实体之间传递信息的开放标准(RFC 7519),主要用于身份验证和授权领域。 主要特点: 自包含:不需要在服务器端存储会话信息 适用于分布式系统和微服务架构 在网络应用程序和服务之间传递声明(claims)信息 二、JWT结构 JWT由三部分组成,使用点号(.)分隔: 1. Header (头部) 包含令牌元信息,如加密算法 Base64编码但未加密 主要字段: alg (Algorithm):指定签名算法,如HS256(HMAC SHA-256) typ (Type):令牌类型,通常为"JWT" 示例: 2. Payload (载荷) 包含三类声明(claims): 注册声明(Registered claims) :预定义标准声明 iss (issuer):发行者 sub (subject):主题(通常为用户ID) exp (expiration time):过期时间 iat (issued at):签发时间 私有声明(Private claims) :用户自定义 公共声明(Public claims) :应公开定义的声明 示例: 3. Signature (签名) 用于验证令牌完整性和真实性,生成方式: 三、JWT工作原理 生成令牌流程: 创建头部(Header),选择加密算法 创建载荷(Payload),包含声明信息 生成签名(Signature),使用密钥和算法 组合三部分形成完整JWT 验证令牌流程: 接收方拆分JWT为三部分 使用相同算法和密钥重新计算签名 比较新签名与原始签名 验证声明(如检查过期时间) 四、Java中的JWT实现 Maven依赖: 示例代码: 五、JWT攻击手法 攻击1:伪造令牌 原理 :利用JWT可被解密的特性,修改Payload部分提升权限 步骤 : 获取正常JWT令牌 解码Payload部分 修改关键字段(如将 sub 改为"administrator") 重新编码Payload 替换原Payload部分 防御 : 使用强密钥 验证签名有效性 不信任客户端提供的令牌 攻击2:签名算法设为None 原理 :当 alg 设为"None"时,服务器可能不验证签名 步骤 : 修改Header部分,将 alg 改为"None" 移除Signature部分 修改Payload提升权限 发送伪造的JWT 防御 : 生产环境禁用"None"算法 严格验证签名算法 拒绝没有签名的JWT 六、实战演练 靶场1:未验证签名的JWT 登录获取普通用户JWT 解码Payload,修改 sub 为"administrator" 重新编码并替换原Payload 使用伪造JWT访问/admin路径 靶场2:有缺陷的签名验证 登录获取JWT 修改Header将 alg 设为"None" 移除Signature部分 修改Payload提升权限 使用伪造JWT访问特权接口 七、安全建议 密钥管理 : 使用强密钥(足够长度和复杂度) 定期轮换密钥 不要硬编码密钥 算法选择 : 避免使用"None"算法 优先使用RS256而非HS256(非对称优于对称) 明确指定允许的算法列表 声明验证 : 验证所有关键声明(iss, sub, exp等) 检查令牌有效期 验证发行者(iss)是否可信 传输安全 : 使用HTTPS传输JWT 避免在URL中传递JWT 考虑使用HttpOnly和Secure标志的Cookie 其他 : 实现令牌撤销机制 限制令牌有效期 监控异常令牌使用