A few months ago I was working on a very simple forum site. It was to be used by medical professionals to discuss different medical treatment best practices.
Our client always uses an external online security specialist to advise all agencies of the security levels and features expected to be included in the build (this was standard practice by the company for all websites / applications built). Although I found this a little strange working with an external company purely on security I am glad I did. There were 10 key point’s made by the company. Some were clear as day to me and I had been using them for years and other I had never really thought of before! By no means do I feel that the points below cover all manor of website security but it is a good starting point.
1) Clear Text Authentication
Nowadays using SSL(Secure Socket Layer) to make sure your application is always served over a secure channel is a must if sensitive data is involved. If an attacker were in a position to intercept network traffic they could sniff sensitive information, including login credentials. It is recommended that an application is configured such that it uses encryption for the transmission of all sensitive information. Also really there is no excuse not to use it as it has become increasingly cheap to buy SSL certificates (http://www.instantssl.com/). It is quite easy to force your entire application to run under SSL by adding the following code to your global.asax (plus this is easy to turn off during development as it is only specified once in the application!) .
void Application_BeginRequest(object sender, EventArgs e)
{
if(!Request.IsSecureConnection)
{
Response.Redirect(Request.Url.ToString().Replace("http:", "https:"));
}
}
2) XSS / CSRF
Cross site scripting is an attack where a user will pass in malicious data into a form potentially enabling an attacker to trick users into revealing sensitive details such as authentication credentials or access tokens or even just causing a nuisance popup messages to be shown on a page . A quick remedial action is to enable event validation attribute in the top of an aspx page but I would recommend encoding all HTML output with Server.HtmlEncode(). For more detailed information on XSS please visit http://msdn.microsoft.com/en-us/library/ms998274.aspx .
Cross Site Request Forgery (session riding)
Cross Site Request Forgery is an attack that manages to trick the user into executing a script or getting them to browse to a site where they are currently authenticated. If a user has not logged out of an application or the session token was still valid, and then they were sent an email asking them to browse to a link the results could be bad. Below is an example that could possibly transfer money from Bob’s account to Mallory’s account if Bob was still authenticated on his banking site.
http://bank.example/withdraw?account=bob&amount=1000000&for=mallory"
Below are a few things you can do to help combat CSRF:-
1) Requiring authentication in GET and POST parameters, not only cookies;
2) Checking the HTTP Referer header;
3) Limiting the lifetime of authentication cookie;
For a more detailed overview of CSRF please visit http://www.cgisecurity.com/csrf-faq.html
3) Auto Complete Restriction
Auto complete is a function offered by modern browsers to prevent users from having to retype data entered previously. Whilst this function is a convenient usability feature it can result in the exposure of sensitive information. The screenshot included here highlights the auto complete function on the login page of an application allowing auto completion(and this screen shot is from a very well known site!).
To stop auto completion being captured on a form you are able to disable it at a form or element level. Although it is not guaranteed to work as a small number of browsers will override the settings presented by the web application. Also the code below is not WC3 compliant but there are JavaScript alternatives if this is a concern.
<form action="page.aspx" method="POST" AUTOCOMPLETE="off">
Or
<input type="text" name="Username" AUTOCOMPLETE="off">
4) Account Lockout
Locking out accounts after a set number of failed login attempts is a must. It forces hackers to have to communicate with a system administrator or automated service requiring more information (usually personal data) to re-enable the account. Remember hackers are scared of human interaction :->. Also this security technique helps fight off automated systems trying to brute force hack an account. Usually throwing thousands or hundreds of thousands of different password combinations at the server to see if a positive authentication response is given. If a user is locked out after a few failed login attempts then this would no longer be an issue (apart from DOS attacks but this is outside the scope of this blog post http://en.wikipedia.org/wiki/Denial-of-service_attack).
5) Password Change Mechanism
Once an account is locked out it is best practice to ask for further details of the user to re-enable it. Personal data such as mother maiden name or even first pets name are usually enough to put a hacker off trying to get a password reset. Remember when storing this data in a database it should be encrypted and not human readable.
I tend to get the user to setup there own secret question and answer on registration as they are more likely to remember the details if it is a question unique to them.
6) Password Policy
A suitable password policy should be set up. I feel there has to be a balance between usability and the security of an application (who is going to remember a password if it has to be 15 characters long with numbers and special characters – certainly not me!) A good rule of thumb is that a password should be 6-8 characters long including one upper case character and one number. Using regular expressions are a great way of enforcing password policy rules. For information on using regular expressions please see this link http://msdn.microsoft.com/en-us/library/ms998267.aspx.
7) Email Enumeration – Forgot Password Page
When a user requests their password to be reset there a few clear rules to adhere to. If the email address of the user does not match any registered emails do not set an error message informing them that “there is no user in the system with that email address”. This enables a hacker to keep fishing for valid email addresses held within the system (Email Enumeration). Always give a positive response informing the user that an email has been sent with details on how to reset there password regardless of whether it has been sent or has not.
Once a user has received an email never send the password in plain text to the email address. I would recommend sending the user a link they can use to reset the password. The link should only be valid for a short period of time (around 30 minutes) and should also be unique to each forgotten password request. A good way to do this is to add a GUID to the users table that is changed per user request for a password reset and this is set in the query string of the change password link.
8) Logout Button
Make sure a logout button is clearly marked on each page. The easier it is for a user to log out of an application the more likely they will be to use it! Rather than just shutting down the browser window. If the user clicks a logout button you can abandon sessions and clear authentication tokens if they don’t these may be hanging around for a while (please see CSRF)!
9) Cookies and HTTPONLY Flag
If you set the HTTPONLY flag of a cookie to true it means that scripts will not be able to call your cookies and remember where does the session token live? Yes that's right in a Cookie! Now we don't want any old JavaScript function calling that do we!
<script type="text/javascript">
// This code returns the cookie name.
alert("Getting HTTP Cookie");
alert(getCookie("MyHttpCookie"));
// Because the cookie is set to HttpOnly,
// this returns null.
alert("Getting HTTP Only Cookie");
alert(getCookie("MyHttpOnlyCookie"));
</script>
To learn more about this please visit http://msdn.microsoft.com/en-us/library/system.web.httpcookie.httponly.aspx
10) Keystroke Loggers
Now its time to think outside the box! Let’s imagine we have built an application and our user is logging in at an internet cafe but wait!
 |
That’s right there is a key logger wired up to the machine! Now this hacker is going to know our users login credentials. One way around this is to ask the user to pick a memorable number from a drop down list that they have chosen at registration. Now lets see a key logger get that information! |
Remember!
Using the membership API will save you lots of time when using ASP.NET but not all of the above recommendations come wired up directly out of the box. Over the next few months I will be developing my own membership provider to incorporate all of the above functionality! And hopefully I will be able to release the code open source on codeplex!