Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Asp Net 2.0 Security Membership And Role Management

.pdf
Скачиваний:
48
Добавлен:
17.08.2013
Размер:
12.33 Mб
Скачать

Configuration

System Security

Many .NET Framework features depend on initialization information stored in various configuration files. ASP.NET especially is heavily dependent on configuration sections for defining the behavior of many aspects of the ASP.NET runtime. As a result the configuration information frequently contains sensitive information (usernames, passwords, connections strings, and so on). Configuration information can also directly affect the security settings enforced by certain features. As a result, configuration security is an important aspect of ensuring that a web application works as expected.

This chapter covers the following aspects of securing configuration information:

Using the <location /> element

Implementing granular inheritance control using the new “lock” attributes

Setting access rights to read and modify configuration

Implementing partial trust restrictions when using configuration

Using the new protected configuration feature

Using the <location /> Element

The <location /> element has existed since ASP.NET 1.0 as a convenient way to define configuration inheritance without the need to create and deploy multiple separate configuration files. Because web applications always have some type of hierarchy, and thus the concept of configuration inheritance, you commonly need to define configuration settings at different levels of the ASP.NET inheritance hierarchy. The following list shows the ASP.NET 2.0 inheritance chain:

Chapter 4

1.Settings defined in machine.config — In ASP.NET 2.0 many of the default ASP.NET settings have been moved out of machine.config to minimize startup time of non-web applications.

2.Settings defined in the root web.config — This new configuration file exists in

%windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG. Most of the ASP.NET-specific default settings are now defined in the root web.config file.

3.Settings defined in the web.config file located in the root folder of a website — For the Default Web Site this would be a folder resembling c:\inetpub\wwwroot.

4.Settings defined in the root directory of the application — This is the web.config file that you normally work with in your applications. If the application is the website (meaning the application exists at “/”), the website configuration file and the application’s configuration file are one and the same.

5.Settings defined in a configuration file located in a subdirectory of a web application

Settings that can be changed on a per-directory basis can be placed in a web.config file in a directory. For example you can define <authorization /> elements in web.config files that apply only to a specific virtual directory.

Usually, you set some global defaults once in the machine.config and root web.config files, and spend most of your time editing the application’s web.config file.

The contents of the <location /> element are the same configuration sections that you would normally set up inside of the various configuration files. Using the URL authorization section as an example, you could place the following into the web.config located at the root of a website (for example at c:\inetpub\wwwroot\yourwebsite\web.config ) as follows:

<location path=”Virtual Path A”> <system.web>

<authorization>

<allow roles=”Secured, Administrators” /> <deny users=”*” />

</authorization>

</system.web>

</location>

The <location /> element is interpreted as the beginning of a new virtual configuration file, meaning the element (or elements) that are nested immediately beneath the <location /> element must be toplevel elements allowed in a normal configuration file. Thus, in the example just shown, the <system

.web> declaration is needed. You cannot place the <authorization /> element inside a <location /> element because it wouldn’t be allowed as a top-level element in a web.config file.

The thing that becomes awkward with configuration inheritance is that you can quickly end up with a proliferation of .config files. For example, the URL authorization section (<authorization />) often requires many configuration files because the <authorization /> section can be applied down to the level of a specific web page. Developers who need to lock individual folders can drop a web.config file into each separate folder containing the folder-specific authorization rules. You saw an example of this back in Chapter 2 when URL authorization was covered.

You can determine how far down the inheritance chain a configuration section can be defined by looking at the section definitions. Most section definitions can be found within <section /> elements up in machine.config (Configuration section definitions are typically global to a machine so it makes sense to define them up in machine.config.) In a section definition like the following one:

144

Configuration System Security

<section name=”healthMonitoring” type=”...”

allowDefinition=”MachineToApplication” />

the attribute allowDefinition indicates that the health monitoring configuration section can be defined all the way down to the web.config file for an application. So, you aren’t going to run into a problem with needing health-monitoring definitions for each your application’s subfolders.

As a counterpoint, the URL authorization configuration section definition is:

<section name=”authorization” type=”...” />

The lack of the allowDefinition attribute for this configuration section is an indication that the authorization configuration can be redefined to any level of folder nesting. As a result, this configuration section is a good candidate for centralizing in an application’s web.config to prevent the number of folder-specific web.config files from growing out of control.

Just looking at the section definition in machine.config is not always going to tell you whether the configuration makes sense at nested configuration levels. For example, the browser capabilities section can also be redefined at any level of the configuration hierarchy. Most likely though, you wouldn’t redefine this section beneath the level of the application’s web.config.

The Path Attribute

The <location /> element is a way to control the number of .config files deployed for an application. The path attribute within the <location> element tells the configuration system where in the configuration inheritance chain the information contained within the <location /> element should be applied.

You can place a <location /> element inside of any configuration file within the inheritance chain — from machine.config all the way down to a configuration file in a subfolder of a web application — and then use the path attribute to indicate where the enclosed configuration information applies.

Probably the most confusing aspect though of the <location /> element are the potential values for the path attribute. You can place the following values inside of the path attribute:

A specific page (that is, default.aspx)

A specific folder (that is, “subfolder” )

A combined path (that is, “subfolder/default.aspx” or “subfolderA/subfolderB”*. The name of a website as defined in IIS (that is, “Default Web Site” )

The combination of a website name and nested path information (that is, “Default Web Site/subfolderA”)

With the path attribute, you can centralize configurations settings into a single physical configuration while still having the flexibility to define configuration settings for different applications, folders, pages, and so on.

Your decision about how to centralize configuration settings should be based on the relationship between the desired configuration information and the location of the configuration file. The root web.config file is an appropriate location for defining configuration information applicable to all web applications on a server. For example, this is the reason that the trust level configuration exists within a

<location /> element in the root web.config file.

145

Chapter 4

The web.config file that can be placed at the root of an IIS website is probably used as an application configuration file by most developers. When you have no applications running at /, the website’s configuration file is an appropriate location for defining configuration information applicable to all applications running beneath the website’s root.

Each application’s web.config file can be used for centralizing configuration information applicable to the application’s subfolders. Although you can spread out configuration information into configuration files in subfolders (as was shown in the URL authorization discussion in Chapter 2), it can be confusing to debug application problems. Unless someone who knows the application intimately realizes that configuration files are located in subfolders, you may end up scratching your head wondering why an application is behaving in a specific manner. Centralizing configuration information using <location /> tags in the application’s web.config file makes it easier for you to know exactly which configuration settings are in effect in different parts of the application.

The AllowOverride Attribute

An additional level of security is available with the <location /> element through the allowOverride attribute. Commonly, a web server administrator defines some ASP.NET settings in machine.config. However, this wouldn’t be very useful if in each web application the developer simply redefined the configuration sections. The solution is to set the allowOverride attribute to false. After this is done, any attempt to redefine the configuration information contained within the <location /> element results in a configuration exception.

If you globally define the trust level in machine.config as follows:

<location allowOverride=”false”> <system.web>

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

</location>

. . . attempting to redefine this in your application’s web.config file results in an error page telling you that the parser encountered an error because the section has been locked down in a higher-level configuration file (in this case, machine.config). The amount of leverage the <location /> element plus the allowOverride attribute gives you is the reason security sensitive configuration sections should be defined in either machine.config or the new root web.config file. Both of these files are also ACL’d on the file system to allow only write access by machine administrators so individual application developers can’t subvert the settings. Setting allowOverride to false guarantees the person who can change a locked configuration section is a member of the machine’s Administrator group.

Using the lock Attributes

Around the time that Beta 1 was worked on the development team came up with the idea of allowing the session state feature to lock portions of its configuration. The idea was to allow developers using session state to configure application-specific behavior such as the session timeout, while allowing machine administrators to define more global settings such as the session state mode and connection string. As part of this work, the team realized that the existing 1.0/1.1 <location /> based lockdown approach was too restrictive.

146

Configuration System Security

For instance, if an administrator wanted to enforce just connection string used by all applications with SQL Server session state, an administrator would also have to drag in enforced settings for session timeout, cookieless support, and so on. On some web servers, this constraint might be reasonable, but in corporate hosting environments the likelihood is rather high that different internal corporate customers want different application-specific behavior.

Rather than taking the early work for session state and limiting it to that feature, the concept of locking down individual configuration attributes as well as nested configuration elements was expanded and made available to any arbitrary configuration section. The following list describes the set of common attributes:

lockAttributes — You can specify specific attributes on a configuration element that cannot be redefined lower down in the configuration hierarchy.

lockElements — You can specify nested elements for a given configuration element that should not be redefined in child configuration files. This attribute is applicable only to complex configuration sections that contain nested elements.

lockAllAttributesExcept — This is the companion attribute to lockAttributes. Depending on how many attributes you are locking down, it may be faster to lock all attributes except for a select few, rather than listing specific locked attributes with lockAttributes.

lockAllElementsExcept — The companion attribute to lockElements. For complex configuration sections, it may be easier to define the nested elements that can be redefined, rather than list the locked elements with lockElements.

Locking Attributes

You can define the configuration for a feature in a higher level configuration file and then selectively choose which attributes are allowed to be redefined in child configuration files. The lockAttributes and lockAllAttributesExcept attributes can be placed inside of any configuration element to limit the attributes that can be redefined in child configuration files.

Take the Membership feature as an example of how you can lock individual attributes of a configuration element. The <membership /> element has three attributes: defaultProvider, userIsOnlineTimeWindow, and hashAlgorithmType. Of the three attributes, perhaps as an administrator you would like to ensure that any providers configured to use hashing should always use a stronger hashing variant, specifically SHA256.

To test the effect of locking the hashAlgorithmType attribute, you can write a sample application that defines the <membership /> element in its web.config:

<membership defaultProvider=”FirstProviderDefinition” hashAlgorithmType=”SHA1” userIsOnlineTimeWindow=”15” >

The membership feature comes preconfigured in machine.config with just an empty <membership /> element. However, for testing the attribute-based configuration lockdown, machine.config can be modified to look as follows:

<membership hashAlgorithmType=”SHA256”> ...

147

Chapter 4

You can see the hash algorithm that has been configured for the Membership feature by just outputting the setting on a web page in the sample application:

Response.Write(Membership.HashAlgorithmType);

The first time you run the sample application the redefined configuration in the application takes effect, and thus the output on the web page is “SHA1”. Now lock the settings in machine.config to prevent redefinition of the hashAlgorithmType attribute:

<membership hashAlgorithmType=”SHA256” lockAttributes=”hashAlgorithmType”>

Now when you attempt to run the sample application you get a configuration error stating that the hashAlgorithmType attribute has been locked in a higher-level configuration file. If you remove the hashAlgorithmType attribute from the application’s web.config file, the application runs successfully and the new hash algorithm is SHA256. Just for the heck of it, you can extend the attribute lock in machine.config to include the userIsOnlineTimeWindow and defaultProvider attributes as well:

<membership hashAlgorithmType=”SHA256” lockAttributes=”hashAlgorithmType;userIsOnlineTimeWindow;defaultProvider”>

Use a comma or a semicolon to delimit the individual attributes defined in lockAttributes and lockAllAttributesExcept.

This basic example with the <membership /> element shows that lockAttributes gets pretty verbose. Locking something like the <sessionState /> element with its 14 different attributes results in a lengthy definition for lockAttributes. Taking the <membership /> section again as an example, to allow the userIsOnlineTimeWindow attribute to be changed in child configuration files, you could use the following more succinct machine.config definition:

<membership hashAlgorithmType=”SHA256” lockAllAttributesExcept=”userIsOnlineTimeWindow” >

This construct allows you to redefine just a subset of the <membership /> element in the application’s web.config file:

<membership userIsOnlineTimeWindow=”15” >

As with the lockAttributes element, you can specify multiple attributes within lockAllAttributesExcept. The comma and semicolon characters are also used as delimiters.

A shorthand for locking all attributes on a configuration element is to use an asterisk for the value of lockAttributes. The following example shows how to prevent the redefinition of any attribute on the

<membership /> element:

<membership ... lockAttributes=”*” />

148

Configuration System Security

Finding Out Which Elements Are Available for Lockdown

To find out which elements are available for lockdown for a specific configuration element, you can create a bogus lockAttributes value. For example, with the following configuration definition (this is in machine.config, but the technique works in any configuration file):

<membership hashAlgorithmType=”SHA256”

lockAllAttributesExcept=”this doesn’t exist” >

The error that is returned from ASP.NET is

The attribute ‘this doesn’t exist’ is not valid in the locked list for this section. The following attributes can be locked: ‘defaultProvider’, ‘userIsOnlineTimeWindow’, ‘hashAlgorithmType’. Multiple attributes may be listed separated by commas.

Self-documenting errors are a good thing in this case!

Although locking specific attribute configuration is a powerful feature of the new configuration system, bear in mind that just because a lockdown is technically possible it may not always make much sense in practice. For example, the previous examples showing how to lock down the hash algorithm for the <membership /> feature wouldn’t be useful if all membership providers used by an application were configured with reversible encryption instead. In this case, the configuration system happily enforces the attribute lockdown, but the end result would have no effect at runtime. This means attribute lockdowns (and element lockdowns discussed in the next section) still require you to look at the final runtime effect to determine whether the locked down configuration really makes sense.

Locking Elements

Because many configuration sections have nested elements, the configuration system provides the ability to lock elements within a configuration section. The lockElements and lockAllElementsExcept attributes control this behavior for any configuration section.

For example, the <membership /> section enables you to define providers using the <providers /> element and <add />, <remove />, and <clear /> elements nested with the <providers /> element. You could allow application developers to change attributes on the <membership /> element but disallow them from changing any of the providers with the following configuration in machine.config:

<membership lockElements=”providers”>

Attempting to make any changes to the <providers /> element for <membership /> in a child web.config file results in an error because the providers element has been locked in higher-level configuration file.

To allow an individual application to add new providers, but disallow individual applications from removing or clearing providers defined in parent configuration files, your configuration in machine.config could look like the following:

149

Chapter 4

<membership>

<providers lockAllElementsExcept=”add”> <!-- provider definitions here -->

</providers>

</membership>

In this example, the “lockAllElementsExcept attribute is used as a shortcut for allowing only child web.config files to use the <add /> element within the membership provider definition.

A shorthand for locking all elements nested within a configuration element is to use an asterisk for the value of lockElements. The following example shows how to prevent the redefinition of any providers for the membership feature:

<membership>

<providers lockElements=”*”>

<!-- provider definitions here --> </providers>

</membership>

The utility of element-based lockdown in Add-Remove-Clear (ARC) collections such as the membership provider collection is somewhat open to question. Locking <membership /> by preventing changes to the <providers /> element is for all practical purposes locking the configuration of the entire Membership feature. Because providers are central to the feature, using a <location /> based lock would achieve about the same result. About the only benefit you gain from using lockElements with a feature like <membership /> is that you could still allow individual applications to customize the online time window setting. A machine.config definition that allowed this would look as follows:

<membership lockElements=”providers” lockAttributes=”defaultProvider,hashAlgorithmType”>

However, some provider-based features like the health-monitoring benefit from the use of the elementbased lock. For example as an administrator you could prevent removal or clearing of health monitoring providers with the following configuration definition:

<healthMonitoring>

<providers lockElements=”remove,clear”>

<add name=”admin configured provider goes here” ... /> </provider>

</healthMonitoring>

With this definition, you can add additional providers to individual web applications. However, you cannot remove any providers defined in machine.config. This approach allows a box administrator to ensure that specific providers are always configured and in use on the machine for centralized web event collection, regardless of whatever other providers may be added by individual applications.

The following list describes the combinations of element-based locks that make sense for any Add- Remove-Clear collection (provider definitions, the Profile properties definition, and so on):

Lock all ARC elements to prevent child modifications by locking the parent collection element. This means putting a lockElements=’*’ definition in the parent element as was shown earlier (for example the <providers /> element, the <properties /> element for a feature like Profile, and so on).

150

Configuration System Security

Allow individual applications to add elements to an ARC collection, but disallow changing any inherited collection elements. This means using a lock definition such as “lockAllElementsExcept=’add’ in the parent collection element.

Allow individual applications to remove elements from an ARC collection, but disallow additions. This can be accomplished with a definition such as lockElements=’add’ in the parent collection element. This approach can be useful if you configure multiple providers on a machine, but leave it up to the individual applications to choose the specific ones to use. Individual applications can then remove the providers they don’t want to use.

Although you can technically do other things, such as disallow<remove /> but not <clear />, or vice versa, these types of locks are ineffective. The <clear /> and <remove /> elements are basically interchangeable. You can simulate a <clear /> with a series of <remove /> elements, so preventing a child configuration file from using <clear /> but not <remove /> is pointless. Similarly, preventing the use of <remove /> but not <clear /> is questionable because <clear /> is just a fast way of removing all previously defined items in a configuration collection.

Locking Provider Definitions

Because a good chunk of this book is about Membership and Role Manager, you may be wondering how the attribute lock feature works with provider-based features. You may be thinking that with the attribute-based lock feature, you can customize portions of your provider definitions and restrict the redefinition of many of the provider attributes.

To see which attributes in a provider <add /> element are lockable by default you can use the trick mentioned earlier. Take the sample application and create the following membership provider <add /> element:

<add lockAttributes=”foo” name=”AspNetSqlMembershipProvider” type=”...” connectionStringName=”LocalSqlServer” enablePasswordRetrieval=”false” enablePasswordReset=”false” requiresQuestionAndAnswer=”false” applicationName=”ConfigurationSample” requiresUniqueEmail=”true” passwordFormat=”Hashed” description=”some description here” />

The following error statement returns:

The following attributes can be locked: ‘name’, ‘type’, ‘connectionStringName’, ‘enablePasswordRetrieval’, ‘enablePasswordReset’, ‘requiresQuestionAndAnswer’, ‘applicationName’, ‘requiresUniqueEmail’, ‘passwordFormat’, ‘description’.

All provider definitions use the same underlying strongly typed configuration class (this is covered extensively in Chapter 9 on the Provider Model). The strongly typed provider configuration class defines only “name” and “type” as common provider attributes. Clearly though, each provider-based feature has a rich set of feature-specific provider attributes, and the error message shown previously is lists much more than the “name” and “type” attributes as available for lock.

151