How to protect your config file in .NET with cryptography

Introduction

In the past several blog posts we’ve looked at various cryptography techniques in .NET: hashing, symmetric and asymmetric encryption and digital signatures. Yet another application of encryption in .NET is protecting the config file of your project. The goal here is that if an attacker gains access to the file system on the application server then they shouldn’t be able to read any sensitive information from it.

The idea is that certain sensitive sections of the config file are encrypted and stored separate from the app.config or web.config files. These sections are then decrypted by ASP.NET automatically. We don’t need to worry about writing complicated decryption code ourselves. In practice this technique is applied to the app settings and connection settings section of the configuration. We can use encryption keys either at the machine or the user level.

We can take one of two approaches: DPAPI which is built-into Windows or RSA, which we discussed in the posts on asymmetric algorithms and digital signatures.

DPAPI

With DPAPI built into Windows we’ll use machine-specific keys so you don’t need to worry about key storage issues. Key storage is managed by DPAPI in a secure way. This approach is very straightforward to use on a single server as the key is specific to that machine. However, you cannot move that encrypted web.config to another server in a web farm as the other servers will have other keys. The RSA-based solution is better suited for web farms which we’ll look at shortly.

DPAPI demo

We’ll use the aspnet_regiis tool to encrypt and decrypt a file. You’ll need to have a project with either a web.config or app.config file. For this be meaningful insert a couple of app settings to the file, they don’t need to make any real sense:

<appSettings>
        <add key="secretKey" value="key" />
	<add key="rsaKey" value="rsaKey" />
	<add key="thisisgreat" value="true" />
	<add key="codetosavetheworld" value="secret" />
</appSettings>

The aspnet_regiis tool is usually located in one of these folders:

C:\Windows\Microsoft.NET\Framework\v4.0.30319
C:\Windows\Microsoft.NET\Framework64\v4.0.30319

Open a command prompt and navigate to the correct folder. Take note of the folder of your application where the config file is located. Enter the following command to encrypt the app settings section:

aspnet_regiis -pef “appSettings” C:\path-to-folder-with-config-file -prov “DataProtectionConfigurationProvider”

DataProtectionConfigurationProvider is the DPAPI provider so we ask the tool to encrypt the appSettings section of the config file with DPAPI.

If the process succeeded then open the config file and you should see some funny-looking EncryptedData and CipherData nodes:

<appSettings configProtectionProvider="DataProtectionConfigurationProvider">
  <EncryptedData>
   <CipherData>
    <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAARlLCV8A5OE2a9bhixy2JFwQAAAACAAAAAAADZgAAwAAAABAAAACtSLR5AiN84R+VKYn18+aPAAAAAASAAACgAAAAEAAAALygmbBS72xqElqrjz32sVmoAQAAFA+MvV+KYs/MZKMsCvYfapjetPvKgWjm/VNsyFkEaTx8A6z9PigAQdB/H64BOyTh5YVCcijhTrO8D6iU2LnXGwdhZeev4Rskk1AkliD+fLXvxfg7f9dnpjlI16694q60FrpDlIL9LQ9lqSUYgjsJvgZmfI48eXifGQ36HYTWYAWAjm2uQc6OUe2HlDdGr27nvZoVBZXy1Lho6JpiqRjD6VmbyH0TctysLCuzRrKx/8hPpIrrcvSVFcuNtFnbk2UGREt4Urh+TgMH8b5F2BM4jtN4jxblnyGbgwJKBMeheaypk2jctsKIkg6Ly8MhFDjgzJ/YqjV43ucnnt4HV13/TwHK1cvvfxQi5Xbs6vAqu4ZnaTfLdgecQ2JScTYbFoJKrti9quTKev3xOqtjj1vq2VC5mkTiSWxDfrVUH/nIZ3zXE6oGE1gQ9NXFZZ0iZ4casOe6Qq6u8hBLCTWVhdwlGftNAEbSILDdDMQUTCC8xeX2NHIukFRfCC9N6MoCqVFI6bkMj9ovDE//BqVGoLT/0VfmfzmDcXvV/PMJyLcuXnpHDJsPlgPyKxQAAADjr4S4XVr4grgNFiaLrr3waoMx3Q==</CipherValue>
   </CipherData>
  </EncryptedData>
 </appSettings>

Later when you try to extract some settings from the appsettings section in code then the decryption process will be performed for you so you can read values as before.

If you want to edit the app settings section then here’s the decryption command:

aspnet_regiis -pdf “appSettings” C:\path-to-folder-with-config-file

This will enable you to edit the appSettings section as normal.

RSA

If you want to reuse the same encrypted config file on multiple servers in a web farm then RSA is the best choice. The flow is the following from a high level:

  • Generate an RSA key-pair on the first server
  • Set up the local config provider for the customer key pair
  • Use aspnet_regiis to encrypt the sensitive sections in the config file
  • Grant access to the key for the Network Service account
  • Export the key pair for reuse on the other servers of the farm
  • On all other servers we import the key pair and grant Network Service access to it

RSA demo

In the post on asymmetric encryption we discussed how to generate and export RSA key pairs using aspnet_regiis. Make sure that the key-pair is exportable using the -exp flag. Let’s say that the key container is called “MyCustomKeys”:

aspnet_regiis -pc “MyCustomKeys” -exp

We need to set a reference to this container in the config file in a section called configProtectedData within the configuration root node. We also specify that we use RSA to do the file protection:

<configProtectedData>
	<providers>
		<add keyContainerName="MyCustomKeys"
				 useMachineContainer="true"
				 name="CustomProvider"
				 type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
	</providers>
</configProtectedData>

Again use aspnet_regiis to encrypt the appSettings section referring to the config protection provider we named “CustomProvider” in the configProtectedData:

aspnet_regiis -pef “appSettings” c:\path-to-folder-with-config-file -prov “CustomProvider”

You export those keys like this:

aspnet_regiis -px “CustomKeys” “c:\myCustomKeys.xml” -pri

This creates an XML file we’ve seen before.

This is how you import those keys on the other servers:

aspnet_regiis -pi “CustomKeys” “c:\myCustomKeys.xml”

Make sure to copy over the XML file of course.

Decrypting a config file is done the same way as before:

aspnet_regiis -pdf “appSettings” c:\path-to-folder-with-config-file

Just like with DPAPI you don’t need to set any decryption data yourself when you want to read some app settings in the config file, it’s performed for you automatically.

We also mentioned that Network Service will need access to those keys. Guess which tool can be used to achieve that… …aspnet_regiis of course!

The following command will do just that:

aspnet_regiis -pa “MyCustomKeys” “NT Authority\Network Service”

If this fails on one of the web farm machines then it might be that you need to grant access to the ID that the app-pool is running under:

aspnet_regiis -pa “CustomKeys” “IIS APPPOOL\.NET v4.5” -full

So in case decryption fails on the web servers then make sure you try both of these commands. You’ll obviously need to look up the app-pool ID for your website.

Protecting XML

To wrap up this post here comes a little note on XML strings in particular. The config file may not not be the only XML-formatted data the you want to protect. You may work a lot with XML in you code and you may want to protect portions of those strings. You can learn about the System.Security.Cryptography.Xml namespace on MSDN.

You can view the list of posts on Security and Cryptography here.

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a comment

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.