MongoDB: is it safe to use document's ID "in public"?

SecurityMongodb

Security Problem Overview


I really like MongoDB's automatically generated ids. They are really useful.

However, is it save to use them publicly?

Let's say there is a posts collection, and the /posts page that takes id paramater (something like /posts/4d901acd8df94c1fe600009b) and displays info about it.

This way the user/hacker will know the real object id of the document. Is it okay or is it not secure?

Thanks

Security Solutions


Solution 1 - Security

The ObjectID documentation states that the automatically generated IDs include a 3-byte machine ID (presumably a hash of the MAC address). It's not inconceivable that someone could figure out things about your internal network by comparing those three bytes in various ids, but unless you're working for the Pentagon that doesn't seem worth worrying about (you're much more likely to be vulnerable to something more boring like a misconfigured Apache).

Other than that, Epcylon's right; there's nothing inherently insecure about exposing ids through URLs. Whether it's ugly is another matter, of course. You can base64 them to make them shorter (been thinking about this myself), but then there's the weird fact that they're all about half the same.

Solution 2 - Security

I have no experience with MongoDB in a production environment, so don't take my answer as the truth, but I can't imagine why it shouldn't be safe.

Compare to a Auto-ID type column in a RDBMS. You expose those to the outside all the time, I don't know of any reason for not doing the same with MongoDB ids.

As always, the security should be in validating your input and not letting anyone near your database without proper protection. Do it properly and it shouldn't matter if they know how to pick a particular object in your database, as they still can't do anything with it.

Solution 3 - Security

I thought mongodb _id was based on a datestamp, and sever address and other things you might prefer to keep private.

If you're worried it might be worth encrypting mongoids and using the result as a client-side identifier (and then un-encrypting when requests come back in).

If the encryption key is partially based on some unique attribute of the user or session in question, that makes it difficult for users to access content when they shouldn't.

Obviously still important to validate the user by other means!

Solution 4 - Security

Starting with version MongoDB 3.4, MongoDB no longer contains a machine identifier like the marked answer. But the id still contains a timestamp that can be used to find out when the data was created. If you don't want the ID to store any information related to data that people can use to map data, you can follow what I do.

I have used MongoDB at the production stage. On my system, generally, all MongoDB documents have 2 unique IDs.


First: Default MongoDB _id (Generated automatically by MongoDB)

I use this ID to query in the internal system. Examples such as those used for relations between collection, caching, etc. Querying with ObjectId is much faster than you querying other data types such as string.

> See https://stackoverflow.com/a/27897720/10861398


Second: Public ID (Generated by your application)

  • Field: pubId - You can replace it with anything. (still make sure to use the relevant and concise name)
  • Type: nanoid
    • Small
    • Fast (40% faster than UUID)
    • Safe (Can be used in cluster)
    • Compact (A-Za-z0-9_-)
    • Portable (Nano ID was ported to 14 programming languages)

I use this as the main ID when the data is exported out and consumed by the client application. Examples such as data entry and exit between APIs, integration with third-party applications, as id elements for rows in tables in client applications, etc.

Solution 5 - Security

Perhaps think of this more as a privacy than security issue.

I'm facing exactly the same issue. In storing user contributed content in web-accessible directories based on the Mongo-generated ID, there's a risk if those IDs are predictable that one user could access another user's content.

I think the advice of others is the right route: knowing the URL of user-specific private content shouldn't be enough to access it. An attempt to access should check the matching user is making the request.

I intend to do this in Symfony2 by storing the user content outside of the web root, then allowing access to it via a new route/Controller which before passing the response will validate some identifying information about the user.

Solution 6 - Security

  1. If id gives link to "unlisted" content that requires only link - it's privacy issue.

  2. If id gives a link to content that is under user login - not a problem.

No matter if it's MongoDb, SQL or any other id. Id is the key to data. If this key is only thing you need to view content that you should not - that's an issue. For such situation - generate unguessable id.

Solution 7 - Security

It's not any more unsafe that using the value of auto increment id from MySql. It's not a security breach in any way.

Solution 8 - Security

let say we have order 1 by user a order 2 by user b

it's safe to expose the docid for order 1 or 2 for both users ( your code should expose 1 for a and 2 for b though )

but what important is validating

if the user is allowed to read it only and you have like /api/modifyorder/:docid you must validate that the user is an admin

if user B have order 1 ( user A ) docid you need to check the order user id before serving the respond ( and log a security log if he try to do that )

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlexView Question on Stackoverflow
Solution 1 - SecurityLuke MaurerView Answer on Stackoverflow
Solution 2 - SecurityEpcylonView Answer on Stackoverflow
Solution 3 - Securityorange21View Answer on Stackoverflow
Solution 4 - SecurityLaode Muhammad Al FatihView Answer on Stackoverflow
Solution 5 - SecurityAdam KnowlesView Answer on Stackoverflow
Solution 6 - SecurityLukas LiesisView Answer on Stackoverflow
Solution 7 - SecurityDmitriView Answer on Stackoverflow
Solution 8 - SecurityZack HeisenbergView Answer on Stackoverflow