How to encrypt web.config sections

Here's another quick tip for anybody interested in protecting sensitive information declared on your Web application web.config. In this example I'm going to use Windows Data Protection API (DPAPI) to encrypt connection strings and session state SQL connections string on all web.configs found under 'C:\inetpub' (default location for web applications running on IIS).

Web.config sections encrypted with DPAPI will only be able to be decrypted on the machine where you originally ran the encryption method. In other words, you won't be able to copy-paste your DPAPI encrypted web.config files to different server. If you intend to run the encryption once and move the web.configs to different servers, you must use RSA encryption. There are a few additional commands you will need to invoke, but it's very straight forward (please check the reference here).

# search for all 'web.config' located under 'C:\inetpub\'
Get-ChildItem 'C:\inetpub\' -Filter 'web.config' -Recurse | ForEach-Object {
  $directory = $_.Directory.FullName
  $filePath = $_.FullName
  $webConfig = [xml](Get-Content $filePath)

  # check if there are any connection string sections declared
  if($webConfig.SelectSingleNode('//connectionStrings').HasChildNodes) {
    Write-Output "encrypting '$filePath' connection strings..."

    # let's tell 'aspnet_regiis' to encrypt it
    & $env:windir\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pef 'connectionStrings' $directory -prov 'DataProtectionConfigurationProvider'

  # check if there are any session state sections with the attribute 'sqlConnectionString' defined
  if(-not ([string]::IsNullOrWhiteSpace($webConfig.SelectSingleNode('//system.web/sessionState[@sqlConnectionString]')))) {
    Write-Output "encrypting '$filePath' session state..."

    # let's tell 'aspnet_regiis' to encrypt it
    & $env:windir\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pef 'system.web/sessionState' $directory -prov 'DataProtectionConfigurationProvider'

Here's the original connection string section:

  <add name="mainConnStr" connectionString="Data;Initial Catalog=MainDb;User ID=SqlDbo;Password=SqlDbo!;Network Library=DBMSSOCN" providerName="System.Data.SqlClient" />

And the same connection string section after being encrypted:

<connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">

Decrypting them is equally easy simply run the same command without the provider specified and use "-pdf" as the desired command

& $env:windir\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pdf 'connectionStrings' $directory 

Additionally, only users with elevated privileges with the able to run this command, so obviously you are not hiding connection string details from System Administrators. On the other hand, if an attacker is able to get elevated privileges, connection strings might be the least of your concerns (assuming the SQL user defined on your connection string doesn't have Database Owner access). This method simply adds another small barrier on your application security.

For reference, the following sections usually contain sensitive information that you need to encrypt:

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

Here's the reference articles, and even though the following articles mention ASP.NET 2.0, those are compatible with any version above 2.0:

web services