Security with QueryString values in Asp.net MVC - asp.net

How do you properly ensure that a user isnt tampering with querystring values or action url values? For example, you might have a Delete Comment action on your CommentController which takes a CommentID. The action url might look like /Comments/Delete/3 to delete the comment with the id 3.
Now obviously you dont want anyone to be able to delete comment 3. Normally on the owner of the comment or an admin has permission to do so. Ive seen this security enforced different ways and would like to know how some of you do it.
Do you make multiple Database calls to retrieve the comment and check that the author of the comment matches the user invoking the delete action?
Do you instead pass the CommentID and the UserID down to the stored procedure who does the delete and do a Delete where UserID and CommentID equal the values passed in?
Is it better to encrypt the query string values?

You don't.
It is a cardinal rule of programming, especially in this day and age, that you never trust any input which comes from the user, the browser, the client, etc.
It is also a cardinal rule of programming that you should probably not try to implement encryption and security yourself, unless you really know what you are doing. And even if you do know what you are doing, you will only remain one step ahead of the tard-crackers. The smart ones are still going to laugh at you.
Do the extra query to ensure the logged-in user has the right set of permissions. That will make everyone's lives just that much simpler.

Enrypting and decrypting query params is a trivial process and there are some great examples of how to do so using an HttpModule here on StackOverflow.
"You Don't", "You can't", or "It's not easy" are simply not acceptable responses in this day and age...

Vyrotek: The input method is not important. GET, POST, encrypted/obfuscated GET - no real difference. No matter the way your application receives commands, to perform an administrative action it must make sure that the issuing user is allowed to do the stuff he wants. The permission check must take place AFTER the command is received and BEFORE it gets executed. Otherwise it's no security at all.

Consider using technique outlined in Stephen Walther's article Tip #46 – Don’t use Delete Links because they create Security Holes which uses [AcceptVerbs(HttpVerbs.Delete)]

You can also allow only Post requests to Delete controller action by using the Accept Verbs attribute as seen below.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(int? id)
{
//Delete
}
Then you could also use the antiforgery token as discussed here:
http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/

I've done funky things take the querystring, compress it, Base64 or just hex encode it, so that "commentid=4&userid=12345" becomes "code=1a2b23de12769"
It's basically "Security through obscurity" but it does make a lot of work for someone trying to hack the site.

You cannot easily do this.
I have fond memories of a site that used action urls to do deletes.
All was good until they started search crawling the intranet.
Ooops, goodbye data.
I would recommend a solution whereby you do not use querystrings for anything you do not wish to be edited.

Related

Firebase Security rule to restrict up to some characters of a string

How to restrict user to save string that is above some limit?
I am getting Invalid property access: target is not an object if try to validate in security rules with length property of a string.
The Firebase Security Rules now support a length property for strings, as well as several other string methods including replace(), contains(), toUpperCase(), toLowerCase(), etc.
See https://firebase.google.com/docs/reference/security/database/#string_properties for more information.
The syntax you can use in rules are detailed here.
Unfortunately, being able to perform string operations (match, length, etc) are not available at this time. SEE ROB'S ANSWER BELOW, THIS FEATURE IS NOW AVAILABLE
I know this is at least on the Firebase radar because I requested a similar feature some time ago.
If you explain the exact details of what you want to solve, it will allow for a much more specific answer; for now I'll give you some general ideas.
Use a privileged app
Monitor Firebase with a privileged application and whenever a value is written to the specific fields you need string validation on, check it manually and delete it if invalid.
Naturally, client validation will take care of all valid use cases. So this is only needed to prevent malicious insertions.
Alternately, you can approach this more as an audit. Just email any invalid strings to some address to be reviewed. Since the client is going to make sure the string is valid before insertion, you are once again just looking at bugs or malicious behaviors.
Delegate writing to an API
Instead of letting the client write privileged data, send it to an API and have the API write that data--making it read only to the client.
Don't worry about it
Do you really need to validate the length? Is it sufficient to simply look and see if it's a string? Is it really a concern that someone would "hack" the contents of a string? Probably not. It could be, but probably not.
And if it is a concern, can it be solved by another avenue? If there is a server involved, just use the process outlined above.

Why do we do a POST to confirm deletion in asp.net MVC?

The following is a note from Professional ASP.NET MVC 2 by Scott Hanselman ++
You might ask — why did we go through
the effort of creating a <form> within
our Delete Confi rmation screen? Why
not just use a standard hyperlink to
link to an action method that does the
actual delete operation? The reason is
because we want to be careful to guard
against Web-crawlers and search
engines discovering our URLs and
inadvertently causing data to be
deleted when they follow the links.
HTTP-GET-based URLs are considered
safe for them to access/crawl, and
they are supposed to not follow
HTTP-POST ones. A good rule is to make
sure that you always put destructive
or data-modifying operations behind
HTTP-POST requests.
If web-crawlers and search engine have no access to the page containing deletion button, is it safe to use a standard hyperlink to link to an action method doing the actual delete operation?
A good rule of thumb is that GET shouldn't change data. If you want to change some data you use POST.
That is why ScottHa etc used a form to submit the delete. If it doesn't work for your app you can use GET if needed.
Alternatively you could use JavaScript to submit the form whe the user clicks link.
Yes, it's safe if a search engine can't reach it. But make sure to include some sort of confirmation or undo function. Links are easy to mis-click.
I would add what even if admin page is protected by password, delete links could be "clicked" by some locally installed web accelerator software. So using POST method is safer.
If you use GET requests to do any changes to your database at all, you will more than likely get hit with Cross-Site Request Forgery attacks at some point. The book you are reading discusses that more, and I have a few posts about it on my blog. It's an extremely common vulnerability I find these days; as frequent as SQL Injection, and much simpler to exploit.
There's a good reason not to use GET for operations which change data. It's not just for semantic purity. http://haacked.com/archive/2009/01/30/simple-jquery-delete-link-for-asp.net-mvc.aspx
#xport: POST take 2 times to executed one action, and GET only take 1 time. In POST, the first time, it will contact to server for authenticate action, and after that it will executing this action. In GET situation, it only call to action that not authenticate. So in usual, POST spend more time to execute action than GET (2 round trips). If you have some actions as DELETE, UPDATE, ADD,... you must execute it with POST and if some actions only select data from database, only GET. That is my understand in GET and POST.

Is it old-fashioned use query string for id?

I am curious if is out-of-date to use query string for id. We have webapp running on Net 2.0. When we display detail of something (can be product) we use query string like this : http://www.somesite.com/Shop/Product/Detail.aspx?ProductId=100
We use query string for reason that user can save the link somewhere and come back any time later. I suppose that we use url rewriting soon or later but in mean time I would like to know your opinion. Thanks.Cheers, X.
A common strategy is to use an item ID in the URL, coupled with some keywords that describe the item. This is good from a user's perspective, because they can easily see what a URL refers to if they save it somewhere. More importantly, it's useful from a SEO (Search Engine Optimisation) point of view, as search engines will - it is said - rate a given URL more highly if it contains the keywords someone is searching for.
You can see this approach on this very site, where the ID after 'questions' is used for the database query and the text is purely for the benefit of users and search engines.
Whether you use a straightforward query string, or a more advanced approach that makes the ID look like part of the folder path, is up to you. It's largely a matter of personal taste.
Yes, it is old fashioned!
However, if you are thinking about changing it to a RESTful implementation as others have suggested, then you should continue to support the old URL and querystring addresses by implementing an HTTP 301 redirect to forward from the querystring URLs, to the new restful URLs. This will ensure that any users old links and bookmarks will continue to work while telling the search engine bots that the url has changed.
Since your post is tagged ASP.Net, there is a good write-up on how you can support both, using the new ASP.Net routing mechanism here: http://msdn.microsoft.com/en-us/magazine/dd347546.aspx
Nothing wrong with query string parameters. Simple to create and understand. A lot of sites are using fancy urls like 'www.somesite.com/Shop/Product/white_sox_t_shirt` which is cool and sort-of user friendly, but more work for us poor developers.
Using query strings is not outdated at all, it just has to be used in the right places. However, never place anything in the query string that could be a security issue and remember that anything you read from the query string could have been modified so you should be validating all input in your checks.
It's not outdated, but anothter alternative is a more RESTful approach:
yourwebsite.com/products/100/usb-coffee-maker
The reason is that a) search engines usually ignore any URL with a QueryString (so the product.aspx?id=100 page may never get indexed) and b) having the name in the url purely for display purposes supposedly helps SEO as well.
Permanent links are best for SEO and also , what if your product moved to another database , and the ID of the product needs to be changed ?
I don't think the chances of a product's name will be changed or the manufacturer.
E.g Apple/Iphone won't change :) Seems to me a good Permalink

So why should we use POST instead of GET for posting data? [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicates:
How should I choose between GET and POST methods in HTML forms?
When do you use POST and when do you use GET?
Obviously, you should. But apart from doing so to fulfil the HTTP protocol, are there any reasons to do so? Less overhead? Some kind of security thing?
because GET must not alter the state of the server by definition.
see RFC2616 9.1.1 Safe Methods:
9.1.1 Safe Methods
Implementors should be aware that the
software represents the user in their
interactions over the Internet, and
should be careful to allow the user to
be aware of any actions they might
take which may have an unexpected
significance to themselves or others.
In particular, the convention has been
established that the GET and HEAD
methods SHOULD NOT have the
significance of taking an action other
than retrieval. These methods ought to
be considered "safe". This allows user
agents to represent other methods,
such as POST, PUT and DELETE, in a
special way, so that the user is made
aware of the fact that a possibly
unsafe action is being requested.
If you use GET to alter the state of the server then a search engine bot or some link prefetching extension in a web browser can wreak havoc on your site and (for example) delete all user data just by following links to your site.
There is a nice paper by the W3C about this: URIs, Addressability, and the use of HTTP GET and POST.
1.3 Quick Checklist for Choosing HTTP GET or POST
Use GET if:
The interaction is more like a question (i.e., it is a safe operation such as a query, read operation, or lookup).
Use POST if:
The interaction is more like an order, or
The interaction changes the state of the resource in a way that the user would perceive (e.g., a subscription to a service), or
The user be held accountable for the results of the interaction
Because, if you use GET to alter state, Google can delete your stuff.
When do you use POST and when do you use GET?
How should I choose between GET and POST methods in HTML forms?
If you accept GETs to perform write operations then a malicious hacker could inject somewhere links to perform an unauthorized operation. Your user clicks on a link - and something is deleted from a database. Or maybe some amount of money is transferred away from the user's account if he's still logged in to their online banking.
http://superbank.com/TransferMoney?amount=1000&recipient=2342524
Send a malicious email with an embedded image referencing this link, and as soon as the document is opened, something funny has happened behind the scenes.
GET is limited by the length of URL the browser/server can handle. This used to be as short as 256 characters.
There is atleast one situation where you want a GET to change data on the server. That is when a GET returns data, and you need to record which data was given to a user and when it was given.
If you use complex data types then it must be in a POST it cannot be in a GET. For example testing a WCF web service in a browser can only be done when the contract uses simple data types.
Using GET and POST where it is expected helps to keep your program understandable.
When you use POST, you can see the information being "posted" in the address-bar of the web browser. This is [apparently] not the case when you use the GET method.
This article was somewhere on http://www.w3schools.com/ Once I've found the exact page it was on, I'll repost. :-)

Fetch userdata on each request

My problem is quite simple - I think. I'm doing an ASP.NET MVC project. It's a project that requires the user to be logged in at all time. I probably need the current user's information in the MasterPage, like so; "Howdy, Mark - you're logged in!".
But what if I need the same information in the view? Or some validation in my servicelayer?
So how to make sure this information is available when I need it, and where I need it?
How much user information do you need? You can always access the Thread.Current.Principal and get the user's name - and possibly use that to look up more info on the user in a database.
Or if you really really really need some piece of information at all times, you could implement your own custom principal deriving from IPrincipal (this is really not a big deal!), and add those bits of information there, and when the user logs in, create an instance of the MyCustomPrincipal and attach that to the current thread. Then it'll be available anywhere, everywhere, anytime.
Marc
I've had exactly the same issue, and have yet to find a satisfactory answer. All the options we've explored have had various issues. In the specific example you mention, you could obviously store that data in the session, as that would work for that example. There may be other scenarios, that we've had, where that may not work, but simple user info like that would be fine in the session.
We've just setup a BaseController that handles making sure that info is always set and correct for each view. Depending on how you're handling authentication, etc, you will have some user data available in HttpContext.User.Identity.Name at all times. Which can also be referenced.
Build a hierarchy of your models and put the shared information in the base model. This way it will be available to any view or partial view.
Of course it has to be retrieved on each request since web applications are not persistent.
You should store this in Session and retrieve it into your controllers via a custom ModelBinder.
Not sure if I get what you want to ask, but if you are looking for things like authentication and role-based authorization, actually ASP.net is providing a great framework to work on/start with.
This article (with also 2nd part) is something I recently discovered and read about which is really good start with the provider-pattern which help to understand the underlying authentication framework of ASP.net. Be sure to read about the membershipProvider class and the RoleProvider class in msdn also, they together make a great framework on most basic role-base authentication to work with (if you are comfortable with the function they provided, you even don't need to code data-access part, all are provided in the default implementation!)
PS: Check out Context.Users property too! It stores the current authenticated user information.
HttpContext.Current.Users.Identity returns the current user's information. Though I am not sure whether it gets passed implicitly when you make a webservice call.

Resources