Get details of object from database - keep ID secure - asp.net

I have a list of books obtained from the database. When a user selects a book, I'd like it to retrieve the information for that book and display it on screen. However, I'd like to keep the ID of the book hidden from the client-side, so what would be the best way to transfer the ID of the selected book? I think my brain has melted, so I'm probably missing something obvious. Sessions seem to be the only way to not have any ID information transferred, but I'm not sure how to implement a system where an item is selected (from whichever control type is most suited) and the ID of the item is somehow picked up by the server and the relevant information retrieved. (Using ASP.NET + SQL Server).
Thanks for any advice

Do you really want to hide the database id from the user, as in a scenario where the user has some alternate access to the database and you want him to search for the book the hard way?
Usually the requirement is not to keep the ID secret, but to prevent the user from figuring out IDs of other items (eg. to enforce a certain funnel of navigation to reach an item) or from sharing the ID with other users. So for example is ok to have an URL http://example.com/books/0867316672289 where the 0867316672289 will render the same book to the same visitor, but the user cannot poke around the value, so 0867316672288 or 0867316672290 will land 404s. It may also be required that another user entering 0867316672289 gets also a 404.
Keeping the ID truly 'secret' (ie. storing it in session and having the session state keep track of 'current book') adds little value over the scheme described above and only complicates things.
One solution is to encrypt the IDs using a site secret key. From a int ID you get a 16 bytes encrypted block (eg if AES block size is used) that can be reverted back by the site into the original ID on subsequent visits. Visitors cannot guess other IDs due to the sheer size of the solution space (16 bytes). If you want also to make the pseudo-ids sticky to an user you can make the encryption key user specific (eg. derived from user id) or add extra information into the pseudo-id (eg. encrypt also the user-id and check it in your request handler).

Is exposing the IDs a risk? (SO question)

How about using a "pseudo id" for each book? I am assuming you need something on the client side to tell the server which book the client chose.
Generate a Guid for each book to use as the web side "pseudo id", that should keep the real id fairly secure.

I am not sure I understand your question, because the answer seems too obvious: just don't send the entity's id to the client. Use it on the server side to compose the ASP.NET page, but don't include the id itself on the output page that is sent to the client.
Does this make sense? :-)

Related

Prevent users change of hidden field value

I'm currently developing one project and I just discovered that the value of hidden fields can be edited. So that causes me a problem of security.
Imagine that I have a form to edit personal information. Currently, the form has a hidden input that has the value of the primary key. So if someone change that value can update data from another people.
I already check here and on google and found a possible solution on https://mvcsecurity.codeplex.com/. But unfortunately, that's not available to the recent version of ASP.NET MVC.
So I want to know if someone knows the properly way to prevent that.
The short answer is, Never trust data coming from client!
You should never trust data coming from a client browser. It can be altered by the end user. So don't simply trust the value. Always do needed validations on server side to make sure that the data / operation is valid.
In your specific case, When the form is submitted, you should check the value of the hidden field (the primary key value of the record being edited) is valid for the current user to be edited. Depending upon your systems user permissions/role system, you can do some if checks and determine whether the current user is authorized to do this operation with the value coming from client.
One solution is to encrypt the primary key before putting it in the hidden variable. That's the approach alot of site use, although often the encrypted var will be in the query string.

Is there an inherent risk in publishing other users' ids?

I have a collection called Vouchers. A user can, if they know the unique number ID of a Voucher, "claim" that voucher, which will give it a user_id attribute, tying it to them.
I'm at a point where I need to check a user's ID query against the existing database, but I'm wondering if I can do so on the client instead of the server (the client would be much more convenient because I'm using utility functions to tie the query form to the database operation.... it's a long story). If I do so on the client, I'll have to publish the entire Vouchers collection with correct user_id fields, and although I won't be showing those ids through any templates, they would be available through the console.
Is there an inherent risk in publishing all of the IDs like this? Can they be used maliciously even if I don't leave any specific holes for them to be used in?
First, in general it sounds like a bad idea to publish all user_ids to the client. What would happen if you have 1 million users? That would be a lot of data.
Second, in specific, we cannot know if there is inherent risk in publishing your user_ids, because we do not know what could be done with it in your system. If you use a typical design of user_ids chosen by the user themselves (for instance email), then you MUST design your system to be safe even if an attacker has guessed the user_id.
Short Version: not so good idea.
I have a similar setup up: user can sign-up, if she knows the voucher code. You can only publish those vouchers where the user_id is identical to the logged in user. All other checks like "does the user input correspond to a valid voucher?" must be handled on the server.
Remember: client code is not trusted.

Risks to database and front-end coupling

I could not come up with any better title, after reading the question you can suggest a better one. Also you can suggest some better tags, I could not find web-development.
I am a student so I don't know the standard way to achieve the following issue.
I usually set the IDs of elements (div,span,tr,etc) according to the database primary key to reference it later easily.
For example on page having some rows of entries having their id set to the sno in the DB which is primary key and on click on any row checking the id and display the result from database using that id.
But I think its a bad idea as anyone can use Inspect Element or Dev Tools and change the ID.
What is the standard way to achieve this?
EDIT 1
I know that web browser wont enforce the security policy for me that's why I am asking for the standard way, or standard practices to use for this matter.
Anyway, you must assume that any request that comes to the back end may be forged, any any data sent to browser (visible or hidden) is public.
If you considere the the id are private (rather uncommon requirement), you could instead simply use a row order and keep on server session a table row_order <-> id.
If you simply want to ensure that the id are correct, just control them (server side) before updating the database, or at the time of the database write if you cannot control them before.
If you want to enforce any other policy (users have roles and depending on roles are allowed or not to update some values) all those controls have to be done server side.

Documents/links on preventing HTML form fiddling?

I'm using ASP.Net but my question is a little more general than that. I'm interested in reading about strategies to prevent users from fooling with their HTML form values and links in an attempt to update records that don't belong to them.
For instance, if my application dealt with used cars and had links to add/remove inventory, which included as part of the URL the userid, what can I do to intercept attempts to munge the link and put someone else's ID in there? In this limited instance I can always run a check at the server to ensure that userid XYZ actually has rights to car ABC, but I was curious what other strategies are out there to keep the clever at bay. (Doing a checksum of the page, perhaps? Not sure.)
Thanks for your input.
The following that you are describing is a vulnerability called "Insecure Direct Object References" And it is recognized by A4 in the The OWASP top 10 for 2010.
what can I do to intercept attempts to
munge the link and put someone else's
ID in there?
There are a few ways that this vulnerability can be addressed. The first is to store the User's primary key in a session variable so you don't have to worry about it being manipulated by an attacker. For all future requests, especially ones that update user information like password, make sure to check this session variable.
Here is an example of the security system i am describing:
"update users set password='new_pass_hash' where user_id='"&Session("user_id")&"'";
Edit:
Another approach is a Hashed Message Authentication Code. This approach is much less secure than using Session as it introduces a new attack pattern of brute force instead of avoiding the problem all togather. An hmac allows you to see if a message has been modified by someone who doesn't have the secret key. The hmac value could be calculated as follows on the server side and then stored as a hidden variable.
hmac_value=hash('secret'&user_name&user_id&todays_date)
The idea is that if the user trys to change his username or userid then the hmac_value will not be valid unless the attacker can obtain the 'secret', which can be brute forced. Again you should avoid this security system at all costs. Although sometimes you don't have a choice (You do have a choice in your example vulnerability).
You want to find out how to use a session.
Sessions on tiztag.
If you keep track of the user session you don't need to keep looking at the URL to find out who is making a request/post.

Query String Parameters make my app at risk?

I'm writing an Asp.Net WebForms app where I am calling an edit page an passing in the data about the record to be edited using query string parameters in the URL.
Like:
http://myapp.path/QuoteItemEdit.aspx?PK=1234&DeviceType=12&Mode=Edit
On a previous page in the app, I have presented the user with a GridView of screened items he can edit based on his account privileges, and I call the edit page with these above parameter list, and the page know what to do. I do NOT do any additional checking on the target page to validate whether the user has access to the passed in PK record value as I planned to rely on the previous page to filter the list down and I would be fine.
However, it is clear the user can now type in a URL to a different PK and get access to edit that record. (Or, he may have access to Mode=View, but not Mode=Edit or Mode=Delete. Basically, I was hoping to avoid validating the record and access rights on the target page.
I have also tested the same workflow using Session variables to store PK, DeviceType, and Mode before calling the target page, and then reading them from Session in the target page. So there are no query string paramaters involved. This would take control away from the user.
So, I'm looking for feedback on these two approaches so that I choose an accepted/standard way of dealing with this, as it seems like a very common app design pattern for CRUD apps.
Agreed, you'll want to validate permissions on the target page, it's the only way to be absolutely sure. When it comes to security, redundancy isn't a bad thing. Secure your database as if you don't trust the business layer, secure your business layer as if you don't trust the UI, and secure the UI as well.
You should always validate before the real execution of the action, especially if passing the parameters by query string. For the second page that does the execution you might not need as much feedback for the user since you do not have to be nice to the user if he tries to cirumvent your security, so error handling should be a lot easier.
Passing the variables per session is acceptable but imho you should still validate the values.
We always use querystrings so records can be bookmarked easily, however always validate in both places, if you write you access control code nicely it should just be a case of re-using the existing code...
I believe the common practice is to do what you're avoiding: On the original page, you need to check to see what the user should have capabilities to do, and display their options appropriately. Then on the actual work page, you need to check the user again to verify they are allowed to be there, with access to that specific task.
From a usability standpoint, this is what the user would want (keeps it simple, allows them to bookmark certain pages, etc), and security on both pages is the only way to do this.
If you really don't want to check access rights on the target page:
You could hash the PK with the UserID and then add the hash value to the query string.
string hash = hashFunction(PK.toString() + UserID.toString());
Then you have to make sure the hash in the queryString equals the hash value calculated before loading the page.
Assuming this is an internal organization Web application.
Session variables can be manipulated as well, although not as easily. Whatever authentication you're using throughout your site, you should definitely use on your target page as well. Otherwise, you'll be open to exposing data you may not want as you have found out.
You could do the following to make your URLs a bit more secure:
-Use Guids for Primary Keys so users cant guess other record ID's
-The Mode couls be implicit: Guid = Edit, no Guid = New
and..
-Server-side validation is the only way to go.

Resources