Sunday 3 May 2009

Encrypting the web.config online

One of the things that possibly gets overlooked when you are first developing web applications is the concept of security and defending against possible security breaches.

Even though the web.config file is not served by IIS, it may happen that someone accidently changes that! It has being known to happen. Or someone may get access to the machine through some other nefarious means.

So how do you secure the web.config. Well here is how

I have a simple Config.aspx file. This ASPX file only shows the current encryption status of the connectionString section in the web.config and allows you to reverse it.

So here is how to do it

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Config Tools</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="_ConnStatus" runat="server"></asp:Label>
        <br />
        <asp:Label ID="_Conn" runat="server"></asp:Label>
        <br />
        <br />
        <asp:Button ID="Encrypt" runat="server" onclick="EncryptConfig"
            Text="Encrypt" />
            &nbsp;&nbsp;
            <asp:Button ID="Decrypt" runat="server"
            Text="Decrypt" onclick="DecryptConfig" />
        <br />
        <br />
        <br />
        <br />
    </div>
    </form>
</body>
</html>

That is the front end and in the code behind we have this

protected void Page_Load(object sender, EventArgs e)
        {
            string strConnDesc;

            if (Business.Config.IsEncrypted(Request.ApplicationPath))
            {
                Decrypt.Enabled = true;
                Encrypt.Enabled = false;
                strConnDesc = "is encrypted";
            }
            else
            {
                Encrypt.Enabled = true;
                Decrypt.Enabled = false;
                strConnDesc = "is not encrypted!";
            }
            _Conn.Text = "The connection string is currently " + strConnDesc;
        }

        protected void EncryptConfig(object sender, EventArgs e)
        {
            Business.Config.EncryptConnString(Request.ApplicationPath);
            Decrypt.Enabled = true;
            Encrypt.Enabled = false;
            _Conn.Text = "The connection string is currently is encrypted ";
        }

        protected void DecryptConfig(object sender, EventArgs e)
        {
            Business.Config.DecryptConnString(Request.ApplicationPath);
            Encrypt.Enabled = true;
            Decrypt.Enabled = false;
            _Conn.Text = "The connection string is currently is not encrypted!";
        }

Now the main two things are the EncryptConfig and DecryptConfig

I have the logic for these functions in another assembly.

To encrypt the web.config file you can use the following function

public 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();
       }

First thing you do is you open the web.config file and get the connectionStrings section.

Check and see if its currently protected, and if its not, encrypt it with the RSA provider. And then save the file

To decrypt its much the same

public 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();
        }

Again open the web.config and look for the connectionStrings section and check if its encrypt and then decrypt and save.

Now I also have a help function that tells me if the section is encrypted or not

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

A couple of words of warning though.

You should only encrypt the web.config on the machine that it will be residing on. The reason is that the config is encrypted using the machine key of the encypting machine. Or put simply, encrypting it on your dev machine will mean you cant use it on another machine.

You will also need to make sure that the config file is writable otherwise you wont be able to encrypt or decrypt. So you should check if the file is writable first.

You can download the Config.aspx sample and also the helper class as part of the shopping cart demo here

No comments: