前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JWT认证机制和漏洞利用

JWT认证机制和漏洞利用

作者头像
用户2700375
发布2022-06-09 14:38:00
3.7K0
发布2022-06-09 14:38:00
举报
文章被收录于专栏:很菜的web狗很菜的web狗
image-20220408105946033
image-20220408105946033

JSON Web Token(JWT) 简称JWT

JWT的组成部分

1、头部

2、payload 数据

3、验证签名

img
img
代码语言:javascript
复制
{
  "alg": "None",
  "typ": "jwt"
}

#alg
#是说明这个JWT的签名使用的算法的参数,常见值用HS256(默认),HS512等,也可以为None。HS256表示HMAC SHA256。
#typ
#说明这个token的类型为JWT
[
  {
    "iss": "admin",
    "iat": 1649316004,
    "exp": 1649323204,
    "nbf": 1649316004,
    "sub": "user",
    "jti": "2df98b5b4695c8a6a555a74ab1566e3f"
  }
]

#下方是声明部分一些常见的键,其中一些键不是必须的
#iss:发行人
#exp:到期时间
#sub:主题
#aud:用户
#nbf:在此之前不可用
#iat:发布时间
#jti:JWT ID用于标识该JWT

下面是一个用HS256生成JWT的代码例子的结构 HMACSHA256(base64UrlEncode(header) + “.” + base64UrlEncode(payload),secret)

#头部base64.数据段base64 然后加上自己的一个密钥 构成了一个jwt认证

1、用户端登录,用户名和密码在请求中被发往服务器 2、(确认登录信息正确后)服务器生成JSON头部和声明,将登录信息写入JSON的声明中(通常不应写入密码,因为JWT的声明是不加密的),并用secret用指定算法进行加密,生成该用户的JWT。此时,服务器并没有保存登录状态信息。 3、服务器将JWT返回给客户端 4、用户下次会话时,客户端会自动将JWT写在HTTP请求头部的Authorization字段中 5、服务器对JWT进行验证,若验证成功,则确认此用户的登录状态

img
img

稍稍解释下,就是客户端登录,带着一些账号密码等信息,服务器接收并判断登录成功后,通过秘钥生成jwt返回给浏览器,在之后每次客户端发请求都会带上jwt表示身份,然后服务器验证令牌并根据身份匹配权限,对行为进行相应。

JWT加密算法

JWT最常用的两种算法是HMAC和RSA。

HMAC(对称加密算法)用同一个密钥对token进行签名和认证。

RSA(非对称加密算法)需要两个密钥,先用私钥加密生成JWT,然后使用其对应的公钥来解密验证。

解密: https://jwt.io/

通常用该网站进行解密

img
img

科普完了,正好在刷ctfshow(再次安利一波)

这类题目我本身做的也不多,实战的话,实习时候在公司遇到过,不过不好拿出来放到博客。

就先演示ctfshow吧,会一直更新

web 345

img
img

查看源码发现有admin 我直接访问是会跳转到首页的。

img
img

auth参数貌似就是jwt,这里我直接base64解密看看

img
img

jwt头部的加密方式是None。所以这是一个jwt不加密验证漏洞。 JWT支持将算法设定为“None”。如果“alg”字段设为“ None”,那么签名会被置空,这样任何token都是有效的。

alg字段设置为“None”就可以伪造我们想要的任何token,接着便可以使用伪造的token冒充任意用户登陆网站。

直接把user改为admin 在进行base64编码后提交给cookie 访问admin 直接提交发现get flag。

img
img

web 346

img
img

跟上题类似,我这边直接url访问admin发现还是会跳转到首页,看下cookie 把auth参数拿去官网解密一下看看

img
img

第一反应应该是一个弱密钥,爆破一下试试看

这个脚本可以进行解密,和伪造jwt https://github.com/ticarpi/jwt_tool

python3 jwt_tool.py <jwt值> -C -d <字典>

img
img
img
img

填上密钥并修改 sub的值为admin重新生成了jwt 替换掉

img
img

web 349

img
img

此题目给了源码

发现公私钥都放在了public文件夹下面,nodejs中可以直接访问此文件。直接访问私钥

img
img

这回看一下jwt解码的结果。

加密为RS256 非对称加密 利用私钥生成 jwt ,利用公钥解密 jwt。

而 HS256这种对称加密,双方之间仅共享一个密钥,要千万注意密钥不要被泄露。

img
img

既然我们已经拿到了私钥,我就用Python生成jwt

代码语言:javascript
复制
import jwt

#payload
token_dict = {
    "user":"admin"
}
#headers
headers = {
    'alg':"RS256",
}
#私钥
key = open('private.key','r').read()

jwt_token = jwt.encode(payload=token_dict,key=key,algorithm='RS256',headers=headers)
print(jwt_token)
img
img

这里补充下 我用Python最开始无法生成加密后的jwt后来发现是 加密版本很低

pyjwt 2 需要 加密包版本稍高

代码语言:javascript
复制
python3 -m pip install --upgrade cryptography

拿来解密发现没任何问题

img
img

直接替换 并用post请求

img
img

web 350

这题直接给了源码。

源码里面呢也附带了 公钥

img
img

这题属于是密钥混淆攻击 。

如果将算法RS256修改为HS256(非对称密码算法=>对称密码算法)?

那么,后端代码会使用公钥作为秘密密钥,然后使用HS256算法验证签名。由于公钥有时可以被攻击者获取到,所以攻击者可以修改header中算法为HS256,然后使用RSA公钥对数据进行签名。

直接用上面的Python脚本去改,也会生成响应的jwt但是,提交到题目却拿不到flag,猜测难道是

jwt在python和nodejs的库不同。

直接用node

代码语言:javascript
复制
const jwt = require('jsonwebtoken');
var fs = require('fs');
var privateKey = fs.readFileSync('public.key');
var token = jwt.sign({ user: 'admin' }, privateKey, { algorithm: 'HS256' });
console.log(token)

npm install jsonwebtoken 安装模块 node jwt.js 运行

img
img
img
img

其实直接使用jwt.io也是可以的,但是经过测试如果密钥较复杂,例如有换行,粘贴到jwt.io以后会被替换为空格,最后导致结果不正确,所以直接采用了node,方便快捷。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-04-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JWT的组成部分
  • JWT加密算法
  • web 345
  • web 346
  • web 349
  • web 350
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档