jwt安全
什么是jwt?
JWT(全称:Json Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。用通俗易懂的话来讲,JWT主要用于用户登录鉴权,就是一个认证机制。
jwt的数据格式
jwt的数据格式分为三部分,用 点( . ) 来分隔
1 | xxxxx.yyyyy.zzzzz |
我们可以把数据放到网站中去解析
我们一般拿到的JWT数据都是经过base64 url算法转换过的
jwt CTF题目
在ctf hub里有关于jwt的题,那么我们来试一试
打开题目链接发现是一个登录界面,先注册一个账号,登录进去看看是什么东西
既然是jwt相关的题目,那么登录包我们肯定要抓一下
可以看到这就是一个jwt的验证数据。我们拿到网站里解码一下
登录进来之后发现flag提示,尝试获取flag,被拒绝
这个应该是权限不够,那么我们肯定要伪造用户
然后因为这个题是用的nodejs环境,在nodejs中有一个注册用户js文件
1 | /controllers/api.js |
经过拼接访问可以知道只有admin用户可以拿到flag
所以接下来我们来伪造一下
更改header头
先来伪造加密算法,把HS256改为none
更改用户名为admin
在这个题中,我们会发现这里还有一个secretid值,看样子还用到了id值来进行判断,所以我们把这个id值0改为空,也就是用 [] 中括号来表示,里面什么也没有
应该注意到了,还有一个数据iat:1651642943,这个一般是一个时间戳的值,用于表示你这个登录验证有效期有多长时间,所以我们得改在现在得时间后面,今天是5.4,我改为5.5
密钥
第三部分密钥因为我们在header头已经设置了不使用任何签名算法,所以这部分为空
最终的的jwt数据为
1 | ewogICJhbGciOiAibm9uZSIsCiAgInR5cCI6ICJKV1QiCn0=ewogICJzZWNyZXRpZCI6IFtdLAogICJ1c2VybmFtZSI6ICJhZG1pbiIsCiAgInBhc3N3b3JkIjogInRlc3QiLAogICJpYXQiOiAxNjUxNzMwNTQ3Cn0= |
这里有两部分数据,前面是header,后面是主体payload
因为base64编码格式会在jwt里面起冲突,所以我们把所有的等号(=)都给删除,然后每段用 点(.) 来连接,最终的jwt数据格式为
1 | ewogICJhbGciOiAibm9uZSIsCiAgInR5cCI6ICJKV1QiCn0.ewogICJzZWNyZXRpZCI6IFtdLAogICJ1c2VybmFtZSI6ICJhZG1pbiIsCiAgInBhc3N3b3JkIjogInRlc3QiLAogICJpYXQiOiAxNjUxNzMwNTQ3Cn0. |
第三部分没有,所以什么也不添加
然后我们拿着伪造的admin用户去替换登陆包数据
还有一个地方需要更改,别忘了改前面username的值,把test改为admin
成功以admin用户身份登录,获取一下返回包,拿到flag
jwt脚本爆破
上面这个题如果说允许我们修改签名的算法等等这些,假如遇到不能修改的,那我们还可以爆破签名的密钥
1 | import jwt |
我们设置密钥为123456,然后拿去爆破
运气好是能够爆破出来的