Wizer CTF #5: Willy Wonka's Secret

Link to challenge: CTF #5

Goal

In this fun challenge, we identify a NoSQL Injection and an IDOR (Insecure Direct Object Reference) vulnerabilities which result in gaining unauthorized access to data about a user from a different company.

Description of code

Our code is a pretty straightforward set of API endpoints running NoSQL queries against a MongoDB database. It's intended to provide access to the companies and users data models as well as get a secret-key upon having the user IDs.

The first endpoint (secret.js) fetches a list of secret codes, which are effectively UUIDs, from the database upon providing an array of known User-IDs. The second endpoint (users.js) gets a list of User records upon providing known Company-IDs, in the same way. The last endpoint (companies.js) gets a company record when provided with a known Company-ID, which is also a UUID and is designed to fetch only a single company at a time. The last query is sensitive to a NoSQL Injection.


What’s wrong with that approach?

The approach in the code above bears two main flaws:

1. The /companies endpoint is sensitive to a NoSQL injection. The user input isn't sanitized and hence an attacker is free to inject almost any alternative condition into the field value. The code will insert the company id provided into a query using { company_id:req.body.company_id }. The assumption here is that the user can only ever supply a string, but that is not the case. An attacker can set the req.body.company_id to an Object like { "$ne":null }. Now the full query is { company_id:{ "$ne":null } } . This query will return every document for which the company_id is not equal to null, which is every result. The attacker can use this to get a list of all companies.

2. Relying on UUIDs and assuming that they are non-guessible, is a common mistake among developers. While maybe tough to guess, IDs are used in the app, and once an attacker finds a way to get access to some other UUIDs of existing records, nothing protects the app from serving unauthorized data.

What would a successful IDOR attack look like in this case?

Given the known Company-ID in the instructions, an attacker can start exploring the structure of the data (and quite frankly, even this known company-ID isn't required to exploit the vuln). Quickly one can figure out what they need to do to get Willy Wonka's Secret. By exploiting the /companies endpoint NoSQL Injection vuln, for instance by specifying { "$ne": null } as the Company-ID, an attacker can get the list of companies, then using the /users endpoint, find Willy Wonka's user and ID within one of the companies in the database and use it to get the secret code via the /secret endpoint.

So what?

An IDOR, which in some cases is also referred to as Broken Access Control, is a serious vulnerability. By gaining access to unauthorized data, an attacker can exploit the data itself or take over an admin/superadmin account. One might think, oh, that's not too bad, since you'd need to have access to a valid user account first to take advantage of an IDOR, but in 99% of the cases, that isn't hard, since many apps allow free signups, trials etc. Also, there are other ways to gain access to a valid user context, such as using Phishing emails or other forms of social engineering and exploiting other vulns (i.e. XSS). The other vuln here is a NoSQL Injection, which is a way for an attacker to gain unauthorized access to data as well, hence needless to say, it is dangerous independently.

Main Takeaways:


Code Wizer!