An OWASP note suggests that direct object references are considered insecure in some contexts. They defined "direct object reference" as follows:

“A direct object reference occurs when a developer exposes a reference to an internal implementation object, such as a file, directory, database record, or key, as a URL or form parameter.”

Someone suggests a solution to this problem:

An object reference map is first populated with a list of authorized values which are temporarily stored in the session. When the user requests a field (ex: color=654321), the application does a lookup in this map from the session to determine the appropriate column name. If the value does not exist in this limited map, the user is not authorized. Reference maps should not be global (i.e. include every possible value), they are temporary maps/dictionaries that are only ever populated with authorized values.

However, somebody else argues on the Wiki that DOR’s are really insecure only for files, directories. That person adds:

There is no way to practically DOR all database primary keys in a real enterprise or post-enterprise system.

My question is, how insecure are direct object references to database primary keys? Can you provide concrete examples of vulnerabilities? How often do people go to extraordinary lengths (as suggested by the first person) to mask ALL database keys?

2 Answers
2

The issue is not as much direct object references as it is insecure direct object references. For example, let's say you have a script that displays a private message, and that script takes an ID as a parameter. If you view the list for your user, you'll see links to the messages you have access to. But if you can change that ID in the parameter, and use that to view arbitrary other messages, then that constitutes an insecure direct object reference.

Some people feel that creating a mechanism that maps user-specific IDs across to objects is safer, because it inherently requires you to consider access control.

Hiding database keys isn't exactly required, but it does make life more difficult if an attacker is trying to reference internal IDs in an attack. Direct references to file names and other such internal identifiers can allow attackers to map the internal structure of the server, which might be useful in other attacks. This also invites path injection and directory traversal problems.

There are many factors to worry about when exposing IDs to the public. I believe the most important one is to avoid crawlers. If I know that /page.php?id=1 will display information relative to a record in the database, then /page.php?id=2 must display information of the next record in order, and /page.php?id=3 is the next and so on, so I can read all the information on the table, potentially getting access to stuff I was not supposed to, like, for instance, posts under a password-protected section on a forum.

But if the ID is actually encrypted using a cypher unknown to me, I can no longer crawl through the database records so easily, I will have to obtain the IDs from pages I have access to and as result I will only have access to information I'm supposed to.

I have myself a case where you should be able to see the profile of a game character, but you are not supposed to reach this page by your own. You must only see it if the character owner provide you with the URL. This URL carrys an encrypted phrase, containing the encrypted ID, CRC checks to avoid bruteforce and even an expiration date for itself.