Part 2 - Best practices for storing secrets and other cool stuff (regarding setup etc)

In this second part of my ASP.NET Security FAQ I'm going to cover the "storing secrets securely" theme and I'm going to tell something about other nices and useful features that have to do with security.

Question 1: What about storing secrets that are needed in your application?

People often ask "where is the best place to store a DSN (data source name) containing a password?" or an analogue question regarding the storage of some secret. Of course it's a best practice to put this string somewhere in a shared location so that all files of your application can access it. The obvious solution is to use the web.config file and create a section as follows:

<configuration>
   <add key="dsn" value="server=myserver;uid=myuser;pwd=Passw0rd!;database=MyDb" />
</configuration>

However, when telling this to people the answer is bounced back once again: is this safe? Then answer is not as easy as yes or no. First of all, it's safe in the sense that the .config file is mapped to the HttpForbiddenHandler of ASP.NET in the machine.config file, so nobody can download this file through a web request (luckily!). The only people who can read the file are you as the web developer and of course the administrator of the machine. In some cases this is not a problem (in cases where the web server admin is also the DBA of the database server, so he knows these secrets as well) but of course it's always better to make sure it's safe in case somebody can compromise the security of the machine to grab the file, or when the file contains other secrets as well. In my opinion, you should always go for the maximum level of security. The nice thing is that ASP.NET provides support for this, the dark side is that you'll only be able to apply the trick if you have local access to the machine.

Let me explain. The .NET Framework contains a tool that can do encryption of secrets and store these encrypted values in the registry on the server. In fact, there are several cases where this can be useful: to store secrets in a configuration section, to store the credentials of an impersonation account, to store the credentials of the processModel user and password to run ASP.NET under, to store the DSN for session state using a database server, etc. As all tools in the .NET Framework, once you get to know them, it's really easy to use and you will end up as a .NET Framework command-line tools addict :-). Here we go: the name is aspnet_setreg.exe and it can be downloaded from http://support.microsoft.com/default.aspx?scid=kb;en-us;329290:

C:\Documents and Settings\Administrator>aspnet_setreg
ASP.NET Encryption Tool Version 1.0.3705.361
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

Usage:
------
aspnet_setreg -k: [-u:] -p:
aspnet_setreg -k: -c:
aspnet_setreg -k: -d:
aspnet_setreg -k: -g

As an intermezzo, allow me to tell you that ASP.NET Whidbey will have native support to encrypt connection strings in the web.config file but I won't cover this right now.

In fact, the tool is self-explaining. If you want to encrypt a connection string, just use something like this:

aspnet_setreg -k:"SOFTWARE\My ASP.NET App\Configuration" -c:server=myserver;uid=myuser;pwd=Passw0rd!;database=MyDb

Important: don't forget the quotes around the -k parameter value, since otherwise you'll end up with an exception :-(. Seems the tool still has some issues. However, once it has executed fine, you'll end up with a new registry key that can be found through the regedit.exe tool under HKEY_LOCAL_MACHINE\SOFTWARE\My ASP.NET App\Configuration\ASPNET_SETREG. As you'll see, the result is an encrypted string. The last thing to do is to point to the entry in the configuration file, as you're told to do by the tool:

Please edit your configuration to contain the following:

sqlConnectionString="registry:HKLM\SOFTWARE\My ASP.NET App\Configuration\ASPNET_SETREG,sqlConnectionString"

The registry: prefix tells ASP.NET to get the value (and decrypt it) from the registry.

Question 2: I just installed IIS 6 on my machine and every request to an ASP.NET file issues a 404 error message. What am I doing wrong?

This is a typical IIS 6.0 question. The answer is as easy as: "secure by default". First of all, on Windows Server 2003, IIS is not installed by default (it was on Windows 2000!). Furthermore, once it's installed through the Windows Components Setup or through the Configure Your Server tool, it will only handle static files (.htm for example). All the rest is blocked by default, including ASP, ASP.NET, etc. To enable ASP.NET on the box, you should go to the inetmgr.exe tool and go under Web Service Extensions to enable the ASP.NET ISAPI. The question people have asked me quite often as well, is why a 404 is thrown. The answer is pretty easy as well: don't tell hackers more than what's good for you :-). So, we should not tell people who want to get into the system that there are aspx files on the system, except that these are not enabled. Also a "secure by default" feature...

Question 3: I installed ASP.NET and IIS on my machine but ASP.NET does not seem to work (question for IIS versions lower than 6). What am I doing wrong?

The answer is in the question: you installed ASP.NET first and then you installed IIS. On IIS versions lower than version 6.0 (thus in Windows XP, 2000) IIS does not know anything about ASP.NET so it can't have support for it natively (also called: "backward compatibility"). The point is that the framework needs to register the ASP.NET ISAPI during the installation to tell IIS that some thing called ASP.NET is on there and that requests with extension .aspx, .asmx, etc should be sent to that "new strange thing" (strange from the IIS perspective). Fortunately, there is a tool (again!) called aspnet_regiis.exe that will help you to do this job. It's installed in the .NET Framework folder on the system (%windir%\Microsoft.NET\Framework\v1.1.4322 typically).

The most interesting command-line flags include:

  • -i to register the ASP.NET ISAPI on IIS, including scriptmaps (aspnet_client)
  • -ir to register the ISAPI only
  • -enable (for IIS 6) to enable the extension in IIS (see question 2), when combined with -i or -ir

Other flags are used to install scriptmaps on applications (needed for postbacks etc using JavaScript) and to uninstall ASP.NET again (the mapping).

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks