Export (0) Print
Expand All

Chapter 19 – Securing Your ASP.NET Application and Web Services

 

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

patterns & practices Developer Center

Improving Web Application Security: Threats and Countermeasures

J.D. Meier, Alex Mackman, Michael Dunner, Srinath Vasireddy, Ray Escamilla and Anandha Murukan
Microsoft Corporation

Published: June 2003

Last Revised: January 2006

Applies to:

  • ASP.NET version 1.1
  • Web Services (.NET Framework 1.1)
  • .NET Framework 1.1

See the "patterns & practices Security Guidance for Applications Index" for links to additional security resources.

See the Landing Page for the starting point and a complete overview of Improving Web Application Security: Threats and Countermeasures.

Summary: This chapter describes how to apply ASP.NET configuration to secure ASP.NET Web applications and Web services. It includes an overview of ASP.NET and .NET Framework configuration for administrators who are new to .NET and it explains the structure and operations of .NET Framework configuration files. The chapter explains the security related configuration settings and describes how they should be configured. The chapter also shows you how to secure ASP.NET session state, and remote data access from an ASP.NET application.

Contents

In This Chapter
Overview
How to Use This Chapter
Methodology
What You Must Know
Machine.Config and Web.Config Explained
Machine.Config and Web.Config Guidelines
Trust Levels in ASP.NET
Process Identity for ASP.NET
Impersonation
Authentication
Authorization
Session State
View State
Machine Key
Debugging
Tracing
Exception Management
Remoting
Web Services
Forbidden Resources
Bin Directory
Event Log
File Access
ACLs and Permissions
Registry
Data Access
UNC Shares
COM/DCOM Resources
Denial of Service Considerations
Web Farm Considerations
Snapshot of a Secure ASP.NET Application
Summary
Additional Resources

In This Chapter

  • Locking down an ASP.NET application
  • ASP.NET process identity security considerations
  • Encrypting account credentials in configuration files
  • Enforcing machine-wide and Web application security policy
  • Accessing resources securely from ASP.NET
  • Securing a Web service configuration
  • Securing a Forms authentication configuration
  • Securing ASP.NET session state and view state
  • Securing a Web farm
  • A reference table that illustrates a secure ASP.NET application
  • Attributes of a secure ASP.NET application

Overview

Secure ASP.NET Web applications rely on a fully secured network, host, and platform infrastructure. When trust boundaries are set at each level to block the intruder, the attacker will attempt to exploit vulnerabilities in Web applications and Web services that are listening on port 80. If the Web application is configured defectively, attackers can gain access and exploit the system. As an administrator, you should review the default machine-level configuration and the individual application configurations to address and remove any vulnerable and insecure settings.

This chapter describes what is new with ASP.NET from a system administrator's standpoint and how to configure machine-wide and application-specific security settings.

How to Use This Chapter

This chapter focuses on the key security considerations for ASP.NET applications. To get the most out of this chapter:

  • Read Chapter 16, "Securing Your Web Server." This shows you how to secure the Microsoft® Windows® 2000 / Microsoft Windows Server™ 2003 operating system and the Microsoft .NET Framework. A secure underlying platform is a prerequisite for securing an ASP.NET Web application or Web service.
  • Use the snapshot. Table 19.4, which is at the end of this chapter, gives a snapshot of a secure ASP.NET application with secure configuration settings in Machine.config and Web.config. Use this table when configuring your server and application settings.
  • Use the checklist. The "Checklist: Securing Your ASP.NET Application" in the "Checklist" section of this guide provides a printable job aid for quick reference. Use the task-based checklist to quickly evaluate the scope of the required steps and to help you work through individual steps.

For related guidance, read Chapter 20, "Hosting Multiple ASP.NET Applications," which shows you how to isolate multiple Web applications running on the same server from critical system resources and from one another. For more information about configuring code access security (CAS) policy for partial-trust Web applications and Web services, see Chapter 9, "Using Code Access Security with ASP.NET."

Methodology

To secure your ASP.NET application, start with a hardened operating system and .NET Framework installation base, and then apply secure application configuration settings to reduce the application's attack profile. The methodology that is applied in this chapter to secure ASP.NET Web applications and Web services is consistent with the methodology used to secure the underlying Web server host, and it shares common configuration categories. These include:

  • Services. The .NET Framework installs the ASP.NET state service to manage out-of-process ASP.NET session state. Secure the ASP.NET state service if you install it. Disable the ASP.NET state service if you do not require it.
  • Protocols. Restrict Web service protocols to reduce the attack surface area.
  • Accounts. The default ASPNET account is created for running Web applications, Web services, and the ASP.NET state service. If you create custom accounts to run processes or services, they must be configured as least privileged accounts with the minimum set of required NTFS permissions and Windows privileges.
  • Files and Directories. Application Bin directories that are used to hold private assemblies should be secured to mitigate the risk of an attacker downloading business logic.
  • Configuration Store. Many security-related settings that control functional areas such as authentication, authorization, session state, and so on, are maintained in the Machine.config and Web.config XML configuration files. To secure ASP.NET applications, you must use secure configuration settings.

What You Must Know

Before you begin securing your Web applications and Web services, there are overarching considerations and details of which you should be aware.

ASP.NET Process Model

In Microsoft Windows 2000, Internet Information Services (IIS) 5.0 runs all Web applications and Web services in the ASP.NET worker process (Aspnet_wp.exe). The unit of isolation is the application domain and each virtual directory has its own application domain. Process-level configuration settings are maintained by the <processModel> element in Machine.config.

In Microsoft Windows Server 2003, IIS 6.0 application pools allow you to isolate applications using separate processes. For more information, see Chapter 20, "Hosting Multiple ASP.NET Applications."

ASP.NET Account

With IIS 5.0 running on Windows 2000, the ASPNET account is a least privileged, local account created when you install the .NET Framework. By default, it runs the ASP.NET worker process and the ASP.NET state service.

If you decide to run Web applications using a custom account, make sure you configure the account with minimum privileges. This reduces the risks associated with an attacker who manages to execute code using the application's security context. You must also specify the account's credentials on the <processModel> element. Make sure you do not store credentials in plaintext. Instead, use the Aspnet_setreg.exe tool to store encrypted credentials in the registry. The custom account must also be granted the appropriate NTFS permissions.

Note   With IIS 6.0 running on Windows Server 2003, the Network Service account is a least privileged account. By default, this account runs the ASP.NET worker process and the ASP.NET state service.. For more information, see "How To: Create a Service Account for an ASP.NET 2.0 Application."

Aspnet_setreg.exe and Process, Session, and Identity

Note   The .NET Framework 2.0 provides a protected configuration feature to encrypt configuration data. For more information, see "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI" and "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA."

The following information is applicable to .NET Framework 1.1 only.

Aspnet_setreg.exe allows you to store credentials and connection strings in encrypted format in the registry. This tool allows you to encrypt the following attributes:

  • <processModel userName = password= />
  • <identity username = password= />
  • <sessionState sqlConnectionString = stateConnectionString= />

The following example shows the <processModel> element with a custom account both before and after running Aspnet_setreg.exe to secure the credentials:

<!--Before-->
<processModel userName="CustomAccount" password="Str0ngPassword" />
<!--After-->
<processModel
 userName="registry:HKLM\SOFTWARE\YourApp\process\ASPNET_SETREG,userName"
 password="registry:HKLM\SOFTWARE\YourApp\process\ASPNET_SETREG,password"/>

You can choose the registry location that stores the encrypted data, although it must be beneath HKEY_LOCAL_MACHINE. In addition to encrypting the data using the Data Protection API (DPAPI) and storing it in the registry, the tool applies a secure ACL to restrict access to the registry key. The ACL on the registry key grants Full Control to System, Administrators, and Creator Owner. If you use the tool to encrypt the credentials for the <identity> element or the connection string for the <sessionState> element, you must also grant read access to the ASP.NET process account.

To obtain the Aspnet_setreg.exe tool and for more information, see Microsoft Knowledge Base article 329290, "How To: Use the ASP.NET Utility to Encrypt Credentials and Session State Connection Strings."

Impersonation is Not the Default

By default, ASP.NET applications do not impersonate. As a result, resource access is performed using the ASP.NET worker process identity. You must grant the process identity read access (at minimum) to the Windows resources that your application requires access to by creating an appropriately configured ACL.

If you do enable impersonation, you can either impersonate the original caller — that is, the IIS authenticated identity — or a fixed identity specified on the <identity> element. For more information, see "Impersonation" later in this chapter.

Generally, ASP.NET applications do not use impersonation because it can negatively affect design, implementation, and scalability. For example, using impersonation prevents effective middle-tier connection pooling, which limits application scalability. Impersonation might make sense in specific scenarios, for example, when the application uses the anonymous user account's security context for resource access. This is a common technique often used when multiple applications are hosted on the same server. For more information, see Chapter 20, "Hosting Multiple ASP.NET Applications."

HttpForbiddenHandler, Urlscan, and the 404.dll

There are a number of techniques you can use to prevent access to restricted resources. ASP.NET provides the HttpForbiddenHandler to which you can map ASP.NET file types that should not be downloadable over HTTP. Mappings are applied using the <httpHandlers> element.

IISLockdown.exe provides the 404.dll. Using this, you can configure IIS to map unwanted file extensions to the 404.dll, which results in the "HTTP 404 - File not found" message when the file type is requested.

Finally, the URLScan ISAPI filter can be used to block requests for restricted file types and program executables. URLScan ships with the IISLockdown tool, although it can be obtained separately. For more information, see Microsoft Knowledge Base article 307608, "INFO: Availability of URLScan Version 2.5 Security Tool," and "How To: Use URLScan" in the "How To" section of this guide.

For more information about IISLockdown and URLScan, see Chapter 16, "Securing Your Web Server."

Note   By default, IIS 6.0 has security-related configuration settings similar to those made by the IIS Lockdown Tool. Therefore, you do not need to run the IIS Lockdown Tool on Web servers running IIS 6.0.
IIS 6.0 on Windows Server 2003 has functionality equivalent to URLScan built in. Your decision whether to install UrlScan should be based on your specific organizational requirements. For more information, see "Installing UrlScan 2.5" under "UrlScan Security Tool" at http://technet.microsoft.com/en-us/security/cc242650.aspx.

AppSettings

The <appSettings> element in Web.config allows applications to store configuration data, such as database connection strings or service account credentials. The advantage of this element is that it allows developers to centralize and standardize the storage and retrieval of configuration data. A single location in Web.config also eases administration and deployment.

Sensitive data, such as connection strings and credentials, should not be stored in plaintext format in configuration files. Instead, the developer should use DPAPI to encrypt secrets prior to storage.

For more information about AppSettings, see the "AppSettings in ASP.NET" show on MSDN® TV at http://msdn.microsoft.com/Message-Error.htm?aspxerrorpath=/cc311642.aspx.

Note   The .NET Framework 2.0 supports a configuration section named connectionStrings that can be used for storing database connection strings. Additionally, .NET Framework 2.0 provides a protected configuration feature to encrypt configuration data. For more information, see "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI" and "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA."

Machine.Config and Web.Config Explained

The configuration management provided by the .NET Framework encompasses a broad range of settings that allow an administrator to manage the Web application and its environment. These settings are stored in XML configuration files, some of which control machine-wide settings, while others control application-specific configuration.

XML configuration files can be edited with any text editor, such as Notepad, or with XML editors. XML tags are case sensitive, so ensure that the correct case is used.

Figure 19.1 shows the configuration files used to configure ASP.NET Web applications that are available to administrators.

Ff648667.f19thcm01(en-us,PandP.10).gif

Figure 19.1

ASP.NET configuration files

The Machine.config and Web.config files share many of the same configuration sections and XML elements. Machine.config is used to apply machine-wide policy to all .NET Framework applications running on the local computer. Developers can also use application-specific Web.config files to customize settings for individual applications.

Note   The .NET Framework 2.0 provides a machine-level Web.config file that has ASP.NET–specific configuration settings. The .NET Framework 2.0 also provides an Aspnet.config file that can be used to change the default behavior of ASP.NET applications for flowing the impersonation token across threads.
Note   Windows executables, such as WinForm applications, are configured using configuration files. The names of these files are derived from the application executable name, for example, App.exe.config, where app is the application name.

Changes that you make to configuration files are applied dynamically and do not normally require that you restart the server or any service, except if changes are made to the <processModel> element in Machine.config, which is discussed later in this chapter.

Table 19.1 shows where the configuration files are located.

Table 19.1   Configuration File Locations

Configuration fileLocation
Machine.config
(one per machine per installed version of the .NET Framework)
%windir%\Microsoft.NET\Framework\{version}\CONFIG
Web.config
(zero, one, or many per application)
\inetpub\wwwroot\web.config

\inetpub\wwwroot\YourApplication\web.config

\inetpub\wwwroot\YourApplication\SubDir\web.config

Enterprisesec.config
(enterprise-level CAS) configuration)
%windir%\Microsoft.NET\Framework\{version}\CONFIG
Security.config
(machine-level CAS configuration)
%windir%\Microsoft.NET\Framework\{version}\CONFIG
Security.config
(user-level CAS configuration)
\Documents and Settings\{user}\Application Data
\Microsoft\CLR Security Config\{version}
Web_hightrust.config

Web_mediumtrust.config

Web_lowtrust.config

Web_minimaltrust.config
(ASP.NET Web application CAS configuration)

%windir%\Microsoft.NET\Framework\{version}\CONFIG

For more information about ASP.NET Web application CAS configuration files, see Chapter 9, "Using Code Access Security with ASP.NET."

Hierarchical Policy Evaluation

Important   The .NET Framework 2.0 provides a machine-level Web.config file that has ASP.NET-specific configuration settings. In the discussion below, for .NET 2.0, you must evaluate both the machine.config and the machine-level Web.config files.

For centralized administration, settings can be applied in the Machine.config file. The settings in the Machine.config file define machine-wide policy and can also be used to apply application-specific configuration using <location> elements. Developers can provide application-configuration files to override aspects of machine policy. For ASP.NET Web applications, a Web.config file is located in the application's virtual root directory and optionally in subdirectories beneath the virtual root. Consider the arrangement shown in Figure 19.2.

Ff648667.f19thcm02(en-us,PandP.10).gif

Figure 19.2

Hierarchical configuration for .NET 1.1

In Figure 19.2, the AppRoot Web application has a Web.config file in its virtual root directory. SubDir1 (not a virtual directory) also contains its own Web.config file, which gets applied when an HTTP request is directed at http://AppRoot/SubDir1. If a request is directed at SubDir2 (a virtual directory) through AppRoot, for example, http://Server/AppRoot/SubDir2, settings from the Machine.config file and the Web.config file in the AppRoot directory are applied. If, however, a request is directed at SubDir2 bypassing AppRoot, for example, http://Server/SubDir2, then only the settings from the Machine.config file are applied.

In all cases, base settings are obtained from the Machine.config file. Next, overrides and additions are applied from any relevant Web.config files.

If the same configuration element is used in the Machine.config file and in one or more Web.config files, the setting from the file lowest in the hierarchy overrides the higher-level settings. New configuration settings that are not applied at the machine level can also be applied to application Web.config files and certain elements can clear the parent-level settings using the <clear> element.

The following table shows where the combined configuration settings are obtained from for a combination of Web requests that apply to Figure 19.2.

Table 19.2   Applying Configuration Settings

HTTP RequestCombined Settings Obtained From
http://Server/AppRootMachine.config

Web.config (AppRoot v-dir)

http://Server/AppRoot/SubDir1Machine.config

Web.config (AppRoot v-dir)

Web.config (SubDir1)

http://Server/AppRoot/SubDir2Machine.config

Web.config (AppRoot v-dir)

http://Server/Subdir2Machine.config

<location>

The <location> element is used for three main purposes:

  • To apply configuration settings to specific application files.
  • To centralize administration by applying application-specific settings in Machine.config.
  • To lock configuration settings to prevent override at the application level.

The <location> tag can be used in the Machine.config file or the Web.config file. With Machine.config, if you specify the path, it must be fully qualified and include the Web site name, virtual directory name, and optionally, a subdirectory and file name. For example:

<location path="Web Site Name/VDirName/SubDirName/PageName.aspx" >
  <system.web>
   . . .
  </system.web>
</location>
Note   You must include the Web site name when using the location tag from Machine.config.

With Web.config, the path is relative from the application's virtual directory. For example:

<location path="SubDirName/PageName.aspx" >
   <system.web>
   . . .
   </system.web>
</location>

Applying Configuration Settings to Specific Files

Use the path attribute to apply configuration settings for a specific file. For example, to apply authorization rules to the file Pagename.aspx from within Web.config, use the following <location> element:

<location path="SubDirName/PageName.aspx" >
  <system.web>
    <authorization>
      <deny roles="hackers" />
    </authorization>
    </system.web>
</location>

Applying Application Configuration Settings in Machine.config

You can also apply application-specific settings in Machine.config by using <location> statements that specify paths to application directories. This has the advantage of centralizing administration. For example, the following fragment shows how to enforce the use of Windows authentication and prevent the use of impersonation in a particular application.

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

Locking Configuration Settings

To prevent individual applications from overriding machine-level policy configuration, place settings within a <location> element in Machine.config and set the allowOverride="false" attribute.

For example, to apply machine-wide policy that cannot be overridden at the application level, use the following <location> element:

<location path="" allowOverride="false">
  <system.web>
    ... machine-wide defaults
  </system.web>
</location>

By leaving the path attribute empty, you indicate that the settings apply to the machine, while allowOverride="false" ensures that Web.config settings do not override the specified values. Any attempt to add elements in Web.config will generate an exception, even if the elements in Machine.config match with those of Web.config.

Machine.Config and Web.Config Guidelines

Settings in Machine.config apply machine-level defaults for your server. Where you want to enforce a particular configuration for all applications on your server, use allowOverride="false" on the <location> element as described above. This is particularly appropriate for hosting scenarios, where you need to enforce aspects of security policy for all applications on the server.

Note   Additionally, .NET 2.0 provides a machine-level Web.config file that has ASP.NET-specific configuration settings.

For those settings that can be configured on an individual application basis, it is normal for the application to provide a Web.config file. While it is possible to configure individual applications from Machine.config using multiple <location> elements, separate application-level Web.config files provide deployment advantages and lead to smaller Machine.config files.

The main item to consider is which settings should be enforced by machine policy. This depends on your specific scenario. Some common scenarios follow:

  • Windows authentication. Consider a corporate intranet portal scenario where you want authentication to be abstracted away from the application and controlled by the organization through Active Directory. In this scenario, you can enforce Windows authentication, but allow individual applications to impersonate with the following configuration:
    <location path="" allowOverride="false">
      <system.web>
        <authentication mode="Windows"/>
      </system.web>
    </location>
    
  • Hosting scenario. Hosting companies need to constrain applications so they cannot access each other's resources and so that they have limited access to critical system resources. To do so, you can configure all applications to run at a partial-trust level. For example, the medium-trust level constrains an application so that it can only access files within its own virtual directory hierarchy and restricts access to other types of resources. For more information, see Chapter 9, "Using Code Access Security with ASP.NET." To apply a medium-trust policy for all applications on your server, use the following configuration:
    <location path="" allowOverride="false>
      <system.web>
        <trust level="Medium" />
      </system.web>
    </location>
    

ACLs and Permissions

Configuration files contain sensitive data and therefore require appropriately configured ACLs to restrict access.

Machine.config

By default, Machine.config is configured with the following ACL:

Administrators: Full Control
System: Full Control
Power Users: Modify
Users: Read and Execute
LocalMachine\ASPNET (process identity): Read and Execute
Note   On Windows Server 2003, the Local Service and Network Service accounts are also granted read access.

Members of the Users group are granted read access by default, since all managed code that runs on the computer must be able to read Machine.config.

The default ACL on Machine.config is a secure default. If, however, you only have a single Web application running on the server, or all of your Web applications use the same process identity, you can further restrict the ACL by removing the user's access control entry (ACE). If you do remove "users" from the DACL, you need to explicitly add the Web process identity.

Web.config

The .NET Framework does not install any Web.config files. If you install an application that supplies its own Web.config, it usually inherits its ACL from the inetpub directory, which by default grants read access to members of the Everyone group. To lock down an application-specific Web.config, use one the following ACLs.

For .NET Framework version 1.0:

Administrators: Full control
System: Full control
ASP.NET process identity: Read
UNC Identity: Read
Impersonated Identity (Fixed Identity): Read
Impersonated Identity (Original Caller): Read

For .NET Framework version 1.1:

Administrators: Full control
System: Full control
ASP.NET process identity: Read
UNC Identity: Read
Impersonated Identity (Fixed Identity): Read

If your applications use impersonation of an explicit account (that is, if they impersonate a fixed identity), such as <identity impersonate="true" username="WebUser" password="Y0urStr0ngPassw0rd$"/>, then both that account (WebUser, in this case) and the process need Read access.

If your code base is on a Universal Naming Convention (UNC) share, you must grant read access to the IIS-provided UNC token identity.

If you are impersonating but not using explicit credentials, such as <identity impersonate="true"/>, and no UNC, then only the process should need access in the .NET Framework 1.1. For the .NET Framework 1.0, you must additionally configure the ACL to grant read access to any identity that will be impersonated (that is, you must grant read access to the original caller).

Trust Levels in ASP.NET

An application's trust level determines the permissions it is granted by CAS policy. This determines the extent to which the application can access secure resources and perform privileged operations.

<trust>

Use the <trust> element to configure the application's trust level. By default, the configuration level is set to Full, as shown below:

<!--  level="[Full|High|Medium|Low|Minimal]" -->
<trust level="Full" originUrl=""/>

This means that the application is granted full and unrestricted CAS permissions. With this configuration, the success or failure of any resource access performed by the application depends only on operating system security.

If you change the trust level to a level other than Full, you may break existing ASP.NET Web applications depending on the types of resources they access and the operations they perform. Applications should be thoroughly tested at each trust level.

For more information about building partial-trust Web applications that use CAS, see Chapter 9, "Using Code Access Security with ASP.NET." For more information about using trust levels to provide application isolation, see Chapter 20, "Hosting Multiple ASP.NET Web Applications."

Process Identity for ASP.NET

ASP.NET Web applications and Web services run in a shared instance of the ASP.NET worker process (Aspnet_wp.exe). Process-level settings, including the process identity, are configured using the <processModel> element in Machine.config.

Note   With IIS 6.0 running on Windows Server 2003 in process isolation mode, by default, ASP.NET applications and Web Services run in different instances of the ASP.NET worker process (w3wp.exe) using the application pool named ASP.NET V2.0. This application pool uses the built-in Network Service account. The processModel user credential settings are ignored in this scenario.

<processModel>

The identity for the ASP.NET worker process is configured using the userName and password attributes on the <processModel> element. When you configure process identity:

  • Use the default ASPNET account.
  • Use a least-privileged custom account.
  • Encrypt <processModel> credentials.
  • Do not run ASP.NET as SYSTEM.

Use the Default ASPNET Account

The local ASPNET account is the default least privileged account specifically for running ASP.NET Web applications and Web services. Use this account if you can by using the following default configuration:

<processModel enable="true" userName="machine" password="AutoGenerate" ... />

Use a Least Privileged Custom Account

If you must use an alternate identity to run the ASP.NET worker process, make sure the account that you use is configured as a least privileged account. This limits the damage that can be done by an attacker who manages to execute code using the process security context.

You might decide to use an alternate account because you need to connect to a remote Microsoft SQL Server® database or network resource using Windows authentication. Note that you can use the local ASPNET account for this purpose. For more information, see "Data Access" later in this chapter.

For more information about the NTFS permissions that the ASP.NET process account requires, see "NFTS Permission Requirements" later in this chapter.

You should also grant the following user rights to the ASP.NET process accounts:

  • Access this computer from the network.
  • Logon as a batch job.
  • Logon as a service.
  • Deny logon locally.
  • Deny logon through terminal services.
Note   With IIS 6.0 running on Windows Server 2003 in process isolation mode, you can configure the application pool to run with the least-privileged custom account. For more information, see "How To: Create a Service Account for an ASP.NET 2.0 Application."

Encrypt <processModel> Credentials

If you need to use a custom account, do not store plaintext credentials in Machine.config. Use the Aspnet_setreg.exe utility to store encrypted credentials in the registry.

To encrypt credentials for <processModel>

  1. Run the following command from the command prompt:
    aspnet_setreg -k:Software\YourApp\process -u:CustomAccount :p:StrongPassword
    

    This stores the encrypted credentials in the specified registry key and secures the registry key with a restricted ACL that grants Full Control to System, Administrators, and Creator Owner.

  2. Reconfigure the <processModel> element and add the following userName and password attributes.
    <processModel
    userName="registry:HKLM\SOFTWARE\YourApp\process\ASPNET_SETREG,userName"
    password="registry:HKLM\SOFTWARE\YourApp\process\ASPNET_SETREG,password"/>
    

For more information, see Microsoft Knowledge Base article 329290, "How To: Use the ASP.NET Utility to Encrypt Credentials and Session State Connection Strings."

Do Not Run ASP.NET as SYSTEM

Do not use the SYSTEM account to run ASP.NET and do not grant the ASP.NET process account the "Act as part of the operating system" user right. Doing so defeats the principle of least privilege and increases the damage that can be done by an attacker who is able to execute code using the Web application's process security context.

Impersonation

By default, ASP.NET applications do not impersonate. The security context of the ASP.NET worker process account (ASPNET by default) is used when your application accesses Windows resources.

<identity>

The <identity> element is used to enable impersonation. You can impersonate:

  • The original caller (the IIS authenticated identity)
  • A fixed identity

Impersonating the Original Caller

To impersonate the original caller, use the following configuration:

<identity impersonate="true" />

The impersonation uses the access token provided by IIS that represents the authenticated caller. This may be the anonymous Internet user account, for example, if your application uses Forms authentication, or it may be a Windows account that represents the original caller, if your application uses Windows authentication.

If you do enable original caller impersonation, note the following issues:

  • Application scalability is reduced because database connections cannot be effectively pooled.
  • Administration effort increases as ACLs on back-end resources need to be configured for individual users.
  • Delegation requires Kerberos authentication and a suitably configured Windows 2000 / Windows Server 2003 environment.

For more information, see "How To: Implement Kerberos Delegation for Windows 2000" in the "How To" section of "Microsoft patterns & practices Volume I, Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication" at http://msdn.microsoft.com/en-us/library/aa302400.aspx.

For more information on using Kerberos delegation in Windows Server 2003, see "How To: Use Protocol Transition and Constrained Delegation in ASP.NET 2.0."

Impersonating a Fixed Identity

To impersonate a fixed identity, specify the identity using the userName and password attributes on the <identity> element:

<identity impersonate="true" userName="MyServiceAccount"
                             password="Str0ng!Passw0rd"/>

Do not store credentials in plaintext as shown here. Instead, use the Aspnet_setreg.exe tool to encrypt the credentials and store them in the registry.

Note   The .NET Framework 2.0 introduces a Protected Configuration feature that allows you to encrypt sensitive configuration data by using a command line tool (aspnet_regiis.exe). For more information, see "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI" and "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA."

The following information is applicable to .NET 1.1.

To encrypt credentials for <identity>

  1. Run the following command from the command prompt:
    aspnet_setreg -k:Software\YourApp\identity -u:CustomAccount :p:StrongPassword
    

    This stores the encrypted credentials in the specified registry key and secures the registry key with a restricted ACL that grants Full Control to System, Administrators, and Creator Owner.

  2. Reconfigure the <identity> element and add the following userName and password attributes.
    <identity impersonate="true"
    userName="registry:HKLM\SOFTWARE\YourApp\identity\ASPNET_SETREG,userName"
    password="registry:HKLM\SOFTWARE\YourApp\identity\ASPNET_SETREG,password"/>
    
  3. Use Regedt32.exe to create an ACL on the above registry key that grants read access to the ASP.NET process account.

For more information, see Microsoft Knowledge Base article 329290, "How To: Use the ASP.NET Utility to Encrypt Credentials and Session State Connection Strings."

Act as Part of the Operating System

The ASP.NET version 1.0 process account requires the "Act as part of the operating system" user right on Windows 2000 when you impersonate a fixed identity by specifying userName and password attributes. Because this effectively elevates the ASP.NET process account to a privilege level approaching the local System account, impersonating a fixed identity is not recommended with ASP.NET version 1.0.

Note   If you are running ASP.NET version 1.1 or .NET 2.0 on Windows 2000 or Windows 2003 Server, this user right is not required.

NTFS Permission Requirements

NTFS permissions must be appropriately configured for impersonation identities. For more information, see "NTFS Permission Requirements" later in this chapter.

Authentication

The <authentication> element configures the authentication mode that your applications use.

<authentication>

The appropriate authentication mode depends on how your application or Web service has been designed. The default Machine.config setting applies a secure Windows authentication default as shown below.

<!-- authentication Attributes:
     mode="[Windows|Forms|Passport|None]" -->
<authentication mode="Windows" />

Forms Authentication Guidelines

To use Forms authentication, set mode="Forms" on the <authentication> element. Next, configure Forms authentication using the child <forms> element. The following fragment shows a secure <forms> authentication element configuration:

<authentication mode="Forms">
  <forms loginUrl="Restricted\login.aspx"  Login page in an SSL protected folder
         protection="All"                  Privacy and integrity
         requireSSL="true"                 Prevents cookie being sent over http
         timeout="10"                      Limited session lifetime
         name="AppNameCookie"              Unique per-application name
         path="/FormsAuth"                    and path
         slidingExpiration="true" >        Sliding session lifetime
  </forms>
</authentication>

Use the following recommendations to improve Forms authentication security:

  • Partition your Web site.
  • Set protection="All".
  • Use small cookie time-out values.
  • Consider using a fixed expiration period.
  • Use SSL with Forms authentication.
  • If you do not use SSL, set slidingExpiration = "false".
  • Do not use the <credentials> element on production servers.
  • Configure the <machineKey> element.
  • Use unique cookie names and paths.

Partition Your Web Site

Separate the public and restricted access areas of your Web site. Place your application's logon page and other pages and resources that should only be accessed by authentication users in a separate folder from the public access areas. Protect the restricted subfolders by configuring them in IIS to require SSL access, and then use <authorization> elements to restrict access and force a login. For example, the following Web.config configuration allows anyone to access the current directory (this provides public access), but prevents unauthenticated users from accessing the restricted sub folder. Any attempt to do so forces a Forms login.

<system.web>
  <!-- The virtual directory root folder contains general pages.
       Unauthenticated users can view them and they do not need
       to be secured with SSL. -->
  <authorization>
    <allow users="*" />
  </authorization>
</system.web>

<!-- The restricted folder is for authenticated and SSL access only. -->
<location path="Restricted" >
  <system.web>
    <authorization>
      <deny users="?" />
    </authorization>   
  </system.web>
</location>

For additional programmatic considerations, such as how to navigate between restricted and non-restricted pages, see "Forms Authentication" in Chapter 10, "Building ASP.NET Web Pages and Controls."

Set Protection="All"

This setting ensures that the Forms authentication cookie is encrypted to provide privacy and integrity. The keys and algorithms used for cookie encryption are specified on the <machineKey> element.

Encryption and integrity checks prevent cookie tampering, although they do not mitigate the risk of cookie replay attacks if an attacker manages to capture the cookie. Also use SSL to prevent an attacker from capturing the cookie by using network monitoring software. Despite SSL, cookies can still be stolen with cross-site scripting (XSS) attacks. The application must take adequate precautions with an appropriate input validation strategy to mitigate this risk.

Use Small Cookie Time-out Values

Use small time-out values to limit the session lifetime and to reduce the window of opportunity for cookie replay attacks.

Consider Using a Fixed Expiration Period

Consider setting slidingExpiration="false" on the <forms> element to fix the cookie expiration, rather than resetting the expiration period after each Web request. This is important if you are not using SSL to protect the cookie.

Note   This feature is available with .NET Framework versions 1.1 and 2.0.

Use SSL with Forms Authentication

Use SSL to protect credentials and the authentication cookie. SSL prevents an attacker from capturing credentials or the Forms authentication cookie that is used to identify you to the application. A stolen authentication cookie is a stolen logon.

Set requireSSL="true". This sets the Secure attribute in the cookie, which ensures that the cookie is not transmitted from a browser to the server over an HTTP link. HTTPS (SSL) is required.

Note   This is a .NET Framework version 1.1 and 2.0 setting. It takes explicit programming to set the cookie Secure attribute in applications built on version 1.0. For more information and sample code, see Chapter 10, "Building Secure ASP.NET Web Pages and Controls."

If You Do Not Use SSL, Set slidingExpiration = "false"

With slidingExpiration set to false, you fix the cookie time-out period as a number of minutes from initial cookie creation. Otherwise, the time-out is renewed on each request to the Web server. If the cookie is captured, it gives an attacker as much time as he needs to access your application as an authenticated user.

Note   This feature is available in .NET Framework versions 1.1 and 2.0.

Do Not Use the <credentials> Element on Production Servers

The ability to store user credentials in XML configuration files is provided to support rapid development and limited testing. Do not use actual end-user credentials. End-user credentials should not be stored in configuration files on production servers. Production applications should implement custom user credential stores, for example, in a SQL Server database.

Configure the MachineKey

The <machineKey> element defines the encryption algorithms that are used to encrypt the Forms authentication cookie. This element also maintains encryption keys. For more information, see the "MachineKey" section in this chapter.

Use Unique Cookie Names and Paths

Use unique name and path attribute values. By ensuring unique names, you prevent problems that can occur when you host multiple applications on the same server.

Authorization

Unless a user has explicit permission to access a resource, such as a particular Web page, a resource file, a directory, and so on, the configuration should deny access by default. ASP.NET provides two configurable gatekeepers that you can use to control access to restricted resources. These are:

  • File Authorization. This gatekeeper is implemented by the ASP.NET FileAuthorizationModule HTTP module.
  • URL Authorization. This gatekeeper is implemented by the ASP.NET UrlAuthorizationModule HTTP module.

File Authorization

Only applications that use Windows authentication and have the following configuration can use this gatekeeper:

<authentication mode="Windows"/>

This gatekeeper is automatically effective when you use Windows authentication, and there is no need to impersonate. To configure the gatekeeper, configure Windows ACLs on files and folders. Note that the gatekeeper only controls access to the file types mapped by IIS to the following ASP.NET ISAPI extension: Aspnet_isapi.dll.

URL Authorization

Any application can use this gatekeeper. It is configured using <authorization> elements that control which users and groups of users should have access to the application. The default element from Machine.config is shown below:

<authorization>
  <!-- allow/deny Attributes:
     users="[*|?|name]"
        * - All users
        ? - Anonymous users
        [name] - Named user
     roles="[name]" -->
 <allow users="*"/>
</authorization>

URL Authorization Notes

Use the following to help you successfully configure URL Authorization:

  • Authorization settings in Web.config usually 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.
  • URL authorization only applies to file types that are mapped by IIS to the ASP.NET ISAPI extension: Aspnet_isapi.dll.
  • When your application uses Windows authentication, you are authorizing access to Windows user and group accounts. User names take the form of "authority\WindowsUserName" and role names take the form of "authority\WindowsGroupName", where authority is either a domain name or the local machine name depending on the account type.

    A number of well known accounts are represented with "BUILTIN" strings. For example, the local administrators group is referred to as "BUILTIN\Administrators". The local users group is referred to as "BUILTIN\Users".

    Note   With.NET Framework version 1.0, the authority and the group name are case sensitive. The group name must match the group name that appears in Windows exactly.
  • When your application uses Forms authentication, you authorize the custom user and roles maintained in your custom user store. For example, if you use Forms to authenticate users against a database, you authorize against the roles retrieved from the database.
  • You can use the <location> tag to apply authorization settings to an individual file or directory. The following example shows how you can apply authorization to a specific file (page.aspx):
    <location path="page.aspx" />
      <authorization>
        <allow users="DomainName\Bob, DomainName\Mary" />
        <deny users="*" />
      </authorization>
    </location>
    

Session State

Applications that rely on per user session state can store session state in the following locations:

  • In the ASP.NET worker process
  • In an out-of-process state service, which can run on the Web server, or on a remote server
  • In a SQL Server data store

<sessionState>

The relevant location, combined with connection details, is stored in the <sessionState> element in Machine.config. This is the default setting:

<sessionState mode="InProc"
              stateConnectionString="tcpip=127.0.0.1:42424"
              stateNetworkTimeout="10" sqlConnectionString="data
              source=127.0.0.1;Integrated Security=SSPI"
              cookieless="false" timeout="20"/>
Note   If you do not use the ASP.NET state service on the Web server, use the MMC Services snap-in to disable it.

Securing a SQL Server Session State Store

If you use a SQL Server session state store, use the following recommendations to help secure the session state:

  • Use Windows authentication to the database
  • Encrypt sqlConnectionString
  • Limit the application's login in the database
  • Secure the channel

For more information about setting up the SQL Server session state store database, see Microsoft Knowledge Base article 311209, "How To: Configure ASP.NET for Persistent SQL Server Session State Management."

Use Windows Authentication to the Database

If you use mode="SQLServer", use Windows authentication to connect to the state database and use a least privileged account, such as a duplicate local ASPNET account. This means that you can use a trusted connection, you do not have credentials in the connection string, and credentials are not passed over the wire to the database.

Encrypt the sqlConnectionString

Encrypt the sqlConnectionString attribute value using the Aspnet_setreg.exe tool. This is particularly important if you use SQL authentication to connect to the state database because of the credentials in the connection string, but it is also recommended if you use Windows authentication.

Note   If you are running .NET 2.0, you should encrypt the connectionString configuration section by using the protected configuration feature. For more information, see "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI" and "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA."

The following information is applicable to .NET 1.1.

To encrypt the sqlConnectionString

  1. Run the following command from the command prompt.
    aspnet_setreg -k:Software\YourApp\sessionState -c:{your connection string}
    

    This stores the encrypted connection string in the specified registry key and secures the registry key with a restricted ACL that grants Full Control to System, Administrators, and Creator Owner.

  2. Reconfigure the <sessionState> element and add the following sqlConnectionString attribute.
    <sessionState mode="SQLServer"
    sqlConnectionString="registry:HKLM\SOFTWARE\YourApp\sessionState\ASPNET_SETREG,sqlConnectionString" />
    
  3. Use Regedt32.exe to create an ACL on the above registry key that grants read access to the ASP.NET process account.

Limit the Application's Login in the Database

The application's login in the database should be restricted so that it can only be used to access the necessary state tables and the stored procedures used by ASP.NET to query the database.

Note   With IIS 6.0 running on Windows Server 2003 in process isolation mode, the default ASP.NET process identity is identified on the network as DomainName\MachineName$. You can use this identity to configure database access in the following steps instead of using mirror accounts.

To limit the application's login in the state database

  1. Create a duplicate local account on the state database server with the same name and strong password of the account that runs your ASP.NET application.

    For more information about using the ASPNET account to access a remote database, see "Data Access" later in this chapter.

  2. Create a local Windows group, for example ASPNETWebApps, on the database server and add the local ASPNET account to the group.
  3. Grant the Windows group access to SQL Server by creating a new login.
    sp_grantlogin 'MACHINE\ASPNETWebApps'
    
    Note   Replace MACHINE with your database server name.
  4. Grant the SQL login access to the ASPState database. The following T-SQL creates a database user called WebAppUser, with which the login is associated.
    USE ASPState
    GO
    sp_grantdbaccess 'MACHINE\ASPNETWebApps', 'WebAppUser'
    
  5. Create a user-defined database role.
    USE ASPState
    GO
    sp_addrole 'WebAppUserRole'
    
  6. Add the database user to the new database role.
    USE ASPState
    GO
    sp_addrolemember 'WebAppUserRole', 'WebAppUser'
    
  7. Configure permissions in the database for the database role. Grant execute permissions for the stored procedures that are provided with the ASPState database.
    grant execute on CreateTempTables to WebAppUserRole
    

    Repeat this command for all of the stored procedures that are provided with the ASPState database. Use SQL Server Enterprise Manager to see the full list.

Secure the Channel

To protect sensitive session state over the network between the Web server and remote state store, secure the channel to the two servers using IPSec or SSL. This provides privacy and integrity for the session state data across the network. If you use SSL, you must install a server certificate on the database server. For more information about using SSL with SQL Server, see Chapter 18, "Securing Your Database Server."

Securing the Out-of-Process State Service

If you use mode=StateServer, use the following recommendations to help secure session state:

  • Use a least privileged account to run the state service
  • Secure the channel
  • Consider changing the default port
  • Encrypt the state connection string

Use a Least Privileged Account to Run the State Service

The state service runs by default using the ASPNET local, least privileged account. You should not need to change this configuration.

Secure the Channel

If the state service is located on a remote server, secure the channel to the remote state store using IPSec to ensure the user state remains private and unaltered.

Consider Changing the Default Port

The ASP.NET state service listens on port 42424. To avoid using this default, well known port, you can change the port by editing the following registry key:

HKLM\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters

The port number is defined by the Port named value. If you change the port number in the registry, for example, to 45678, you must also change the connection string on the <sessionState> element, as follows:

stateConnectionString="tcpip=127.0.0.1:45678"

Encrypt the stateConnectionString

Encrypt the stateConnectionString attribute value to hide the IP address and port number of your state store. Use the Aspnet_setreg.exe tool.

Note   If you are running .NET 2.0, you should encrypt the sessionState configuration section by using the Protected Configuration feature. For more information, see "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI" and "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA."

If you are running .NET 1.1, use the Aspnet_setreg.exe tool by performing the following procedure.

To encrypt the stateConnectionString

  1. Run the following command from the command prompt.
    aspnet_setreg -k:Software\YourApp\sessionState -d:{your connection string}
    

    This stores the encrypted connection string in the specified registry key and secures the registry key with a restricted ACL that grants Full Control to System, Administrators, and Creator Owner.

  2. Reconfigure the <sessionState> element and add the following stateConnectionString attribute:
    <sessionState mode="StateServer"
    sqlConnectionString="registry:HKLM\SOFTWARE\YourApp\sessionState\ASPNET_SETREG,sqlConnectionString" ... />
    
  3. Use Regedt32.exe to create an ACL on the above registry key that grants read access to the ASP.NET process account.

View State

If your applications use view state, make sure it is protected with message authentication codes (MACs) to ensure it is not modified at the client. View state and MAC protection can be enabled or disabled for all applications on the machine using the <pages> element in Machine.config.

<pages>

By default, the enableViewStateMac attribute on the <pages> element in Machine.config ensures that view state is protected with a MAC.

<pages buffer="true" enableSessionState="true"
       enableViewState="true" enableViewStateMac="true"
       autoEventWireup="true" validateRequest="true"/>

If you use view state, make sure that enableViewStateMac is set to true. The <machineKey> element defines the algorithms used to protect view state.

Machine Key

The <machineKey> element is used to specify encryption keys, validation keys, and algorithms that are used to protect Forms authentication cookies and page-level view state. The following code sample shows the default setting from Machine.config:

For .NET 1.1:
<machineKey validationKey="AutoGenerate,IsolateApps"
            decryptionKey="AutoGenerate,IsolateApps" validation="SHA1"/>
For .NET 2.0:
<machineKey validationKey="AutoGenerate,IsolateApps"  
            decryptionKey="AutoGenerate,IsolateApps" 
            validation="SHA1" decryption="Auto" />
Note   ASP.NET version 2.0 introduces the decryption attribute in the <machineKey> element. This attribute specifies the symmetric encryption algorithm used to encrypt and decrypt Forms authentication tickets. For more information see How To: Configure MachineKey in ASP.NET 2.0.

Consider the following recommendations when you configure the <machineKey>:

  • Use unique encryption keys with multiple applications
  • Set validation="SHA1"
  • Generate keys manually for Web farms

Use Unique Encryption Keys with Multiple Applications

If you host multiple applications on a single Web server, use unique keys for each application on the machine instead of using a single key across all applications. This eliminates the likelihood that one application can spoof view state or encrypted Forms authentication cookies in hosting environments.

Also use the IsolateApps setting. This setting instructs ASP.NET to automatically generate encryption keys and to make them unique for each application.

Set validation="SHA1"

The validation attribute specifies the algorithm used for integrity-checking, page-level view state. Possible values are "SHA1", "MD5", and "3DES".

If you used protection="All" on the <forms> element, then the Forms authentication cookie is encrypted, which also ensures integrity. Regardless of the validation attribute setting, Forms authentication uses TripleDES (3DES) to encrypt the cookie.

Note   Forms-authentication cookie encryption is independent of the validationkey setting, and the key is based on the decryptionKey attribute.

If you set validation="SHA1" on the <machineKey>, then page-level view state is integrity checked using the SHA1 algorithm, assuming that the <pages> element is configured for view state MACs. For more information, see "View State" earlier in this chapter.

You can also set the validation attribute to MD5. You should use SHA1 because this produces a larger hash than MD5 and is therefore considered more secure.

If you set validation="3DES" on the <machineKey>, then page-level view state is encrypted (which also provides integrity checking) using the 3DES algorithm, even if the <pages> element is configured for view state MACs.

Generate Keys Manually For Web Farms

In Web farms, you must set explicit key values and use the same ones across all machines in the Web farm. See "Web Farm Considerations" later in this chapter.

Debugging

The <compilation> element controls compiler settings that are used for dynamic page compilation, which is initiated when a client requests a Web page (.aspx file) or Web service (.asmx file). It is important that debug builds are not used on the production server because debug information is valuable to attackers and can reveal source code details.

<compilation>

This element controls the compilation process. Make sure that debug compiles are disabled on production servers. Set debug="false" as follows:

<compilation debug="false" explicit="true" defaultLanguage="vb" />

By default, temporary files are created and compiled in the following directory:

%winnt%\Microsoft.NET\Framework\{version}\Temporary ASP.NET Files

You can specify the location on a per application basis using the tempDirectory attribute, although this provides no security benefit.

Note   The ASP.NET process identity specified on the <processModel> element requires Full Control access rights on the temporary compilation directory.

Make sure you do not store debug files (with .pdb extensions) on a production server with your assemblies.

Tracing

Tracing should not be enabled on production servers because system-level trace information can greatly help an attacker profile an application and probe for weak spots.

<trace>

Tracing is configured using the <trace> element. Set enabled="false" on production servers as follows:

<trace enabled="false" localOnly="true" pageOutput="false"
       requestLimit="10" traceMode="SortByTime"/>

If you do need to trace problems with live applications, it is preferable that you simulate the problem in a test environment, or if necessary, enable tracing and set localOnly="true" to prevent trace details from being returned to remote clients.

Exception Management

Do not allow exception details to propagate from your Web applications back to the client. A malicious user could use system-level diagnostic information to learn about your application and probe for weaknesses to exploit in future attacks.

<customErrors>

The <customErrors> element can be used to configure custom, generic error messages that should be returned to the client in the event of an application exception condition. The error page should include a suitably generic error message, optionally with additional support details. You can also use this element to return different error pages depending on the exception condition.

Make sure that the mode attribute is set to "On" and that you have specified a default redirect page as shown below:

<customErrors mode="On" defaultRedirect="YourErrorPage.htm" />

The defaultRedirect attribute allows you to use a custom error page for your application, which for example might include support contact details.

Note   Do not use mode="Off" because it causes detailed error pages that contain system-level information to be returned to the client.

If you want separate error pages for different types of error, use one or more <error> elements as shown below. In this example, "404 (not found)" errors are redirected to one page, "500 (internal system errors)" are directed to another page, and all other errors are directed to the page specified on the defaultRedirect attribute.

<customErrors mode="On" defaultRedirect="YourErrorPage.htm">
   <error statusCode="404" redirect="YourNotFoundPage.htm"/>
   <error statusCode="500" redirect="YourInternalErrorPage.htm"/>
</customErrors>

Remoting

Do not expose .NET Remoting endpoints on Internet-facing Web servers. To disable Remoting, disable requests for .rem and .soap extensions by mapping requests for these file extensions to the HttpForbiddenHandler. Use the following elements beneath <httpHandlers>:

<httpHandlers>
  <add verb="*" path="*.rem" type="System.Web.HttpForbiddenHandler"/>
  <add verb="*" path="*.soap" type="System.Web.HttpForbiddenHandler"/>
  . . .
</httpHandlers>
Note   This does not prevent a Web application on the Web server from connecting to a downstream object by using the Remoting infrastructure. However, it prevents clients from being able to connect to objects on the Web server.

Web Services

Configure Web services using the <webServices> element. To establish a secure Web services configuration:

  • Disable Web services if they are not required
  • Disable unused protocols
  • Disable the automatic generation of WSDL

Disable Web Services if They Are Not Required

If you do not use Web services, disable them by mapping requests for the .asmx (Web service) file extension to HttpForbiddenHandler in Machine.config as follows:

<httpHandlers>
  <add verb="*" path="*.asmx" type="System.Web.HttpForbiddenHandler"/>
  . . .
</httpHandlers>
Note   If you are running .NET 2.0, the <httpHandlers> setting is in the machine-level Web.config file.

Disable Unused Protocols

The <protocols> element defines the protocols that Web services support. By default, HttpPost and HttpGet are disabled on .NET Framework versions 1.1 and 2.0 as follows:

<webServices>
  <protocols>
    <add name="HttpSoap1.2"/>
    <add name="HttpSoap"/>
    <!-- <add name="HttpPost"/> -->
    <!-- <add name="HttpGet"/> -->
    <add name="HttpPostLocalhost"/>
    <add name="Documentation"/>
  </protocols>
</webServices>

By disabling unnecessary protocols, including HttpPost and HttpGet, you reduce the attack surface area. For example, it is possible for an external attacker to embed a malicious link in an e-mail to execute an internal Web service using the end user's security context. Disabling the HttpGet protocol is an effective countermeasure. In many ways, this is similar to an XSS attack. A variation of this attack uses an <img src="..." /> tag on a publicly accessible Web page to embed a GET call to an intranet Web service. Both attacks can allow an outsider to invoke an internal Web service. Disabling protocols mitigates the risk.

If your production server provides publicly discoverable Web services, you must enable HttpGet and HttpPost to allow the service to be discovered over these protocols.

Disable the Automatic Generation of WSDL

The Documentation protocol is used to dynamically generate Web Service Description Language (WSDL). WSDL describes the characteristics of a Web service, such as its method signatures and supported protocols. Clients use this information to construct appropriately formatted messages. By default, Web services publicly expose WSDL, which makes it available to anyone who can connect to the Web server over the Internet.

At times, you might want to distribute the WSDL files manually to your partners and prevent public access. With this approach, the development team can provide individual .wsdl files for each Web service to the operations team. The operations team can then distribute them to specified partners who want to use the Web services.

To disable the Documentation protocol, comment it out in Machine.config as follows:

<webServices>
  <protocols>
    <add name="HttpSoap"/>
    <!-- <add name="Documentation"/> -->
  </protocols>
</webServices>

Forbidden Resources

To prevent protected resources and files from being downloaded over HTTP, map them to the ASP.NET HttpForbiddenHandler.

Map Protected Resources to HttpForbiddenHandler

HTTP handlers are located in Machine.config beneath the <httpHandlers> element. HTTP handlers are responsible for processing Web requests for specific file extensions. Remoting should not be enabled on front-end Web servers; enable Remoting only on middle-tier application servers that are isolated from the Internet.

  • The following file extensions are mapped in Machine.config to HTTP handlers:
  • .aspx is used for ASP.NET pages.
  • .rem and .soap are used for Remoting.
  • .asmx is used for Web Services.
  • .asax, .ascx, .config, .cs, .csproj, .vb, .vbproj, .webinfo, .asp, .licx, .resx, and .resources are protected resources and are mapped to System.Web.HttpForbiddenHandler.

For .NET Framework resources, if you do not use a file extension, then map the extension to System.Web.HttpForbiddenHandler in the configuration file, as shown in the following example:

Note   If you are running .NET 2.0, the <httpHandlers> setting is in the machine-level Web.config file.
<add verb="*" path="*.vbproj" type="System.Web.HttpForbiddenHandler" />

In this case, the .vbproj file extension is mapped to System.Web.HttpForbiddenHandler. If a client requests a path that ends with .vbproj, then ASP.NET returns a message that states "This type of page is not served."

The following guidelines apply to handling .NET Framework file extensions:

  • Map extensions you do not use to HttpForbiddenHandler. If you do not serve ASP.NET pages, then map .aspx to HttpForbiddenHandler. If you do not use Web Services, then map .asmx to HttpForbiddenHandler.
  • Disable Remoting on Internet-facing Web servers. Map remoting extensions (.soap and .rem) on Internet-facing Web servers to HttpForbiddenHandler.

Bin Directory

The bin directory beneath an ASP.NET application's virtual root directory contains the application's private assemblies, including the application's page-class implementations if code-behind files have been used during development.

Secure the Bin Directory

To secure the application's bin directory and protect your business logic against inadvertent download:

  • Remove Web permissions.
  • Remove all authentication settings.

Remove Web Permissions

Use the IIS snap-in and ensure that the bin directory does not have Read, Write, or Directory browsing permissions. Also ensure Execute permissions are set to None.

Remove All Authentication Settings

Use the IIS snap-in to remove authentication settings from the bin directory. This results in all access being denied.

Event Log

Least privileged accounts, such as the default ASP.NET process identity, have sufficient permissions to be able to write records to the event log using existing event sources. However, they do not have sufficient permissions to create new event sources. To do this, you must place a new entry beneath the following registry key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\<log>

To avoid this issue, you can create event sources at installation 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 if you are not. For more information about using event log installers, see Chapter 10, "Building Secure ASP.NET Web Pages and Controls."

If you are unable to create event sources at installation time, and you are in deployment, the administrator should manually create new event source entry beneath the following registry key

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\<LogName>
Note    You should not grant write permission to the ASP.NET process account (or any impersonated account if your application uses impersonation) on the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\ registry key. If you allow write access to this key and the account is compromised, the attacker can modify any log-related setting, including access control to the log, for any log on the system.

File Access

Any file that your application accesses must have an access control entry (ACE) in the ACL that grants, at minimum, read access to the ASP.NET process account or impersonated identity. Normally, ACLs are configured on the directory and the file inherits the setting.

In addition to using NTFS permissions to restrict access to files and directories, you can also use ASP.NET trust levels to place constraints on Web applications and Web services to restrict which areas of the file system they can access. For example, Medium-trust Web applications can only access files within their own virtual directory hierarchy.

For more information about ASP.NET CAS policy, see Chapter 9, "Using Code Access Security with ASP.NET."

ACLs and Permissions

The ASP.NET process account and, for certain directories, any impersonation identities (if your applications use impersonation) require the following NTFS permissions. The permissions shown in Table 19.3 should be used in addition to any permissions your applications might require to access application-specific file system resources.

Table 19.3   Required NTFS Permissions for ASP.NET Process Accounts

DirectoryRequired permissions
Temporary ASP.NET Files
%windir%\Microsoft.NET\Framework\
{version}Temporary ASP.NET Files
Process account and impersonated identities:

Full Control

Temporary Directory
(%temp%)
Process account:

Full Control

.NET Framework directory
%windir%\Microsoft.NET\Framework\
{version}
Process account and impersonated identities:

Read and Execute
List Folder Contents
Read

.NET Framework configuration directory
%windir%\Microsoft.NET\Framework\
{version}\CONFIG
Process account and impersonated Identities:

Read and Execute
List Folder Contents
Read

Web site root
C:\inetpub\wwwroot

or the path that the default Web site points to

Process account:

Read

System root directory
%windir%\system32
Process account:

Read

Global assembly cache
%windir%\assembly
Process account and impersonated identities:

Read

Content directory
C:\inetpub\wwwroot\YourWebApp
Process account:

Read and Execute
List Folder Contents
Read

Note   With .NET Framework version 1.0, all parent directories, back up to the file system root directory, also require the above permissions. Parent directories include:

C:\
C:\inetpub\
C:\inetpub\wwwroot\

Registry

Any registry key that your application accesses must have an ACE in the ACL that grants, at minimum, read access to the ASP.NET process account or impersonated identity.

Data Access

To access a remote database using Windows authentication from your ASP.NET application, you have the following options:

  • Use the default ASP.NET process account. Use the default ASP.NET process account by creating a mirrored account with the same user name and password on the database server. On Windows 2000, the default process account is ASPNET. On Windows Server 2003, the default process account is NetworkService.
    Note   With IIS 6.0 running on Windows Server 2003 in process isolation mode, the default ASP.NET process account is identified in the network as DomainName\MachineName$. You can use this account to directly configure access on the remote database, instead of using a mirrored account.

    The disadvantage of using local accounts is that if you can dump the SAM database, which requires administration privileges, then you can access the credentials. The main advantage is that local accounts can be scoped to specific servers, which is difficult to achieve using domain accounts.

  • Use a least privileged domain account to run ASP.NET. This approach simplifies administration, and it means that you do not need to synchronize the passwords of mirrored accounts. It will not work if the Web server and database server are in separate non-trusting domains, or if a firewall separates the two servers and the firewall does not permit the necessary ports for Windows authentication.
  • Impersonate the Anonymous Web account. If you are using Forms or Passport authentication, you can impersonate the anonymous Web account (IUSR_MACHINE by default) and create a mirrored account on the database server. This approach is useful in scenarios where you host multiple Web applications on the same Web server. You can use IIS to configure each application's virtual directory with a different anonymous account.

    On Windows Server 2003, you can run multiple applications in separate worker processes, using IIS 6.0 application pools and configuring a separate identity for each one.

Configuring Data Access for Your ASP.NET Application

Whichever approach you use, restrict the application's account in the database. To do this, create a SQL Server login for the account, grant it access to the required database, and restrict its permissions so that it only has access to the minimum required database objects. Ideally, you should restrict permissions so that the login has access only to the stored procedures used by your application or Web service.

The following procedure assumes that you are using a mirrored local account, but you can use the same approach with a domain account to restrict the account's capabilities in the database.

Note   With IIS 6.0 running on Windows Server 2003 in process isolation mode, the ASP.NET process identity is identified in the network as DomainName\MachineName$. You can use this account to directly configure access on the remote database, instead of using a mirrored account.

To configure database access for your ASP.NET application

  1. Use the Computer Management tool to change the password of the local ASPNET account on the Web server to a known strong password.

    You need to do this so that you can create a mirrored account on the database server.

  2. Change the password attribute on the <processModel> element in Machine.config so that the ASP.NET worker process continues to run using the ASPNET account. Use Aspnet_setreg.exe to store the encrypted credentials in the registry.
  3. Create a local account on the database server with the same name (ASPNET) and strong password on the database server.
  4. Create a local Windows group, such as ASPNETWebApp, on the database server, and then add the local ASPNET account to the group.
  5. Grant the Windows group access to SQL Server by creating a new login, as follows:
    sp_grantlogin 'MACHINE\ASPNETWebApp'
    
    Note   Replace MACHINE with your database server name.
  6. Grant the SQL login access to the database. The following T-SQL creates a database user called WebAppUser to which the login is associated.
    USE YourDatabase
    GO
    sp_grantdbaccess 'MACHINE\ASPNETWebApp', 'WebAppUser'
    
  7. Create a user-defined database role.
    USE YourDatabase
    GO
    sp_addrole 'WebAppUserRole'
    
  8. Add the database user to the new database role.
    USE YourDatabase
    GO
    sp_addrolemember 'WebAppUserRole', 'WebAppUser'
    
  9. Configure permissions in the database for the database role. Ideally, grant execute permissions only for the stored procedures that the application uses to query the database and do not provide direct table access.
    grant execute on sprocname to WebAppUserRole
    

UNC Shares

There are two main ways that your ASP.NET application might use UNC shares:

  • Accessing files on UNC shares

    For example, your application must access a remote file such as \\remoteserver\share\somefile.dat.

  • Hosting applications on UNC shares

    Your application's IIS virtual directory is mapped to a remote share, for example, \\remoteserver\appname. In this scenario, HTTP requests are processed by your Web server, but the application's pages, resources, and private assemblies are located on the remote share.

Accessing Files on UNC Shares

If your application accesses files on a UNC share, the ASP.NET process account or any impersonation identities must have the appropriate access rights defined by the ACL on the share and on the underlying directory or file.

If you use the local ASPNET process account, this does not have a network identity, so you must create a mirrored account on the remote server with a matching user name and password, or you must use a least privileged domain account that has access to both servers. On Windows Server 2003, the Network Service account that is used to run ASP.NET Web applications can be authenticated over the network, so all you need to do is grant access rights to the machine account.

Hosting Applications on UNC Shares

You can use IIS to configure a virtual directory to point to a UNC share located on another computer, for example \\remoteserver\appname. When you do so, IIS prompts you to supply account credentials, which it uses to establish a connection to the remote computer.

Note   The account credentials are stored in encrypted format in the IIS metabase but are available through an API. You should ensure that you use a least privileged account. For more information, see Microsoft Knowledge Base article 280383, "IIS Security Recommendations When You Use a UNC Share and Username and Password Credentials."

If your application resides on a UNC share, ASP.NET impersonates the IIS-provided UNC token (created from the account credentials that you supplied to IIS) to access that share, unless you have enabled impersonation and have used a fixed impersonation identity.

If a fixed impersonation account is provided through the userName and password attributes, ASP.NET uses that account instead of the IIS UNC token to access the share. Any resource access performed by your application also uses the fixed impersonation account.

If you enable impersonation of the original caller (IIS authenticated identity) by using the following configuration, ASP.NET still uses the UNC-provided token to access your application's files on the share, although any resource access performed by your application uses the impersonation token.

<identity impersonate="true" />
Note   The account used for the UNC share must also be able to read Machine.config.

Code Access Security Considerations

Applications on a UNC share are granted the intranet permission set by code access security policy. The intranet permission set does not contain AspNetHostingPermission, which ASP.NET Web applications require to run, so your application will not run without explicit policy modifications.

You have two options:

  • Grant full trust to the UNC share on which your application is hosted.

    This is the simplest option to manage and if you run .NET Framework version 1.0, this is the only option because ASP.NET version 1.0 Web applications require full trust.

  • Configure code access security policy to grant your code the AspNetHostingPermission and any other permission it might require based on the types of resources it accesses and the operations it performs.

    Because of the way in which ASP.NET dynamically creates code and compiles page classes, you must use a code group for the UNC and the Temporary ASP.NET Files directory when you configure policy. The default temporary directory is \WINNT\Microsoft.NET\Framework\{version}\Temporary ASP.NET Files, but the location is configurable on a per application basis by using the tempDirectory attribute of the <compilation> element.

    For more information about ASP.NET code access security policy and sandboxing privileged code, see Chapter 9, "Using Code Access Security with ASP.NET."

    Note   When configuring policy, you should grant trust to the share (by using a file location) rather than to the zone. This provides finer granularity because you do not affect all the applications in a particular zone.

COM/DCOM Resources

Your application uses the process or impersonation identity when it calls COM-based resources, such as serviced components. Client-side authentication and impersonation levels are configured using the comAuthenticationLevel and comImpersonation level attributes on the <processModel> element in Machine.config.

For more information and recommendations, see "Enterprise Services (COM+) Security Considerations" in Chapter 17, "Securing Your Application Server."

Denial of Service Considerations

ASP.NET has the following features to help counteract denial of service attacks aimed at your ASP.NET applications:

  • POST requests are constrained by default to 4 megabytes (MB).
  • Clients are checked to ensure that they are still connected before requests are queued for work. This is done in case an attacker sends multiple requests and then disconnects them.
  • Request execution times out after a configurable limit.

<httpRuntime>

Configuration values are maintained on the <httpRuntime> element in Machine.config. The following code sample shows default settings from a version 1.1 and 2.0 Machine.config file:

<httpRuntime executionTimeout="90"
             maxRequestLength="4096"
             useFullyQualifiedRedirectUrl="false"
             minFreeThreads="8"
             minLocalRequestFreeThreads="4"
             appRequestQueueLimit="100"
             enableVersionHeader="true"/>

You might want to reduce the maxRequestLength attribute to prevent users from uploading very large files. The maximum allowed value is 4 MB. In the Open Hack competition, the maxRequestLength was constrained to 1/2 MB as shown in the following example:

<system.web>
   <!-- 1/2 MB Max POST length -->
   <httpRuntime maxRequestLength="512"/>
</system.web>
Note   ASP.NET does not address packet-level attacks. You must address this by hardening the TCP/IP stack. For more information about configuring the TCP/IP stack, see "How To: Harden the TCP/IP Stack" in the "How To" section of this guide.

Web Farm Considerations

If your ASP.NET Web application runs in a Web farm, there is no guarantee that successive requests from the same client will be serviced by the same Web server. This has implications for:

  • Session state
  • Encryption and verification
  • DPAPI

Session State

To avoid server affinity, maintain ASP.NET session state out of process in the ASP.NET SQL Server state database or in the out-of-process state service that runs on a remote machine. For more information about securing session state in a remote state store, see the "Session State" section earlier in this document.

Encryption and Verification

The keys used to encrypt and verify Forms authentication cookies and view state must be the same across all servers in a Web farm. The AutoGenerate settings on the <machineKey> element must be replaced with common key values.

For more information on generating and configuring the keys, see Microsoft Knowledge Base article 312906, "How To: Create Keys by Using Visual C# .NET for Use in Forms."

DPAPI

To encrypt data, developers sometimes use DPAPI. If you use DPAPI with the machine key to store secrets, the encrypted string is specific to a given computer and you cannot copy the encrypted data across computers in a Web farm or cluster.

If you use DPAPI with a user key, you can decrypt the data on any computer with a roaming user profile. However, this is not recommended because the data can be decrypted by any machine on the network that can execute code using the account which encrypted the data.

DPAPI is ideally suited to storing configuration secrets, for example, database connection strings, that live on the Web server. Other encryption techniques should be used when the encrypted data is stored on a remote server, for example, in a database. For more information about storing encrypted data in the database, see Chapter 14, "Building Secure Data Access."

Snapshot of a Secure ASP.NET Application

The following snapshot view shows the attributes of a secure ASP.NET application and allows you to quickly and easily compare settings with your own configuration.

Table 19.4   Snapshot of a Secure ASP.NET Application Configuration

ComponentCharacteristics
Process identityThe ASP.NET worker process runs as ASPNET:
<processModel username="machine"
              password="AutoGenerate" />

The custom account (if used) is least privileged.

The custom account credentials are encrypted in the registry:

<processModel
    userName="registry:HKLM\SOFTWARE\YourApp\
process\ASPNET_SETREG,userName"
    password="registry:HKLM\SOFTWARE\YourApp\
process\ASPNET_SETREG,password"/>
Note   With IIS 6.0 running on Windows Server 2003 in process isolation mode, the application pool identity is used for running ASP.NET instead of the <processModel> element.
ImpersonationImpersonation identities are encrypted in the registry:
<identity impersonate="true"
          userName="registry:HKLM\SOFTWARE\YourApp\
identity\ASPNET_SETREG,userName"
          password="registry:HKLM\SOFTWARE\YourApp\
identity\ASPNET_SETREG,password"/>
Note   In ASP.NET 2.0, the <identity> configuration section can be encrypted by using the Protected Configuration feature. For more information, see "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI" and "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA."
AuthenticationThe Web site is partitioned for public and restricted access.

The Forms authentication configuration is secure:

<forms loginUrl="Restricted\login.aspx"
       protection="All"
       requireSSL="true"
       timeout="10"
       name="AppNameCookie"
       path="/FormsAuth"
       slidingExpiration="true" />

The authentication cookie is encrypted and integrity checked.

SSL is required for authentication cookie.

Sliding expiration is set to false, if SSL is it is not used.

The session lifetime is restricted.

Cookie names and paths are unique.

The <credentials> element is not used.

AuthorizationACLs are configured on ASP.NET resources.

<authorization> elements are configured.

Session stateThe ASP.NET state service is disabled if it is not required.
<sessionState  mode="Off " />

The communication channel to the remote state store is encrypted if necessary.

Windows authentication is used to connect to ASPState database.

The application login has restricted access to ASPState database.

The connection parameters (sqlConnectionString and stateConnectionString) are encrypted in the registry.

Note   In.NET 2.0, the connection strings are encrypted by using the Protected Configuration feature. For more information, see "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI" and "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA."

The ASP.NET state service is configured for a non-default port.

View stateThe view-state MAC is enabled on the <pages> element in Machine.config.
Machine keyThe validation attribute set to SHA1.

Keys are unique for each application running on the Web server.

ViewState and Forms Authentication are protected:

Forbidden resourcesProtected resources are mapped to System.Web.HttpForbiddenHandler.
DebuggingDebug builds are disabled:
<compilation debug="false" . . .
TracingTracing is disabled.
<trace enabled='false' localOnly='true . . .
Exception managementCustom errors are enabled.

Default redirect page is used:

<customErrors mode="On"
              defaultRedirect="YourErrorPage.htm" />
RemotingRemoting is disabled on Internet-facing Web servers:
<httpHandlers>
  <add verb="*" path="*.soap"
       type="System.Web.HttpForbiddenHandler"/>
  <add verb="*" path="*.rem"
       type="System.Web.HttpForbiddenHandler"/>
  . . .
</httpHandlers>
Web servicesWeb services are disabled if they are not required:
<httpHandlers>
    <add verb="*" path="*.asmx"
         type="System.Web.HttpForbiddenHandler"/>
      . . .
</httpHandlers>

Unnecessary protocols are disabled:

<webServices>
  <protocols>
      <!-- <add name="HttpPost"/> -->
      <!-- <add name="HttpGet"/> -->
 . . .

The documentation protocol is disabled to prevent the automatic generation of WSDL:

<webServices>
  <protocols>
      <!--<add name="Documentation"/>-->
. . .
Bin directoryThe bin directory is secured.

(Read, Write, and Directory browsing permissions removed from bin. Execute permissions are set to None.)

Authentication settings are removed from bin directory

Summary

This chapter has shown you how to secure an ASP.NET Web application or Web service by focusing on configuration categories that include accounts, services, protocols, files and directories, and configuration data that are maintained in Machine.config and Web.config files. This chapter has also shown you how to secure the various functional areas that are relied upon by ASP.NET Web applications and Web services, including authentication, authorization, session state, and data access.

For a related checklist, see "Checklist: Securing ASP.NET" in the "Checklist" section of this guide.

Additional Resources

For more information, see the following resources and articles:

patterns & practices Developer Center

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Show:
© 2014 Microsoft