Category 战队专区

JSON Web Token(JWT) 简称JWT

JWT的组成部分1、头部

2、payload 数据

3、验证签名

代码语言: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进行验证,若验证成功,则确认此用户的登录状态

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

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

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

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

解密: https://jwt.io/

通常用该网站进行解密

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

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

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

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

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

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

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

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

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

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

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

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

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

web 349此题目给了源码

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

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

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

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

既然我们已经拿到了私钥,我就用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)这里补充下 我用Python最开始无法生成加密后的jwt后来发现是 加密版本很低

pyjwt 2 需要 加密包版本稍高

代码语言:javascript复制python3 -m pip install --upgrade cryptography拿来解密发现没任何问题

直接替换 并用post请求

web 350这题直接给了源码。

源码里面呢也附带了 公钥

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

如果将算法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 运行

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

Copyright © 2088 竞技暴风-网游赛事活动中心 All Rights Reserved.
友情链接