How To: Improve Security When Hosting Multiple Applications in ASP.NET 2.0

 

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

patterns & practices Developer Center

J.D. Meier, Alex Mackman, Blaine Wastell, Prashant Bansode, Chaitanya Bijwe

Microsoft Corporation

November 2005

Applies To

  • ASP.NET version 2.0
  • Windows Server 2003
  • Internet Information Services (IIS) 6.0

Summary

This How To shows how you can isolate multiple applications from one another and from shared system resources in a Web hosting environment. The hosting environment might be a Web server provided by an Internet Service Provider (ISP) that hosts multiple untrusted applications from different companies, or it might be a shared Web server in a single organization that hosts multiple applications. Without adequate isolation, a poorly designed application or an application containing malicious code can adversely affect the operations of other applications on the server.

Contents

Objectives
Overview
What's New in 2.0
IIS 6.0 Process-Model Isolation
Summary of Steps
Step 1. Configure Your Application for Partial Trust
Step 2. Use Application Pool for Process Isolation
Step 3. Review machineKey Settings
Trust Levels Summary
Additional Resources

Objectives

  • Use code access security to isolate multiple applications on a shared server.
  • Run multiple applications in separate IIS 6.0 application pools with custom identities.
  • Establish appropriate machineKey element settings for servers that host multiple applications.

Overview

If you host multiple ASP.NET Web applications on a shared Web server, you should consider using application isolation. For example, how can you ensure that individual applications will not affect one another at run time? How can you prevent a single, poorly designed application from consuming critical system-level resources on the server that are necessary to keep other applications running properly? How can you ensure that one application from one company cannot access sensitive data contained in another company's application?

The issue of security is particularly significant for Internet Service Providers (ISPs) who host large numbers of untrusted applications from different companies. In a hosting scenario, it is essential to ensure that the installation of a new application cannot adversely affect the operation of existing applications.

The main ways to isolate ASP.NET 2.0 applications are as follows:

  • Use code access security. You can run each application with partial trust, for example, by using the ASP.NET Medium trust level. This provides a constrained execution environment (which is also known as a sandbox) for each application where permissions to access system resources and resources belonging to other applications are limited.
  • Use separate processes for each application. On Windows Server 2003 and IIS 6.0, run each application in its own application pool that is configured to run under a unique identity. This enables you to use Windows auditing to audit the activity of each application separately, and it allows you to configure Windows access control lists (ACLs) independently for each application.
  • Use separate encryption and decryption keys. Ensure that the keys specified in the machineKey element are unique for each application. These keys are used to encrypt items, including forms authentication tickets and view state. By having separate keys, you help ensure data integrity, even if data from one application is accessed by another.

What's New in 2.0

The .NET Framework version 2.0 introduces the following changes that have implications for hosting multiple applications on a shared server:

  • .NET Framework Data Providers for OLE DB, Oracle, and ODBC work in partial trust. Partial-trust Web applications can now use the .NET Framework Data Providers for OLE DB, Oracle, and ODBC to access data sources because these providers no longer require Full trust. However, Medium trust policy does not grant the necessary code access security permissions by default, so you need to create custom policy if you want applications to use anything other than the .NET Framework Data Provider for SQL Server. Note that the OleDbPermission class supports more advanced XML declarative syntax than a simple yes or no decision. This enables you to lock down the OleDbPermission class settings in the machine-level Web.config file to specify which databases can be accessed.

    Note   Medium trust policy does grant the SqlClientPermission permission, which means that medium-trust applications can access a SQL Server database by using the .NET Framework Data Provider for SQL Server.

  • Decryption attribute added for the machineKey element. The new decryptionattribute of the machineKey element specifies the symmetric encryption algorithm that is used to encrypt and decrypt forms authentication tickets. Previously, only 3DES encryption was supported for encrypting forms authentication tickets. The default in ASP.NET 2.0 is now AES encryption, but the decryption attribute can be used to revert to 3DES, which was the algorithm used in ASP.NET versions 1.0 and 1.1. The validation attribute now supports AES as an option. This enables you to use AES to encrypt view state.

IIS 6.0 Process-Model Isolation

In Windows Server 2003, IIS 6.0 enables multiple worker processes to be used to host separate Web applications. This is shown in Figure 1.

Ff649316.iis6architecture(en-us,PandP.10).gif

Figure 1. ASP.NET architecture on Windows Server 2003 with IIS 6.0

Separate instances of the IIS worker process (W3wp.exe) can be used to host Web applications. By default, these processes run using the NetworkService account, which is a local account with restricted permissions that acts as the computer account over the network. A Web application that runs in the context of the NetworkService account presents the computer's credentials to remote servers for authentication.

To help provide isolation, you should run each application on a shared server by using a separate custom account. This allows you to audit the activity of each application separately, and to authorize each application with Windows access control lists (ACLs) separately.

Summary of Steps

To improve security when hosting multiple applications in ASP.NET, perform the following steps:

  • Step 1. Configure your application for partial trust
  • Step 2. Use application pools for process isolation
  • Step 3. Review machineKey settings.

Step 1. Configure Your Application for Partial Trust

By default, ASP.NET 2.0 Web applications and Web services run with Full trust. As a result, code access security places no restrictions on the resources and operations that applications can access, and resource access is based solely on operating-system security and ACLs.

You can use code access security to provide a constrained execution environment (or a sandbox) to restrict which resources and operations your application can perform and to isolate applications from one another. Choose the appropriate trust level for your hosting scenario. Medium trust has been provided specifically for the needs of ISPs and other deployment environments that need to enforce strict security isolation between application code bases that are written by different organizations or customers. In other scenarios, you might need to create custom policy that grants a custom permission set.

Using Medium Trust

If you need to host multiple applications on a shared server, such as in an ISP scenario, use the Medium trust level to constrain the applications. The ASP.NET Medium trust level provides a constrained execution environment that is suitable for isolating multiple applications hosted on ISP servers.

To configure all applications on your server to run with Medium trust

  1. Open the machine-level Web.config file in the %windir%\Microsoft.NET\Framework\{version}\CONFIG folder.

  2. Configure the trust element by changing the default setting for the trust level attribute from Full to Medium as shown in the following code example:

    <location allowOverride="true">
      <system.web>
        <securityPolicy>
        ...
        </securityPolicy>
        <trust level="Medium" originUrl="" />
      </system.web>
    </location>
    
    

    Note   If present, the originUrl attribute can be used by certain permissions, such as WebPermission, to restrict connectivity to a defined set of network addresses.

  3. Ensure that the trust setting is locked in the machine-level Web.config file to prevent individual application settings from overriding the global setting.

Lock the Trust Level

Service providers, or anyone responsible for running multiple Web applications on the same server, should apply the trust policy setting in the machine-level Web.config file, and then lock the trust level for all Web applications.

To do this, set the allowOverride attribute to false in the machine-level Web.config file, as shown in the following code example:

<location allowOverride="false">
  <system.web>
    <securityPolicy>
      <trustLevel name="Full" policyFile="internal" />
      <trustLevel name="High" policyFile="web_hightrust.config" />
      <trustLevel name="Medium"
                  policyFile="web_mediumtrust.config" />
      <trustLevel name="Low"  
                  policyFile="web_lowtrust.config" />
      <trustLevel name="Minimal" 
                  policyFile="web_minimaltrust.config" />  
    </securityPolicy>
  <trust level="Medium" originUrl="" />
  </system.web>
</location>
  

Setting the allowOverride attribute to false prevents an individual developer from overriding the Medium trust setting in their application's Web.config file.

Using Custom Policy

If you are hosting multiple applications on a shared intranet server, you might need to develop custom policy to support the specific requirements of your applications.

To choose an appropriate trust level

  1. Determine the permission requirements of the application to be hosted. You can determine permission requirements manually by analyzing the code and determining the types of resources it accesses, the kind of resource access it requires (such as read/write), and the privileged operations it performs. You can also use the PermCalc tool to help.

  2. Examine each trust level, beginning with High trust. Open the Web_HighTrust.config policy file from the %windir%\Microsoft.NET\Framework\{version}\CONFIG folder, and then examine the permissions to determine whether the High trust level settings are restrictive enough for your application

  3. If your application requires fewer code access security permissions than those provided by the High trust level, then examine the Medium trust level.

    Note   The Low and Minimal trust levels are designed for locked down execution environments or environments where most of the Web application exists in assemblies in the global assembly cache (GAC) instead of the physical .aspx page code.

This process will help you to identify a trust level that matches your application's permission requirements for code access security as closely as possible without granting permissions that your application does not need. You might need to create a custom policy file if your application's permission requirements are not directly suited to one of the provided trust levels. For more information about how to do this, see How To: Use Code Access Security with ASP.NET 2.0

Step 2. Use Application Pools for Process Isolation

When running Windows Server 2003 and IIS 6.0, you should use multiple application pools and configure each application to run in its own worker process (W3wp.exe) with its own unique identity. This provides process-level isolation, which enables you to audit applications separately and to restrict individual applications with appropriately configured ACLs.

Note   You can only use application pools when IIS is running in worker process isolation mode (the default) and not in IIS 5.0 isolation mode.

To use application pools for isolation

  1. Create a set of custom local or domain accounts, one per application, to run each application-pool process instance.

    Note   By not running your application as the default NetworkService account, you ensure that deliberate or accidental changes to the permission of this account do not impact your applications. In addition, having separate identities enables you to benefit from separate auditing and the ability to configure ACLs separately for each application.

  2. Configure NTFS permissions for each account to ensure that each account has access to only the appropriate file system files and folders and cannot access critical resources, such as operating system tools. To add your custom service account to the local IIS_WPG group:

    1. On the Start menu, click Control Panel, click AdministrativeTools, and then click Computer Management.
    2. Double-click (expand) Local Users and Groups, and then double-click (expand) Groups.
    3. Right-click the IIS_WPG group, and then click Add to Group.
    4. Click Add, type the custom account name, and then click OK.

    By adding your account to the IIS_WPG group, you grant the account appropriate access rights to file-system folders and registry keys, and you give the account the necessary user rights for running a Web application process. For more information about creating and configuring a custom service account, see How To: Create a Service Account for an ASP.NET 2.0 Application.

  3. For each account, run the following ASP.NET IIS Registration Tool (Aspnet_regiis.exe) command to assign the relevant ASP.NET permissions to the account:

    aspnet_regiis –ga accountname

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

    For more information about this tool, see "ASP.NET IIS Registration Tool (Aspnet_regiis.exe)" at https://msdn.microsoft.com/en-us/library/k6h9cz8h(VS.71).aspx.

  4. Create new application pools and configure them to run under the new accounts.

    1. Start Internet Information Services (IIS) Manager and in the left pane, double-click (expand) the local computer node and then double-click (expand) Application Pools.
    2. Right-click Application Pools, and then click New -Application Pool
    3. In the Add New Application Pool dialog box, type a unique application pool name that is relevant to your hosted application. Leave the Use default settings for new application pool option selected and click OK. A new application pool with the specified name is created.
    4. Right-click the new application pool and click Properties.
    5. Click the Identity tab. In the Application pool identity section, click Configurable.
    6. Type an account name and password, and then click Apply. The Confirm Password dialog box appears. Type the password again, click OK, and then click OK again.
  5. Configure each application to run in its own application pool.

    1. In IIS, right-click your hosted application's virtual directory, and then click Properties.
    2. On the Directory tab, in the Application settings section, select the application pool you created earlier and then click OK.

For more information about creating custom accounts to run your ASP.NET applications, see How To: Create a Service Account for an ASP.NET 2.0 Application.

Step 3. Review machineKey Settings

The machineKey element in the Web.config file is used to specify encryption and validation algorithms and keys used to help protect forms authentication cookies, role cookies, anonymous identification cookies, and page-level view state. You should ensure that the encryption and validation keys are different for each application. This prevents cross-application authentication, authorization, and anonymous identification; and it helps ensure that view state is not accessible between different applications. By default, the validation and encryption keys are set to unique values for each application with the following default configuration:

...
<system.web>
  <machineKey validationKey="AutoGenerate,IsolateApps" 
              decryptionKey="AutoGenerate,IsolateApps" ... />
</system.web>
...
  

For additional security, you should specify custom validationKey and decryptionKey values in each application's Web.config file.

Note   If you deploy your application in a Web farm, you must ensure that the configuration files on each server for a specific application share the same value for validationKey and decryptionKey. This is required because you cannot guarantee which server will handle successive requests. You must also ensure that they are set to different values for separate applications.

Trust Levels Summary

The capabilities that are available to applications running at the various trust levels are summarized in Table 1.

Table 1. Trust Levels and Their Key Capabilities and Restrictions

Trust level Key capabilities and restrictions
Full No restrictions imposed by code access security.
High No unmanaged code.
No enterprise services.
Can access Microsoft SQL Server and other OLE DB data sources.
Can send e-mail by using SMTP servers.
Very limited reflection permissions. No ability to invoke private 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 data sources.
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 or Web services, 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 or an application where most of the code is located in assemblies stored in the global assembly cache.
Read only access for file I/O within the application's virtual directory structure.
No ability to change the IPrincipal on a thread or on the HttpContext
Minimal Execute only.
No ability to change the IPrincipal on a thread or on the HttpContext.

Additional Resources

Feedback

Provide feedback by using either a Wiki or e-mail:

We are particularly interested in feedback regarding the following:

  • Technical issues specific to recommendations
  • Usefulness and usability issues

Technical Support

Technical support for the Microsoft products and technologies referenced in this guidance is provided by Microsoft Support Services. For product support information, please visit the Microsoft Support Web site at https://support.microsoft.com.

Community and Newsgroups

Community support is provided in the forums and newsgroups:

To get the most benefit, find the newsgroup that corresponds to your technology or problem. For example, if you have a problem with ASP.NET security features, you would use the ASP.NET Security forum.

Contributors and Reviewers

  • External Contributors and Reviewers: Jason Taylor, Security Innovation; Rudolph Araujo, Foundstone Professional Services
  • Microsoft PSS Contributors and Reviewers: Tom Christian, Wade Mascia
  • Microsoft Product Group: Mike Downen, Stefan Schackow
  • Test team: Larry Brader, Microsoft Corporation; Nadupalli Venkata Surya Sateesh, Sivanthapatham Shanmugasundaram, Infosys Technologies Ltd.
  • Edit team: Lara Ballinger, Nelly Delgado, Microsoft Corporation
  • Release Management: Sanjeev Garg, Microsoft Corporation

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.