0

Obviously depending on the type/context of data returned to a web front-end (in my case the setup is HTML/Javascript, .NET Csharp back-end and JSON as the data transport), if I have to return an ID say of a message that is an auto-generated primary key (Int64), what is the best way to "hide" this real ID?

For most things of course, I can understand it doesn't make too much difference, however an application I am working on means if a user "guesses" an ID in the URL to pull back another record, it could prove to be a security issue..

There seems to be lots of ideas/commentary about methods, but nothing has quite clicked.

I was thinking of having an auto-generated primary INT, but also a secondary alternate GUID too. It would be the GUID returned to any front-end process, and of course the auto-generated primary ID would still be used in the backend..

The thinking of course is the GUID would be far more difficult to guess/obtain another one to access a record?

Any ideas or best practices people use?

Thanks in advance, David.

Dav.id
  • 2,757
  • 3
  • 45
  • 57
  • I guess this question is similar to http://stackoverflow.com/questions/1500087/i-have-a-simple-database-of-content-should-i-hash-the-id-so-that-people-dont however I would still like to hear about other options perhaps? – Dav.id Aug 24 '11 at 02:29
  • 1
    You can always encrypt it before passing it.... GUIDs are pretty safe as well... an encrypted GUID is probably the safest (extreme, but safe) – M.R. Aug 24 '11 at 02:30

5 Answers5

3

I am working on means if a user "guesses" an ID in the URL to pull back another record, it could prove to be a security issue.."

If this is the case then you really need to step back and review the approach to security. If a user can access records which they don't have authorisation to view you do not provide appropriate security of your Object References - https://www.owasp.org/index.php/Top_10_2010-A4-Insecure_Direct_Object_References

The GUID approach will attempt to provide security by obscurity see Is using a GUID security though obscurity? as to whether or not it does you will have to make your own mind up based on your circumstances.

Community
  • 1
  • 1
rabs
  • 1,807
  • 3
  • 18
  • 29
  • Thanks, yes see my comments to the first answer.. I should have obviously explained a little more for context.. thanks for the link too! – Dav.id Aug 24 '11 at 04:38
3

Regarding security you have several aspects:

  • Session hijacking
  • Accessing/Modifying/Creating/Deleting records the user is not authorized to
  • Non-Authenticated access
  • Cross-Site* attacks
  • Man-in-the-middle attacks
  • etc.

The measures to deal with these depend on your architecture and security needs.

Since you don't say much about your arhcitecture and security needs it is really hard to give any specific advice...

Some points regarding "ID shouldn't be guessable":

  • "Correct" solution
    The problem goes away in the moment you implement authentication + autherization properly because properly implemented these two make sure that only authenticated users can access anything at all AND that every user can only access things he is allowed to. Even if an authenticated user knows the correct ID of something he is not allowed to access this would be secure because he would prevented from accessing it.

  • "weak solution"
    create a ConcurrentDictionary as a thread-safe in-memory-cache and put the real IDs plus the "temporary IDs" (for example upon first record access freshly generated GUIDs) in there. You can combine that temporary ID with some salt and/or encryption and/or hash of some connection-specific aspects (like client IP, time etc.). Then on every access you check with the ConcurrentDictionary and act accordingly... one positive effect: after app restart (for example app pool recycling) the same record gets a different ID because this is only an in-memory-cache... though this is hardly usable in a web-farming scenario

Yahia
  • 69,653
  • 9
  • 115
  • 144
  • Hi @Yahia thanks for the input. Absolutely correct, I should have explained a little more about the architecture. Basically ALL of the users have to login, and yes they can only see what they are allowed to (i.e. they might have a userID for a certain company etc). This the flows onto not letting certain users of even the same company see other records purely by "guessing" the ID of that item.. maybe just overkill as correctly speaking, the current users credentials are checked each time a backend process is actioned.. just trying to make even the perception of the ID being visible be reduced. – Dav.id Aug 24 '11 at 04:33
  • You are welcome - IF what you describe is properly impelemented (authentication + authorization) then why do you feel that "guessing an ID" could be a problem ? – Yahia Aug 24 '11 at 04:35
  • Hi, I think again it is more about the perception.. this app is for fashion designers, and they are very paranoid. So more about the fact the url/id "looks" secure - because rightly so, we have a login, and that login can only access the data they are meant to etc. Looking back, I should have re-phrased the question and provided the all important context... – Dav.id Aug 24 '11 at 05:14
  • then implement the ConcurrentDictionary approach - it is threadsafe and really fast since most operations are implemented lock-free – Yahia Aug 24 '11 at 05:15
  • Very cool - I had no idea about that class (ConcurrentDictionary) ! – Dav.id Aug 24 '11 at 07:53
2

Ofcourse technically, pulling back another record by quessing another ID is a bad thing- only when that other ID shouldnt be visible for the user who's pulling it back. But then you have a security problem anyways and you should focus on that rather then find a way to obfuscate the ID

Anyways, if you want to mess up the url, i recommend you looking into Rijndael. We use it alot here to pass around tokens. Basically, this encryption technique allows you to both encrypt and decrypt. Therefore you can encrypt the ID, send it to the client, the client posts it back and you can simply decrypt again. No need for an extra database record. Even more secure is to encrypt/decrypt the record ID salted with something like an IP for the current client, therefore even URL fishing will be a reduced problem.

See: http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael.aspx

Polity
  • 14,734
  • 2
  • 40
  • 40
  • Obfuscate means "Render obscure, unclear, or unintelligible." The OP is not talking about obfusication, but rather using a true secret (after all, isn't most cryprtography and authentication based on secrets at some level?) – gahooa Aug 24 '11 at 02:42
  • If something is obscure, unclear, or unintelligible is it not secure on some level? be it a very weak level. http://en.wikipedia.org/wiki/Security_through_obscurity – rabs Aug 24 '11 at 03:33
  • Actually again, I must apologise for not putting my query in context (see my comment for the first answer above).. so I do have security (obviously learning more and more how to make that better of course).. and so it really is about obscuring the ID, and also because the app has a perceived stress around security (for the fashion industry, and so design images etc are rather guarded etc),the app needs any extra security, even perceived ones... so thanks for the comments, and I will check out that link!!! – Dav.id Aug 24 '11 at 04:50
1

I would like to say that, the URL are meant to be public, it is not kind of confidential data. There's no need to hide the url from users. If a url can be seen by one user and should not be accessable to another user, you should check the privilege of the user from the server side instead of hiding that url.

gekowa
  • 452
  • 2
  • 10
1

All of the other answers (3) failed to cover the possibility of this being a non-cookied, non-authenticated, non-sessioned, non-logged-in user.

For example, a confirmation page after a order, etc...

In that case, your authentication is based on a secret in the URL. You use a secret that for all practical purposes is unguessable, and very unique per record. Then you assume that if the user has that secret, then they have access to said record, etc...

The real chalenge is to find a good way to make a secret UUID. Many developers will take the SHA1() of rand() + time() + uuid() + remote_ip() or something like that (which is typically sufficient), but I'm sure there is plenty of documentation out there on this.

Yes, in a situation where you have a non-authenticated user accessing a specific piece of data or performing an action (such as password reset), you need to have a second identifier (eg, varchar 40) on your records with a unique key (as you had outlined). Fill it with very random data, and if they have that secret, then let them in.

Take care.

gahooa
  • 131,293
  • 12
  • 98
  • 101
  • Thank you for your comment! again, see my comment to answer 1 above.. I really should have provided more details/context. But certainly I still wish to obscure the ID regardless, even to provide an extra level of "perceived" security (given that the app must have a login, and users are part of a companyID etc etc). – Dav.id Aug 24 '11 at 04:42