Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles

Ken Getz shows how the CollectionChanged event lets you reflect changes to your underlying data source in your bound data controls.

Ken Getz

MSDN Magazine December 2008

...

Read more!

Here we introduce Microsoft Code Name “Geneva,” the new framework for building claims-based applications and services, and federated security scenarios.

Michele Leroux Bustamante

MSDN Magazine December 2008

...

Read more!

Understanding the ACLs that govern permissions and rights before an operation is allowed to proceed is critical to enhancing security.

John R. Michener

MSDN Magazine November 2008

...

Read more!

Using threat models to drive your security engineering process helps prioritize the code review, fuzz testing, and attack surface analysis tasks.

Michael Howard

MSDN Magazine November 2008

...

Read more!

The heart of Windows Workflow Foundation is its declarative programming model. Here are some best practices to consider when using WF to realize software solutions in the real world.

Josh Lane

MSDN Magazine December 2008

...

Read more!

Also by this Author

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.

Rob Howard

MSDN Magazine May 2005

...

Read more!

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).

Rob Howard

MSDN Magazine August 2005

...

Read more!

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.

Rob Howard

MSDN Magazine January 2005

...

Read more!

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.

Rob Howard

MSDN Magazine June 2005

...

Read more!

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.

Rob Howard

MSDN Magazine October 2005

...

Read more!

Popular Articles

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.

Rob Howard

MSDN Magazine January 2005

...

Read more!

Ray Djajadinata

MSDN Magazine May 2007

...

Read more!

Jason Clark

MSDN Magazine July 2003

...

Read more!

Learn how to automate custom SharePoint application deployments, use the SharePoint API, and avoid the hassle of custom site definitions.

E. Wilansky, P. Olszewski, and R. Sneddon

MSDN Magazine May 2008

...

Read more!

When incorporating the ASP.NET DataGrid control into your Web apps, common operations such as paging, sorting, editing, and deleting data require more effort than you might like to expend. But all that is about to change. The GridView control--the successor to the DataGrid-- extends the DataGrid's functionality it in a number of ways. First, it fully supports data source components and can automatically handle data operations, such as paging, sorting, and editing, as long as its bound data source object supports these capabilities. In addition, ...

Read more!

Our Blog

So many factors can affect the performance of a Web page—the distance between server and client, the size of the elements on the page, how the browser loads these elements, available bandwidth. Finding those bottlenecks and identifying the culprits is no easy task.

In the November 2008 issue of MSDN Magazine, Jim Pierson introduces ...

Read more!

Earlier this year MSDN Magazine embarked on a collaborative project with Behind the Code, an interview program airing on MSDN Channel 9. In this program, Robert Hess interviews prominent developers at Microsoft, and those developers also write a column for { End Bracket } in MSDN Magazine. In the newest interview, Richard Ward talks about working on the core infrastructure components of future versions of Windows, as well as ...

Read more!

We're currently in the process of stepping back and taking a critical look at our Web site to see how you all are using it - and how we can redesign parts of it (big or small) to make that experience better.  We are continuously receiving your feedback on existing frustrations and we are working hard to remedy those (as a general fyi, most of the frustrations have to do with navigation).  However, in order to get a sense of whether we need to look at some of the more fundamental ...

Read more!

C# developers can use the Visual Studio Tools for the Office System (VSTO) Power Tools Office interop API extensions to streamline Office application development. The extensions provide a thin, strongly typed layer over the loosely typed Office object models.

In the December 2008 issue of MSDN Magazine, Andrew Whitechapel, Phillip Hoff, and Vladimir Morozov walk you through developing ...

Read more!

Every month, the CLR team gives us insight into the core of managed code, .NET programming best practices, technologies underlying the CLR and .NET Framework, and other tips and suggestions.

In the December 2008 issue of MSDN Magazine, Erika Fuentes and Eric Eilebrecht cover some common issues developers encounter when tuning ...

Read 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).
<connectionStrings>
  <EncryptedData>
   <CipherData>
<CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAALJZXjMW9c0G4r/2N3hAQAAAACAAAAAAADZgAAqAAAABAAAAD7l2fNIXMFeuAohZ1FjRP+AAAAAASAAACgAAAAEA
AAALK0hmPPfWgWJRVr69wbkSWAAQAAr+idwrf3qkg5NPzXa4HnpbeMy1ngAQyn5GlIO99JT40
FC8bY3keUqVkDlUhwj1WrHV/i7+tMbkj5MJPvRV4z33tp4d6H1PVsMVpjsbmRb/9YdY50kRCN
tWxWye/chGbDDoNePcQhdidPmdH5Yf2lDdpMT3hX1K8JCiWXTXa7sk0/Vu6oQARZpqWMxXJAU
GGY4G/WNAUchQ0Rw3U09ygn3aykMb4loqBwvhdlW7EuuGB3OXCrZ2SfrGGwiw0CD3BWHoOdKV
2yH6TQYUED7yLYHPATEUyj42T2H1J0B6SaQLIA9N61lThZQWdLbeWCpBAkOcUpivO9jhPJtB2
zNs3RnCaPOKyhpX650nBH/qRzO8D5B7PmJ4RHFN97ePoIZ0nz5LnOWUGWra+kQBD3/F9Dl9XO
al6pVvO/EEXbJZFhIobAzynjoec1msAPcIWxzx3PypoLUQEjMHeEkk1TtKiZbmznnPu8lPzlJ
SECfbyajQLTQOtetxCmpOKdhEFgsnHRFAAAAEcgWPEHOEF32JkblJNOzL/Sh4ux
</CipherValue>
   </CipherData>
  </EncryptedData>
</connectionStrings>
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