Sorry for the no-new-posts-November, FogMarks has been very busy experiencing new fields and worlds. But now — we’re back on baby!
Today’s case-study is about an old incident (and by “old” I mean 3 months old), but due to recent developments in an active research of a very known company’s popular product, I want to present and explain the huge importance of having an Anti-IDOR mechanism in your application.
Basically, an IDOR (Insecure Direct Object Reference) allows an attacker to mess around with an object that does not belong to him. This could be the private credentials of users (like an email address), private object that the attacker should not have access to (like a private event), or public information that should simply and rationally not be changed (or viewed) by a 3rd-party.
When an attacker is able to mess around with an object that does not belong to him, the consequences can be devastating. I’m not just talking about critical information disclosure that could lead the business to the ground (like Facebook’s recent discoveries), I am also talking about messing around with objects that could lead the attacker to execute code on the server. Don’t be so shocked — it is very much possible.
From an IDOR to RCE
I’m not going to disclose the name of the company or software that this serious vulnerability was found on. I am not even going to say that this is a huge company with a QA and security response team that could fill an entire mall. Twice.
But, as you might have already guessed, gaining access to a certain object thay you shouldn’t have had access to allows you sometimes to actually run commands on the server.
Although I can’t talk about that specific vulnerability, I am going to reveal my logic of preventing an IDOR from its roots.
An IDOR is being prevented using an Anti-IDOR Mechanism (AIM). We at FogMarks have developed one a few years ago, and, knock-on-wood, none of our customers have ever dealt with an IDOR problem. Don’t worry, we’re not going to offer you to buy it. This mechanism was created only for two large customers who shared the same code base. Create your own mechanism with the info down below, jeez!
But seriously, AIM’s main goal is to AIM (got the word game?) the usage of a certain object only to the user who created it, or to a user(s) who have access to it.
This is being done by storing that information in a database, especially for sensitive objects that could be targeted from the web clients.
When an object is being inserted to the DB, the mechanism generates it a unique 32 chars long identifier. This identifier is only being used by the server, and it’s called “SUID” (Server Used ID). In addition, the mechanism issues a 15 chars long integer identifier for the client side that is called, of course, “CUID” (Client Used ID). The CUID integer is being made from part of the 32 chars long SUID and part of the object details (like it’s name) using a special algorithm.
The idea of generating two identifiers to the same object is to not reveal the identifier of the actual sensitive object to the client side, so no direct access could be made in unexpected parts of the application.
Since object attributes tend to change (like their names, for example) the CUID is being replaced every once in a while, and the “heart” of the logic is to carefully match the CUID to SUID.
In the users’ permissions there is also a list of nodes that contains the SUID of objects that the user has access to.
When the user issues a request from the client side — the algorithm tries to generate part of the SUID from the supplied CUID. If it succeeded, it tries to match that part to one of the SUIDs list in the users’ permissions collection. If they match, the requesting user gets a one time limited access to the object. This one time access is being enabled for x minutes and for one static IP, until the next process of matching a CUID to SUID.
All this process, of course, is being managed by only one mechanism — The AIM.
The AIM handles requests in a queue form, so when dealing with multiple parallel requests — the AIM might not be the perfect solution (due to the possibility that the object will be changed by two different users at the same time).
In order to keep your platform safe from IDORs, requests to access sensitive objects should be managed only by one mechanism.
You don’t have to implement the exact logic like I did and compile two different identifiers for the same object, but you should definitely manage requests and permissions to private objects in only one place.
Here are some more examples of IDORs found by FogMarks in some very popular companies (and were patched, of course):
Until next time!