12 October 2015

Encrypting sections of .NET configuration files (web.config/app.config)

In a .NET application, we generally store application specific configuration information under “appSettings” sections of our configuration file (web.config / app.config). Under normal circumstances, this information is stored as plain text and anyone having read access to the configuration file can read them. If we need to store some confidential information in configuration file, it is a good idea to encrypt them so that it is not legible to prying eyes. It also ensures that if a hacker is able to get access to the configuration file, the information will still be safe due to its encrypted nature.

To achieve our objective, we can use ASP.NET IIS Registration tool (aspnet_regiis.exe), to encrypt sections in configuration file.

Let’s take a simple example of a web.config file in your website “C:\inetpub\wwwroot\MySampleWebSite” having “appSettings” section as shown below:-

<?xml version="1.0"?>
<configuration>
 
  <appSettings>
    <add key="SampleAppSettingKey" value="SampleAppSettingValue" />
  </appSettings>

  <system.web>
    <compilation debug="true"/>
    <authentication mode="Windows"/>
  </system.web>
</configuration>

To access the value of appSetting key in code behind, you will be using code like this:-


string sampleKeyValue = ConfigurationManager.AppSettings["SampleAppSettingKey"].ToString();


Let’s say you want to encrypt all the data under “appSettings” section in your website “C:\inetpub\wwwroot\MySampleWebSite”. To do this, we need to execute the following command in Visual Studio command prompt.

General syntax of command


aspnet_regiis.exe -pef <section> <physical_directory> –prov <provider>

   -- or --

aspnet_regiis.exe -pe <section> -app <virtual_directory> –prov <provider>


Concrete syntax for our example


aspnet_regiis.exe -pef "appSettings" "C:\Inetpub\wwwroot\MySampleWebSite" –prov "DataProtectionConfigurationProvider"

   -- or --

aspnet_regiis.exe -pe "appSettings" -app "/MySampleWebSite" –prov "DataProtectionConfigurationProvider"


  • appSettings” is the name of section in web.config file which needs to be encrypted.
  • C:\Inetpub\wwwroot\MySampleWebSite” is the physical directory where our web.config file is located.
  • DataProtectionConfigurationProvider” is the name of in-built .NET provider which is used to encrypt the data.

After executing this command, our web.config will look something like this:-


<?xml version="1.0"?>

<appSettings configProtectionProvider="DataProtectionConfigurationProvider">
    <EncryptedData>
      <CipherData>
<CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAASQ/EStxMHUyguKcdTy1AzQQAAAACAAAAAAADZgAAqAAAABAAAABfeSptP6xLarF/zp02qg7AAAAAAASAAACgAAAAEAAAAKq03YHFEHRUId9btkN7pqnoAAAA2XEU9DY3KxRrDBxtdgSiLKLZW6uJv9zRuKQfBTkLiEhsXF+jtg5pIwec4yZ4/10xkYJL293nC/o7jCiFMvtdX0c9m18YlIr2xK1ux2FCrQURNCEUXJ+M4szB8OZTRZmZoiXMEqmwr9Wvernkn2RdjoCXrWIAYTG5ut+/PHiA42yv69TLJI7jQvdPyRKofjKyw4j2iJJyzNSG6V+KiPIlzgP494tmo+CAGMxcQTIp44CgIoruchcr3oKtGWgTk1KF4nbM3iFa3T06AwFMRtG0ZDtPOVv5uYX5vubmg0jGGaCXlKbTQQLLXRQAAADrc9Rr9YwhIo0tLYERIHWKoy+F0A==</CipherValue>
      </CipherData>
    </EncryptedData>
 </appSettings>

  <system.web>
   <compilation debug="true"/>
   <authentication mode="Windows"/>
 </system.web>
</configuration>


Note that the “appSettings” section has been modified by command to contain encrypted data as shown.

The advantage that lies with .NET is that inspite of appSetting values being encrypted, you need not write any additional code to decrypt the values in your code. You can continue using the following code to retrieve the value back.


string sampleKeyValue = ConfigurationManager.AppSettings["SampleAppSettingKey"].ToString();


The .NET internally decrypts the value on its own when reading them in C# code.

Selectively encrypting sections of configuration file

Generally, in our actual application, we do not want to encrypt the whole appSettings section but only certain keys which have confidential data. Unfortunately, .NET does not provide any way to selectively encrypt only certain appSetting keys in your configuration file. It only gives us the option to encrypt a whole section in configuration file. To circumvent this inflexibility, we can take following approach:-

  1. Create our own custom configuration section in configuration file.
  2. Store all the confidential data in the custom configuration section.
  3. Encrypt the custom configuration section.
  4. Write custom C# code to access the custom configuration section keys.

This approach is described below.

Define custom configuration section

To create a custom configuration section in configuration file, we need to first define a new section name in web.config file.


  <configSections>
    <section name="secureAppSettings" type="System.Configuration.NameValueSectionHandler,
        System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </configSections>


The version and public-key-token of DLL for System.Configuration may differ on your system and you may need to change it accordingly.

Add custom configuration section

Once the custom section name is defined, we can add the section in our web.config file like this:-


<secureAppSettings>
<add key="SampleSecureKey" value="SampleSecureKeyValue"/>
</secureAppSettings>


Encrypt the custom configuration section

Once all the keys are created in custom creation section, we can use following command to encrypt it.


aspnet_regiis.exe -pef "secureAppSettings" "C:\Inetpub\wwwroot\MySampleWebSite" –prov "DataProtectionConfigurationProvider"

   -- or –

aspnet_regiis.exe -pe "secureAppSettings" -app "/MySampleWebSite" –prov "DataProtectionConfigurationProvider"


Access custom configuration section keys

To access the keys of custom configuration section we need to write following code.


NameValueCollection secureAppSettings =          (NameValueCollection)ConfigurationManager.GetSection("secureAppSettings");

string sampleSecureKeyValue = secureAppSettings["SampleSecureKey"];



A sample web.config file before encryption is shown below:-


<?xml version="1.0"?>

<configuration>

  <configSections>
    <section name="secureAppSettings" type="System.Configuration.NameValueSectionHandler,
        System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </configSections>

  <appSettings>
    <add key="SampleAppSettingKey" value="SampleAppSettingValue" />
  </appSettings>
 
<secureAppSettings>
<add key="SampleSecureKey" value="SampleSecureKeyValue"/>
</secureAppSettings>

<system.web>
    <compilation debug="true"/>
    <authentication mode="Windows"/>
</system.web>

</configuration>


The same file after section “secureAppSettings” is encrypted is shown below:-


<?xml version="1.0"?>

<configuration>

  <configSections>
    <section name="secureAppSettings" type="System.Configuration.NameValueSectionHandler,
        System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </configSections>
 
  <appSettings>
    <add key="SampleAppSettingKey" value="SampleAppSettingValue" />
  </appSettings>

  <secureAppSettings configProtectionProvider="DataProtectionConfigurationProvider">
    <EncryptedData>
      <CipherData>
  <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAASQ/EStxMHUyguKcdTy1AzQQAAAACAAAAAAADZgAAqAAAABAAAABfeSptP6xLarF/zp02qg7AAAAAAASAAACgAAAAEAAAAKq03YHFEHRUId9btkN7pqnoAAAA2XEU9DY3KxRrDBxtdgSiLKLZW6uJv9zRuKQfBTkLiEhsXF+jtg5pIwec4yZ4/10xkYJL293nC/o7jCiFMvtdX0c9m18YlIr2xK1ux2FCrQURNCEUXJ+M4szB8OZTRZmZoiXMEqmwr9Wvernkn2RdjoCXrWIAYTG5ut+/PHiA42yv69TLJI7jQvdPyRKofjKyw4j2iJJyzNSG6V+KiPIlzgP494tmo+CAGMxcQTIp44CgIoruchcr3oKtGWgTk1KF4nbM3iFa3T06AwFMRtG0ZDtPOVv5uYX5vubmg0jGGaCXlKbTQQLLXRQAAADrc9Rr9YwhIo0tLYERIHWKoy+F0A==</CipherValue>
      </CipherData>
    </EncryptedData>
  </secureAppSettings>

<system.web>
    <compilation debug="true"/>
    <authentication mode="Windows"/>
</system.web>

</configuration>


Decrypting an encrypted section in configuration file

Sometimes, we may need to add another key in our encrypted section. At these times, we may first need to decrypt the section, add the new key and re-encrypt it again. To decrypt an already encrypted section, we just need to tweak the aspnet_regiis command a bit as shown:-

General syntax of command


aspnet_regiis.exe -pdf <section> <physical_directory> –prov <provider>

   -- or --

aspnet_regiis.exe -pd <section> -app <virtual_directory> –prov <provider>


Concrete syntax for our example


aspnet_regiis.exe -pdf "appSettings" "C:\Inetpub\wwwroot\MySampleWebSite" –prov "DataProtectionConfigurationProvider"

   -- or --

aspnet_regiis.exe -pd "appSettings" -app "/MySampleWebSite" –prov "DataProtectionConfigurationProvider"



Note that option “-pef/-pe” in earlier commands was replaced with “-pdf/-pd” for decrypting a particular section.

No comments: