Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Security Features Analysis for ASP.NET

0.00/5 (No votes)
10 Nov 2008 1  
To analyse the various security featutes for ASP.NET

Introduction

ASP.NET is a very potential technology for developing web applications. Now a day many applications are being developed in ASP.NET. For any web application Security is a very important feature. Especially those web applications which contain some sensitive user information or any financial data, security is a crucial aspect for them. Some times extra security features provided in the web application may degrade the overall performance of the web application. So one should properly choose security features so as the application is reliable as well as performance is also not very much affected. This article considers the security features in ASP.NET 2.0. But these are applicable to higher versions also.

We can divide the whole Security feature analysis to following major categories:

  • Authentication
  • Configuration
  • Data Access Security
  • Code Access Security
  • Exception Handling
  • Communication Security

Security2.JPG

Authentication

Authentication means to check whether the user is the registered user or the trusted user. There are two types of Authentication provided by ASP.NET 2.0

  • Forms Authentication
  • Windows Authentication

One should use windows authentication, wherever it is possible. Because Windows Authentication uses the active directory or similar structure to store the user name and passwords, and we need not to create password policies and password encryption to store them in database. ASP.NET uses identity object to represent the current user’s identity. This object internally implements the System.Security.Principal.IIdentity interface to represent the authenticated user. We can access the authenticated user through HttpContext.Principal.IIdentity regardless of authentication method, whether it is Forms authentication or Windows authentication.

Forms Authentication

In forms authentication, user name and password combination are stored in database or configuration file. The user provides the credentials and that are validated against these stored credentials. ASP.NET 2.0 provides MembershipProvider abstract class. The membership feature has built-in providers for user stores including SQL Server, Active Directory, and Active Directory Application Mode (ADAM).

Security1.JPG

We should consider following points before implementing the forms Authentication:

  1. We should use ASP.NET built in class MemberShip provider rather than implementing our own custom logic for validating credentials.
  2. In the authentication user credentials are passed across the network, so we should use the SSL to send the credentials across the network.
  3. We should try to reduce the session time out, if we can not use Secure Socket Layer.
  4. Passwords should not be directly stored in configuration files. If it is directly stored anywhere then the password should be properly encrypted and logic for encryption and decryption should be handled.
  5. Strong password policies should be enforced so as to get more security.
  6. We should never persists Authentication cookies, because they are stored in user’s profile and can be stolen by some attacker.

Windows Authentication

We should use Windows Authentication where it is possible. Because by windows authentication we are having the benefits of Active directory, enforceable account and password policy and one centralized storage of credentials. For making Secure Windows authentication we can consider the followings:

  1. Password length and complexity should be set.
  2. There should be some password expiration. So that after a particular period of time password keeps changing.

Where possible, you should use Windows authentication because this enables you to use an existing identity store such as your corporate Active Directory, it enables you to enforce strong password policies, you do not need to build custom identity store management tools and passwords are not transmitted over the network.

Configuration

There are lots of configuration settings for any ASP.NET web application. These settings are very important for any web application. There is connection string, the most important part for database connectivity. Some times developers directly give database credentials in plane in web.config file. That is a bad practice, if you are giving the credentials in connection string then we should encrypt the connection string with the help of following command:

aspnet_regiis -pe "connectionStrings" -app "/<Name of the application>"

And now if you want to decrypt the connection string back, you can run the following command:

aspnet_regiis -pd "connectionStrings" -app "/<Name of the application>"

The modified connection string will look like this:

<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
      xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <KeyName>Rsa Key</KeyName>
          </KeyInfo>
          <CipherData>
            <CipherValue>R7cyuRk+SXJoimz7wlOpJr/YLeADGnwJVcmElHbrG/B5dDTE4C9rzSmm
                TsbJ9Xcl2oDQt1qYma9L7pzQsQQYqLrkajqJ4i6ZQH1cmiot8ja7Vh+yItes7TRU1AoXN9
                T0mbX5H1Axm0O3X/285/MdXXTUlPkDMAZXmzNVeEJHSCE=</CipherValue>
          </CipherData>
        </EncryptedKey>
      </KeyInfo>
      <CipherData>
        <CipherValue>
           d2++QtjcVwIkJLsye+dNJbCveORxeWiVSJIbcQQqAFofhay1wMci8FFlbQWttiRYFcvxrmVfNS
           xoZV8GjfPtppiodhOzQZ+0/QIFiU9Cifqh/T/7JyFkFSn13bTKjbYmHObKAzZ+Eg6gCXBxsVEr
           zH9GRphlsz5ru1BytFYxo/lUGRvZfpLHLYWRuFyLXnxNoAGfL1mpQM7M46x5YWRMsNsNEKTo/
           PU9/Jvnh/lT+GlcgCs2JRpyzSfKE7zSJH+TpIRtd86PwQ5HG3Pd2frYdYw0rmlmlI9D
        </CipherValue>
      </CipherData>
    </EncryptedData>
  </connectionStrings>

Data Access Security

By the Data access Security we mean to say that unauthorized illegal access to database should not be provided. Some hackers may inject the harmful code through forms that can access the database illegally. So every data should be properly validated before submitting it to back end.

For checking such securities we should consider following points:

  1. All data should be validated for length, input and format before doing any processing.
  2. We should use proper regular expression class for validating the data for formatting at back end.
  3. Dynamic query generation on the basis of data provided by the user should be avoided, means whatever parameters user is providing should not be directly involved in a query generation.
  4. Use the stored procedures wherever possible, rather than just batch of queries.
  5. If any error occurs then do the proper roll back, so database will never be in an in consistent state.
  6. Use the views with restricted privileges rather than using the table names in Database stored procedures and direct SQL queries.
  7. Create a window account that contains the least permissions on each object and use that account for accessing the database.
  8. Even database should not directly contain any passwords. If passwords are there then they must be in encrypted form.
  9. Try to use windows authentication for database access also, because it provides some benefits, like storing of credentials at centralized and safe place and also password policies and all that are already implemented by the active directory.
  10. Proper exception handling must be there for each and every data accessing function. Best practice is we should create the log file for logging the exceptions. I am giving an example code here used to create the log files.
//*******************************************************************************************************
//1. File Name      :  CreateLogFiles.cs					                      *
//2. Description    :  This is the class for logging all the erros in log files wherever the            *
//                     exceptions occurred in web application                                           *
//3. Created by     :  Mudit Agarwal						                      *
//4. Modification Log                                                                                   *
// |=======================================================================================|            *
// |  Ver. No       |  Date		            |  Author		            |  Modification  | *
// |  1.0           |  April-01, 2008       |  Mudit Agarwal         |  First Version   |               *
// |  1.01          |  May  -13, 2008       |  Mudit Agarwal         |  Second Version  |               *
// |=======================================================================================|            *
//*******************************************************************************************************
using System;
using System.IO;
using System.Text;

/// <summary>
/// Summary description for CreateLogFiles
/// </summary>
/// 

namespace DataAccessLayer
{
    /// <summary>
    /// The class used for creating the log files
    /// </summary>
    public class CreateLogFiles
    {
        /// <summary>
        /// Declaration of variables
        /// </summary>

        //The static variable intCount for keeping track of number of exceptions before writing to log
        private static int intCount;

        //The string in which we are appending the exceptions and after 20 exceptions we write it in file
        private static String strError;

        //Starting format for writing to log file
        private string sLogFormat;

        //The name of LogFile so as to create the log files at daily basis
        private string sErrorTime;

        /// <summary>
        /// The constructor for CreateLogFiles class
        /// </summary>
        public CreateLogFiles()
        {
            //Setting the values for sLogFormat as date Time + arrow sign
            sLogFormat = DateTime.Now.ToShortDateString().ToString() + " " +
                DateTime.Now.ToLongTimeString().ToString() + " ==> ";

            //Store the value of sYear, sMonth, sDay and concatenate them to create
            //sErrorTime
            string sYear = DateTime.Now.Year.ToString();
            string sMonth = DateTime.Now.Month.ToString();
            string sDay = DateTime.Now.Day.ToString();
            sErrorTime = sYear + sMonth + sDay;
        }

        /// <summary>
        /// This function is used to write the exception(s) to log file. Path to log
        /// file, and exception message are
        /// passed as parameters
        /// </summary>
        /// <param name="sPathName">This is the path for Log file, if it is empty
        /// string then some default path is set</param>
        /// <param name="sErrMsg">This is the actual error message</param>
        public void ErrorLog(string sPathName, string sErrMsg)
        {
            //If the path is empty string then set some default path
            if (sPathName == "")
            {
                sPathName = "<Path>\\ErrorLog";
            }

            //Format the error message
            sErrMsg = DateTime.Now.ToString() + " ==> " + sErrMsg;

            //Use try catch block for file handling operations
            try
            {
                //Create the object of stream writer class for logging into the file
                StreamWriter sw = new StreamWriter(sPathName + sErrorTime + ".txt", true);

                //Use synchronization in case of multiple users access the file at same time
                lock (sw)
                {
                    //Writing the error message to log file
                    sw.WriteLine(sErrMsg);

                    //Use flush to remove the message from buffer and then close the streamwriter object
                    sw.Flush();
                    sw.Close();
                }
            }
            catch (Exception) // For handling all the exceptions
            {
            }
        }
        /// <summary>
        /// The function used to create error string which contains multiple exceptions, when it reached to 20; 
        /// it writes all of them at one go
        /// </summary>
        /// <param name="msg">The message to be written as Exception</param>
        public void CreateErrorString(String msg)
        {
            //If 20 exceptions has not been occurred then append the exception to string
            if (intCount < 21)
            {
                intCount++;
                strError += DateTime.Now.ToString() + "==> " + msg + "\r\n";
            }
            //As soon as 20 exceptions occurred then write them to file and set the
            //counter again to 0
            else
            {
                CreateLogFiles obj = new CreateLogFiles();
                obj.ErrorLog("<Path>\\ErrorLog", strError);
                strError = "";
                intCount = 0;
            }
        }
    }
}

The above code contains two methods “public void ErrorLog(string sPathName, string sErrMsg)”, and “public void CreateErrorString(String msg)” . The first method should be used when there is low user load or number of occurrences of error is less and the second one is used when higher number of concurrent users is there.

Code Access Security

By code Access Security we mean to say restrict the access to system resources which our code may do, and the type of privileged operations that our code may do. These restrictions are independent of user who calls the code. For using the code access security we should consider the following guidelines:

  1. If our application only uses managed code then we can use the various trust levels to limit the exposure to security attacks. For that we can add the following line in our web.config file.
    <trust level="Full|High|Medium|Low|Minimal" />
  2. We should a trust level that does not exceed our application’s requirements. We can use the Permission calculator tool (Permcal.exe) provided by ASP.NET to calculate the required permissions for any code.
  3. We should use Medium Trust in shared networks.
  4. We can use health monitoring and auditing events of ASP.NET to check some sensitive code accessibility by various users. What it does, simply log the events whenever they access some resource or something restricted.

    Internally these events log the errors and warnings of web Application in Event Viewer.

  5. To use code access security we should follow following steps in the application:

    First we should identify the permissions that our application requires. We can do that by manually analyzing the permissions or use Permcal.exe tool. To see the required permissions for an assembly we should run following command from Visual Studio Command prompt:

Permcal –Show <assembly>

The output of above command is like this:

<assembly />
  <namespace name="ClassLibrary1" />
      <type name="Class1" />
       <method sig="instance void test()" /> 
       <method sig="instance void .ctor()">
         <demand />
          <permissionset class="System.Security.PermissionSet" version="1" />
           <ipermission class="System.Security.Permissions.RegistryPermission, mscorlib,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" read="true" />
           <ipermission class="System.Security.Permissions.FileIOPermission, mscorlib,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" unrestricted="true" /> 
         </permissionset />
       </demand />
       <sandbox />
        <permissionset class="System.Security.PermissionSet" version="1" />
         <ipermission class="System.Security.Permissions.RegistryPermission, mscorlib,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" read="true" />
         <ipermission class="System.Security.Permissions.FileIOPermission, mscorlib,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" unrestricted="true" /> 
       </permissionset />
      </sandbox />
    </method>
    </type />
  </namespace />
</assembly />

Examine the permissions listed in the <demand> element. After that try to evaluate the trust level that our application may require on the basis of following table .

Trust Level Key Capabilities and Restrictions
Full No restrictions imposed by code access security.
High No unmanaged code.
No enterprise services.
Can access Microsoft SQL Server and other OLE DB data sources.
Can send e-mail by using SMTP servers.
Very limited reflection permissions. No ability to invoke code by using reflection.
A broad set of other framework features are available. Applications have full access to the file system and to sockets.
Medium Permissions are limited to what the application can access within the directory structure of the application.
No file access is permitted outside of the application's virtual directory hierarchy.
Can access SQL Server.
Can send e-mail by using SMTP servers.
Limited rights to certain common environment variables.
No reflection permissions whatsoever.
No sockets permission.
To access Web resources, you must explicitly add endpoint URLs—either in the originUrl attribute of the <trust> element or inside the policy file.
Low Intended to model the concept of a read-only application with no network connectivity.
Read only access for file I/O within the application's virtual directory structure.
Minimal Execute only.
No ability to change the IPrincipal on a thread or on the HttpContext.

Configure the ASP.NET application for that particular trust level. Use the following node in web,config.

...
<system.web>
  ...
  <trust level="Medium" />
  ...
</system.web>
...

Exception Handling

Exception handling is also an important part of the security. ASP.NET provides us the functionality to handle all the unhandled exceptions at once. We can add an Global Application Error Handler in global.asax, and that will handle all the exceptions that are occurring in our application. I am writing an sample example for Global Error Handler, this should be added in the file global.asax.

void Application_Error(object sender, EventArgs e)
    {
        // Code that runs when an unhandled error occurs
        Exception ex = Server.GetLastError().GetBaseException();


        // log the details of the exception and page state to the
        // event log
CreateLogFiles Err = new CreateLogFiles();

        try
        {
            HttpException httpException = (HttpException)ex;
            httpCode = httpException.GetHttpCode();
        }
        catch
        {
        }
        finally
        {
            Err.ErrorLog("<path>\\ErrorLog", DateTime.Now.ToString() +
                " User : " + name[1].ToString() + " ==>" + Server.GetLastError().TargetSite.ToString()
                + " Error Status code : " + httpCode.ToString() + ex.Message);
            switch (httpCode)
            {
                case 500: Response.Redirect("../../../ErrorPages/InternalServerError.htm"); break;
                case 403: Response.Redirect("../../../ErrorPages/NoAccess.htm"); break;
                case 404: Response.Redirect("../../../ErrorPages/PageNotFound.htm"); break;
                default: Response.Redirect("../../../ErrorPages/ErrorStatus.htm"); break;
            }

        }
    }

CreateLogFiles is the same class as we added at the starting for logging the errors. Apart from that we can write separate exception handling codes for each function, or wherever it is required. We can add custom error node to web.config to redirect the users to some error page rather than displaying the error.

Communication Security

While using the sensitive data we should consider the following, we should use the SSL or IPSec. And also we should consider optimizing those pages which uses the SSL. For pages where you must use SSL, We should consider the followings:

  • We should make the page size as small as possible.
  • We should avoid using images or video contents on such pages.

Summary

This article helps the developer quickly review the security features for the ASP.NET web application. Developer can quickly implement security features for the web application, rather than going through the whole big books for Security features of ASP.NET.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here