1753CTF 2025
- Orel Gispan
- 17 hours ago
- 3 min read
This time I couldn't invest a lot of time, but I still solved some easy challenges.
1753CTF 2025 was different from those I participated in the past, in a way that the interaction with the platform (submitting flags, registering, etc.) was handled through a Discord AI bot, and it was refreshing and fun.

Challenges:
The first two challenges use the same source code.
Escatlate (flag #1) - Web
The challenge provided a URL and the source code of 'index.js'

After I opened 'index.js', I immediately searched for the keyword 'flag' to get an idea of what I should do.

It looks like there are two separate flags for the two different challenges.
If the user role is admin, the server will send the admin flag when accessing the '/api/message' endpoint. If the user role is moderator, it will send the moderator flag.
I searched for the keyword 'moderator' and there were no other places with this keyword.
I continued reading the code, specifically the '/api/register' endpoint.
We can see that this function checks if the user already exists (line 85-86), validates that the 'role' parameter in the request body is not the admin role (88-89), and then creates the user.

So it might be simple - all we have to do is register with the 'moderator' role.

And we can access the flag.

Escatlate (flag #2) - Web
Let's move on to retrieving the admin's flag. We know that we need an 'admin' role, but the registration functionality checks if we register with the administrative role:
if(req.body.role?.toLowerCase() == 'admin')
As we previously saw, the flag will be exposed only if the output of 'role.toUpperCase()' would be 'ADMIN':
if(req.user.role.toUpperCase() === 'ADMIN')
return res.json({ message: `Hi Admin! Your flag is ${process.env.ADMIN_FLAG}` });
It means that we need to find an input for the 'role' value which will behave like this:
role.toLowerCase() == 'admin' //false
role.toUpperCase() === 'ADMIN' //true
And the solution for this is to use a character that looks like 'i' instead of the 'i' in 'admin' (Unicode normalization), for example 'Latin Small Letter Dotless I':

We can see that it should work:

And here's the PoC:


Entropyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy - Web/Crypto
Description: It's finally here. Something everyone's been waiting for. A service that solves the biggest problem of humanity. People passwords. They are tooooooooooo short. This service applies so much fresh organic gluten free salt to the password that even the biggest noob who has the word 'dog' as their password can feel safe. So much entropy that I can't even imagine it!

We got a PHP app. By looking at the code (specifically the long entropy and the use of Bcrypt, I knew the solution right away.

We can see that the password is hashed using bcrypt and is generated by the combination of username, entropy and password.
A few months ago, I read an article about a potential issue with bcrypt, which was discovered in Okta (but of course relevant to other applications too).
Bcrypt only uses the first 72 characters for the hash.
As we said, the hash is derived from the username, entropy and password:
$hash = password_hash($usernameAdmin . $entropy . $passwordAdmin, PASSWORD_BCRYPT);
The username is Admin which is 5 chars and the entropy length is 66 chars. Both of them are 71 chars long. The 72nd character, is the first character of the password, which means it ignores all the rest of the password. So we only need to guess the first character of the password.

Happy Hacking,
Orel 🌏
Comments