ctfshow web入门 JWT

目录

JWT介绍

web345

web346

web347

web348

web349

web350

JWT介绍

JWT 全称 JSON Web Token。使用 JSON 作为数据载体,通过对称/非对称方式加密方式对数据进行加密并加签,可以安全传输数据保证不被数据篡改。

JWT由头部(Header)、有效载荷(Payload)、签名(Signature)三部分组成,它们之间用点分隔然后每部分数据采用 base64url编码。

头部(Header)包含alg(签名算法)和typ(令牌类型)示例如下:

{
"alg": "HS256",
"typ": "JWT"
}

 有效载荷(Payload)包含一些实际需要传输的数据,在这里JWT 规定了以下7个官方字段,供选用

iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号

 除了官方字段以外,还可以在这个部分定义私有字段,Payload部分示例如下:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

签名(Signature)这个部分是对头部(Header)和有效载荷(Payload)两部分进行签名,防止数据被篡改。要产生这个部分需要有经过base64url编码的头部,和经过base64url编码的有效载荷,同时服务器还要有一个密钥。然后用头部中指定的加密算法,例如下面的HMACSHA256算法

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  your-256-bit-secret
)

产生签名。签名出来之后把头部,有效载荷,签名三个部分用点分隔拼成一个字符串。完成之后就是完整的jwt。

web345

打开题目先F12看一下源码发现一个admin目录,然后抓包看见cookie里面有jwt

 然后将jwt进行base64解密,然后将解码后的user换成admin

再进行base64加密,然后抓包访问admin目录,之后将刚才生成的jwt,替换cookie里的jwt然后发包拿到flag

这里只需要注意访问的是/admin/而不是/admin因为访问/admin表示访问admin.php而访问/admin/表示访问的是admin目录下默认的index.php

web346

这个题考JWT的三种常见的攻击方式之一修改算法为none,也是 json web token存在的一个CVE漏洞CVE-2015-9235。这个攻击方式就是修改alg字段为none,这样的话后端就不会进行签名校验。

打开题目还是先抓个包

 先放到JSON Web Tokens - jwt.io网站解析一下

然后我们需要将这个jwt里面的alg字段改为none,user改为admin,因为这个网站不支持将算法改为none所以用python脚本生成一个jwt,脚本如下

import jwt
Payload = {
  "iss": "admin",
  "iat": 1645605971,
  "exp": 1645613171,
  "nbf": 1645605971,
  "sub": "admin",
  "jti": "b89d811ca6831c1d63978fd7bff502e0"
}
headers = {
  "alg": "none",
  "typ": "JWT"
}
json_web_token = jwt.encode(payload=Payload,key="",algorithm="none",headers=headers)
print(json_web_token)

生成之后,抓包访问admin目录将刚才生成的jwt,替换cookie里的jwt然后发包拿到flag

web347

还是先抓个包看见cookie里面的jwt,看题目描述说是弱口令,那就用jwt_tool工具爆破一下密码

 可以看到密钥是123456,然后用JSON Web Tokens - jwt.io这个网站生成一下新的jwt

 之后抓包访问admin目录,将刚才生成的jwt替换cookie里的jwt然后发包拿到flag

web348

继续先抓包拿到cookie里面的jwt然后看见题目描述说是开始爆破,那就爆破一下密钥,这里用jwt_tool没跑出来,用c-jwt-cracker工具试试,没想到秒出。

 可以看到密钥是aaab,之后就继续用刚才的网站生成新的jwt,密钥填aaab,user改成admin

 最后抓包访问admin目录,将刚才生成的jwt替换cookie里的jwt然后发包拿到flag

web349

这个题给了个app.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');
	  }
	});
});

我们可以看到这个就是利用私钥去生成一个jwt然后利用公钥去解密,并且我们访问/private.key可以得到私钥,访问/public.key可以得到公钥,那我们就用他给的这个代码本地自己搭一个网站,将源码里面的user换成admin然后访问自己搭的网站,这时我们自己搭的网站里cookie里面的jwt就是我们新生成的jwt。

 

之后就打开题目抓包替换jwt然后请求方式换为POST拿到flag

当然这里还有第二种方法,先下载私钥,然后我们用私钥去生成一个jwt。具体的就是先用之前题目用的jwt网站解析一下payload和header然后用python生成一个jwt,之后抓包用新生成的jwt替换原来的jwt最后post发包一样能拿到flag。

import jwt
private_key = open('private.key', 'r').read()
payload={"user":"admin","iat": 1645612970}
print(jwt.encode(payload=payload, key=private_key, algorithm='RS256'))

web350

这个题也考JWT的三种常见的攻击方式之一把非对称算法 RS256 改为对称算法 HS256,用泄露的公钥签名数据,服务器尝试用公钥作为 secret 验证签名。也就是CVE-2016-5431漏洞

首先题目给了源码,然后和之前一样访问/public.key可以拿到公钥文件,那就和之前一样本地自己搭一下然后访问拿到新的jwt。这里注意一下要将源码的//routes换成//public然后将user换成admin。

 

 之后就打开题目抓包替换jwt然后请求方式换为POST拿到flag

 JWT攻击参考文章:https://xz.aliyun.com/t/2338

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值