Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using MongoDB generated _ids as "secret data" (eg, OAuth Tokens)

Tags:

mongodb

Are MongoDB _id fields sufficiently random / unguessable to act as secret data?

For example: if I'm building a server-side OAuth, could I use the _id as the OAuth Token for the user? I want to do this because of the cleanliness & indexability it gives the database (eg, "tokens._id" => oauth_token).

Inspecting the structure of MongoDB _id objects, they do seem to be decently random, but I do have some lingering concern about a malicious entity brute-force guessing one.

like image 830
Zane Claes Avatar asked Mar 15 '13 14:03

Zane Claes


2 Answers

In short, no. Mongo ObjectIds are easy to guess. In particular, under high load, these are often consecutive numbers, because timestamp, machine and process id don't change. If you look at the structure of Objectid, they are composed of

a 4-byte timestamp, 
a 3-byte machine identifier, 
a 2-byte process id, and 
a 3-byte counter, starting with a random value.

Hence, they have very little randomness. I often see consecutive ids in the database, for instance if some controller action writes a domain object, and a log entry in quick succession.

If the timestamp can be guessed and the machine id is determinable (which it is unless you have a huge cluster), there are only five bytes left. By looking at a number of generated ids, I can probably reduce that to like 50 processes so the effective entropy is somewhere in the 28 bit range. This is still hard to guess, but it's way too risky for an access token.

Use a cryptographically strong pseudo random number generator instead and create a token from that. For example, in .NET, the RNGCryptoServiceProvider allows to create arbitrary length random data.

As a sidenote, I suggest to have an additional cryptographic wrapper around your OAuthTokens, for two reasons:

a) You want to be able to determine invalid tokens quickly. A valid cryptographic shell might still include an invalid token (a revoked or expired grant), but you don't have to hit the database on brute force attacks every time. Also, the client

b) Clients can request tokens over and over. While it's not a requirement, almost all systems I know return different tokens every time (no matter if they are self-validating or not). Usually, that's because the token itself has a limited validity period. That is not the same validity period that the OAuth grant has.

In the database, what you really want to store is the grant, i.e. the permission that was given by some user to some client. If this grant is removed, all tokens become invalid. Inserting a new token every time is very unhandy because the user would have to delete all of them to effective remove the application grant.

like image 182
mnemosyn Avatar answered Nov 15 '22 11:11

mnemosyn


Guesing it is possible though extremely difficult. You might actually have better luck guessing most other OAuth tokens.

One example of how it can become very hard is that it contains the PID. If you are using a language like PHP or something then the PID changes to every PHP process spawned, which means each _id could poentially have its own moving PID and be completely and utterly random, of course that depends on what mode you run PHP in; if in fcgi mode then the PID could be constant.

The mahcine id is also another one. Most websites have auto scaling clusters of servers for their database so even under heavy load etc the only real predictable variable is the timestamp in quite a lot of cases and even then, since that is on milisecond level, it still is not super easy to guess; you need to know exactly how much traffic the site had to build an algorithm to claculate time in a reasonable manner. Of course the only way to garnish that info in the first place is to actually get its _id's, catch 22.

However, that considered, the only way I can think of brute forcing a _id is to get enough computing power to iterate all ObjectIds that could ever exist (could be trillions/infinite here considering the randomness of the variables of a ObjectId) and then ping those to each App ID (you should be demanding a OAuth token and a App ID at all times) in your database which again provides yet another level of mystery here.

So in my opinion, yes, some one could brute force but it would take a LOT of computing power and maybe even a couple of years to crack something not really worth it.

like image 26
Sammaye Avatar answered Nov 15 '22 09:11

Sammaye