Click to Rate and Give Feedback
MSDN
MSDN Library
Security
 ASP.NET 2.0 FAQs

  Switch on low bandwidth view
Prescriptive Architecture
ASP.NET 2.0 FAQs
 

Patterns and Practices home

J.D. Meier, Blaine Wastell, Prashant Bansode, Alex Mackman
Microsoft Corporation

November 2007

Applies To

  • ASP.NET 2.0

Contents

Authentication

Authorization

Auditing and Logging

Code Access Security

Impersonation/Delegation

Configuration

Exception Handling

Data Access

Input / Data Validation

Sensitive Data

Strong Naming and Signing

Obfuscation

Authentication

  • What’s new in ASP.NET in terms of authentication?
  • How do I decide my Authentication strategy in ASP.NET?
  • How do I use Forms Authentication with SQL Server database?
  • How do I use Forms Authentication with Active Directory?
  • How do I enable Forms Authentication to work with multiple Active Directory domains?
  • How do I protect Forms Authentication?
  • How do I enforce strong passwords using membership feature in ASP.NET 2.0?
  • How do I protect passwords in user store?
  • What are the issues with Forms Authentication in Web Farm Scenario?
  • How do I implement single sign on using forms authentication?
  • How do I use my custom user / identity store with forms authentication?
  • How do I configure account lockout using membership feature in ASP.Net 2.0?
  • When and how do I use windows authentication in ASP.NET 2.0?
  • When and how do I use Kerberos authentication in ASP.NET 2.0?

What's new in ASP.NET 2.0 in terms of Authentication?

ASP.NET 2.0 introduces a new feature called Membership, which provides a consistent and simple APIs for user storage and management and enables easy implementation of Forms Authentication.

The membership feature supports provider model, with the SqlMembershipProvider for SQL Server databases and ActiveDirectoryMembershipProvider for Active Directory and Active Directory Application Mode (ADAM) stores provided as built-in providers. The provider model is extensible and you can create custom providers for your custom user stores.

ASP.NET 2.0 provides built in Login controls like Login, LoginView, LoginName, CreateUserWizard, ChangePassword etc which by default work with Membership feature, making Forms Authentication implementation simpler.

Additionally you can use membership feature APIs like CreateUser, ValidateUser, etc for manual user management and authentication.

More Information

How do I decide my Authentication strategy in ASP.NET?

Use Windows authentication wherever you can because it provides secure credential management, password policies, and user account management tools.

If your application users have windows accounts, but you cannot use Windows authentication because of firewall issues, use forms authentication using ActiveDirectoryMembershipProvider membership provider.

If your user accounts are in a SQL Server database, use forms authentication using the SqlMembershipProvider membership provider.

If your user accounts are in ADAM, use forms authentication using the ActiveDirectoryMembershipProvider membership provider.

If your user accounts are in a store other than the previously listed stores, create a custom membership provider and configure forms authentication to use it.

More Information

How do I use Forms Authentication with SQL Server database?

Use the built-in SqlMembershipProvider of the new Membership feature in ASP.NET 2.0 along with login control for forms authentication with user store in SQL server database.

The membership feature provides a consistent and simple APIs for user authentication and user management. The login control by default, work with the Membership feature. This control reduces the custom code required to make Forms Authentication work.

For using forms authentication with a SQL Server database as the user store,

  • Install the user store database on the SQL Server using the aspnet_regsql.exe utility From a Visual Studio 2005 command prompt, run the following command
    aspnet_regsql -S (local) -E -A m
    • -S specifies the server, which is (local) in this example.
    • -E specifies to use Windows authentication to connect to SQL Server.
    • -A m specifies to add only the membership feature. For simple authentication against a SQL Server user store, only the membership feature is required.
  • Create a SQL Server login for your ASP.NET application's process identity (or impersonated identity if your application uses impersonation) and grant it the appropriate permissions in the membership database.
  • Configure your application for Forms Authentication in Web.Config file as follows
    <authentication mode="Forms">
  • Configure your application to deny access to unauthenticated users in Web.config file as follows
         <authorization>
           <deny users="?" />
         </authorization>
         
  • Configure a database connection string in connectionStrings section pointing to the membership database in SQL Server as follows
         <connectionStrings>
           <add name="MyLocalSQLServer"
                connectionString="Initial Catalog=aspnetdb;data source=localhost;Integrated
         Security=SSPI;" />
         </connectionStrings>
         
  • Configure the SqlMembershipProvider, using the connection string, configured. Ensure that the defaultProvider attribute is set to the provider configured as follows
         <membership
         defaultProvider="MySqlMembershipProvider" >
           <providers>
             <clear/>
             <add name="MySqlMembershipProvider"
                  connectionStringName="MyLocalSQLServer"
                  applicationName="MyAppName"
                  type="System.Web.Security.SqlMembershipProvider, System.Web,
         Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
         />
           </providers>
         </membership>
         
  • Configure password complexity rules if you need to override the defaults, which ensure a minimum length of 7 characters with one of them being non-alphanumeric.
  • Use the Login and CreateUserWizard controls for creating login page (login.aspx) for forms authentication.
  • Encrypt the connectionStrings configuration section using protected configuration feature.

More Information

How do I use Forms Authentication with Active Directory?

Use the built-in ActiveDirectoryMembershipProvider of the new Membership feature in ASP.NET 2.0 along with login control for forms authentication with Active Directory.

The membership feature provides a consistent and simple APIs for user authentication and user management. The login control by default, work with the Membership feature. This control reduces the custom code required to make Forms Authentication work.

For using forms authentication with Active Directory as the user store,

  • Configure your application for Forms Authentication in Web.Config file as follows
    <authentication mode="Forms">
  • Configure your application to deny access to unauthenticated users in Web.config file as follows
         <authorization>
           <deny users="?"/>
         </authorization>
         
  • Configure a LDAP connection string in connectionStrings section pointing to the Active Directory to be used in Web.config file as follows.
         <connectionStrings>
           <add name="ADConnectionString"
         connectionString="LDAP://testdomain.test.com/CN=Users,DC=testdomain,DC=test,DC=com"
         />
         </connectionStrings>
         
  • Configure the ActiveDirectoryMembershipProvider in the web.config file specifying at least the connection string name and optionally the credentials, using connectionUserName and connectionPassword attributes, of an account capable of accessing Active Directory with the necessary permissions. If you do not specify account credentials, your application's process identity is used to access Active Directory, regardless of whether your application uses impersonation. Either the account specified in the Web.config file or your process account must have the appropriate permissions to access Active Directory.
  • Ensure that the defaultProvider attribute is set to the provider configured.
         <membership defaultProvider="MyADMembershipProvider">
           <providers>
             <add
                name="MyADMembershipProvider"
                type="System.Web.Security.ActiveDirectoryMembershipProvider,
         System.Web, Version=2.0.0.0, 
                      Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                connectionStringName="ADConnectionString"
                connectionUsername="testdomain\administrator"
                connectionPassword="password"/>
           </providers>
          </membership>
          
  • Use the Login control for creating login page (login.aspx) for forms authentication.
  • Encrypt the connectionStrings section using the protected configuration feature. Also if you specify user credentials in the ActiveDirectoryMembershipProvider configuration encrypt the membership configuration section as well.

More Information

How do I enable forms authentication to work with multiple Active Directory domains?

Configure ActiveDirectoryMembershipProvider for each domain. Create a custom login form using TextBox server control to get user credentials and domain information. Depending upon the domain information, use the domain specific ActiveDirectoryMembershipProvider instance for manually authenticating the user.

The Membership feature by default works with a single domain only (configured as defaultProvider). Also you cannot use the login controls in a multiple domain scenario, as they work with only the default membership provider configured. Hence you need to use custom login form using TextBox server control.

Here is how to get the forms authentication working with multiple domains.

  • Configure your application for Forms Authentication in Web.Config file as follows
    <authentication mode="Forms">
  • Configure your application to deny access to unauthenticated users in Web.config file as follows
         <authorization>
            <deny users="?"/>
         </authorization>
         
  • Configure connections strings for multiple domains, corresponding one for each in Web.config file as follows.
         <connectionStrings>
           <add name="TestDomain1ConnectionString"
         connectionString="LDAP://testdomain1.test.com/CN=Users,DC=testdomain1,DC=test,DC=com"
         />
           <add name="TestDomain2ConnectionString"
         connectionString="LDAP://testdomain2.test.com/CN=Users,DC=testdomain2,DC=test,DC=com"
         />
           <add name="TestDomain3ConnectionString"
         connectionString="LDAP://testdomain3.test.com/CN=Users,DC=testdomain3,DC=test,DC=com"
         />
         </connectionStrings>
         
  • Configure one ActiveDirectoryMembershipProvider for each domain in the web.config file specifying at least the connection string name and optionally the credentials, using connectionUserName and connectionPassword attributes, of an account capable of accessing Active Directory with the necessary permissions in that domain. If you do not specify account credentials, your application's process identity is used to access Active Directory, regardless of whether your application uses impersonation. Either the account specified in the Web.config file or your process account must have the appropriate permissions to access Active Directory in that domain.
  • Ensure that the defaultProvider attribute is set to the domain provider which you are going to use as default domain (if any).
         <membership>
           <providers>
             <add
               name="TestDomain1ADMembershipProvider"
               type="System.Web.Security.ActiveDirectoryMembershipProvider,
         System.Web, Version=2.0.0.0, 
                     Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
               connectionStringName="TestDomain1ConnectionString"
               connectionUsername="testdomain1\administrator"
               connectionPassword="password"/>
             <add
               name="TestDomain2ADMembershipProvider"
               type="System.Web.Security.ActiveDirectoryMembershipProvider,
         System.Web, Version=2.0.0.0, 
                     Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
               connectionStringName="TestDomain2ConnectionString"  
               connectionUsername="testdomain2\administrator" 
               connectionPassword="password"/>
               <add
                 name="TestDomain3ADMembershipProvider"
                 type="System.Web.Security.ActiveDirectoryMembershipProvider,
         System.Web, Version=2.0.0.0, 
                     Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                 connectionStringName="TestDomain3ConnectionString"
                 connectionUsername="testdomain3\administrator" 
                 connectionPassword="password"/>
           </providers>
         </membership>
         
  • On the login page (login.aspx) instead of using login control provided by ASP.NET 2.0, use TextBox server control to get information about the domain, user and password. Depending upon the domain information get the instance of specific provider and use Membership APIs for validating / authenticating the user as follows.
         // Get the specific provider
         MembershipProvider domainProvider =
         Membership.Providers["TestDomain1ADMembershipProvider"];
         // validate the user
         Bool IsValidate = domainProvider.ValidateUser(
                      UserNameTextBox.Text, PasswordTextBox.Text);
         
  • Encrypt the connectionStrings section using the protected configuration feature. Also if you specify user credentials in the ActiveDirectoryMembershipProvider configuration encrypt the membership configuration section as well.

More Information

How do I protect Forms Authentication?

For protecting forms authentication you need to encrypt and integrity check the authentication ticket, use SSL to protect user credentials and authentication ticket over wire, do not persist authentication cookie at client side, enforce strong passwords, use non-reversible password hashes with salt and protect your user store.   

Protecting authentication tickets helps to avoid unauthorized spoofing and impersonation, session hijacking, and elevation of privilege.

Strong passwords help in defending against brute force attacks, and password stored as hashes with salt further slows down dictionary attacks hence giving time for countermeasure to react.

Here is how you protect forms authentication

  • Ensure that your forms authentication tickets are encrypted and integrity checked by setting protection="All".
  • Use Secure Sockets Layer (SSL) to protect the forms authentication credentials and the forms authentication cookie passed from browser to server by setting requireSSL="true".
  • If you cannot use SSL, consider reducing the cookie lifetime by reducing the timeout value to minimize the time window within which an attacker can use a captured authentication cookie to access your site.
  • If you are in a scenario where you are concerned about cookie hijacking, consider reducing the timeout and setting slidingExpiration="false".
  • Use unique name and path attribute values on the <forms> element.
  • Here is sample of secure forms authentication configuration
         <forms loginUrl="Restricted\login.aspx"
                  protection="All"
                  requireSSL="true"
                  timeout="10"
                  name="AppNameCookie"
                  path="/FormsAuth"
                  slidingExpiration="true" >
         </forms>
         
  • Do not persist authentication cookie on the client computer, and do not use it for personalization purposes.
  • Enforce strong passwords and store it as non-reversible password hashes.
  • When using SQL Server database as user store, protect your authentication login form against SQL injection attacks by validating and constraining input credentials, and by using parameterized stored procedures while accessing the user store.
  • Protect the connection string that point to your user store for example by encrypting the connectionStrings section in your Web.config file.
  • Protect access to the user store by granting appropriate access to only the accounts that require it. Additionally store should be residing on physically separate server.

More Information

How do I enforce strong passwords using membership feature in ASP.NET 2.0?

You can enforce strong passwords using membership by configuring the attributes minRequiredPasswordLength, minRequiredNonAlphanumericCharacters, and passwordStrengthRegularExpression on your membership provider configuration.

Strong passwords help in defending against brute force attacks and dictionary attacks.

The default password strength is set to a minimum password length of 7 characters with at least 1 non-alphanumeric character for both SqlMembershipProvider and ActiveDirectoryMembershipProvider.

If you are using the ActiveDirectoryMembershipProvider with Active Directory, your domain password policy is used by default, although you can further strengthen password policy by overriding this with your membership configuration by using the attributes listed earlier. Similarly, if you are using ActiveDirectoryMembershipProvider with ADAM, your local password policy is used, although you can override this with your membership configuration.

Here is how you configure membership provider for enforcing strong password.

Using regular expression

<membership ...>
  <providers>
    <add passwordStrengthRegularExpression= 
                    "^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$" .../>
  </providers>
</membership>

Using minimum length and non-alphanumeric character

<membership ...>
  <providers>
    <add minRequiredPasswordLength=10 minRequiredNonalphanumericCharacters=2 .../>
  </providers>
</membership>

More Information

How do I protect passwords in user store?

For protecting password in user store, you should not store user passwords either in plaintext or encrypted format instead, store password hashes with salt. Ensure only required accounts have the access to user store database. Store your credential database on a physically separate server.

By storing your password with hashes and salt, you help prevent an attacker who has compromised your user store from obtaining the user passwords and also it slows down an attacker who is attempting to perform a dictionary attack. This gives you additional time to detect and react to the compromise

By giving access only to required accounts it limits access to your credentials store, hence less chances of attacker compromising it.

By locating the credentials store database on a separate physical server makes it harder for an attacker to compromise your credential store even if he or she manages to take control of your Web server.

Use one of the membership providers that ensure secure credential storage and where possible, specify a hashed password format on your provider configuration.

If you must implement your own user stores, store one-way password hashes with salt. Generate the hash from a combination of the password and a random salt value. Use an algorithm such as SHA256.

More Information

What are the issues with Forms Authentication in a Web Farm Scenario?

In a web farm scenario you cannot guarantee which server will handle successive requests. With default settings of each server, if user is authenticated on one server and the next request goes to another server the authentication ticket will fail the validation and force user to re-authenticate.

The validationKey and decryptionKey in <machineKey> section is used for hashing and encryption of the form’s authentication ticket. The default value of this keys is “AutoGenerate,IsolateApps”, i.e. the keys are auto generated for each application and they will be different on each server. Hence authentication tickets encrypted and tamper proofed on one machine cannot be decrypted and integrity checked on another machine in web farm.

To address this issue, validationKey and decryptionKey must be identical on all machines

For this you must manually generate validationKey and decryptionKey and copy the key values to all machines in the web farm. Additionally you must ensure that the name and path attributes in the <forms> element in configuration files on each server share the same value.

If you deploy multiple applications in the web farm, ensure that you use separate validationKey and decryptionKey values and name and path attribute values in <forms> element for each application, but duplicate each application's validationKey and decryptionKey values and name and path attribute values in <forms> element across all servers in the farm.

To generate cryptographically random keys, use the '''RNGCryptoServiceProvider''' class to generate a cryptographically strong random number. The key must be a minimum of 40 hexadecimal characters (20 bytes) and a maximum of 256 hexadecimal characters (64 bytes) long.

using System;
using System.Text;
using System.Security;
using System.Security.Cryptography;
class App
{
 static void Main(string[] argv) 
 {
    int len = 128;
    if (argv.Length > 0)
        len = int.Parse(argv[0]);
    byte[] buff = new byte[len/2];
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    rng.GetBytes(buff);
    StringBuilder sb = new StringBuilder(len);
    for (int i=0; i<buff.Length; i++)
          sb.Append(string.Format("{0:X2}", buff[i]));
    Console.WriteLine(sb);
   }
}

Use the keys generated thus to configure in machine key settings in machine.config / Web.config file as follows. Use separate keys for validationKey and decryptpionKey. Here is the sample configuration.

<machineKey validationKey="Hsbfb636576sahfj\mfhhshnj234235"  
            decryptionKey="shakh7857jkjjco985\fhhegf476343" 
            validation="SHA1" decryption="Auto" />

More Information

How do I implement single sign on using forms authentication?

If you need a single sign on to work across multiple applications located in separate virtual directories, you need to share a common authentication ticket which can be decrypted and integrity checked by every application.

For this you must manually generate validationKey and decryptionKey values and set these values on the <machineKey> element in the machine level config file. Additionally you must ensure that the name and path attributes in the <forms> element is same for each application.

To generate cryptographically random keys, use the '''RNGCryptoServiceProvider''' class to generate a cryptographically strong random number. The key must be a minimum of 40 hexadecimal characters (20 bytes) and a maximum of 256 hexadecimal characters (64 bytes) long.

using System;
using System.Text;
using System.Security;
using System.Security.Cryptography;
class App
{
 static void Main(string[] argv) 
 {
    int len = 128;
    if (argv.Length > 0)
        len = int.Parse(argv[0]);
    byte[] buff = new byte[len/2];
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    rng.GetBytes(buff);
    StringBuilder sb = new StringBuilder(len);
    for (int i=0; i<buff.Length; i++)
          sb.Append(string.Format("{0:X2}", buff[i]));
    Console.WriteLine(sb);
   }
}

Use the keys generated thus to configure in machine key settings in machine.config / web.config file as follows. Use separate keys for validationKey and decryptpionKey. Here is the sample configuration

<machineKey validationKey="Hsbfb636576sahfj\mfhhshnj234235"  
            decryptionKey="shakh7857jkjjco985\fhhegf476343" 
            validation="SHA1" decryption="Auto" />

More Information

How do I use my custom user / identity store with forms authentication?

Implement a custom membership provider inheriting from MembershipProvider abstract base class which works with the custom user/identity store. Use this custom provider along with login control for forms authentication with custom user/identity store.

The membership feature provides a consistent and simple APIs for user authentication and user management. The login control by default, work with the Membership feature. This control reduces the custom code required to make Forms Authentication work.

Here is how you can use custom user / identify store with forms authentication.

  • Implement a custom membership provider that inherits from the MembershipProvider abstract base class. This custom provider class should interact with your custom user / identity store.
  • Configure connection string for your provider (if required) in connectionStrings section
  • Configure the custom provider in your application’s Web.config file and set the defaultProvider as your custom provider as follows
         <membership defaultProvider="MyCustomMembershipProvider" >
           <providers>
             <clear/>
             <add name="MyCustomMembershipProvider"
                  applicationName="MyAppName"
                  type="CustomMembershipProvider, CustomDll, Version=1.0.0.0,
         Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
           </providers>
         </membership>
         
  • Configure your application for Forms Authentication in Web.Config file as follows
    <authentication mode="Forms">
  • Configure your application to deny access to unauthenticated users in Web.config file as follows
         <authorization>
           <deny users="?" />
         </authorization>
         
  • Use the Login and CreateUserWizard controls for creating login page (login.aspx) for forms authentication.

More Information

How do I configure account lockout using membership feature in ASP.NET 2.0?

If you are using the SqlMembershipProvider or ActiveDirectoryMembershipProvider, you use the maxInvalidPasswordAttempts and passwordAttemptWindows attributes on the provider configuration. By default, these values are 5 and 10, respectively. This means you get 5 invalid attempts within 10 minutes before you are locked out.

If you are using the ActiveDirectoryMembershipProvider, your domain or local security policy controls the password lockout. Note that if an account is locked out by the provider, it is not locked out within Active Directory, so you could still log on to Windows with the account. However, the ActiveDirectoryMembershipProvider treats the account as locked out, so the user cannot logon through an application that uses the provider until the lockout duration elapses. Accounts locked out by the provider are re-enabled after a time interval defined by the attributeMapFailedPasswordAnswerLockoutTime attribute, default is 30 minutes. Alternatively, you can write code that calls the UnlockUser method on the MembershipUser object.

Here is how you configure account lockout settings

<membership defaultProvider=NewProvider>
    <providers>
      <add name=NewProvider maxInvalidPasswordAttempts=3 and passwordAttemptWindows=10 …/>
    <providers>
</membership>

More Information

When and how do I use windows authentication in ASP.NET 2.0?

Your ASP.NET application should use windows authentication when your users have windows accounts that can be authenticated by a server. The accounts can be local windows accounts or domain accounts.

For using Windows Authentication in ASP.NET in conjunction with Integrated Windows authentication on IIS

  • Configure the virtual directory on IIS to disable anonymous access and configure to use Integrated Windows authentication alone (by default anonymous access is enabled).
  • Configure your applications Web.config for windows authentication which is the default setting in Web.config file as follows
    <authentication mode="Windows">

More Information

When and how do I use Kerberos authentication in ASP.NET 2.0?

If all your computers are in a Windows Server 2000 or later domain and your clients are using Internet Explorer version 5.5 or later, you can use Kerberos authentication in ASP.NET.

For using Kerberos Authentication in ASP.NET

  • Configure the virtual directory on IIS to disable anonymous access and configure to use Integrated Windows authentication alone (by default anonymous access is enabled).
  • Configure your applications web.config for windows authentication which is the default setting in web.config file as follows
    <authentication mode="Windows">

If you run your application using a domain service account, you must register a service principal name (SPN) for that account in Active Directory to associate the account with the HTTP service on the Web server. To register an SPN, use the Setspn.exe utility as follows:

setspn -A HTTP/webservername domain\customAccountName
setspn -A HTTP/webservername.fullyqualifieddomainname domain\customAccountName 

Note that you cannot have multiple Web applications with the same host name if you want them to have multiple identities and to use Kerberos authentication. This is an HTTP limitation, not a Kerberos limitation. The workaround is to have multiple Domain Name System (DNS) names for the same host, and start the URLs for each Web application with a different DNS name. For example, you would use http://app1 and http://app2 instead of http://site/app1 and http://site/app2.

Note: If your clients run Internet Explorer 6, you must enable the browser to respond to a negotiate challenge and perform Kerberos authentication. To do this, select the Enable Integrated Windows Authentication check box in the Security section of the Advanced tab of the Internet Options menu, and then restart the browser. Administrators can enable Integrated Windows authentication by setting the EnableNegotiate DWORD value to 1 in the following registry key: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings

Authorization

  • What's new in ASP.NET 2.0 in terms of Authorization?
  • What's the difference between URL Authorization, File Authorization and Role Authorization?
  • How do I use URL Authorization in ASP.NET 2.0?
  • How do I use File Authorization in ASP.NET 2.0?
  • How do I use Role Authorization in ASP.NET 2.0?
  • How is the AuthorizationStoreRoleProvider different from Authorization Manager APIs?
  • How do I use Windows Groups for role authorization in ASP.NET 2.0?
  • How do I use my custom role store for roles authorization?
  • How do I cache roles in ASP.NET 2.0?
  • How do I protect authorization cookie when using role caching in ASP.NET 2.0?
  • How do I lock authorization settings?

What's new in ASP.NET 2.0 in terms of Authorization?

ASP.NET 2.0 introduces a new feature called Role Manager, which enables easy implementation of Roles Authorization in ASP.NET 2.0.

The Role Manager feature supports provider model with the WindowsTokenRoleProvider for Windows groups in AD, SqlRoleProvider for role store in SQL Server database and AuthorizationStoreRoleProvider for AzMan policy role store in Active Directory, Active Directory Application Mode (ADAM) and XML provided as built-in providers. The provider model is extensible and you can create custom providers for your custom role stores.

The Role Manager feature provides APIs like CreateRole, AddUserToRole, IsUserInRole etc for roles management and roles authorization.

Additionally ASP.NET 2.0 role manager provides roles caching feature, which caches roles read from the roles store for a user and reuses them on subsequent roles checks, thus improving the performance.

The Role Manager is not enabled by default. Therefore, before you can use the Role manager you need to explicitly enable it in your application's web.config

More Information

What's the difference between URL Authorization, File Authorization and Role Authorization?

  • URL Authorization is configured by settings within machine and application configuration files. It allows you to restrict access to specific files and folders within your application's Uniform Resource Identifier (URI) namespace. For example, you can selectively deny or allow access to specific files or folders (addressed by means of a URL) to nominated users. You can also restrict access based on the user's role membership or User's Identity. URL Authorization requires an authenticated identity. This can be obtained by a Windows or ticket-based authentication scheme. Important: When using roles in URL authorization, the role manager should be enabled and configured for using correct role store.
  • File Authorization applies only if you use one of the IIS-supplied Windows authentication mechanisms to authenticate callers and ASP.NET is configured for Windows authentication. For file types mapped by IIS to the ASP.NET ISAPI extension (Aspnet_isapi.dll), automatic access checks are performed using the authenticated user's Windows access token (which may be IUSR_MACHINE for anonymous users) against the access control list (ACL) attached to the requested ASP.NET file.
  • Roles authorization can be used for fine grained authorization to control access to resources and operations and they can be configured both declaratively and programmatically. .NET Framework 2.0 provides a new Role Manager feature for role based authorization.

How do I use URL Authorization in ASP.NET 2.0?

Configure URL authorization, use an <authorization> element in Web.config and specify which user and/or role names are allowed access to the current directory or the nominated directory or file.

URL authorization allows you to restrict access to specific files and folders within your application's Uniform Resource Identifier (URI) namespace using the authenticated user's name or user's role membership held in the HttpContext.User object. ASP.NET version 2.0 on Windows Server 2003 protects all files in a given directory, even those not mapped to ASP.NET, such as .html, .gif, and .jpg files.

This can be done by configuring the <authorization> element in Web.config as follows. Authorization settings in Web.config refer to all of the files in the current directory and all subdirectories unless a subdirectory contains its own Web.config with an <authorization> element. In this case, the settings in the subdirectory override the parent directory settings

<system.web>
….
<authorization>
  <allow users="userName1, userName2" />
  <allow roles="roleName1, roleName2" />
  <deny users="*" />
</authorization>
….
</system.web>

Important: When using roles in URL authorization, the role manager should be enabled and configured for using correct role store.

Note: URL authorization can be used for both forms authentication and Windows authentication. In the case of Windows authentication, user names take the form "DomainName\WindowsUserName" and role names take the form "DomainName\WindowsGroupName". The local administrators group is referred to as "BUILTIN\Administrators". The local users group is referred to as "BUILTIN\Users". The following example shows Windows users and Windows roles.

How do I use File Authorization in ASP.NET 2.0?

Configure the access control lists (ACLs) for the right identities to have appropriate permissions on your ASP.NET files. The FileAuthorizationModule automatically performs access checks against the requested file.

The identities that you need to consider for file authorization:

  • Your Web application identity. If you are using a custom service account to run your ASP.NET application, you can grant the appropriate permissions to the IIS metabase and to the file system by running Aspnet_regiis.exe with the–ga switch.
  • Your application's users. ASP.NET file authorization performs access checks for file types mapped by IIS to the ASP.NET ISAPI extension (Aspnet_isapi.dll). If you are using Windows authentication, the authenticated user's Windows access token (which may be IUSR_MACHINE for anonymous users) is checked against the ACL attached to the requested ASP.NET file. If you are using forms authentication, access is checked against IUSR_MACHINE.

Note: File Authorization works automatically when using Windows Authentication; Impersonation is not required.

How do I use Role Authorization in ASP.NET 2.0?

Use Role manager feature with built-in providers introduced in ASP.NET 2.0 for role authorization. You can do role authorization in code by performing explicit role checks using Role Manager APIs like IsUserInRole etc.

The Role Manager feature provides a consistent and simple APIs for role authorization and role management. And it supports built-in providers like WindowsTokenRoleProvider for Windows groups as roles, SqlRoleProvider for roles store in SQL Server database and AuthorizationStoreRoleProvider for AzMan policy roles store in Active Directory, Active Directory Application Mode (ADAM) or XML.

For using role authorization do the following

  • Decide on the role provider to be used depending upon the role store.
  • Enable Role Manager in web.config file, by setting the enabled attribute to true as follows
         <system.web>
             <roleManager enabled="true" />
         </system.web>
         
  • Add a connection string to the <connectionStrings> section to point to your roles store. If you are using the AuthorizationStoreRoleProvider, this is an LDAP query string pointing to your Authorization Manager Policy store in Active Directory or ADAM. If you are using the SqlRoleProvider, this is a database connection string that points to your role store database.
  • Configure the role provider and make sure the defaultProvider is set correctly to point to the configured role provider. Here is sample for SqlRoleProvider
         <configuration>
           <connectionStrings>
             <add name="SqlRoleManagerConnection" 
                  connectionString="Data Source=sqlinstance;
                                   Initial Catalog=aspnetdb;Integrated
         Security=SSPI;">
             </add>
           </connectionStrings>
         </configuration>
         <roleManager enabled="true"
         defaultProvider="SqlRoleManager">
           <providers>
             <add name="SqlRoleManager" 
                  type="System.Web.Security.SqlRoleProvider"
                  connectionStringName="SqlRoleManagerConnection"
                  applicationName="MyApplication" />
           </providers>
         </roleManager>
         
  • Use Role Manager APIs for accessing and validating the role membership for the user. By default it uses the HttpContext.User object for user identity.
    bool isInRole
         = Roles.IsUserInRole("TestRole");
  • You can also do Role Authorization using PrincipalPermission demands

More Information

How is the AuthorizationStoreRoleProvider different from Authorization Manager APIs?

AuthorizationStoreRoleProvider only exposes a subset of Authorization Manager's functionality. For example, you cannot use Authorization Manager's authorization business logic, such as tasks and operations.

You can use AuthorizationStoreRoleProvider only for role membership checks.  The benefit of using AuthorizationStoreRoleProvider is that it gives a consistent APIs for role authorization, hence at development time any role store can be used and then in production it can be deployed on AzMan policy store without affecting the code. 

If you have to use business logic of Authorization manager you will need to use the Authorization Manager APIs directly

More Information

How do I use Windows Groups for role authorization in ASP.NET 2.0?

If you use Windows authentication, you can use the ASP.NET 2.0 Role Manager feature with the WindowsTokenRoleProvider for role-based authorization using Windows Groups.

Enable role manager by setting the enabled attribute on the <roleManager> element to true. Note that the Machine.config file contains a default configuration for a WindowsTokenRoleProvider instance named AspNetWindowsTokenRoleProvider. You can use this provider instance and set it as the default provider by modifying your Web.config file as follows.

<system.web>
    <roleManager enabled="true" 
        defaultProvider="AspNetWindowsTokenRoleProvider" />
</system.web>  

To check role membership to authorize callers, use the Role Manager APIs such as IsUserInRole.

if(Roles.IsUserInRole("Readers")){};  

More Information

How do I use my custom role store for roles authorization?

Implement a custom roles provider inheriting from RoleProvider abstract base class which works with the custom role store. Use this custom provider along with Role Manager APIs for roles authorization using your custom role store.

The role manager feature provides a consistent and simple APIs for role authorization and role management.

Here is how you can use custom role store for roles authorization.

  • Implement a custom membership provider that inherits from the RoleProvider abstract base class. This custom provider class should interact with your custom role store.
  • Configure connection string for your provider (if required) in connectionStrings section
  • Configure the custom provider in your application’s Web.config file, enable role manager and set the defaultProvider as your custom provider as follows
         <roleManager
         enabled=true defaultProvider="MyCustomMembershipProvider" >
           <providers>
             <add name="MyCustomMembershipProvider"
                  applicationName="MyAppName"
                  type="CustomRoleProvider, CustomDll, Version=1.0.0.0,
         Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
           </providers>
         </membership>
         
  • Use Role Manager APIs for accessing and validating the role membership for the user. By default it uses the HttpContext.User object for user identity.
    bool isInRole = Roles.IsUserInRole("TestRole");

More Information

How do I cache roles in ASP.NET 2.0?

If a user's browser accepts cookies, you can cache role information for that user in a cookie. For this set the cacheRolesInCookie attribute to true on <roleManager> element. On each page request, ASP.NET reads the role information for that user from the cookie.

Role caching can improve application performance by reducing the amount of communication required with the data source to retrieve role information. If the role information for a user is too long to store in a cookie, ASP.NET stores only the most recently used role information in the cookie and then looks up additional role information in the data source as and when required.

To configure and enable role caching, set cacheRoleInCookie to true on the <roleManager> element as shown here.

<roleManager enabled="true"
        cacheRolesInCookie="true" .../>

Note: When using role caching its important to protect the authorization cookie.

More Information

How do I protect authorization cookie when using role caching in ASP.NET 2.0?

For protecting authorization cookie you need to encrypt and integrity check the authorization cookie, use SSL to protect authorization cookie over wire, do not persist authorization cookie client side

When using role caching securing the roles cookie is of prime importance. This is to stop users modifying the list of roles to which they belong, and to stop intruders from gaining information about the roles used by your application

  • Ensure the cookie is encrypted and integrity checked by setting the cookieProtection attribute to All.
  • Ensure that the authorization cookie is only transmitted over HTTPS connections by setting cookieRequireSSL to true.
  • Ensure that the Roles cookie is not persisted on client computer by setting createPersistentCookie to false.
  • If you cannot use SSL, consider reducing the cookie lifetime by reducing the cookieTimeout value to minimize the time window within which an attacker can use a captured roles cookie to access your site with privileged rights.
  • If you are in a scenario where you are concerned about cookie hijacking, consider reducing the timeout and setting slidingExpiration="false".

Here is a sample of secured role caching

<roleManager enabled="true"
             cacheRolesInCookie="true"
             cookieName=".ASPROLES"
             cookieTimeout="30"
             cookiePath="/"
             cookieRequireSSL="true"
             cookieSlidingExpiration="true"
             cookieProtection="All" 
             createPersistentCookie="false">
</roleManager>

More Information

How do I lock authorization settings?

Server administrators can lock authorization settings by using the <authorization> element in the machine-level Web.config file. This ensures that an individual application cannot override machine-level policy. To lock authorization settings, surround the <authorization> element inside a <location> element and set allowOverride="false" as shown here.

<location allowOverride="false">
  <system.web>
     <authorization>
        <deny users="?" />
       <allow users="*" />
     </authorization>
  </system.web>
</location>

Auditing and Logging

  • What's new in ASP.NET 2.0 in terms of Auditing and Logging?
  • How do I use the Health Monitoring feature in ASP.NET 2.0?
  • What all security events do health monitoring feature logs by default?
  • How do I instrument my application for security?
  • When writing to a new event source from my ASP.NET application running under the Network service security context, I get registry permission exception. Why is this and how do I correct this?
  • How do I protect audit and log files?

What's new in ASP.NET 2.0 in terms of Auditing and Logging?

ASP.NET version 2.0 introduces the health monitoring system. It supports many standard events that you can use to monitor the health of your application. Examples of security related events include logon failures when using the ASP.NET membership system, attempts to tamper with or reuse forms authentication tickets, and infrastructure events such as disk access failures etc.

By default, all Web error and Audit failure events are logged to the windows event log. Health monitoring uses event providers to deliver event notifications. The following event providers are available out of box:

  • SimpleMailWebEventProvider. This provider sends e-mail for event notifications.
  • TemplatedMailWebEventProvider. This provider uses templates to define and format e-mail messages sent for event notifications.
  • SqlWebEventProvider. This provider logs event details to a SQL Server database. If you use this provider, you should encrypt the connection string in your Web.config file by using the Aspnet_regiis.exe tool.
  • EventLogWebEventProvider. This provider logs events to the Windows application event log.
  • TraceWebEventProvider. This provider logs events as ASP.NET trace messages.
  • WmiWebEventProvider. This provider maps ASP.NET health monitoring events to Windows Management Instrumentation (WMI) events.

In addition you can also create custom event providers to write events to custom stores by creating a class that inherits from System.Web.Management.WebEventProvider.

You can also create custom events to instrument your application for other security and non-security related notable events and log them using Health Monitoring feature.

More Information

How do I use the Health monitoring feature in ASP.NET 2.0?

You can use the health monitoring feature introduced in ASP.NET version 2.0 to instrument key application events. You can choose where to log events by configuring an appropriate provider. You can instrument built-in events or create custom events by deriving from one of the provided base events to monitor specific business logic or operations in your Web application.

By default health monitoring is enabled for ASP.NET applications and it logs all Web Error and Audit failure events to Windows Event log.

Here is how you use Health Monitoring feature

  • Identify all the security related events that you need to log for your application, including the default events available with health monitoring and custom security events specific to your application.
  • Configure event mappings for all the identified events in the web.config file as follows; here Membership Authentication Success event is mapped.
         <healthMonitoring
         enabled=”true”>
         ….
           <eventMappings>
                 <add name="LoginAudit" 
                     type="System.Web.Management.
         AuditMembershipAuthenticationSuccess, System.Web, Version=2.0.0.0, 
         Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                     startEventCode="0"
         endEventCode="2147483647" />
             </eventMappings>
         ….
         </healthMonitoring>
         
  • Identify the event store where you want to log the security events, you can choose multiple event stores for logging events based on event criticality etc.
  • Configure event providers corresponding to event store identified in web.config file as follows, here windows event log is used as event store
         <healthMonitoring
         enabled=”true”>
         ….
             <providers>
                 <add name="EventLogProvider"
                     type="System.Web.Management.EventLogWebEventProvider, System.Web,Version=2.0.0.0,
         Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
             </providers>
         ….
         </healthMonitoring>
         
  • Configure <rules> to specify as to which security event is to be logged through which provider (event store).
         <healthMonitoring
         enabled=”true”>
         ….
             <rules>
                 <add provider="EventLogProvider" name="Login
         Audits" eventName="LoginAudit" />
             </rules>
         ….
         </healthMonitoring>
         

Now when ever a membership authentication in your application is successful an event is raised by membership feature, which will be logged to Windows Event log automatically.

More Information

What all security events do health monitoring feature logs by default?

By default, health monitoring audits the most critical security events which are those of types WebErrorEvent and WebFailureAuditEvent (including its descendants, WebAuthenticationFailureAuditEvent and WebViewStateFailureAuditEvent). These events and are logged to the Windows Event log.

WebAuthenticationFailureAuditEvent is logged for Forms based authentication failures, Membership Authentication failures because of invalid user credentials, passing of expired authentication ticket and passing of invalid authentication ticket. This can be used for identifying dictionary attacks, brute force attacks etc.

WebViewStateFailureAuditEvent is logged for invalid view state failures. This can be used for identifying ViewState tampering.

WebFailureAuditEvent is logged for authorization failures for accessing files, folders, or any other resources to which users don’t have access. This can be used identifying attacks on the application.

WebErrorEvent is logged for any error occurred during application compilation and execution including configuration errors. This can be used to identify any changes made by an attacker to the application.

More Information

How do I instrument my application for security?

To instrument your application for security, understand the security critical events logged by default. Analyze the standard available security events which are not logged by default, if you need to log them. Additionally create custom event to instrument application specific security events.

Tracking of security related events is very important for deducing any attack on the application and to retrace in case an application is compromised.

 

To instrument your application for security is three step process.

  • Identify all the events that are logged by default, the ASP.NET health monitoring system is configured to report all security-related error events (WebFailureAuditEvent and its descendants), and all infrastructure-related error events, to the Windows event log (WebBaseErrorEvent and its descendants). It monitors all the Forms Authentication, Authorization, ViewState failure events and also monitors application error events.
  • There are number of important security events that are available with health monitoring by default, but not logged. These events can be used to detect potential attacks on your application. Review the events and identify the ones which your application needs to monitor. Here you have Life time events, Forms Authentication Success events, Authorization Success events and Web heart beat events.
  • In addition to standard events you need to monitor other important security events specific to your application. These events can improve your ability to detect and understand attacks on your application. You can create custom events to monitor more authorization specific event, session management events, user management events, and any application specific critical operations monitoring events.

More Information

When writing to a new event source from my ASP.NET application running under the Network service security context, I get registry permission exception. Why is this and how do I correct this?

On Windows Server 2003, ASP.NET runs by default using the Network Service account. This account has the required privileges to write to any existing event source in the Application event log, but not to create a new event source. The first time your application tries to write to the event log, it checks to see if an event source for your application (typically the application name) already exists. If not, it tries to create it. To create an event source, your ASP.NET account needs permissions to create a new registry entry beneath the following key: HKLM\SYSTEM\CurrentControlSet\Services\Eventlog\.

To enable your ASP.NET application to write to the event log using new event source, you have two options:

  • Grant your ASP.NET process account (or impersonated identity if your application uses impersonation) permissions on the following registry key: HKLM\SYSTEM\CurrentControlSet\Services\Eventlog\.
  • Create the event source at application install time when administrator privileges are available. You can use a .NET installer class, which can be instantiated by the Windows Installer (if you are using .msi deployment) or by the InstallUtil.exe system utility.

Note: When you use the event log provider with ASP.NET health monitoring, events are logged by using an event source named "ASP.NET <<.Net Version Number>>". This event source is created when you install the .NET Framework. This is not configurable and you cannot change the event source used by health monitoring events.

More Information

How do I protect audit and log files?

Secure audit and log files using Windows ACLs and restrict access to the log files. If you log events to SQL Server or to some custom event sink, use appropriate access controls to limit access to the event data. For example, grant write access to the account or accounts used by your application, grant full control to administrators, and read-only access to operators.

This makes it more difficult for attackers to tamper with log files to cover their tracks. Minimize the number of individuals who can manipulate the log files. Authorize access only to highly trusted accounts such as administrators.

Code Access Security

  • What's new in ASP.NET 2.0 in terms of Code Access Security?
  • How do I use Code Access Security with ASP.NET?
  • How do I create a custom trust level for ASP.NET?
  • What are the permissions at the various trust levels?
  • How do I write partial trust applications?
  • When should I put assemblies in GAC, what are security implications?

What's new in ASP.NET 2.0 in terms of Code Access Security?

The main differences between ASP.NET 1.1 and ASP.NET 2.0 for Code Access Security are the following:

  • A new class of evidence (GacEvidence) tells you whether an assembly was loaded from the global assembly cache (GAC).
  • OLEDB managed provider no longer requires full trust callers - they just need OleDbPermission - now granted to High and Medium trust ASP.NET Applications
  • Now SqlPermission available on medium trust, which is beneficial for hosting environments.
  • SmtpPermission is available at Full, High, and Medium trust levels. This allows applications to send e-mail.
  • New permission types DataProtectionPermission which controls the ability to use encryption/decryption with DPAPI.
  • All the Assemblies installed in GAC by default get full trust.
  • In .Net 2.0, demands for identity permissions will always succeed in FullTrust.
  • Improved protection of public APIs (new security actions DemandChoice and LinkDemandChoice that allow use of multiple permission sets)
  • Expanded System.Security.SecurityException type, Now possible to tell precisely what failed and why (includes failed assembly info – security action that failed, failed assembly’s permission set grant)

How do I use Code Access Security with ASP.NET?

Administrators can use code access security trust levels with ASP.NET to isolate applications and to restrict which resource types they can access and which privileged operations they can perform.

By default all ASP.NET applications run at Full trust level. You should worry about code access security only when you are developing / deploying applications in partial trust, as in case of ISVs hosting multiple applications on the same server from various users / organizations that do not trust each other. For using code access security do the following.

  • Identify the permissions that your applications need. You can do this my doing a manual code review or by using PermCalc tool available with .NET Framework 2.0. Here is the command for running the tool against a assembly which will show the permissions required for the assembly
    permcalc -Show <assemblyName>
  • Depending upon the permissions required choose a standard trust level (High, Medium, Low, or Minimal) for your applications. Ensure that you do not grant more permissions than needed. If you do not find a perfect match with standard trust levels, create a custom trust policy to meet application requirements.
  • Configure your Machine.Config file to use the trust level chosen in previous step as follows.
         <system.web>
           ...
           <trust level="Medium" originUrl="" />
           ...
         </system.web>
         
  • Lock the trust level settings so that it can not be overridden by the application, do the configuration as follows in Machine.Config file.
         <location allowOverride="false">
            <system.web>
              ...
             <trust level="Medium" originUrl=""/>
             ...
            </system.web>
         ...
         </location>  
         

More Information

How do I create a custom trust level for ASP.NET?

Create a custom trust file based on standard trust file that most closely matches your application requirements. Add / Remove the permissions in the custom trust file depending upon your requirements.

From security perspective, you should give your applications only the required permissions and nothing more. This is important because even if your application is compromised an attacker won’t be able to access resources other than permission given to your application.

Here is how you create a custom trust level. 

  • Identify the trust level that satisfies most of your application's permission requirements.
  • Copy the trust policy file of that trust level from %windir%\Microsoft.NET\Framework\{version}\CONFIG\   to a file named Web_CustomTrust.config in the same directory.
  • Add or remove permissions from the custom trust policy file such that your requirements are satisfied. For example, to add the registry permission to a custom trust policy file: Add a <SecurityClass> element.
         <SecurityClass Name="RegistryPermission"
         Description="System.Security.Permissions.RegistryPermission,
                   mscorlib, Version=2.0.0.0, Culture=neutral,
                  PublicKeyToken=b77a5c561934e089"/>
         
         
    Add an <IPermission> element to the "ASP.Net" named permission set.
         <PermissionSet
                   class="NamedPermissionSet"
                   version="1"
                   Name="ASP.Net">
         
                   . . .
              <IPermission
                    class="RegistryPermission"
                    version="1"
                    Unrestricted="true" />
                   . . .
         </PermissionSet>
         
  • Configure your application's root Web.config file to make your application use the custom trust policy file.
           ...
           <location allowOverride="false">
              <system.web>
                 <securityPolicy>
                    <trustLevel name="Custom" policyFile="web_CustomTrust.config"/>
                 </securityPolicy>
                 <trust level="Custom" originUrl="" />
              </system.web>
           </location>
        

Now your application is ready to use the custom trust policy.

More Information

What are the permissions at the various trust levels?

The key capabilities and restrictions for each trust level are summarized in the following table.

Trust Level

Key capabilities and restrictions

Full

  • This is the default trust level. No restrictions are imposed by code access security.

High

  • No unmanaged code.
  • No enterprise services.
  • Can access SQL Server and OLEDB 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 use OLEDN data sources only OledbPermission is required.
  • 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.

More Information

How do I write partial trust applications?

In ASP.NET you can write partially trusted code by using Code Access security. For this first you need to identify the trust level which you want target for your partially trusted code. If any of the standard partial trust levels like High, Medium, Low etc do not match your requirement then you can create custom trust policy as per your partial trust requirement and use the same.

The second option is to choose one of the matching standard trust levels, lower then your requirement and move the privileged operation to a separate assembly which has full trust, and demand a custom permission to identify the calling code and then assert the required privilege permission before executing the privileged operation.

More Information

When should I put assemblies in GAC, what are security implications?

You should put assemblies in GAC only when the assembly is to be shared by several applications on the computer. Assemblies deployed in the GAC must be strong named, as they are integrity checked at the time of addition to GAC.

The security implications of assemblies added to GAC is that the assemblies by default get full trust. Hence it becomes important to add only trusted third party assemblies to GAC.

Assemblies put in GAC, to be accessed by partially trusted code, needs to be marked with APTCA attribute. You need to be cautious while marking assemblies with APTCA as any malicious code can access the assembly and perform privileged operations. Hence before performing the privileged operation the APTCA marked assemblies should demand custom or some specific permission which allowed partial trust code will have.   

Impersonation / Delegation

  • When do I use impersonation in ASP.NET 2.0?
  • How do I impersonate the original caller?
  • How do I temporarily impersonate the original caller?
  • How do I impersonate a specific (fixed) identity?
  • When should I use programmatic impersonation?
  • How do I use programmatic impersonation?
  • What is protocol transition and when do I care?
  • What is Constrained Delegation?
  • How can I retain impersonation in the new thread created from ASP.NET application?

When do I use impersonation in ASP.NET 2.0?

You should use impersonation in an ASP.NET application when you need to access local resources using security context of the original caller or a fixed identity.

By default any resources accessed by ASP.NET application are accessed under the security context of the ASP.NET process identity. In IIS 6.0 that is the Network Service account by default.

Furthermore, impersonation can be fixed for the lifetime of the entire HTTP request or it can be enabled programmatically.

More Information

How do I impersonate the original caller?

ASP.NET does not impersonate the original caller by default. If you need to impersonate the original caller, set the mode attribute of the <authentication> element in the Web.config file to Windows and the impersonate attribute of the <identity> element to true. In IIS, disable anonymous access and select Integrated Windows authentication mechanism. If you do not do this, the ASP.NET application will impersonate the anonymous IIS account IUSR_machineName.

Impersonate original caller to access all the local resources from ASP.NET application using original user’s security context. With impersonation you can use operating system auditing because you can track which users have attempted to access specific resources. You can also enforce access controls on the resources for individual user accounts.

For impersonating original caller, configure the web.config as follows.

<authentication mode="Windows" />
<identity impersonate="true" />

More Information

How do I temporarily impersonate the original caller?

To temporarily impersonate the original caller in your application's Web.config file, set the mode attribute of the <authentication> element to Windows and the impersonate attribute of the <identity> element to false. In IIS, disable anonymous access and select Integrated Windows authentication mechanism.

If your application is such that it uses the ASP.NET worker process Identity for the most part and needs to use original users security context for accessing specific resources or perform specific operation. You should temporarily impersonate the original caller

Here is how you impersonate the original caller temporarily

  • Configure web.config file as follows
         <authentication mode="Windows" />
         <identity impersonate="false" />
         
  • Use following code for impersonating the original caller
         using System.Security.Principal;
         ….
         // Obtain the authenticated user's Identity token
         WindowsIdentity winId =(WindowsIdentity)
                               HttpContext.Current.User.Identity;
         WindowsImpersonationContext ctx = winId.Impersonate();
         
         // Access resources using the identity of the authenticated 
         // user
         // Revert impersonation
         ctx.Undo();
         

More Information

How do I impersonate a specific (fixed) identity?

If you need to impersonate a specific (fixed) identity, set the impersonate attribute to true and supply the identity credentials using username and password attributes of the <identity> element.

 

Impersonate specific or fixed identity to access all the local resources from ASP.NET application using original user’s security context.

Important: Ideally you should not use fixed identity impersonation, instead create a application pool running under that identity and assign your application to the application pool. As impersonation carries lot of overhead and should be used only when required.

For impersonating a fixed windows identity, configure the web.config as follows.

<authentication mode="Windows" />
<identity impersonate="true" username="UserName" password="P@ssw0rd" />

More Information

When should I use programmatic impersonation?

If your application is such that it uses the ASP.NET worker process Identity for the most part and you only want to temporarily impersonate the original caller (or any other identity) to perform specific set of operations or access specific resources, you should use programmatic impersonation.

More Information

How do I use programmatic impersonation?

There are two approaches to using programmatic impersonation in your code and these are based on which form of authentication your ASP.NET application employs. For both cases however, you need to ensure that ASP.NET built-in impersonation is disabled. This, you can specify in the web.config file.

<identity impersonate="false">

If your ASP.NET web application uses Windows authentication, then to use programmatic impersonation, you need to obtain the WindowsIdentity object from HTTPContext.User. This WindowsIdentity represents the authenticated user. You need then call its Impersonate method as shown below:

using System.Security.Principal;
….
WindowsIdentity winId = (WindowsIdentity)HttpContext.Current.User.Identity;
WindowsImpersonationContext ctx = null;
try
{
  // Start impersonating
  ctx = winId.Impersonate();
  // Now impersonating
  // Access resources or perform operation impersonated security context
}
finally
{
  // Revert impersonation
  if (ctx != null)
    ctx.Undo();
}
// Back to running under the default ASP.NET process identity

If your ASP.NET web application uses custom authentication, such as Forms authentication, you must programmatically create a WindowsIdentity object for the caller, which you can then use to impersonate the caller. For this you have two options, depending on your deployment environment

  • Use the Win32 LogonUser API (via P/Invoke)
  • Use new WindowsIdentity constructor passing in the user principal name (UPN) for the account. This feature is only available in windows server 2003. An example of this is shown below

Important: Your process identity should have TCB permission for using the new WindowsIdentity constructor to get impersonation level token. 

Here is sample code for using WindowsIdentity constructor

using System.Security.Principal;
….
// Obtain the user Identity token using
// WindowsIdentityConstructor
WindowsIdentity winId = new WindowsIdentity(userName@fullyqualifieddomainName);
WindowsImpersonationContext ctx = winId.Impersonate();
// Access resources using the identity of the impersonated user 
// Revert impersonation
ctx.Undo();

More information

What is protocol transition and when do I care?

Protocol transition is a new feature introduced in Windows Server 2003, which enables applications to use non-Windows authentication mechanism to authenticate users with windows accounts at front tier and transition to Kerberos authentication in middle tier.

You can use protocol transition in scenarios where it’s not possible for your web application to authenticate your users using Kerberos authentication, although your users have windows accounts. For example, firewalls prevent direct communication with the domain controller. In such scenarios Forms authentication or client certificate authentication are used instead. In these scenarios protocol transition is used for changing to Kerberos authentication at the backend for accessing network resources using delegation. 

More Information

What is Constrained Delegation?

Kerberos delegation on Windows Server 2000 is unconstrained and servers that are configured as trusted for delegation in Active Directory can access any network resources or any machine on the network while using the impersonated user's security context. This represents a potential security threat, particularly if the Web server is compromised.

To address this issue, Windows Server 2003 introduces constrained delegation. This allows administrators to specify exactly which services on a downstream server or a domain account can access when using an impersonated user's security context.

Note: The list of services that can be accessed by delegation is maintained in an Active Directory list referred to as the A2D2 list.

More Information

How can I retain impersonation in the new thread created from ASP.NET application?

In .NET Framework 1.1, impersonation tokens did not automatically flow to newly created threads. This situation could lead to security vulnerabilities because new threads assume the security context of the process. In .NET Framework 2.0, by default the impersonation token still does not flow across threads, but for ASP.NET applications you can change this default behavior with appropriate configuration of the ASPNET.config file in the %Windir%Microsoft.NET\Framework\{Version Number\ directory.

If you need to flow the impersonation token to new threads, set the enabled attribute to true on the alwaysFlowImpersonationPolicy element and enabled attribute to false on legacyImpersonationPolicy element in the ASPNET.config file, as shown in the following example.

<configuration>
  <runtime>
    <alwaysFlowImpersonationPolicy enabled="true"/>
    <legacyImpersonationPolicy enabled="false"/>
  </runtime>
</configuration>

If you need to prevent impersonation tokens from being passed to new threads programmatically, you can use the ExecutionContext.SuppressFlow method.

Configuration

  • What does a secure web.config look like?
  • How do I encrypt sensitive data in machine.config or web.config file?
  • How do I run an ASP.NET application with a particular identity?
  • How do I create a service account for running my ASP.NET applications?
  • Do I need to create a unique user account for each application pool?
  • How do I lock configuration settings?

What does a secure web.config file look like?

A secure web.config file should conform to the following guidelines:

  • connectionStrings configuration section is encrypted using aspnet_regiis.exe utility.
  • All the configuration sections which store user credentials or sensitive data are encrypted using aspnet_regiis.exe utility.
  • Trace is disabled for the application and custom errors mode is set to “On”, so that no detailed error message are returned to the user.
  • When using Forms authentication, the authentication ticket is secured via the configuration setting. Correct membership provider is configured and set as defaultProvider.
  • When using role manager’s role caching feature the authorization cookie is secured via configuration settings.
  • Impersonation is turned off if not required.
  • Only authenticated users have access to the secured part of the web site.
  • Session state is turned off if not used.
  • In MachineKey element decryptionKey and validationKey are separate for each application where as same keys are used in Web Farm scenario on each machine for the application.
  • Application exception details are not propagated to the client.
  • A trust level that matches your application's requirements precisely is specified and it does not grant more permissions than is required by your application.

More information

How do I encrypt sensitive data in machine.config or web.config file?

In ASP.NET 2.0, use the aspnet_regiis.exe tool with the -pe (provider encryption) option to encrypt sections of the Machine.config and Web.config files.

To encrypt a configuration section for example connectionStrings, by using the DPAPI provider with the machine key store (the default configuration), run the following command from a command prompt:

aspnet_regiis -pe "connectionStrings" -app "/MachineDPAPI" 
-prov "DataProtectionConfigurationProvider" 
  • -pe specifies the configuration section to encrypt.
  • -app specifies your Web application's virtual path. If your application is nested, you need to specify the nested path from the root directory, for example "/test/aspnet/MachineDPAPI"
  • -prov specifies the provider name.

The .NET Framework 2.0 SDK supports RSAProtectedConfigurationProvider and DPAPIProtectedConfigurationProvider protected configuration providers, which you use with the Aspnet_regiis.exe tool:

  • RSAProtectedConfigurationProvider. This is the default provider and uses the RSA public key encryption to encrypt and decrypt data. Use this provider to encrypt configuration files for use on multiple Web servers in a Web farm.
  • DPAPIProtectedConfigurationProvider. This provider uses the Windows Data Protection API (DPAPI) to encrypt and decrypt data. Use this provider to encrypt configuration files for use on a single Windows Server.

The following sections often contain sensitive information that you need to encrypt:

  • <appSettings>. Custom application settings.
  • <connectionStrings>. Connection strings.
  • <identity>. Web application identity. Can contain impersonation credentials.
  • <sessionState>. Contains connection string for out of process session provider.

You do not need any special steps for decryption, because the ASP.NET runtime takes care of this for you. You cannot use the Aspnet_regiis.exe tool and protected configuration to encrypt the following sections in Web.config and Machine.config:

<processModel>, <runtime>, <mscorlib>, <startup>, <system.runtime.remoting>, <protectedData>, <satelliteassemblies>, <cryptographySettings>, <cryptoNameMapping>, and <cryptoClasses>.

For these sections, use the Aspnet_setreg.exe tool. You must also use this tool with ASP.NET 1.1. For more information about AspNet-setreg.exe, see Microsoft Knowledge Base article 329290, How to use the ASP.NET utility to encrypt credentials and session state connection strings at http://support.microsoft.com/kb/329290

More Information

How do I run an ASP.NET application with a particular identity?

In IIS 6.0, use IIS Manager to create an application pool running as a specific identity. Use IIS Manager to assign your application to that application pool.

Running ASP.NET application with a specific identities helps to isolate your application isolation, allows you to restrict application resources to your application's account, allows you to use Windows auditing to track the activity of the application separately from other applications.

In IIS 5.0, you can configure the ASP.NET process identity by setting the userName and password attributes on the <processModel> element in Machine.config. If you do this, you should encrypt the credentials by using the aspnet_setreg.exe utility.

More Information

How do I create a service account for running my ASP.NET applications?

  • Create a Windows account
  • Run the following aspnet_regiis.exe command to assign the relevant ASP.NET permissions to the account:
    aspnet_regiis.exe -ga machineName\userName 

On Windows 2003, running the Aspnet_regiis.exe -ga command will add the account to the IIS_WPG group. The IIS_WPG group provides the Log on as a batch job permission and ensures that the necessary file system permissions are granted.

Note: At the time of this writing, the aspnet_regiis –ga command on .NET Framework 2.0 beta 2 does not add the account to the IIS_WPG group and this must be done manually. The release version of the .NET Framework 2.0 will fix this issue and the account will be added to the IIS_WPG group.

  • Use the Local Security Policy tool to grant the Windows account the Deny logon locally user right. This reduces the privileges of the account and prevents anyone logging onto Windows locally with this account.
  • Use IIS Manager to create an application pool running under the new account's identity and assign your ASP.NET application(s) to this pool.

More Information

Do I need to create a unique user account for each application pool?

No, you don’t need to create a unique user account for each application pool. However, you might want to do so if you want to audit and authorize each application separately. This is especially the case if you're in a hosted environment running multiple web applications on the same server.

Maintaining a separate identity for each application in such scenarios enables process isolation and auditing for each application. You can create ACL's for the various operating system resources (includes file system) on an individual application's identity. You also have the ability to establish granular database permissions, which might vary for each application.

More information

How do I lock configuration settings?

To lock the configuration settings for all the Web applications on a Web server to prevent an individual application from overriding them, place the configuration settings inside a <system.web> element nested within a <location> element in the machine-level Web.config file, and then set the allowOverride attribute to false.

The following example enforces the use of Windows authentication for all Web applications on the server.

<location allowOverride="false">
  <system.web>
    <authentication mode="Windows"/>
  </system.web>
</location>  

If you need to apply and lock settings for a specific Web application, use the path attribute on the <location> element to identify the Web application as shown here.

<location path="Default Web Site/VDirName">
  <system.web>
    <authentication mode="Windows"/>
    <identity impersonate="false"/>
  </system.web>
</location>  

If you specify the path, it must be fully qualified and include the Web site name and virtual directory name.

Important: If it is critical that there are no cross-application breaches, then it better to configure the web.config file in the /VDirName for locking the configuration instead of using path attribute to lock the specific web application.

Exception Handling

  • How do I handle exceptions securely?
  • How do I prevent detailed errors from returning to the client?
  • How do I use structured exception handling?
  • How do I setup a global exception handler for my application?
  • How do I enable my ASP.NET application to write to new event source?

How do I handle exceptions securely?

You should use try/catch/finally structured exception handling in your code to avoid unhandled exceptions. Do not reveal internal system or application details, such as stack traces, SQL statement fragments, and table or database names. Ensure that this type of information is not allowed to propagate to the end user or beyond your current trust boundary.

This is important because any malicious user could use system-level diagnostic information to learn about your application and probe for weaknesses to exploit in future attacks.

If an exception is thrown, make sure your application fails securely, denies access, and is not left in an insecure state. Do not log sensitive or private data, such as passwords, that could be compromised. When you log or report exceptions, if user input is included in exception messages, validate it or sanitize it. For example, if you return an HTML error message, you should encode the output to avoid possible script injection.

How do I prevent detailed errors from returning to the client?

To prevent detailed errors from returning to the client set the mode attribute of <customErrors> element to On, so that all callers receive filtered exception information. Also you can set pageOutput="false" on the <trace> element to disable trace output.

Alternatively you can set the retail=”true” on the <deployment> element which disable configuration settings such as trace output, custom errors, and debug capabilities. It overrides all application level settings hence when using this setting the trace output, custom errors and debug settings need not be configured.

This is important because any malicious user could use system-level diagnostic information to learn about your application and probe for weaknesses to exploit in future attacks.

Here is how you configure the application for preventing from detailed errors from returning to the client.

  • Set the mode attribute of <customErrors> element to On  and set the defaultRedirect to a default error page displaying friendly error message page which, for example, might include support contact details.
         <customErrors mode="On" defaultRedirect="YourErrorPage.htm" />
  • If you have any known errors before hand you can set the specific error pages for those errors as follows.
         <customErrors mode="On" defaultRedirect="YourErrorPage.htm">
            <error statusCode="404"
         redirect="customerror404.htm"/>
            <error statusCode="405"
         redirect="customerror405.htm"/>
         </customErrors>
  • Set pageOutput="false" on the <trace> element to disable trace output. To prevent trace being accidentally being re-enabled, consider locking this for all applications on a server by applying the following configuration in the machine-level Web.config file. Enclose the <trace> element in a <location> element and set allowOverride to false.
         <location path="" allowOverride="false">
           <system.web>
             <trace pageOutput="false" ... />
           </system.web>
         </location>
  • Alternatively Set the retail=true on the <deployment> element as follows
    <deployment retail="true"/>

How do I use structured exception handling?

Use try/catch/finally structured exception handling blocks around code to avoid unhandled exceptions. Use finally blocks to execute code that runs whether an exception is trapped; this is useful for releasing resources such as closing files or disposing of objects.

A structured exception handling helps you create and maintain programs with robust, comprehensive error handlers. If an exception is not handled properly it might leave your application unstable and un-usable. Also finally blocks guarantees that any resources allocated in the try block of the code will get a chance to be cleaned in the finally block which is executed at the last.

Here is how you use the structured exception handling

Try
{
   // code that might throw an exception
}
catch (knownException)
{
   // do exception handling
}
catch
{
   // generic exception handler, do exception handling
}
finally
{
   // free any allocated resources
} 

How do I setup a global exception handler for my application?

To set up a global exception handler for your application, write your exception handling code in the Application_Error event handler that is implemented in Gloabal.asax. This event is raised when exceptions are allowed to propagate from page-level error handlers or if there is no page error handler. Ideally, the exception handling code you write in the Application_Error method will collect and log as much exception details necessary for you to diagnose the error.

An unhandled exception might leave your application in an unstable and un-usable form, hence as a fall back mechanism you should always implement a global exception handler.

A sample global exception handler that writes exception details to the event log is shown below:

 <%@ Application Language="C#" %>
 <%@ Import Namespace="System.Diagnostics" %>
 <script language="C#" runat="server">
 void Application_Error(object sender, EventArgs e)
 {
   //get reference to the source of the exception chain
   Exception ex = Server.GetLastError().GetBaseException(); 
   //log the details of the exception and page state to the
   //Event Log
   EventLog.WriteEntry("My Web Application",
     "MESSAGE: " + ex.Message + 
     "\nSOURCE: " + ex.Source +
     "\nFORM: " + Request.Form.ToString() + 
     "\nQUERYSTRING: " + Request.QueryString.ToString() +
     "\nTARGETSITE: " + ex.TargetSite +
     "\nSTACKTRACE: " + ex.StackTrace, 
     EventLogEntryType.Error);
   //Optional email or other notification here...
 }
 </script>

How do I enable my ASP.NET application to write to a new event source?

To enable your ASP.NET application to write to the event log using its own event source, you have two options:

  • Grant your ASP.NET process account (or impersonated identity if your application uses impersonation) permissions on the following registry key: HKLM\SYSTEM\CurrentControlSet\Services\Eventlog\.
  • To avoid editing the registry, if administrator privileges are available at installation time, create the event source at application install time. You can use a .NET installer class, which can be instantiated by the Windows Installer (if you are using .msi deployment) or by the InstallUtil.exe system utility.

The default ASP.NET worker process identities have sufficient permissions to write records to the event log using existing event sources. However, if your application needs to create new event sources using the default worker process identity, it would fail as the default worker process identity does not have privileges to create event sources.

In a production scenario where you might be using, custom domain account for running the ASP.Net application instead of the default. The permissions on the registry must be granted to the custom domain account.

If you have configured your application to use impersonation, then permissions must be granted to the authenticated user's account or IUSR_machineName for anonymous callers.

More Information

Data Access

  • How do I protect the database connection strings in web.config file?
  • How do I use windows authentication for connecting to SQL server?
  • How do I use SQL authentication for connecting to SQL server?
  • When using Windows authentication, how can I give the default ASP.NET worker process access to a remote database server?

How do I protect the database connection strings in web.config file?

To protect connection strings present in your application's web.config file, ensure that the connection strings are placed inside the <connectionStrings> setting in the web.config and then encrypt the data by using one of the protected configuration providers (RSA or DPAPI) using aspnet_regiis.exe utility.

It’s important to protect connection strings placed in configuration file, especially SQL Authentication connection strings where user credentials are used. As connection strings have information which can be exploited by an attacker.

To encrypt the connectionStrings section by using the DPAPI provider with the machine key store (the default configuration), run the following command from a command prompt:

aspnet_regiis -pe "connectionStrings" -app "/MachineDPAPI" 
-prov "DataProtectionConfigurationProvider"
  • -pe specifies the configuration section to encrypt.
  • -app specifies your Web application's virtual path. If your application is nested, you need to specify the nested path from the root directory, for example "/test/aspnet/MachineDPAPI"
  • -prov specifies the provider name.

The .NET Framework 2.0 SDK supports RSAProtectedConfigurationProvider and DPAPIProtectedConfigurationProvider protected configuration providers, which you use with the Aspnet_regiis.exe tool:

  • RSAProtectedConfigurationProvider. This is the default provider and uses the RSA public key encryption to encrypt and decrypt data. Use this provider to encrypt configuration files for use on multiple Web servers in a Web farm.
  • DPAPIProtectedConfigurationProvider. This provider uses the Windows Data Protection API (DPAPI) to encrypt and decrypt data. Use this provider to encrypt configuration files for use on a single Windows Server.

More Information

How do I use Windows authentication for connecting to SQL Server?

To use Windows authentication, configure SQL Server appropriately and then use a connection string that contains either "Trusted_Connection=Yes", or "Integrated Security=SSPI" as shown in the following code. The two strings are equivalent and both result in Windows authentication.

"server=MySQL; Integrated Security=SSPI; database=Northwind"
"server=MySQL; Trusted_Connection=Yes; database=Northwind"

Use windows authentications wherever possible as, the accounts are centralized and managed by your Active Directory or local authority store. Strong password policies can be controlled and enforced by your domain or local security policy. Passwords are not transmitted over the network. User IDs and passwords are not specified in database connection strings.

When using Windows authentication, use a trusted service account to access the database when possible. This is usually your application's process account. By using a single trusted service account, your application benefits from connection pooling; this provides greater scalability. Also, account administration and authorization within the database is simplified.

If you need per-user authorization in the database or need to use operating system auditing to track the activity of individual users, you need to use impersonation and delegation and access the database using the caller's identity. This approach has limited scalability because it prevents the efficient use of connection pooling.

Here is how you configure SQL Server for the application’s account

  • Create a SQL login for the application’s account
  • Map the login to a database user
  • Place the database user in a database role
  • Grant permissions to the role. Ideally just grant execute permissions to selected stored procedures and provide no direct table access. 

More Information

How to do I use SQL authentication for connecting to SQL Server?

If you cannot use Windows authentication to SQL Server, you must use SQL authentication.

To use SQL authentication:

  • Use a least-privileged user ID to connect to SQL.
  • Use a strong password for the SQL user account.
  • Protect the channel between the Web server and database server because credentials are passed in an unencrypted format. For example, use SSL or IPSec.
  • Protect the SQL connection string, which contains plaintext credentials.

If you connect to a SQL Server database using credentials (user name and password), your connection string looks like the following.

SqlConnectionString = "Server=YourServer\Instance;
                      Database=YourDatabase;uid=YourUserName;
                      pwd=YourStrongPassword;"

More Information

When using Windows authentication, how can I give the default ASP.NET worker process access to a remote database server?

Create a SQL Login for the Network Service Account, create a database user in the required database and map the login to the database user. Place the database user in database role and then grant the required permission to the database role.

Note: Using the Network Service account will generally be a development scenario, in production scenario’s the ASP.NET process will be running using a custom domain account.

In IIS 6.0, the ASP.NET worker process runs under the Network service account by default. This is a low privileged account that has network credentials. These credentials can be authenticated on the network using the computer's domain account.

So to grant remote database access to the Network Service account, you need do the following

  • Create SQL login for the Network Service Account. The name appears as domainName\<WebServerMachineName>$ if your database is on a separate server. You can use Enterprise Manager or run the following SQL statement to create the SQL Login
    exec sp_grantlogin [domainName\<WebServerMachineName>$] 
  • Create a database user in the required database and map the login to the database user. Or you can run the following SQL statement:
    exec sp_grantdbaccess [domainName\<WebServerMachineName>$] 
  • Place the database user in a database role. This enables you to assign permissions to roles instead of individual users, which helps should, the user account change. Grant the required permissions to the role. Ensure that you grant only necessary permissions with appropriate levels of access. Ideally, this should be execute permissions to select stored procedures with no direct table access

More Information

Input / Data Validation

  • What are the types of input I need to validate in my ASP.NET application?
  • How do I validate input in server-side controls?
  • How do I validate input in HTML controls, QueryString, cookies, and HTTP headers?
  • What is cross-site scripting and how do I protect my ASP.NET application from it?
  • What is SQL injection and how do I protect my application from SQL injection attacks?

What are the types of input I need to validate in my ASP.NET application?

You should assume all input is malicious and design and secure your application based on this. Constrain input for length, range, format, and type, while doing so validate inputs from all sources like Server controls, HTML controls, query strings, cookies, Http headers, shared database etc.

More Information

How do I validate input in server-side controls?

You can use the ASP.NET validator controls, such as the RegularExpressionValidator, RangeValidator and CustomValidator, to validate and constrain input in server side controls.

Regular expressions are a good way to validate text fields such as names, addresses, phone numbers, and other user information. If inputs are not validated appropriately it makes your application vulnerable to injection attacks like SQL Injection and Cross-Site Scripting.

Here is a sample of a RegularExpressionValidator control to validate a name field

<form id="WebForm" method="post" runat="server">
  <asp:TextBox id="txtName" runat="server"></asp:TextBox>
   <asp:RegularExpressionValidator id="nameRegex"runat="server" ControlToValidate="txtName" ValidationExpression="[a-zA-Z'.`-´\s]{1,40}" ErrorMessage="Invalid name">
   </asp:regularexpressionvalidator>
</form>

The validation expression constrains the input name field to alphabetic characters (lowercase and uppercase), the single apostrophe for names such as O’Dell, and the dot character. In addition, the field length is constrained to 40 characters.

The validation controls use client-side script to perform validation on the client browser (if supported by the browser), and also run validation logic on the server after data is posted back.

More Information

How do I validate input in HTML controls, QueryString, cookies, and HTTP headers?

Use regular expression with Regex class for validating input in HTML controls, Query Strings, Cookies and Http header.

Regular expressions are a good way to validate text fields such as names, addresses, phone numbers, and other user information. If inputs are not validated appropriately it makes your application vulnerable to injection attacks like SQL Injection and Cross-Site Scripting.

If your web application obtains input through HTML controls, QueryString, Cookies or Http Headers you cannot use the ASP.NET validator controls. Instead, you can validate your web page's content in the Page_Load event handler using the System.Text.RegularExpression.Regex class as follows:

using System.Text.RegularExpressions;
….
private void Page_Load(object sender, System.EventArgs e)
{
   // Note that IsPostBack applies only for
   // server forms (with runat="server")

   if ( Request.RequestType == "POST" ) // non-server forms
    {
         // Validate the supplied email address
         if( !Regex.Match(Request.Form["email"],@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*",RegexOptions.None).Success)
         {
            // Invalid email address
         }
    }
}

More Information

What is Cross-site scripting and how do I protect my ASP.NET application from it?

Cross-site scripting (XSS) attacks exploit vulnerabilities in web page validation by injecting client-side script code. This code is then subsequently sent back to an unsuspecting user and executed by the browser.

To prevent XSS attacks you need to:

  • Validate Input – Validate any input that is received from outside your application's trust boundary for type, length, format and range. The type and length of the input of the input can be coerced using the RegularExpressionValidator. For range checks, you can use the RangeValidator control to constrain input to a predetermined range
  • Encode Output - If you write text output to a Web page and you do not know with absolute certainty that the text does not contain HTML special characters (such as <, >, and &), then make sure to pre-process it using the HttpUtility.HtmlEncode method. Do this even if the text came from user input, a database, or a local file. Similarly, use HttpUtility.UrlEncode to encode URL strings.

The HtmlEncode method replaces characters that have special meaning in HTML to HTML variables that represent those characters. For example, < is replaced with &lt and " is replaced with &quot. Encoded data does not cause the browser to execute code. Instead, the data is rendered as harmless HTML.

More Information

What is SQL injection and how do I protect my ASP.NET application from it?

If you are generating dynamic SQL queries based on user input, a SQL injection attack can inject malicious SQL commands that can be executed by the database. The injection attack can occur when your application uses user input to construct dynamic SQL statements to access the database or if your code passes string containing unfiltered user input to stored procedures.

To prevent SQL injection attacks you need to:

  • Constraint Input – Constraining the input requires that you validate the input for type, length, format and range. You could do this by using regular expressions with RegularExpressionValidator validator control. Here is a sample of a RegularExpressionValidator control to validate a email address
         <form
         id="WebForm" method="post"
         runat="server">
            <asp:TextBox id="txtName"
         runat="server"></asp:TextBox>
             <asp:RegularExpressionValidator
         id="nameRegex"runat="server"
         ControlToValidate="emailAddress" ValidationExpression"],@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"
         ErrorMessage="Invalid email address">
            </asp:regularexpressionvalidator>
         </form>
  • Use type safe SQL parameters - The Parameters collection in SQL provides type checking and length validation. Parameters can be used when invoking stored procedures as well as regular SQL Select, update, insert and delete statements. If you use the Parameters collection, input is treated as a literal value and SQL does not treat it as executable code. An additional benefit of using the Parameters collection is that you can enforce type and length checks. Values outside of the range trigger an exception. The following code fragment illustrates the use of the parameters collection
         SqlDataAdapter myCommand = new SqlDataAdapter("SELECT au_lname, au_fname FROM
         Authors WHERE au_id = @au_id", conn);
         SqlParameter parm =
         myCommand.SelectCommand.Parameters.Add("@au_id",SqlDbType.VarChar,
         11);
         parm.Value = Login.Text;

More Information

Sensitive Data

  • How do I protect my web application's ViewState?
  • What care should I take when securing ViewState in a web farm scenario?
  • How do I protect sensitive data in the database?
  • How do I protect sensitive data in configuration files?
  • How do I protect sensitive data in memory?
  • How do I protect passwords?

How do I protect my web application's ViewState?

ViewState sent between browser and server should be integrity checked with HMACs, which is the default setting. Avoid storing sensitive data in ViewState. If you must store sensitive data in ViewState, encrypt it.

ViewState should be tamper proofed as it is subject to tampering and eavesdropping threats. Also storing sensitive data unencrypted in ViewState makes your application vulnerable.

Here is how you can protect ViewState.

  • Protect ViewState with HMACs – Hashed message authentication codes (HMACs) is a tamper-resistant protocol that can be used to protect the ViewState. This feature is enabled by default as the system-wide enableViewStateMAC is set to true in machine.config. You could enable ViewState protection at the page level by setting the EnableViewStateMAC attribute to true as show below
         <%@Page EnableViewState="true" EnableViewStateMAC="true" %>
  • Encrypt ViewState if it contains sensitive data - Avoid storing sensitive data in ViewState. If you must store sensitive data in ViewState, encrypt it.
  • To enable encryption of ViewState, you must use one of the following configurations.
         <%@Page viewStateEncryptionMode="Auto" ... /%>
         <%@Page viewStateEncryptionMode="Always" ... /%>
    With viewStateEncryptionMode set to Auto, the page is only encrypted if a control has specifically asked for it by calling the Page.RegisterRequiresViewStateEncryption method to request encryption. If it set to Always, this forces encryption even if a control does not request it.
  • Add the following decryption attribute to the <machineKey> element in either Web.config or Machine.config.
         <system.web>
              <machineKey decryptionKey="AutoGenerate,IsolateApps" 
         decryption='3DES' ... />
         </system.web>
  • If you use ViewState HMACs or encryption, and you deploy your application in a Web farm, you must ensure that the configuration files on each server share hashing and encryption keys.

More Information

What care should I take when securing ViewState in a web farm scenario?

If you use HMACs for tamper proofing (the default configuration) and encryption to protect View state. You must ensure that the configuration files on each server share hashing and encryption keys.

This is required because you cannot guarantee which server will handle successive post-back requests. The validationKey and decryptionKey in <machineKey> section is used for hashing and encryption of the ViewState. The default value of these keys is “AutoGenerate,IsolateApps”, i.e. the keys are auto generated for each application and they will be different on each server. Hence ViewState encrypted and tamper proofed on one machine cannot be decrypted and integrity checked on another machine in web farm.

For this you must manually generate the two cryptographically random key values and copy the keys to each Machine.config (or Web.config) file across your Web farm.

To generate cryptographically random keys, use the '''RNGCryptoServiceProvider''' class to generate a cryptographically strong random number. The key must be a minimum of 40 hexadecimal characters (20 bytes) and a maximum of 256 hexadecimal characters (64 bytes) long.

using System;
using System.Text;
using System.Security;
using System.Security.Cryptography;
class App
{
 static void Main(string[] argv) 
 {
    int len = 128;
    if (argv.Length > 0)
        len = int.Parse(argv[0]);
    byte[] buff = new byte[len/2];
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    rng.GetBytes(buff);
    StringBuilder sb = new StringBuilder(len);
    for (int i=0; i<buff.Length; i++)
          sb.Append(string.Format("{0:X2}", buff[i]));
    Console.WriteLine(sb);
 }
}

Use the keys generated thus to configure in machine key settings in machine.config / web.config file as follows. Please use separate keys for validationKey and decryptpionKey. Here is the sample configuration.

<machineKey validationKey="Hsbfb636576sahfj\mfhhshnj234235"  
            decryptionKey="shakh7857jkjjco985\fhhegf476343" 
            validation="SHA1" decryption="Auto" />

More Information

How do I protect sensitive data in the database?

If you need to protect data in a database that is accessed by multiple Web servers, you need to encrypt the data with a strong symmetric encryption algorithm and protect the encryption key with DPAPI.

To encrypt sensitive data in a database accessed by multiple servers in a Web farm:

  • Use a strong symmetric encryption algorithm such as 3DES or AES.
  • Use the System.Security.Cryptography.RNGCryptoServiceProvider class to generate a strong (192 bit, 24 byte) encryption key. Back up the encryption key, and store the backup in a physically secure location.

Note: Cryptographically, 3DES keys are effectively 168 bits in length rather than 192 bits. This is because in each of the three DES applications, a 56 bit key is used even though the block size is 64. The remainder of the 8 bits were meant to be parity bits but were never really used for that purpose. 3DES therefore, uses three times 56 or 168 bit keys.

  • Use DPAPI to encrypt the symmetric encryption key on each Web server and store it in a secured registry key. Create an ACL to protect the registry key that allows full control for administrators and read only access for your ASP.NET process account.

To encrypt data and decrypt data, retrieve the encrypted symmetric encryption key from the registry, use DPAPI to decrypt the key and then use the System.Security.Cryptography.TripleDESCryptoServiceProvider class with the encryption key to either encrypt or decrypt the data stored in the database.

With this process, if the DPAPI account used to encrypt the encryption key is damaged, the backup of the 3DES key can be retrieved from the backup location and be encrypted using DPAPI under a new account. The new encrypted key can be stored in the registry and the data in the database can still be decrypted.

How do I protect sensitive data in configuration files?

Encrypt the configuration section storing the sensitive data. In ASP.NET 2.0, use the aspnet_regiis.exe tool with the -pe (provider encryption) option to encrypt configuration sections of the Machine.config and Web.config files.

To encrypt a configuration section for example connectionStrings section by using the DPAPI provider with the machine key store (the default configuration), run the following command from a command prompt:

aspnet_regiis -pe "connectionStrings" -app "/MachineDPAPI" 
-prov "DataProtectionConfigurationProvider"
  • -pe specifies the configuration section to encrypt.
  • -app specifies your Web application's virtual path. If your application is nested, you need to specify the nested path from the root directory, for example "/test/aspnet/MachineDPAPI"
  • -prov specifies the provider name.

The .NET Framework 2.0 SDK supports RSAProtectedConfigurationProvider and DPAPIProtectedConfigurationProvider protected configuration providers, which you use with the Aspnet_regiis.exe tool:

  • RSAProtectedConfigurationProvider. This is the default provider and uses the RSA public key encryption to encrypt and decrypt data. Use this provider to encrypt configuration files for use on multiple Web servers in a Web farm.
  • DPAPIProtectedConfigurationProvider. This provider uses the Windows Data Protection API (DPAPI) to encrypt and decrypt data. Use this provider to encrypt configuration files for use on a single Windows Server.

The following sections often contain sensitive information that you need to encrypt:

  • <appSettings>. Custom application settings.
  • <connectionStrings>. Connection strings.
  • <identity>. Web application identity. Can contain impersonation credentials.
  • <sessionState>. Contains connection string for out of process session provider.

You do not need any special steps for decryption, because the ASP.NET runtime takes care of this for you. You cannot use the Aspnet_regiis.exe tool and protected configuration to encrypt the following sections in Web.config and Machine.config:

<processModel>, <runtime>, <mscorlib>, <startup>, <system.runtime.remoting>, <protectedData>, <satelliteassemblies>, <cryptographySettings>, <cryptoNameMapping>, and <cryptoClasses>.

For these sections, use the Aspnet_setreg.exe tool. You must also use this tool with ASP.NET 1.1. For more information about AspNet-setreg.exe, see Microsoft Knowledge Base article 329290, How to use the ASP.NET utility to encrypt credentials and session state connection strings at http://support.microsoft.com/kb/329290

More Information

How do I protect sensitive data in memory?

You can protect sensitive data in memory by using ProtectedMemory class introduced in .Net Framework 2.0 to store the data. ProtectedMemory class a managed wrapper to Data Protection API (DPAPI). You can also use SecureString type for storing sensitive text values securely in memory. SecureString can store text values similar as string, but additionally the values are encrypted automatically. SecureString can be deleted from computer memory programmatically. The SecureString class internally uses ProtectedMemory class for encrypting string in memory.

Important: Avoid converting back and forth between vanilla and secure strings since strings are immutable and hence you could end up with clear copies of your secure and sensitive string in other parts of memory

Sensitive data like user names, passwords, database connection strings, and encryption keys should be encrypted in the memory as well when handling by the application, because attackers ca probe your computers memory or make your process to do a memory dump and retrieve the sensitive information. 

Note: SecureString does not support inspection, comparison, or conversion functionality hence it can not be manipulated to reveal the data.

Here is how you use ProtectedMemory class for encrypting data in memory, contends of byte array are directly encrypted in the memory.   

Here is a sample for using the ProtectedMemory class for encrypting and decrypting data in memory.

using System.Security.Cryptography;
….
byte[] optionalEntropy = {7,5,4,9,0};
byte[] dataToBeEncrypted = Encoding.Unicode.GetBytes("Test String 1211");
// encrypt the data in memory
ProtectedMemory.Protect(dataToBeEncrypted, MemoryProtectionScope.SameLogon);

//decrypt the data in memory
ProtectedMemory.Unprotect(dataToBeEncrypted, MemoryProtectionScope.SameLogon);
string originalData = Encoding.Unicode.GetString(dataToBeEncrypted);

How do I protect passwords?

You should store passwords in a non-reversible hashed format. Generate the hash from a combination of the password and a random salt value. Use an algorithm such as SHA256.

The salt value helps to slow an attacker perform a dictionary attack should your credential store be compromised, giving you additional time to detect and react to the compromise.

Here is how you create non reversible hashes with salt for your user passwords.

  • Generate a random salt value by using the following code.
         byte[] salt = new byte[32];
         System.Security.Cryptography.RNGCryptoServiceProvider.Create().GetBytes(salt);
  • Append the salt to the password.
         // Convert the plain string password into bytes
         byte[] plainTextBytes = System.Text UnicodeEncoding.Unicode.GetBytes(plainText);
         // Append salt to password before hashing
         byte[] combinedBytes = new byte[plainTextBytes.Length + salt.Length];
         System.Buffer.BlockCopy(plainTextBytes, 0, combinedBytes, 0,
         plainTextBytes.Length);
         System.Buffer.BlockCopy(salt, 0, combinedBytes, plainTextBytes.Length,
         salt.Length);
  • Hash the combined password and salt by using the following code.
         // Create hash for the password+salt
         System.Security.Cryptography.HashAlgorithm hashAlgo = new
         System.Security.Cryptography.SHA256Managed();
         byte[] hash = hashAlgo.ComputeHash(combinedBytes);
  • Append the salt to the resultant hash.
         // Append the salt to the hash 
         byte[] hashPlusSalt = new byte[hash.Length + salt.Length];
         System.Buffer.BlockCopy(hash, 0, hashPlusSalt, 0, hash.Length);
         System.Buffer.BlockCopy(salt, 0, hashPlusSalt, hash.Length, salt.Length);
  • Store the result in your user store database.

This approach means you do not need to store the salt separately. To verify a password, you extract the salt from the stored combination of the hash and salt value and then recomputed the hash using the salt value and the plaintext password value obtained from the user.

Strong Naming and Signing

  • How do I strong-name an ASP.NET application assembly?
  • How do I delay sign an ASP.NET application assembly?
  • When should I use .pfx files?
  • When should I pre-compile my ASP.NET application?
  • How do I pre-compile my ASP.NET application?
  • How do I strong name an ASP.NET application?
  • How do I Sign .Net assemblies with Authenticode signature?

How do I strong-name an ASP.NET application assembly?

You can create strong name keys and strong name the assembly using Visual Studio 2005. In the project properties of the assembly, select the Signing pane. By checking the "Sign the assembly" checkbox, you instruct the compiler to sign the assembly with the key file specified.

Strong naming .NET assembly guarantees name uniqueness, protects the version lineage and provides strong integrity check.

Note: Strong names do not imply a level of trust like that provided, by a digital signature and supporting certificate.

Here is how you strong name a .Net assembly.

  • Configure the assembly for strong naming
    • In the Solution Explorer select the .NET assembly project and right click
    • On the popup menu select Properties
    • It will open the Project Designer page; on it select the Signing tab.
    • On the Signing tab select the Sign the assembly check box.
  • Create / Select existing strong name key for signing - You can either select an existing or create a new password protected (.pfx) or plain (.snk) strong name key.

For creating new strong name key:

    • In the Choose a strong name key file: drop down box select <New…>
    • In the Create Strong Name key dialog enter the Key file name
    • Select Protect my key file with a password check box for creating the .pfx file, else keep it unselected for creating plain strong name key file (.snk)
    • If you have selected to protect the file, enter password in Enter password and Confirm password text boxes and then click Ok

For selecting existing strong name key

    • In the Choose a strong name key file: drop down box select <Browse…>
    • In the file selection dialog box browse to the strong name key (either .pfx or .snk)
    • Select the key file, in case of .pfx it will prompt for password, enter the correct password and click ok on ImportPFXKeyDlg dialog box.
  • Sign the assembly - Now you just need to build the assembly, the complier will build a strong named assembly using the strong name key configured.

How do I delay sign an ASP.NET application assembly?

You can delay sign the assembly by using Visual Studio 2005 and a public key extracted from an existing strong name key. In the project properties of the assembly, select the Signing pane. By checking the "Sign the assembly" and "Delay sign only" checkbox, you instruct the compiler to delay sign the assembly with the public key file specified.

Delay signing your assemblies during application development means the public key being placed in the assembly. This allows the public to be available as evidence to code access security policy, but the assembly is not signed. From a security perspective, delay signing has two main advantages:

  • The private key used to sign the assembly and create its digital signature is held securely in a central location. The key is only accessible by a few trusted personnel. As a result, the chance of the private key being compromised is significantly reduced.
  • A single public key, which can be used to represent the development organization or publisher of the software, is used by all members of the development team, instead of each developer using his or her own public, private key pair.

Here is how you delay sign a .NET assembly

  • Extract public key from a strong name key for delay signing.
    • Use Sn.exe utility for extracting public key from the .pfx or .snk key pair file for delay signing. Here is the command for the same; test.pfx is the key pair file
      Sn –p c:\test.pfx   c:\testpublickkey.snk
  • Configure the assembly for delay signing
    • In the Solution Explorer select the .NET assembly project and right click
    • On the popup menu select Properties, it will open the Project Designer page;
    • On it select the Signing tab and select the Sign the assembly and Delay sign only check boxes.
  • Select public key for delay signing
    • In the Choose a strong name key file: drop down box select <Browse…>
    • In the file selection dialog box browse to the public key (.snk) and click Ok
  • Delay sign the assembly - Now you just need to build the assembly, the complier will build a strong named assembly signed using the public key configured.
  • Final signing of the assembly - At the time of final release use following command and resign the assembly
    Sn –R <assemblyName> C:\test.pfx 

Important: Note that a delay signed project will not run and cannot be debugged. You can, however, use the Strong Name Tool (Sn.exe) with the -Vr option to skip verification during development.

When should I use .pfx files?

You should always prefer to use .pfx file when strong naming your application, unless using an existing strong name key pair file (.snk).

The .pfx files are more secure as it is protected by password, so whenever another user tries to use the file, that user will be prompted for the password. Also the other advantage of a .pfx file is that you can add it to a certificate container.

When should I pre-compile my ASP.NET application?

You should consider pre-compiling your application,

  • If you want to deploy your ASP.NET application without copying any of the original source code to the production server. This includes the code and markup in aspx, ascx, and master files. This especially true with shared hosted environment where your source code might be vulnerable.
  • If you want to identify compile-time bugs before users see a site, for better user experience.
  • If you want to strong name your ASP.NET application, so that it can work seamlessly with strong name assemblies.
  • Additionally pre-compilation gives a faster response time for users, since pages do not have to be compiled the first time they are requested. This is particularly useful on large sites that are updated frequently.

How do I pre-compile my ASP.NET application?

You can pre-compile your ASP.NET application using the aspnet_compiler.exe utility or Publishing web site option in Visual Studio 2005. In both cases you will have to create a strong name key pair file using Strong Name (Sn.exe) utility.

Note: You can not use the password protected strong name key pair file (.pfx)

Pre-compiling your ASP.NET helps you deploy your application in production server without the original source code, identifies compile time bugs, allows you to strong name your ASP.NET application, and gives faster response time for users for first time request.

Using Visual Studio 2005

  • In the Build option from the tool menu select Publish http://localhost/....
  • On the Publish Web Site dialog box, enter the Target Location where you want the deployable precompiled site to be copied
  • Here you can choose the "Allow this precompiled site to be updateable" check box if required, please see the note for details.
  • On the Publish Web Site dialog box, click Ok button.

This will pre-compile the ASP.NET application and you can XCopy the complete folder from the target location and deploy it on your production server.

Note: With updateable pre-compilation the ASPX, ASCX, ASHX, and MASTER files are copied to the target directory, you can deploy these files to the server and modify them. The ASP.NET runtime will dynamically parse and compile these files. All of the source code for code-behind files and in the App_Code folder will be compiled into assemblies and will not need to be re-deployed.

Using aspnet_compiler.exe command line utility

  • Open Visual Studio 2005 command Prompt
  • Run the following command, specifying applications virtual path and target directory.
         aspnet_compiler -v /<<ASP.NET Application Virtual path>> <<Target Directory Path>> 
  • For updateable pre-compilation include the -u switch in the command as follows
         aspnet_compiler -v /<<ASP.NET Application Virtual path>> <<Target Directory Path>> -u

This will pre-compile the ASP.NET application and you can XCopy the complete folder from the target location and deploy it on your production server.

How do I strong name an ASP.NET application?

You can strong name an ASP.NET application by pre-compiling the application and signing it with a strong name key. You can pre-compile and strong name ASP.NET application using either Visual Studio .NET 2005 or aspnet_compiler.exe, a command line utility. In both cases you will have to create a strong name key pair file using Strong Name (Sn.exe) utility.

Note: You can not use the password protected strong name key pair file (.pfx)

Strong naming .NET Application provides strong integrity check and can be used with strong named assemblies without needing the strong name assembly to have APTCA attribute on them.

Using Visual Studio 2005

  • In the Build option from the tool menu select Publish http://localhost/....
  • On the Publish Web Site dialog box, enter the Target Location where you want the deployable precompiled site to be copied
  • Select the Enable strong naming on precompiled assembly checkbox
  • Select the "Use a key file generated with Strong Name tool" or "Use a Key Container" radio button depending upon where your strong name key pair is stored.
  • If you choose "Use a key file generated with Strong Name tool" enter the "Key file location" and click Ok

This will pre-compile the ASP.NET application and strong name it, you can XCopy the complete folder from the target location and deploy it on your production server.

Using aspnet_compiler.exe command line utility

  • Open Visual Studio 2005 command Prompt
  • Run the following command, specifying applications virtual path, target directory and strong name key pair file.
         aspnet_compiler -v /<<ASP.NET Application Virtual path>> <<Target
         Directory Path>> -keyfile C:\test.snk

This will pre-compile the ASP.NET application and strong name it, you can XCopy the complete folder from the target location and deploy it on your production server.

How do I Sign .Net assemblies with Authenticode signature?

Use File Signing Tool (Signcode.exe) available with .Net Framework Tools. The File Signing tool signs a portable executable (PE) file (.dll or .exe file) with an Authenticode digital signature. You can sign either an assembly or an individual file contained in a multi-file assembly. If you are distributing an assembly, you should sign the assembly rather than the individual files.

Strong naming an assembly the private key used to sign the assembly is a unique for each organization, it does not provide the same level of non-repudiation that digital certificates provide. For example, there is no way to look up the developer's identity based solely on an assembly's public key. Hence it’s important to strong name and assembly and signs the .Net assemblies with Authenticode signatures.

Here are is how you sign the assemblies with Authenticode signature. Using Visual Studio command prompt run following command from following location C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Deployment\Vspkgs

>signcode /spc myCertificate.spc /v myKey.pvk myAssembly

To sign with a software publisher certificate (SPC) file, you must specify the -spc and -v options if your private key is in a PVK file. If your private key is in a registry key container, you must specify the -spc and -k options.

You can obtain a valid SPC from a Certification Authority such as VeriSign or Thawte

Obfuscation

  • How should I prevent someone from disassembling code?

How should I prevent someone from disassembling IL code?

You can not prevent any one who has copy of your assembly and full trust on a machine to disassemble your IL code. The only way to prevent people from having access to your program logic or details in the code by using obfuscation.

Obfuscation represents the program logic and internal code details incomprehensibly. Thus making it difficult for malicious users to reverse engineer your assembly and understand the program logic and internal details.

The obfuscator does not guarantee complete security but makes it difficult for the attacker to reverse engineer the code and understand the program logic thus protecting intellectual property.

Patterns and Practices home

© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Page view tracker