Monday, December 10, 2007

Engineering Secure Web Apps in ASP.NET 2.0

Security is one of the critical components in the engineering of any web application but unfortunately it isn’t handled in an equally critical way. With an ever increasing popularity of providing access to information over the web at a mouse-click, security concerns are increasing with a similar pace.

Below I have jolted down the list of some of the major security related items (you can call them ASP.NET security best practices, security checklist or the tips and tricks for engineering secure web applications in ASP.NET) which one must keep in mind, while engineering an ASP.NET Web application in which “SECURITY IS A CONCERN”.

My approach is not to provide you the complete end to end solution to each of the concern, but to highlight and provide pointers to the different approaches to cater each of these security items in the check list.

User Authentication

  • You can use the built-in authentication mechanisms (Forms, Windows and Passport) or Custom Authentication (Session Based; storing some user specific value in user’s session at the time of authentication so as to validate the user for subsequent requests by the same user, Using Hidden Fields; the traditional way but un secure way of maintaining authenticated user information etc).
  • You can use the built-in login controls provided in ASP.NET 2.0. Additionally in order to have a granular control over the User Authentication process refer to the Membership and Role Management API. In case you want the Login Controls / Management API to work with your custom database, you can write your own Membership and Role Provider.
  • In case you need to implement the “remember me on this computer” feature, use cookies with “One Time Password” design pattern.

Encrypt sections of the configuration file having confidential information

  • Whenever you need to put any confidential information in the configuration file like the database user name / password, don’t leave that information in plain text in the configuration file, rather encrypt it using the built-in “aspnet_regiis” utility with the command line option “-pe”. The aspnet_regiis.exe is located at :\WINDOWS\Microsoft.NET\Framework\v2.0.50727.
  • Once a section of the web.config file is encrypted then contents of that section aren’t human readable whenever that file is opened in some text editor, however when you access the configuration information through ASP.NET (the .NET 2.0 framework) it knows how to decrypt the contents and provide actual contents to the application.
  • You can use the Management API in order to programmatically encrypt the sections of your Web.Config file. The Management API added in ASP.NET 2.0 is very rich and provides you access to the complete configuration of the application and ability to modify the configuration file on the fly.

One-way encrypt the user passwords before storing in database

  • Never store user passwords in the database, in plain text. Store them in Encrypted format using any one way encryption algorithm like MD5, best is to encrypt (MD5) the user passwords at the client side using JavaScript and then at the server store it in the database.
  • Later on when the user wants to log in, encrypt the user entered password using the same encryption algorithm and then match it with the password in the database.
  • In case the user has forgotten his password, provide user an interface to set a new password after performing necessary validations. You can send a link to set new password for that user at his email address.

Use database user having limited rights

  • Create a user in the database that has limited rights (INSERT, UPDATE, SELECT and may be DELETE from specific tables) only those tables of the database that needs to be accessed by your web application, and use that user to access the database from within your application.

Show custom error pages with user friendly error messages

  • Never show the built in error page, telling the complete error detail for debugging the error to your end user. That discloses a lot of information that’s not intended for an end user.
  • You should better show custom error pages to the user with user friendly error messages while Logging the actual error occurred for the application developers to re-produce / debug and eventually resolve that error.
  • Always handle any of the unhandled exception in the Application_OnError event, use the Server.GetLastError() to get the detailed information about the error that occurred, while showing the user a custom error page and logging the actual error.

Check the Request’s Referrer Property

  • Check that the request has actually originated from your own website (from an intended page). Not checking so can lead to un precedent attacks

Handle SQL Injection Attacks

  • If you are using stored procedures, then you will be using SQL Parameters to send the user input to it and get the results. In that case your application isn’t prone to SQL Injections. However using the Stored Procudures or not in your web application is another debate, lets not get into that and focus on handling SQL Injections.
  • The problem comes when you are using inline queries and concatenates the user input with in the SQL Query. A well tailored user input by a hacker can break your security checks as well as can possibly drop the tables in your database etc. by using the single quotes and comment signs with in the user input. So concatenating the user input’s as is in inline SQL Queries can be fatal for your web application.
  • Use SQL Parameters even with “inline queries”, they automatically cater for the SQL Injection attacks.

Handle Cross Site Scripting Attacks

  • ASP.NET default behavior doesn’t allow the user to enter tags “” and shows an error page if such input is entered in a form field.
  • Some application may need to allow the user to enter information in tags, but this will result in potential security leaks, that’ named Cross Site Scripting. A user can write the <script&rt; tag, which can be possibly rendered to another user browsing the site. That script tag will be executed in the context of that second user, and that intelligently tailored script tag can possibly access the second user cookies etc and moreover can possibly submit a malicious request with the second user credentials using XML Http Request / AJAX etc.
  • Use the Microsoft’s AntiXSS Library to handle cross site scripting attacks.

Handle Dictionary Attacks – Captcha

  • Hackers can attack your website authentication system and submit automated login requests to crack the passwords of authenticated users of your protected website. You should check that your Login form / Authentication system isn’t attacked by this, by ensuring that it’s accessed by humans (asking the user to enter the characters shown on a bit distorted but human readable image). For more information on Dictionary Attacks point to Wikipedia

Denial of Service Attacks

  • The last resort for any hacker of your website is the denial of service attacks. You should track the activity for each of the user and should limit the repeated requests sent by the same IP to a decent number.
  • You can use the ASP.NET AJAX Control Toolkit – No Robot Control to help you out in this, but it should be used with caution as stated on the above website.

Log user activity

  • This way you don’t only capture some very useful data about the user trends but this data can also help you detect any un-desired activity made by the user.
  • You can use the Enterprise Library Logging Application Block log the user activity. Microsoft Enterprise Library’s Logging Application Block has the feature to log in the database, so that you can later on query it and create reports on it to find not only any interesting patterns based on “User Pathology” but can also point out any un-desired user activity.

I hope this pretty much covers most of the security check list items. However, I will be adding more and more to it, to provide a to-date comprehensive guide for engineering secure web apps in ASP.NET 2.0

No comments: