4

When I select, for example, an account, from a list of accounts in my view, the URL shows something like:

http://example.com/BankAccount/EditBankAccount?bankAccountId=12

Is there a way to hide the primary key, because northing stops someone from editing the id in the URL and posting it, to get a different account.

I can add code to see if the current user is allowed to view this account, but is there a better way?

hakre
  • 193,403
  • 52
  • 435
  • 836
Craig
  • 18,074
  • 38
  • 147
  • 248
  • you can hash url parameter, have you tried? – Sirwan Afifi Jan 05 '14 at 06:15
  • No, I am not sure what that means. – Craig Jan 05 '14 at 06:19
  • http://stackoverflow.com/questions/895586/encrypting-an-id-in-an-url-in-asp-net-mvc – Sirwan Afifi Jan 05 '14 at 06:47
  • 6
    "I can add code to see if the current user is allowed to view this account, but is there a better way?" --- you not only can do that, but **SHOULD** do that. – zerkms Jan 05 '14 at 08:16
  • 3
    There is nothing wrong in showing PKs - for example take a look on the url of this page. – zerkms Jan 05 '14 at 08:17
  • @zerkms, as long as the primary key is a surrogate. Displaying some natural keys in a URL can still be dangerous. For example, /BankAccount/Edit?accountNumber=11952443584&type=checking&ABA=10025874 would still be a bad idea. – danludwig Jan 05 '14 at 15:59
  • @danludwig: using natural keys as a PK is an antipattern. So I didn't expect anyone would do that ever – zerkms Jan 05 '14 at 20:17
  • The key I am currently showing is an auto increment key on the table. – Craig Jan 06 '14 at 00:04

3 Answers3

6

There's no need to hide the key from the url. For example have you looked around the urls on StackOverflow? You've got PKs hanging everywhere. Otherwise how are you going to understand which bank account is the current user trying to edit?

What you should do instead is to write an authorization filter that will ensure that the provided id in the url actually is an account that belongs to the currently authenticated user. I have illustrated how such authorization filter might be implemented in this similar thread.

Community
  • 1
  • 1
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
1

You ask:

Is there a way to hide the primary key?

Sure there is, just do not provide it. Let's review your current URI:

http://example.com/BankAccount/EditBankAccount?bankAccountId=12
                                               ^^^^^^^^^^^^^^^^

To hide the primary key, remove it and encode it as part of the transaction-script name, for example:

http://example.com/BankAccount/EditMyBankAccount
                                   ^^

I've highlighted the differences. This new transaction-script does not need any primary key provided as it is always about editing the current users account - and never a different one.

This should help you in preventing Insecure Direct Object References.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • This of course assumes a direct one-to-one relationship between users and bank accounts. Which may not be the case. – pwdst Jan 05 '14 at 10:24
  • @pwdst: The text of question differentiates the accounts and a different then the given one should not be accessed. Therefore this relationship is not assumed but given in the question. Also even if it is not the case, there is no problem to adopt this by the differentiating property rather than the direct object reference of any account (internally you would have in any case the check for the account by that user, so this solution directly requires the needed check). – hakre Jan 05 '14 at 10:28
  • 1
    *"When I select, for example, an account, from a list of accounts in my view"* suggests that the user may have access to multiple accounts - but shouldn't have access to accounts of other users. I upvoted your answer as the Insecure Direct Object References link is applicable to all situations, and inferring primary key based on user will help prevent leaking partial data to someone who can see endpoint addresses but not content (which, for example, is protected using HTTPS). – pwdst Jan 05 '14 at 10:35
  • 1
    Yes, I can see that point. But also user has the solution already in his question. To check if access to that object is allowed or not. That is required in any case and regardless how the information about the concrete account to modify is getting passed. – hakre Jan 05 '14 at 10:39
0

You may:

  1. Not to give explicit meaningful words to describe the query string parameters (like: /EditBankAccount?p1=abc&p2=xyz)

  2. Encrypt the the query string parameters so the page visitor will not figure out the real values

  3. If applicable to your case; use a salt value when encrypting your parameters to prevent rainbow table attacks. Store the salt key in your session.

  4. Keep it as is and apply strict security authorization rules to who should use what functionality on which object (i.e. Apply Functional and Object-Level Authorization)

Of course, the 3rd point will make the URL invalid after the session expires.

Lafi
  • 563
  • 5
  • 15
  • @zerkms: May be from your point of view, but the question initially is asking how to hide it. – Lafi Jan 05 '14 at 11:40
  • 1
    if someone asked how to shave a beard with a chainsaw - will you give advice how to do that in a better way or better explain there is a razor blade for that? – zerkms Jan 05 '14 at 20:17