Need Thorough Explanation Securing Application's Database Connection String

P

Phil C.

Can someone explain in plainer english or expound the missing steps/code
especially regarding what and where and how to use the GAC, plus how to
implement and use "the instantiator's assembly ID" in the below discussion
exerpted from Visual Studio Magazine by Doug Thews

Posted February 6, 2004:

Q:
How can I secure my application's database connection string and prevent
others from getting unauthorized access to my database?

A:
You have a handful of options if you want to secure your database connection
string from prying eyes, but most boil down to one of two choices:
obfuscation (hiding) or encryption. Encryption can affect your application's
performance negatively, so you need to decide who you're securing your
connection string from and why before you choose that option.

For example, assume you're a small shop with a single developer who manages
the servers and databases. In this case, a single level of obfuscation will
probably suit your needs best. If you're deploying a Windows client desktop
application, you might want to consider storing the connection string
(encrypted or not) in a centralized location, accessible only to the
application. If you're implementing your application on a server farm
residing at an application service provider's server farm, you might want to
implement encryption to prevent unauthorized access to your database.

Hiding the connection string means storing it in a location separate from
where you use it in the code. However, be aware that anyone can use ILDASM
on your ASP.NET or Windows client application. This means they can debug
your application and try to get the database connection string by looking
for constants in the code that fit the connection string format.

Popular places to hide a database connection string include the Web.Config
file, the Registry, a database, or a remote location accessible only through
a Web service or remoting call. You can use the System.Security.Cryptography
namespace to add encryption to any of the strategies just mentioned to yield
another level of security to your connection string.

However, the safest way to secure your database connection string is to
never expose it to the application in the first place. You can do this by
developing an assembly that contains a class whose sole responsibility is to
return a database connection (and not the connection string) to the caller.
The assembly can live in the Global Assembly Cache (GAC) and can use the
instantiator's assembly ID as a key to make sure it's on the list of
approved assemblies that can have a database connection. You can use this
approach to ensure you never send any database credentials back and forth to
be intercepted and decrypted. Someone using ILDASM on your application will
see only the database connection object, not the credentials used to create
that connection.

Creating a database connection class is simple (see Listing 4). After
creating the class, deploy it to the GAC, add a reference in your
application, and use the class exactly as you would use the SqlConnection
class. Deploying an assembly to the GAC for a Windows-based client is simple
because you can make it part of the app's installation and you can
auto-update new versions. This code consumes the Get method from your
DBConnection class in the example:

myDBConnection SqlConnection =
new MyConnectionString.DBConnection();

You could pass parameters to the Get method easily if you want to have some
other criteria for validating access to the method. The important thing to
remember is that using this method doesn't expose your database connection
string (or your connection credentials) across the wire.

/*******************************************************************/

LISTING 4:

C# . Secure Your Database Connection String

Listing 4. The key requirement for securing your database connection string
is to avoid exposing your database connection string (or your connection
credentials). Once you create the class, deploy it to the GAC and add a
reference to it in your application.


using System.Data.SqlClient;
using System.Security.Principal;

namespace MyConnectionString
{
public class DBConnection
{
public SqlConnection Get()
{

// Check here to see if this is a valid request
// Use your own business logic
if (false)
{
return null;
}

// Or use the Windows identify to see if the
// caller matches the list of user ids that CAN
// access this class. Make sure the caller was
// authenticated
WindowsIdentity CallersIdentity =
WindowsIdentity.GetCurrent();
if (CallersIdentity.IsAuthenticated ==
false)
{
return null;
}

// Code to get the connection string from a config
// file or a separate database. This is merely a
// sample to make the code work -replace this with
// your business logic
string myConnectionString =
"Initial Catalog=Northwind;Data
Source=localhost;Integrated
Security=SSPI;";

// Now go get a database connection and return it
SqlConnection myConnection = new
SqlConnection(
myConnectionString);
return myConnection;
}
}
}
 
K

Kevin Yu [MSFT]

Hi Phil,

First of all, I would like to confirm my understanding of your issue. From
your description, I understand that you need to know how to install your
assembly that returns a connection in to GAC and how to implement "the
instantiator's assembly ID" in your application. If there is any
misunderstanding, please feel free to let me know.

If you intend to share an assembly among several applications, you can
install it into the global assembly cache. Each computer where the common
language runtime is installed has this machine-wide code cache. The global
assembly cache stores assemblies specifically designated to be shared by
several applications on the computer. An assembly must have a strong name
to be installed in the global assembly cache. GAC often locates at
c:\windows\assembly directory.

When you have implemented your own assembly that can return a connection
object, you can redistribute it with your application. The .NET utility
library that manages the assembly cache provides a command-line interface
tool, named the Global Assembly Cache utility (Gacutil.exe). To add an
assembly to the GAC, simply use the /i swith with the name of the assembly
that contains the manifest. Here is an example:

gacutil /i reverser.dll

For more information about Gacutil.exe and how to install and remove
assemblies to GAC, please check the following links:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cptutorials
/html/Global_Assembly_Cache_Utility__GACUTIL_EXE_.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconinstallingassemblyintoglobalassemblycache.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconremovingassemblyfromglobalassemblycache.asp

Furthermore, in the assembly that returns the connection object, we can
check if the caller assembly is a valid one with the assembly's ID. The ID
for an assembly can be implemented by checking it's public key token,
because if an assembly is strong named, its public key token must be
unique. We can identify the assembly with this. We can get the public key
token with AssemblyName.GetPublicKeyToken Method. Here is an example about
how to get the public key token for currently executing assembly:

byte[] b = Assembly.GetExecutingAssembly().GetName().GetPublicKeyToken();

For more information, please check the following link:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/
frlrfsystemreflectionassemblynameclassgetpublickeytokentopic.asp

HTH. If anything is unclear, please feel free to reply to the post.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
P

Phil C.

Kevin,

Thank you so much for enlightening me and giving me a detailed explanation
for what was a terse explanation for people that have much more experience
than I.

However, I still have some confusion. Once I get the connection assembly
object id from its public key token, I ?? want to make sure that the caller
id is a valid one to

use the connection object. Since I will be writing an ecommerce app in
Asp.net, the web browser client is calling my server side classes to do
things with the sql server database on the server.

I'm not sure I need to validate who the browser client is, as long as they
are calling posting my forms properly?? I won't know in advance who is
using my site.

All I care about is that they can't read my connection string to breach my
database.



The referenced article's code snippet mentioned this:

// Or use the Windows identify to see if the
// caller matches the list of user ids that CAN
// access this class. Make sure the caller was
// authenticated
WindowsIdentity CallersIdentity =
WindowsIdentity.GetCurrent();
if (CallersIdentity.IsAuthenticated ==
false)
{
return null;
}


Phil
 
K

Kevin Yu [MSFT]

Hi Phil,

Since you need to protect your connection string, it doesn't matter who the
browser client it. Because the browser client cannot see what is happening
in the server side assembly. So I think what we need to do is to secure the
server side assembly access with caller's public key token as ID. And let
other assemblies determine whether the client is a valid user.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
K

Kevin Yu [MSFT]

Hi Phil,

I'd like to know if this issue has been resolved yet. Is there anything
that I can help. I'm still monitoring on it. If you have any questions,
please feel free to post them in the community.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top