views:

620

answers:

6

I've heard that exposing database IDs (in URLs, for example) is a security risk, but I'm having trouble understanding why.

Any opinions or links on why it's a risk, or why it isn't?

EDIT: of course the access is scoped, e.g. if you can't see resource foo?id=123 you'll get an error page. Otherwise the URL itself should be secret.

EDIT: if the URL is secret, it will probably contain a generated token that has a limited lifetime, e.g. valid for 1 hour and can only be used once.

EDIT (months later): my current preferred practice for this is to use UUIDS for IDs and expose them. If I'm using sequential numbers (usually for performance on some DBs) as IDs I like generating a UUID token for each entry as an alternate key, and expose that.

+1  A: 

If you are using integer IDs in your db, you may make it easy for users to see data they shouldn't by changing qs variables.

E.g. a user could easily change the id parameter in this qs and see/modify data they shouldn't http://someurl?id=1

Jason
If I don't check permissions I have a different security problem.
orip
but the answer is accurate: "may"
Seun Osewa
+5  A: 

The general thought goes along these lines: "Disclose as little information about the inner workings of your app to anyone."

Exposing the database ID counts as disclosing some information.

Reasons for this is that hackers can use any information about your apps inner workings to attack you, or a user can change the URL to get into a database he/she isn't suppose to see?

Arjan Einbu
Accessing resources they aren't supposed to see - only if I don't check permissions (which I do, otherwise I have a different security problem). Disclosing information about the "inner workings" - that's exactly my question. Why is it a problem?
orip
@orip: It's all about being as secure as possible. If you are the kind of programmer who doesn't make mistakes, then it's not an issue. Otherwise, exposing fewer details makes it more difficult to exploit your code if (when) you do make mistakes. By itself, you're right, it doesn't add security.
Adam Bellaire
@Adam: superficial security can be worse than no security. With no security you're explicit, with superficial security you could think it adds something non-neglible.
orip
+7  A: 

It depends on what the IDs stand for.

Consider a site that for competitive reason don't want to make public how many members they have but by using sequential IDs reveals it anyway in the URL: http://some.domain.name/user?id=3933

On the other hand, if they used the login name of the user instead: http://some.domain.name/user?id=some they haven't disclosed anything the user didn't already know.

some
if you're using sequential IDs you're right, but if not then that doesn't expose anything
orip
@orip: Like I said, it depends on what someone can discover by examining several id's. Is there a pattern? Can they use that information to gain information they are not intended to have?
some
@John: Thanks for the edit. English isn't my native language :)
some
I've done exactly this: used sequential ID numbers to determine the size of a competitor's userbase.
Micah
They are everywhere. Many shoppingsites use a sequential number for the order id. Place one order at one date, and one at another date and you know how many orders they got during that period. Even if you don't know how much money the orders are worth, you still get an indication of how the well the business goes.
some
+2  A: 

When you send database id's to your client you are forced to check security in both cases. If you keep the id's in your web session you can choose if you want/need to do it, meaning potentially less processing.

You are constantly trying to delegate things to your access control ;) This may be the case in your application but I have never seen such a consistent back-end system in my entire career. Most of them have security models that were designed for non-web usage and some have had additional roles added posthumously, and some of these have been bolted on outside of the core security model (because the role was added in a different operational context, say before the web).

So we use synthetic session local id's because it hides as much as we can get away with.

There is also the issue of non-integer key fields, which may be the case for enumerated values and similar. You can try to sanitize that data, but chances are you'll end up like little bobby drop tables.

krosenvold
Interesting, though I would think that checking all input (including URL parameters) for every request is very appropriate for the web.
orip
+7  A: 

Given the proper conditions, exposing identifiers is not a security risk. And, in practice, it would be extremely burdensome to design a web application without exposing identifiers.

Here are some good rules to follow:

  1. Use role-based security to control access to an operation. How this is done depends on the platform and framework you've chosen, but many support a declarative security model that will automatically redirect browsers to an authentication step when an action requires some authority.
  2. Use programmatic security to control access to an object. This is harder to do at a framework level. More often, it is something you have to write into your code and is therefore more error prone. This check goes beyond role-based checking by ensuring not only that the user has authority for the operation, but also has necessary rights on the specific object being modified. In a role-based system, it's easy to check that only managers can give raises, but beyond that, you need to make sure that the employee belongs to the particular manager's department.
  3. For most database records, conditions 1 and 2 are sufficient. But adding unpredictable IDs can be thought of as a little extra insurance, or "security in depth," if you buy into that notion. One place where unpredictable identifiers is a necessity, however, is in session IDs or other authentication tokens, where the ID itself authenticates a request. These should be generated by a cryptographic RNG.
erickson
+3  A: 

We use GUIDs for database ids. Leaking them is a lot less dangerous.

Joshua
This is what I would suggest. Lot less likely to guess the GUIDs in your database.
Jon Erickson