Using a Server Certificate to Protect Web.Config
Using ASP.NET’s protected configuration feature is recommended when your Web.Config file contains sensitive information. The .NET Framework gives you two protected configuration providers, DpapiProtectedConfigurationProvider and RsaProtectedConfigurationProvider. Depending on your application requirements, you can use either of these to get the job done.
You can also create your own protected configuration provider and there is a sample here that shows an implementation using the TripleDESCryptoServiceProvider for encrypting and decryption. Implementing your own protected configuration provider is simply a matter of writing a class that derives from ProtectedConfigurationProvider. In this blog post, I’m going to show a another custom provider option using a server certificate for the encryption and decryption.
Implement the Provider
Using Visual Studio 2010, create a new Class Library project and inherit your class from ProtectedConfigurationProvider. The ProtectedConfigurationProvider class is located in the System.Configuration assembly. So, you will need to add a .NET Reference to System.Configuration and also add a using statement to the top of your class for the System.Configuration namespace.
This provider will perform encryption and decryption using the keys from an X509 Certificate. The X509Certificate2 class is located in the System.Security assembly. So, you will need to add a .NET Reference to System.Security and also add a using statement for the System.Security.Cryptography.X509Certificates namespace. Next, add a private X509Certificate2 member to the class that will be used as a reference to the server certificate.
This provider will be installed in the GAC so it is easily accessible by ASP.NET and the aspnet_regiis.exe tool on the server. Therefore, add a strong name key file to the project. Later on, you will need the public key token from the signed assembly. To make it easy to get this, add the following post-build event to the project properties:
"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\sn.exe" -T "$(TargetPath)"
Note: The path to sn.exe may differ on your machine.
There are 3 methods you must override to implement the provider: Initialize, Encrypt, and Decrypt. The shell of your class should look like this.
The implementation for Initialize is shown below. This code is pretty straight forward. The key thing to note is that this provider expects CertSubjectDistinguishedName to be defined in the <configProtectedData> section of the config. More on how that get’s defined later.
The implementation for Encrypt and Decrypt is shown here.
That’s all there is to it. When you build the project, your provider will be signed and the post-build step from above will display your public key token in the Output window. You will need this later.
Deploy the Provider
This provider needs to be installed in the GAC on the target IIS server. You probably won’t have gacutil.exe available on the target server to install this into the GAC. So, adding a Visual Studio Installer Setup Project to your solution will simplify this process for you.
In your Setup Project, add the Global Assembly Cache Folder to the File System Target and specify the output from the protected configuration provider project.
Build the setup project and copy the Setup.exe and X509ProtectedConfigProviderSetup.msi file to your target IIS server. For the purposes of this post, I’m deploying to IIS 7.5 / Windows Server 2008 R2.
On the target server, run the Setup.exe to install the provider. Choose Everyone when prompted by the installer to make the provider available for Everyone or Just me. The provider assembly will be installed in C:\Windows\Microsoft.NET\assembly\GAC_MSIL.
Create the Server Certificate
I’m using a self-signed certificate from IIS 7.5. This certificate will function as both the SSL certificate for my site as well as provide support for my custom provider to encrypt and decrypt sections of the web.config. Instructions on how to create a self-signed certificate using IIS Manager can be found here.
Since my custom provider will be using the keys from the certificate, the IIS worker process (w3wp.exe) will need read access to the certificate. In IIS 7.5, the default identity for the DefaultAppPool is ApplicationPoolIdentity, which we’ll give read access to. Information on this identity can be found here. To grant read access to the certificate, follow these steps.
- Open Microsoft Management Console (mmc.exe).
- Select File > Add/Remove Snap-in and add the Certificates snap-in for the Computer Account.
- Expand the Personal > Certificates folder, where the self-signed certificate is located.
- Right-click on your certificate and select All Tasks > Manage Private Keys.
- Click the Add button and add IIS AppPool\DefaultAppPool to the object name field.
- Click the Check Names button and it should resolve to DefaultAppPool.
- In the Permissions section, give DefaultAppPool Read permissions only.
Encrypting the Web.Config
A common scenario for encrypting sections of a web.config are when there are connection strings in the file. Suppose I have a web application with a connection string in the web.config such as this that I want to encrypt using my custom protected configuration provider.
Add the <configProtectedData> element to the web.config so that it references the fully qualified name of the custom provider assembly, as shown below. Notice that here is where we add the CertSubjectDistinguishedName setting that our custom provider looks for.
With this information in the web.config, deploy the application to the target IIS server.
On the target IIS server:
- Open a command prompt.
- Change directory to C:\Windows\Microsoft.NET\Framework64\v4.0.30319.
- Type the following command to encrypt the <connectionStrings> section of the web.config.
aspnet_regiis –pe “connectionStrings” –app “/MyWebApp” –prov “X509Provider”
Note: The –app parameter will be the name of your web application.
If you go look at the web.config, you will see that the <connectionStrings> section has been encrypted using the custom provider.
The last thing to do is test it to make sure that ASP.NET can decrypt the contents as needed to return page requests (see below). The certificate error is because I’m using a self-signed certificate in my sample. But, as you can see, ASP.NET is able to successfully use the custom provider to decrypt the connection string to retrieve data from the database.
Comments
- Anonymous
February 28, 2012
It looks very interesting. I will test it for sure, thank you for sharing knowledge! :))