Tuesday, August 11, 2009

Encrypting your web.config file

Ever see a connection string in a configuration file with the Username and Password available to the world?  I know I have, far to many time to be good.  But; did you know that you can quite easily Encrypt and Decrypt this on-the-fly using built in .Net functionality?!?!  Well you can and it’s very easy to do too.

Setting up your project

First create a simple ASP.NET web application in Visual Studio 2008.

  • Edit the current web.config file and add a valid connection string:

<connectionStrings>
  <add name="MyAppConnection" connectionString="Server=dubwsdev001;Database=DevDatabase;Integrated Security=false;User Id=xxxxx;PWD=xxxxxxxxx;" />
</connectionStrings>

  • Edit the default.aspx file

Add two labels and two button to your form or just copy/paste the following code:

<form id="form1" runat="server">
<div>  
    <asp:Label ID="lblStatus" runat="server"></asp:Label>
    <br />
    <asp:Label ID="lblConnection" runat="server"></asp:Label>
    <br />

    <asp:Button ID="btnEncrypt" runat="server" onclick="EncryptConfig" Text="Encrypt" />
        &nbsp;&nbsp;
    <asp:Button ID="btnDecrypt" runat="server" Text="Decrypt" onclick="DecryptConfig" />

    <br />

</div>
</form>

It should look something like the following:

image

  • Edit the code behind “default.aspx.cs” file to populate the lblConnection text label with the connection string we have in the web.config file.  Do this by adding the following code:

using System.Web.Configuration;

protected void Page_Load(object sender, EventArgs e)
{
     string strConnection= WebConfigurationManager.ConnectionStrings["MyAppConnection"].ConnectionString;
     lblConnection.Text = strConnection;
}

protected void EncryptConfig(object sender, EventArgs e)
{

}

protected void DecryptConfig(object sender, EventArgs e)
{

}

Starting the application should result in the following:

image

Encrypt / Decrypt on-the-fly

To do this we need 3 private methods .. one to Encrypt the files, one to decrypt the file and one to see if encryption is already in place (i.e. you don’t want to encrypt an already encrypted section).  So we add these to the button methods in the code behind.

protected void EncryptConfig(object sender, EventArgs e)
{
    if (IsEncrypted(Request.ApplicationPath))
        return;   // alredy done so ignore

   EncryptConnString(Request.ApplicationPath);
    btnDecrypt.Enabled = true;
    btnEncrypt.Enabled = false;
    lblStatus.Text = "The connection string is currently is encrypted ";
    lblConnection.Text = WebConfigurationManager.ConnectionStrings["MyAppConnection"].ConnectionString;
}

protected void DecryptConfig(object sender, EventArgs e)
{
    if (!IsEncrypted(Request.ApplicationPath))
        return;   // alredy decrypted so ignore

    DecryptConnString(Request.ApplicationPath);
    btnEncrypt.Enabled = true;
    btnDecrypt.Enabled = false;
    lblStatus.Text = "The connection string is currently is not encrypted!";
    lblConnection.Text = WebConfigurationManager.ConnectionStrings["MyAppConnection"].ConnectionString;

}

The IsEncrypted, EncryptConnnString and DecryptConString are our methods that do all the work.  Here I’ve implemented them in the page, but there is no reason why it can’t be done in a helper class or within a common framework.

IsEncrypted

Probably the simplest method to understand the “var config” simply opens the configuration file that is passed from the button press.  The path is noted in the ASP.NET request object in a property called ApplicationPath.

private static bool IsEncrypted(string strPath)
{
    var config = WebConfigurationManager.OpenWebConfiguration(strPath);
    return config.GetSection("connectionStrings").SectionInformation.IsProtected;
}

If the of the Section “connectionStrings” has been encrypted a property called IsProtected is set to true.  remember this is all automatic, you don’t have to write any code to check this!

EncryptConnString and DecryptConnString

Here is were it gets a little more complicated, as above the OpenWebConfiguration method will return you an instance of the current web.config file. the commend “section.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider")” however; actually does all the work.  The provider is already built into the .NET and will give you 128bit encryption on whatever section you have selected.  In this case it’s the “ConnectionStrings” area.

private static void EncryptConnString(string strPath)
{
    var config = WebConfigurationManager.OpenWebConfiguration(strPath);
    var section = config.GetSection("connectionStrings");
    if (section.SectionInformation.IsProtected) return;
            section.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider");
    config.Save();
}

DecryptConnString is the same as EncryptConnString but calls the UnprotectSection method.

private static void DecryptConnString(string strPath)
{
    var config = WebConfigurationManager.OpenWebConfiguration(strPath);
    var section = config.GetSection("connectionStrings");
    if (!section.SectionInformation.IsProtected) return;
    section.SectionInformation.UnprotectSection();
    config.Save();
}

Run your web application again and press the “Encrypt” button.

image

Notice that the label now says the connection section has been Encrypted; however the connection string is still read correctly!  Now if you open the web.config file using Visual Studio you’ll see the following:

image

Lets see a hacker get past that baby!!

Press “Decrypt” on your application and the web.config will return to :

image

Best of all there is no code to write!!!!!!!