ARE YOU THE ADMIN? - TFCCTF2022
Source code đi kèm
schema.prisma
1
2
3
4
5
6
7
8
9
10
11
12
13
14
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = "file:./app.db"
}
model User {
id String @id @default(uuid())
username String
isAdmin Boolean @default(false)
}
auth.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
import { NextApiRequest, NextApiResponse } from "next";
import { prisma } from "../../globals/prisma";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const body = req.body;
await prisma.user.create({
data: body,
});
return res.status(200).end();
}
index.tsx
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import type { GetServerSideProps, NextPage } from "next";
import type { User } from "@prisma/client";
import { prisma } from "../globals/prisma";
import { useState } from "react";
import { useRouter } from "next/router";
type Props = {
users: (User &
(
| {
flag: string;
isAdmin: true;
}
| {
flag?: never;
isAdmin: false;
}
))[];
};
const Home: NextPage<Props> = ({ users }) => {
const [username, setUsername] = useState("");
const router = useRouter();
const create = async () => {
await fetch("/api/auth", {
headers: {
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify({
username,
}),
});
await router.replace(router.asPath);
};
return (
<div>
<div>Create user:</div>
<input
value={username}
onChange={(event) => setUsername(event.target.value)}
/>
<button onClick={create}>Create</button>
<div>Users:</div>
{users.map((user) => (
<div key={user.id}>
<div>Username: {user.username}</div>
<div>Is admin? {user.isAdmin ? "yes" : "no"}</div>
{user.isAdmin && <div>{user.flag}</div>}
</div>
))}
</div>
);
};
export default Home;
export const getServerSideProps: GetServerSideProps<Props> = async (
context
) => {
const users = (await prisma.user.findMany()) as Props["users"];
for (const user of users) {
if (user.isAdmin) {
user.flag = process.env.FLAG!;
}
}
return {
props: {
users,
},
};
};
Trang web rất đơn giản, gồm 1 cái form để điền username và nút Create
Khi click vào button Create, web sẽ POST đến endpoint /api/auth với body là username
Đọc code để xem endpoint /api/auth sẽ làm gì
Theo mình hiểu thì nó sẽ lấy dữ liệu được POST lên và tạo 1 user mới
Nếu user là admin, web sẽ lấy flag và in ra
Ok quay trở lại với request create user
Vì /api/auth không hề check lại body hay lọc dữ liệu mà chỉ lấy toàn bộ body nên mình chỉ cần thêm trường “isAdmin”:true
Ok ngon lành
1
Flag: TFCCTF{S4n1t1z3_Y0ur_1nput5!}