Any good strategies, code snippets etc for preventing URL manipulation?
For example I have this url, http://localhost/profile/edit/5
the id could easily be changed to anything and thus people could edit profiles they are not supposed too.
Here are a few ideas I thought of but they all have there drawbacks:
Change my system to use GUID primary keys - makes it almost impossible to guess the keys - but people can still take the GUID from one part of app and use it in another url later.
Use TempData to store the keys - prevents urls being sent around\used later.
Perform checks in the controller before displaying page - means you have to do 'adminy' code everywhere to check operations.
Whats the best thing to do? One of these or something else?
You shouldn't make your URLs "manipulation-proof" to protect underlying functionality. Besides: most websites make URLs more readable like
http://stackoverflow.com/questions/741653/preventing-url-manipulation-attacks-with-mvc
for instance - obfuscation would be a step backwards.Rather check for permissions within your Controllers and raise an exception if the user is not allowed to edit profile 6. If you don't want to have the "checks" everywhere, maybe you could put them into an
ActionFilter
, or create some helper method likeCurrentUser.FindProfileToEditById(profileId)
(which throws an exception if the action is not allowed) instead ofProfile.FindById(id)
.If you want a generic service where you do not have a "current user", you might go with the GUID (so does Doodle for instance) - however this will always be a security threat in various ways (Facebook had this issue with their photo-albums).
The url used to access your site is data from the client, and when security is concerned, you should always consider client provided data hostile.
Unfortunately there are no silver bullets to deal with this problem. You'll need to implement access restrictions throughout the application.
Number 3 is the correct thing to do. Server-Side Security Validation is always what you need, because this is the mechanism that you completely control and can rely on.
Number 1 is Security by Obscurity, and if someone accidentally posts his URL somewhere (like people often do with Session-IDs when they copy/paste links), your "Security" is broken.
Number 2 seems like a weak security - if you go through the hassle, better implement proper security. That also allows people to bookmark the page.
I use custom authorization filters to implement role- and owner-based access control. The standard AuthorizationFilter will allow you to specify named roles or users that can have access to an action. I have extended this to allow you to specify that the current user may have access if they are the "owner" of the data. I have two additional filters, RoleOrOwnerAuthorizationFilter and RoleOrOwnerAssociatedAuthorizationFilter. The first checks that a configurable parameter (usually
id
) passed in the RouteData is the id of the current user in my users table or if the current user is in any of the listed roles. If so the check succeeds, if not, it returns an authorization error view.The second allows me to specify a join table and the parameters to use to relate a parameter in the RouteData to a column in a join table and the current user to another column in the join table. If there is an entry matching both the parameter value and the user, I conclude that the user is related to the data and can have access. It also allows access if you are in a specified role. Between the three different attributes I have nearly all of my access control needs met, which means that I apply security simply by decorating with an appropriately configured attribute.