Click to Rate and Give Feedback
Related Articles
Here the author introduces SQL Server Data Services, which exposes its functionality over standard Web service interfaces.

By David Robinson (July 2008)
Here the author answers questions regarding the Entity Framework and provides an understanding of how and why it was developed.

By Elisa Flasko (July 2008)
Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

By Josh Smith (July 2008)
Systems that handle failure without losing data are elusive. Learn how to achieve systems that are both scalable and robust.

By Udi Dahan (July 2008)
More ...
Articles by this Author
In my childhood I spent several weeks a year in Holland with my extended family. As a young American boy I was fascinated with the electric Dutch trains, something we didn't see in my hometown of Dallas, Texas.

By Rob Howard (October 2005)
In my last column, I discussed Microsoft® Application Center Test and how it could be used to measure the performance of your Web application (see Extreme ASP. NET: Tools of the Trade: Application Center Test).

By Rob Howard (August 2005)
When you sit down to write an ASP. NET application, how much time do you spend thinking about performance? It's unfortunate, but for most developers performance is an afterthought. Performance planning and design really need to be front and center.

By Rob Howard (June 2005)
Having worked for so many years designing and developing ASP. NET while at Microsoft, it's exciting now to have a venue in which to talk about it. In this new column, Extreme ASP. NET, I'll discuss and demonstrate time-tested techniques and approaches to implementing high-performance, reliable, secure, and user-friendly Web applications with ASP.

By Rob Howard (May 2005)
Writing a Web application with ASP.NET is unbelievably easy. So many developers don't take the time to structure their applications for great performance. In this article, the author presents 10 tips for writing high-performance Web apps. The discussion is not limited to ASP.NET applications because they are just one subset of Web applications.

By Rob Howard (January 2005)
More ...
Popular Articles
Animating with Silverlight is easier than you think. Here we create a 3D app that folds a polyhedron using XAML, C#, and by emulating the DirectX math libraries.

By Declan Brennan (April 2008)
Here the author answers questions regarding the Entity Framework and provides an understanding of how and why it was developed.

By Elisa Flasko (July 2008)
Chris Tavares explains how the ASP.NET MVC Framework's Model View Controller pattern helps you build flexible, easily tested Web applications.

By Chris Tavares (March 2008)
We will introduce you to the Visual Studio Profiler by walking through a sample performance investigation, pinpointing code inefficiencies in some sample applications.

By Hari Pulapaka and Boris Vidolov (March 2008)
More ...
Read the Blog
SQL Server Data Services (SSDS) is a robust, scale-free data service that internally uses proven SQL Server technology and exposes its functionality over industry standard Web service interfaces. In the July 2008 issue of MSDN Magazine, David Robinson introduces ...
Read more!
Windows Presentation Foundation (WPF) offers excellent support for managing the display and editing of complex data. In the December 2007 edition of MSDN Magazine, John Papa did a great job of explaining essential WPF data binding concepts. ...
Read more!
The most fundamental form of Web testing is HTTP request/response testing. This involves programmatically sending an HTTP request to the Web application, fetching the HTTP response, and examining the response for an expected value. In the May 2008 issue of MSDN Magazine, Read more!
In the November issue of MSDN Magazine, Jeffrey Richter demonstrates some recent additions to the C# programming language that make working with the APM significantly easier. In the June ...
Read more!
The July 2008 issue of MSDN Magazine is now available online. Here's what's in the issue: Data Services: Develop ...
Read more!
The June 2008 issue features the first installment of a new MSDN Magazine column on software design fundamentals. We’ll discuss design patterns and principles in a manner that isn't bound to a specific tool or lifecycle methodology. In this issue, Jeremy Miller starts the Patterns in Practice column ...
Read more!
More ...
Extreme ASP.NET
Keeping secrets in ASP.NET 2.0.
Rob Howard

Code download available at: ExtremeASPNET05.exe (118 KB)
Browse the Code Online
Storing data securely in a configuration system is not an easy problem to solve. While I was on the ASP.NET team, this particular feature, secure connection string storage, looked as if it wouldn’t get done. A whole host of problems surrounding it, such as key storage, were in the way. The good news is that not only was it eventually completed, but it has become part of the powerful new set of APIs in ASP.NET 2.0 that allow you to manage the ASP.NET configuration file programmatically.
Before diving into ASP.NET 2.0, though, let’s take a look at the problem and various solutions in ASP.NET 1.x. If you have used ASP.NET for any time at all, you are no doubt aware of the recommendation to store shared settings in the web.config file. For example, rather than specifying your connection string each time you create a new database connection, you store the string in the ASP.NET configuration file’s <appSettings /> section. The connection string is then accessible through the ConfigurationSettings.AppSettings property. Here’s an example <appSettings/> section:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="ConnectionString" 
         value="server=.;database=demo;uid=db;pwd=*u%a" />
  </appSettings>
</configuration>
Then, whenever you need to change the connection string you simply open the file, make your changes, and you’re finished.
This feature struck a chord with many developers moving from classic ASP to ASP.NET where most global values were stored as application variables. In fact, for ASP.NET 1.x, it is a recommended practice to store connection strings in <appSettings/>. It’s also worth noting that you can store other common data in <appSettings/>, too, including LDAP paths, common application settings, and other miscellaneous data your application needs. The goal of <appSettings/> is to simplify the writing of custom configuration section handlers—a more advanced technique of interacting with the ASP.NET configuration system. Custom configuration section handlers allow you to author and process your own XML sections within the configuration system.
You may have noticed that the contents stored in <appSettings/> are not encrypted but rather are stored as plain text. The same is true of the <sessionState/> section, which enables the out-of-process storage of Session data. One of the storage options is to use SQL Server™ and have the credentials stored in plain text in the <sessionState/> configuration slot.

Wait, You Can’t Do That
A shortcoming of storing the connection string in <appSettings/> was that this was not secure because the file was neither encrypted nor compiled. Not that compiling the configuration information would do anything to improve security; DVD manufacturers used key-based encryption to protect intellectual property, only to have DVD player software vendors store the decryption key in their compiled code. A little code spelunking by some hackers easily turned up the decryption key. It’s also common to read blog posts about individuals trying to figure out how something works in the Microsoft® .NET Framework, when someone makes the suggestion: "Just use Reflector."

ASP.NET 1.1—A Better Confidant
In ASP.NET 1.0, it was not possible to securely store the connection string in the configuration file without extra custom code. The ASP.NET team addressed this problem in ASP.NET 1.1 by enabling encryption for several configuration entries. The solution was accomplished through the Windows Data Protection APIs (DPAPI), resulting in the ability to encrypt the following configuration entries:
<identity/> Used to store the Windows® identity of the ASP.NET worker process for impersonation.
<processModel/> Used to control the Windows account that the ASP.NET worker process executed under. Not used in IIS 6.0 (see the following note).
<sessionState/> Specifically contains the stateConnectionString and sqlConnectionString attributes used to control how ASP.NET authenticated to the out-of-process state servers.
It’s important to note that IIS 6.0, the Web server included with Windows Server™ 2003, provides its own worker process management subsystem to which ASP.NET defers. Thus some worker process settings found in the configuration system are not used when ASP.NET is hosted by IIS 6.0.
A tool called aspnet_setreg.exe was provided with ASP.NET 1.1 to encrypt data in the configuration files and store the decryption key in a Windows registry entry. The resulting registry key had an Access Control List (ACL) configured to limit the Windows accounts that could access the key. This technique is explained, in detail, in Knowledge Base article Q329290, "How to use the ASP.NET Utility to Encrypt Credentials and Session State Connection Strings".
However, this solution had some shortcomings, too. It broke what the ASP.NET team lovingly referred to as xcopy deployment, which allowed an ASP.NET application to be deployed without access to the server. With the technique outlined earlier, the developer or system administrator had to have local machine access to run the command-line tool to encrypt the configuration data and store the key in the registry.

ASP.NET 2.0 Secrets
This brings me to all of the work the team did to address this problem for ASP.NET 2.0. Yet again, there is a command-line tool for managing the encryption of configuration data: aspnet_regiis.exe. Aspnet_regiis.exe existed in previous versions of ASP.NET and was used primarily for manually registering ASP.NET with IIS. For example, it was used to add the aspnet_isapi.dll to IIS as well as configure the script directories that ASP.NET applications used. You can find this tool in the \Windows\Microsoft.NET\Framework\version#\ directory.
Using aspnet_regiis.exe for encrypting configuration sections is as cryptic as the results it generates! Take a look at the results of executing aspnet_regiis.exe /help in Figure 1 and you’ll see what I mean.
Figure 1 Encrypting Configuration Data 
As you can see, unless you are intimately familiar with security terminology, you’ll be quickly overwhelmed by the number of options and various settings. Unfortunately this is a case of powerful capabilities and confusing tools. Fortunately, the Microsoft patterns & practices team wrote a great in-depth article, "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI," that walks you through aspnet_regiis.exe.
Instead of examining how to use aspnet_regiis.exe, let’s look at an example ASP.NET page that uses the new configuration APIs to accomplish the encryption of configuration sections. The single page, ConnectionEncryption.aspx (available from the MSDN®Magazine Web site), contains a GridView which is populated with a list of all configuration sections. It looks like Figure 2.
Figure 2 Using the New Configuration APIs 
Before examining how the internals of ConnectionEncryption.aspx work, I’ll look at the results from this page. But first a warning: use of this tool requires that the process hosting ASP.NET has the permission to write to the web.config file of the current application. By default, an ASP.NET application running in IIS will not have the necessary permissions. However, an application hosted in the ASP.NET Development Web Server runs with the permission set of the logged-on user. All uses of this tool you see here are shown within the ASP.NET Development Web Server. It is recommended that you do not change permission settings for IIS without a thorough understanding of the effects.
Following is a sample entry found in the new <connectionStrings> section of web.config used to store connection strings. The <connectionStrings> section is nearly identical to <appSettings> and is now the recommended place to store connection string data as there are new APIs specifically for working with connection strings sprinkled throughout ASP.NET:
<connectionStrings>
  <add name="Northwind" providerName="System.Data.SqlClient"
      connectionString="Server=localhost;Integrated 
          Security=True;Database=Northwind" />
</connectionStrings>
Note, in this case Windows authentication is still used for connecting to the database.
Clicking on the Encrypt link in ConnectionEncryption.aspx changes the connection string value in web.config to something like that shown in Figure 3. Once encrypted, the ConnectionEncryption.aspx page reports the state of the entry as encrypted (the link changes to "Decrypt", as you see in Figure 4).
Figure 4 The New Page 
Now that you have seen the page in action, let’s take a look at the code. On Page_Load, the GridView is populated when the new ASP.NET 2.0 WebConfigurationManager class retrieves an instance of the Configuration class for the local path on line 18 in ConnectionEncryption.aspx.cs:
Configuration config =  
  WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
An ArrayList is populated with data retrieved from the configuration variable and is then bound to the GridView. A majority of the other methods in the source (see the code download) are used for business logic rules around the actual data binding operation, such as determining the scope and state of a section (encrypted or unencrypted). The magic happens in the GridView1_RowCommand event when the link for Encrypt or Decrypt is clicked. When the GridViewCommandEvent.CommandName value is "Encrypt", the following code is executed:
section.SectionInformation.ProtectSection(
    "DataProtectionConfigurationProvider");
config.Save();
When the GridViewCommandEvent.CommandName value is "Decrypt", the following code is executed:
section.SectionInformation.UnprotectSection();
config.Save();
Thus the actual work of encrypting and decrypting the data is handed off to a provider. One built-in provider is the DataProtectionConfigurationProvider. It uses the built-in DPAPI to store secure data, which is the same one used by the ASP.NET command-line tool.
You should note that when encrypting data, a provider can be named, but when decrypting it’s not required (if null or an empty string is provided to ProtectSection, the default provider specified in the configProtectedData section of the configuration file will be used). This is because the APIs write another entry into the configuration file that names the encryption protection provider used:
   <connectionStrings configProtectionProvider=
           "DataProtectionConfigurationProvider">
       <EncryptedData>...</EncryptedData>
   </connectionStrings>
This configuration entry is used not only by APIs to determine how to decrypt sections, but also by ASP.NET internally when it needs to read values, such as the connection string, into memory which first must be decrypted.
The great news about the new encryption functionality of ASP.NET 2.0 is that not only can you encrypt many of the built-in configuration sections, but you can also write custom encryption providers! Providers are an awesome new extensibility model in ASP.NET 2.0 that enable developers to provide their own implementation of core functionality such as membership, personalization, and so forth. Additionally, due to the way Configuration Encryption was implemented, custom configuration sections can easily be encrypted as well, so protection of data is not limited to a few configuration sections as was the case in ASP.NET 1.1.

Tell Smarter Secrets
A column on encrypting secrets wouldn’t be complete without several warnings. First, if you can avoid secrets, do so. If you’re using SQL Server and you don’t want to store sensitive connection string information in the configuration system, use integrated authentication with SQL Server. Windows authentication will be used to connect from your application server to the database. With this technique, the connection to SQL Server is authenticated and authorized through Windows directly. Using Windows authentication, SQL Server requests a token from the authenticating server (whether local or remote), which contains a security identifier (SID) for the user along with other information and is compared with a list maintained by SQL Server to determine if access is granted or denied. No passwords or usernames are stored in the configuration file.
Another thing to keep in mind is that just because data in the configuration file is stored securely doesn’t mean you’re safe from all kinds of attacks. Any attacker worth his salt (security pun) could do plenty of harm if he got far enough to access your web.config file on your server. An attacker who obtained access to the system to manipulate the web.config could perform other actions to manipulate the database without requiring knowledge of the connection string. Thus, securely storing your connection string or other application data is simply one line of defense. Another effective defense is using stored procedures and placing more fine-grained control over what the account accessing your database has permissions to. Case in point, an encrypted connection string is worthless if you have SQL injection vulnerabilities (for more on SQL injection attacks, see msdn.microsoft.com/msdnmag/issues/04/09/SQLInjection).
Having built and run a number of high-visibility sites, such as www.asp.net, I’ve seen my fair share of attack attempts. One common attribute is that the attack is often completely unrelated to the initial vulnerability. By not attacking through the original vulnerability, the attacker is attempting to protect the backdoor created through the original vulnerability.

In Closing
Protecting secrets in your ASP.NET applications is possible in any version of ASP.NET, though it’s made easier in ASP.NET 1.1, and much more so in ASP.NET 2.0. With ASP.NET 2.0, rather than configuration encryption being an afterthought, it was something that was built into the new configuration APIs. With ASP.NET 2.0, not only can you use the aspnet_regiis.exe tool to encrypt configuration sections, but you can also write your own custom code—along with custom providers if you wish—to encrypt and decrypt configuration data.
For more information on storing secrets in ASP.NET 1.1, see "Security Considerations for Hosting ASP.NET version 1.1."

Send your questions and comments for Rob to  xtrmasp@microsoft.com.


Rob Howard is a founder of Telligent Systems, specializing in high-performance Web apps, knowledge management, and collaboration systems. Previously, Rob was employed by Microsoft where he helped design the infrastructure features of ASP.NET 1.0, 1.1, and 2.0. You can contact Rob at rhoward@telligentsystems.com.

Page view tracker