If you're a returning visitor to our CTF Recaps, feel free to dive straight into the insights! For first-time explorers, let us quickly introduce you to the essence of these recaps. Wizer CTFs were introduced to challenge developers, encouraging them to adopt a hacker's mindset and thereby code more securely. This initiative is a pivotal part of our new security awareness training, specially crafted for development teams - Wizer's Secure Code Training for Developers!
After a challenge retires, our Wizer Wizard and CTO, Itzik Spitzen, crafts takeaways that offer valuable insights into the challenge, focusing on the defensive perspective for your script. Curious to test-drive a CTF before delving into the notes? Visit wizer-ctf.com – it's free, and there's something for all skill levels!
In this challenge, we're taking a closer look at an IDOR vulnerability in the code below. These issues are incredibly common and can pose a huge risk! Let's dive into it.
Description of code
The code below showcases two API endpoints from a task management system: /users & /tasks. The first endpoint retrieves the users records of a specified list of user_ids and the second retrieves the tasks of a specified user-ID. Many players initially attempted to exploit a possible NO-SQLi vulnerability. However, the code is not actually vulnerable to NO-SQLi because the first endpoint does not allow any nesting, which is the typical NO-SQLi method in similar cases. This limitation is due to the type of argument it accepts—an array of IDs. On the other hand, the second endpoint converts the argument into a number, making NO-SQLi tricks possible as well. The user IDs are assigned as running sequential numbers.
What’s wrong with that approach?
In this particular case, it is easy to guess other User-IDs. Based on one's user ID, an attacker could easily scan the preceding and following IDs i.e. given David's user ID is 10024, preceding numbers would be 10023, 10022, 10021 and so on, and following numbers will be 10025, 10026, 10027 and so on. Since there's no authentication, this example isn't realistic and hence fairly easy to solve.
What would a successful IDOR attack look like in this case?
An attacker who identifies the weakness, could easily scan the preceding and following numbers and fetch other user's tasks using the endpoint. To get the specific user's tasks as the game instructs in this case, the attacker would first start the guesswork on the /users endpoint, then once the targeted user Jeff Gonzales is found, use the /tasks endpoint with that id to fetch his tasks.
The example code lacks a very important element: Authorization. Whenever an application accesses, modifies or deletes data, a check should be in place to verify that the user making that request is actually allowed to perform those actions. IDOR is a vulnerability which assumes someone is authenticated, but focuses on an accurate and effective authorization which prevents access to unauthorized data.
- Always make sure that the user is authorized to access information on the backend:
It is not enough to have a strong authentication on the API level, and it is always required to limit the access of authenticated users to only what they are authorized to access. You might have some UI which blocks it, but always remember that attackers go straight to the backend, putting the client's traffic through a proxy to analyze it directly, hence can easily bypass any frontend protection.
- Unique IDs aren't a type of security:
In this case the IDs are allocated sequentially, so the guesswork is easy and straightforward. However, even if IDs are harder to guess, i.e. UUID or any other more complex ID structure, always remember that obscurity isn't security, and can never replace a solid authorization. In other words, even if IDs are very complex to guess, there might be other endpoints or data-leaks which will allow an attacker to gain access to other, unauthorized IDs.
Wanna join us on our next challenge? Sign up for our mailing list at wizer-ctf.com.