HFCTF2020-EasyLogin

考点

  • jwt攻击

0x01

网页源代码中给了static/js/app.js文件,里面的注释提示了是用node.js写的koa框架,目的是为了提示koa框架中的controllers/api.js文件。

0x02

直接看关键代码

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
41
42
43
44
45
46
47
'POST /api/login': async (ctx, next) => {
const {username, password} = ctx.request.body;

if(!username || !password) {
throw new APIError('login error', 'username or password is necessary');
}

const token = ctx.header.authorization || ctx.request.body.authorization || ctx.request.query.authorization;

const sid = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()).secretid;

console.log(sid)

if(sid === undefined || sid === null || !(sid < global.secrets.length && sid >= 0)) {
throw new APIError('login error', 'no such secret id');
}

const secret = global.secrets[sid];

const user = jwt.verify(token, secret, {algorithm: 'HS256'});

const status = username === user.username && password === user.password;

if(status) {
ctx.session.username = username;
}

ctx.rest({
status
});

await next();
},

'GET /api/flag': async (ctx, next) => {
if(ctx.session.username !== 'admin'){
throw new APIError('permission error', 'permission denied');
}

const flag = fs.readFileSync('/flag').toString();
ctx.rest({
flag
});

await next();
},

api/flag说明要想得到flag,必须是admin用户。

api/login中在登录时会用jwt进行校验,这里存在jwt攻击,一些jwt中的alg字段改为none,系统会从jwt中删除相应的签名数据,这时jwt就只含有header+.+payload+.,然后将其交给服务器。

0x03

这里只需要将alg改为nonesecretid改为[],再重新分别对headerpayload进行base64加密即可(=去掉,用.进行连接)。

参考文章:https://xz.aliyun.com/t/2338