Hey! Not your first time visiting our CTF Recaps? Go ahead and jump on down to the insights! If it is your first time, allow us to give a quick rundown of what these are. Wizer CTFs were launched to challenge developers to learn to think like a hacker in order to learn to code more securely. It's part of our new security awareness training we're designing focused on the dev team!
Once a challenge is retired the Wizer Wizard behind these creations - our very own CTO Itzik Spitzen - creates takeaways that provide clues into the challenge from the perspective of defending your script. Want to testdrive a CTF before reading the notes? Go ahead at wizer-ctf.com - it's free and there's something for all levels.
In this challenge, the developer identifies a Prototype Pollution vulnerability and exploits it to create an admin. Check out this CTF for yourself here.
The code of the challenge allows users to create a user account as well an admin account, yet creating an admin should be possible only if a valid secret invite code is provided. The user object is sent as the request body in a JSON format. In order to make sure that the user gets a default picture upon creation, the code pre-defines an object which includes the default image name, then uses that object as the base for any new user created. The `Object.assign` arguments order in the code is reversed, so logically this wouldn't even work very well, and in fact, this swap is critical for the vulnerability to occur.
Since the user object is sent as a whole and is assigned and directly used to create a user in the system, without proper verification or selectively copying the relevant key values from it, a Prototype Pollution is possible, and with the help of Object.assign, it's actually triggered. To be more precise, it's a Prototype Poisoning in this case, which means that we're able to pollute a specific object and not all objects.
While the opening condition prevents simply sending `isAdmin: true` to create an admin without having access to inviteCode, an attacker could alter the user object prototype (using the `__proto__` key) and include `isAdmin: true`. By doing so, while the condition isn't met, the createAdmin routine will still be invoked since `newUser.isAdmin` will be set to true, due to the prototype alteration.
Prototype Pollution or Poisoning is definitely a dangerous vulnerability. In this case, the API endpoint allowed creating an admin user and bypassing the intended logic of the procedure, which could result in getting access to sensitive data on the system or performing malicious changes to data. With that being said, depending on the poisoned object role in the logic of the code, it could result in a very wide range of outcomes, starting from getting access to sensitive data, causing denial of service or even gaining full control over a system.
Wanna join us on our next challenge? Sign up for our mailing list at wizer-ctf.com.