Configuration File Encryption


It never fails: At some point in your career as a Web application designer or developer you're going to end up with a secret that your application needs to store somewhere, and that's never fun. The most common secret is a connection string that has a password in it, or a user name and password that you need to access a remote resource. Of course your first intuition should be to try to eliminate the secret. For example, you might be able to use integrated security to connect to your database instead of using a connection string with a password in it. Integrated security can often reduce the number of secrets that your application needs to manage, and it is a good place to start. But sometimes that's simply not an option.

When faced with this problem, most people will look for a place on the machine to hide the secret. "Maybe the registry would work, or perhaps I could use a file with an obfuscated name on a different drive than my virtual directory. And I can protect it even further by locking down the access control list, so only my Web application has permission to read the secret."

The next phase is to start thinking about encryption: "Perhaps I can encrypt the secret! Oh wait, now I've got an encryption key that I must hide somewhere. I knowI'll encrypt that key as well! Oh, wait . . ." If you go down this road, you'll quickly discover that encryption doesn't eliminate secrets; it merely transfers them into keys. Ultimately, there's still a secret to worry about.

There's no foolproof way to hide a secret on a machine if your application needs to be able to use that secret on a regular basis. Any resource that's available to your application is available to an attacker who has taken control of your application by exploiting some vulnerability that you missed, be it a buffer overrun, SQL injection vulnerability, or whatever. But that doesn't mean you should just give up and leave secrets in cleartext hardcoded in your ASPX pages, web.config file, or elsewhere. ASP.NET 2.0 helps by providing a standard technique for encrypting sections of your configuration files; stuff that sometimes needs to be encrypted, such as the <connectionStrings> section. There's even a provider model that allows you to decide on the encryption and key management technique.

The simplest way to get started is to use the Data Protection API (DPAPI) provider. DPAPI is a facility built into modern versions of Windows that lets you ask the Local Security Authority Subsystem (LSASS.EXE) to encrypt data for you with a set of keys that it manages. Yes, there's still a secret key, but at least it's one that's being managed by the most secure process on the machine.

To encrypt a section of your web.config file using DPAPI, just run the aspnet_regiis tool and point it at your virtual directory, naming the section you wish to encrypt:

aspnet_regiis -pef connectionStrings e:\web\myVirtualDir   -prov DataProtectionConfigurationProvider 


The -pef switch indicates you want to use the protection facility, encrypt a section, and provide a file path that points to the directory where your web.config file lives. There are many different flavors of protection switches; just run aspnet_regiis -? to get a listing of all the options.

The prov switch indicates which provider you want to use. Providers are listed under the <configProtectedData> section of machine.config. There are two, and I'll explain why you might want to use the other one shortly.

What's nice about this technique is that the code you use to access encrypted configuration sections doesn't change at all. At runtime, you don't need to worry about whether a section is encrypted or not: it'll automatically be decrypted in memory for you when you need it, while anyone who looks at web.config directly will see ciphertext.

So what if the administrator needs to change the connection string? She can either replace the entire section with a normal <connectionStrings> section, or more likely run aspnet_regiis using the -pef switch to decrypt the file on disk, make her change, then run aspnet_regiis with the -pef switch to reencrypt the section.

As an example, I encrypted an empty <connectionStrings/> element using DPAPI, and Listing 5-13 shows what it ended up looking like (the ellipses are mine; the ciphertext is rather long).

Listing 5-13. Encrypted connection strings

<configuration>  <connectionStrings configProtectionProvider=    "DataProtectionConfigurationProvider">   <EncryptedData>    <CipherData>      <CipherValue>AQAAANCMnd8...Cin</CipherValue>    </CipherData>   </EncryptedData>  </connectionStrings> </configuration> 

Since DPAPI uses a key that's hidden away on the machine, it makes xcopy deployment pretty much impossible. Web farms become a nightmare, because each server has its own Local Security Authority with its own key, and you can't synchronize these like you can with the ASP.NET <machineKey> element. If this is a problem, you should use the RSA provider instead. This provider uses a public/private key pair, so it's not quite as fast, but since you can export the key pair, you can synchronize keys across a Web farm.[17]

[17] To learn how to synchronize keys in a Web farm, see http://msdn.microsoft.com/library/en-us/dnpag2/html/paght000006.asp or search for "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA."

Note that if the section you want to encrypt isn't a direct child of the root <configuration> element, you should specify a path to get to it. For example, if you want to encrypt the <machineKey> element, you would do so by specifying "system.web/machineKey" as the section name.

Keep in mind that none of this is foolproof, but if an attacker manages to download your web.config file, he'll need to do more if he wants to decrypt your secrets. He'll either need to run code on your server to decrypt the data or find a way to steal the encryption key. It's all about defense in depth, and it's so easy to do that it's really a no-brainer.




Essential ASP. NET 2.0
Essential ASP.NET 2.0
ISBN: 0321237706
EAN: 2147483647
Year: 2006
Pages: 104

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net