Encrypting Configuration Information for ASP.NET

Posted Wednesday, July 16, 2008 4:11 PM by Nathan Zaugg

Encryption Block Transform Graphic Every company I consult with invariably has their own "security" assembly and they all have a hard-coded encryption key with the IV and the method to decrypt is right next to the method to encrypt.  This is what I call marginal protection.  Yes, it's encrypted and will probably get a security auditor off of your back but don't be fooled into thinking that you are protected!  A similar thing is done with information in the database, but I'll cover how to do this on an upcoming post. 

Why aren't you protected?  The answer to this question is actually quite simple.  If an attacker has access to download your web.config file (say, they brute forced a password on the FTP server) then there is nothing stopping them from downloading the your Security.dll which is responsible for decrypting the password.  Once they have that library it's seconds, not minuets, before they have got the password. 

One possible work around is to encrypt configuration sections of your web.config file using DPAPI as outlined in this MSDN How-to.  This is immune to the download attack because the DPAPI uses encryption that is based on a machine or a user.  Even if someone was able to download your web.config they would effectively have no way to decrypt that information. 

What happens, though, if the attacker has the ability to upload files?  Well, in theory, they may be able to grab that configuration in code which will, of course, be decrypted before it is returned.  Ahh, but they don't even know what the name of the connection string (in the case of databases) is because the entire section was encrypted.  However, they could guess it or get it from other code. By the way, you really shouldn't deploy the .cs files to production anyway; you should use the "publish website" option with the setting to not allow the site to be updated.  If you follow all of the standards pretty closely your in good shape.  Another great idea is to use Integrated Authentication for database access -- that way there is no password to steal!

The How to outlines 3 basic steps summarized below:

  1. Identify the configuration sections to be encrypted
    1. You may only encrypt the following:
    2. <appSettings>. This section contains custom application settings. 
      <connectionStrings>. This section contains connection strings. 
      <identity>. This section can contain impersonation credentials. 
      <sessionState>. The section contains the connection string for the out-of-process session state provider.
  2. Choose Machine or User store
    1. Use Machine store if this is a dedicated server with no other applications running on it or you want to be able to share this information with other applications running on this machine.
    2. Use User store if the above does not match your situation and in a scenario in which the user has limited access to the server.
  3. Encrypt your configuration file data
    1. To encrypt using Machine Store, run the following command from a .NET command prompt:
      aspnet_regiis.exe -pef "{ConfigSectionName}" {PhysicalDirectory} –prov "DataProtectionConfigurationProvider"
      OR
      aspnet_regiis.exe -pef "{ConfigSectionName}" -app "/{VirtualDirectory}" –prov "DataProtectionConfigurationProvider"
    2. To encrypt using User Store:
      Add the following section to your configuration file:
    3. <configProtectedData> 
          <providers> 
              <add useMachineProtection="false" keyEntropy="" 
                      name="MyUserDataProtectionConfigurationProvider" 
                      type="System.Configuration.DpapiProtectedConfigurationProvider, 
                      System.Configuration, Version=2.0.0.0, Culture=neutral, 
                      PublicKeyToken=b03f5f7f11d50a3a" /> 
          </providers> 
      </configProtectedData>

      Open a command prompt using the user you plan to encrypt the file with. To do so, Right click on the Command Prompts shortcut, right click -> Run As.  Or use the following command:

      Runas /profile /user:domain\user cmd
       
      Run the following command:
      Aspnet_regiis -pe "connectionStrings" -app "/{VirtualDirectory}" -prov "MyUserDataProtectionConfigurationProvider"

 

It really is that simple!  The great thing is that we don't have to do anything special in development to benefit from the encryption of the configuration sections. 

 

References:

http://msdn.microsoft.com/en-us/library/ms998280.aspx