The management of secret data is normally one of the most challenging tasks of any web project. It goes without saying that the best solution of allavoid storing secrets at allis not a practical one in many real-world cases. A better approach is using integrated authentication techniques assuming that they work for your scenario. The advantage is that credentials (i.e., user names and passwords) are exchanged out of your control using encrypted channels and, more importantly, no critical information must be stored and managed within the application. If your web application does require secret storage, there are a few options to consider. It should be said up front that it is rather impossible to securely store secret data in software; however, you can make the work harder for the bad guys.
Architecturally speaking, ASP.NET applications are centered around the configuration files and that, in theory, would be a good place for data storage. Storing credentials in a .config file is not a good idea, but it isnt that bad either. In other words, storing a password as clear text in the web.config file doesnt automatically mean that you make it publicly accessible to any sort of attacker. Configuration files, in fact, are not readable over the Web. Whenever a request arrives for a .config resource, IIS and ASP.NET promptly rejects it because in ASP.NET .config resources are mapped to a particular HTTP handler that returns an error:
<httpHandlers> <add verb="*" path="*.config" type="System.Web.HttpForbiddenHandler"/> </httpHandlers>
The HttpForbiddenHandler component bound to *.config files guarantees that an error message is returned and no configuration content is ever displayed to end users. So ASP.NET does block the download of configuration files by default and makes them unaccessible through the web space. In spite of this, its always a good idea not to place credentials or other secret data in configuration files. You never know what can happen with hackers! This brings us back to the original question: Where do we store critical data? Lets briefly review three options: COM+ Catalog, DPAPI, custom configuration files.
Secret data can be stored in the COM+ catalog and administratively configured and read using construct strings. The COM+ catalog doesnt provide a high degree of security, but it is another level up from configuration files. You should write a COM+ component, and this can easily be done in .NET by inheriting the ServicedComponent class and placing the class in a strongly named assembly.
The Data Protection API (DPAPI) relies on two functions called CryptProtectData and CryptUnprotectData, which can produce user- or machine-specific encryptions without explicit key management. These functions are not directly wrapped by managed classes, so youll need to use P/Invoke to call them. The primary downside to DPAPI is that you need to run code on the machine to produce and protect the secret, and the data can only be decrypted by the account used to encrypt the data. It's often effective to use DPAPI in conjunction with a registry key for storing secret data.
Another way to solve the secret storage problem is by writing your own configuration section handler in .config files. The custom section will manage an encrypted section. Of course, the handler still needs a key somewhere to decrypt the section data.
Dino Esposito is Wintellect's ADO.NET and XML expert, and a trainer and consultant based in Rome, Italy. Dino is a contributing editor to Windows Developer Network and MSDN Magazine, and the author of several books for Microsoft Press including Building Web Solutions with ASP.NET and ADO.NET and Applied XML Programming for .NET. Contact Dino at [email protected].