The first time I looked at the OWASP Top Ten web vulnerabilities, they all made sense to me, save for one. That one was A4 - Insecure Direct Object Reference. At the time I was still pretty new to object-oriented programming and so the first thing I thought was that it was referring to those kinds of objects.
But that is not what they are talking about. The are talking about any direct reference to an "implementation object". Meaning objects like files, folders, database records, or other types of "keys".
Direct Object ReferenceFirst we need to learn what a direct object reference is. As I said previously, an object, in this case, is anything that we can make a reference to from our application that can be implemented directly. The primary concern is when we reference them from an untrusted input (FORM, URL, CGI, and COOKIE).
In this URL it is pretty obvious that I am directly referencing a specific file. This immediately flags this URL as one that could be open to a number of attacks. When a hacker sees this, they could try a path traversal attack against it (i.e. 'filename=../../../../../../../tomcat/conf/tomcat-users.xml') or they could try an enumeration attack where they simple try to pass in different file names to see what they get (i.e. 'filename=jasonsPassword.txt').
Both of these attacks can be automated. I hope it becomes obvious that this is a vulnerability and that we would need to build a lot of security around this to ensure it was not abused. However, if we can remove the direct object reference, we can make our lives easier.
Here are some other examples of direct object references we might want to remove. These all use URL parameters, but keep in mind that ANY untrusted scope is vulnerable to this.
<!--- This one may have come from a <select> box where the user is prompted on which credit card from their account they have on file to use for the checkout --->
A more detailed exampleLet's take one of the examples from above and dig a little deeper. I like the credit card example, we'll work with that.
In our vulnerable e-commerce application we have a checkout process that asks the user which credit card, from those on file, they would like to use for this transaction. The code for showing the credit card choices looks like this.
Which results in this select box
Now this select box may be less than ideal for a number of reasons, but the one we are looking at is that it is using a direct object reference where it is referencing which card will be used.
A hacker could use this information and deduce that the credit card id numbers are assigned by predictable increments and then after submitting their own checkout form(but before the form gets to the server) they could intercept it and change the value of the whichCard parameter to, for example, "8767". 8767 likely corresponds, in the database, to a current card belonging to another user. If the card is valid and there are no other checks in place to stop an end user from doing this, then the transaction could go through but be charged to another user's credit card.
We need to remove this direct object reference.
Removing the direct object referenceIn the example above we can easily remove the direct object reference and ensure that they user cannot manipulate the parameter, and the system, as we saw previously.
<cfset userCards = ArrayNew(2) />
<cfset userCards[currentrow] = qGetCardsOnFile.cardID/>
<cfset userCards[currentrow] = qGetCardsOnFile.cardno />
<cfset session.userCards = userCards />
<cfloop from="1" to="#ArrayLen(userCards)#" index="cardIndex">
This will result in a select box that looks like this
In this code, we are taking the values from the query that contains the card numbers and sticking them into a multidimensional array (you could also use a struct or an object). We then store that array in the user's session and use the array, instead of the query, to build the select box. Each value of the select options corresponds to a position in the array instead of to a specific database record.
Now, instead of being given an option to choose a card based on a direct reference to the database, we have a direct reference to an array in the user's session, and that array contains only that user's data. Now he can manipulate parameters all he wants and will never get a credit card other than his own.
Now in whatever page or function that processes this form, the developer can use the passed value and the userCards array that is stored in the session to figure out which card they want to use.