Monday, September 22, 2008

Beware of the Settings Designer

Visual Studio 2008 and 2005 both provide a very simple method of creating default settings for an application. While there is a place for the settings designer, you should be aware of a couple of the "gotchas" that come along with the settings designer, so you don't make a serious security blunder.

.NET settings that are entered using the settings designer create two files: Settings.settings and Settings.designer.cs. Settings.settings is used for viewing the settings at design time, while Settings.Designer.cs is actually compiled into the DLL.

In the settings designer, it's possible to add a connection string by setting the type to "(Connection string)". I believe this is a mistake on the part of Microsoft. While it's extremely convenient to add a connection string via the Connection Properties window that can be used to specify the connection string, it has the added effect of luring unsuspecting developers into actually using it, despite the warning that pops up when you indicate to save the password (manually typing a connection string will not yield this warning), and then compiling the connection string into the DLL. Once the value of the connection string is entered into the settings designer, the IDE automatically updates the Settings.Designer.cs file, as well as the app.config, and it puts this connection string in both locations.

Creating a connection string in the settings designer yielded the following code in the Settings.Designer.cs file:

[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.ConnectionString)]
[global::System.Configuration.DefaultSettingValueAttribute("Data Source=localhost;Initial Catalog=myDatabase;User ID=myUserName;Password=myPa" +
"ssword;")]
public string MyConnectionString {
get {
return ((string)(this["MyConnectionString"]));
}
}


And this code is then compiled into the assembly, and available for viewing in any disassembler program. I was easily able to view my connection string in Reflector by opening the property in Reflector:

.property instance string MyConnectionString
{
.get instance string SecurityNightmare.Properties.Settings::get_MyConnectionString()
.custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor()
.custom instance void [System]System.Configuration.SpecialSettingAttribute::.ctor(valuetype [System]System.Configuration.SpecialSetting) = { int32(0) }
.custom instance void [System]System.Configuration.ApplicationScopedSettingAttribute::.ctor()
.custom instance void [System]System.Configuration.DefaultSettingValueAttribute::.ctor(string) = { string('Data Source=localhost;Initial Catalog=myDatabase;User ID=myUserName;Password=myPassword;') }
}


So, that being said, avoid adding connection strings within the settings.designer. It's much safer to add them manually to the app.config.