Storing SQL credentials correctly - c#

First off, this is an educational question - not something I am implementing in a productional application since I am learning the basics of C#.
Currently I have a solution containing 2 (actually 3, but one is unit testing) projects;
Form
Class Library
Inside the Class Library I have a class called Database.cs and it communicates with a MySQL database. I don't directly communicate with this Database.cs class, but other classes inside the Class Library do (for example Products.cs).
Though, I need credentials to connect to this MySQL database and I am not sure which way to go to do it safely.
Storing it inside the Class Library / hard-coding the credentials inside the class.
This wouldn't make sense to me since a user can easily grab the DLL and he technically got the credentials to the database.
Pass the credentials through the form to a class (like Products.cs) and that class passes it on while initializing the Database object
Could work, tried and it works but I am not sure if this is the 'neatest' way to do it.
Write a static class that contains properties with the credentials
Again, if I create this static class inside the Class Library I am pretty much off the same as my first example. If I would create this static class inside the Form, I require to add a reference to the Form-project from my Class Library (not the way I want it to be).
I tried looking stuff up but I am apparently not doing it right. Is there any other way to do this?

First of all never hard-code credentials into code because credentials tend to change over time so that means you will have to recompile and redeploy your application each time SQL credentials change.
Usually all information needed to connect to database is stored in application configuration file in a form of connection string.
If your application is web application then you're good to go because web.config (a web application configuration file) is stored on a web server and is never served to web requests.
But if your application is windows forms application, then security considerations kick in meaning that any user who uses your app could peek into application configuration file and get credentials. If it would be Microsoft SQL I would advise to use Windows Authentication. But with MySQL I guess you're doomed to store user name and password into connection string. Then I would suggest securing your connection string by encrypting it.
Also if your users can/have to authenticate against MySQL server (enter MySQL username and password), then you could use a connection string template and substitute certain parts of it with user name and password:
app.config
<connectionStrings>
<add name="MyApplication" connectionString="Location=myServerAddress;Data Source=myDataBase;User ID={0};Password={1};
Port=3306;Extended Properties=""""; />
</connectionStrings>
C# code
var username = textboxUsername.Text;
var password = textboxPassword.Text;
var connectionString = string.Format(ConfigurationManager.ConnectionStrings["MyApplication"].ConnectionString, username, password)
// at this point you have a connection string whitch could be passed to your Products class

Do not hardcode your credentials as that may prove to cause issues, firstly if you need to change your login credentials to the database at a later stage then you will have to recompile your class library, secondly as you mention the security will be compromised.
It is a good technique to leave the connection information to the main application instead of storing them in your data layer. Refactor your data layer to accept the connection string during runtime, this value needs to be passed by the main application to the data access layer.
This way you get 2 advantages:
When you deploy your application, the deployed location can have a different connection credential than your development environment
You can encrypt connection strings in your configuration file so as to increase security

Related

DNN Database Repository Reuse in Console Application

I have a project based on the Chris Hammond, Christoc, module template. I have a ton of code that I use to access data an external database. In my repositories I change the database from the default to whichever I need for that particular object. I do so with code that looks like this:
using (IDataContext ctx = DataContext.Instance(MyModuleSettingsBase.DATABASE_CONNECTION_STRING_KEY))
{
var rep = ctx.GetRepository<Product>();
products = rep.Get().ToList();
}
The default database is switched in the call to .Instance(). The repositories are used by my custom DNN modules. The repository is part of the solution that contains multiple custom modules. When I compile and install using the Extensions part of DNN, everything works well. In the code above, MyModuleSettingsBase.DATABASE_CONNECTION_STRING_KEY is found in a file MyModuleSettingsBase.cs file of my module solution. It is set to a simple string like "ProductDatabase". In the solution for the base DNN install (not the module solution), within the web.config file, there is a value in <connectionStrings> with name="ProductDatabase" which contains the actual connection string. This all links up fine on the DNN website.
Now I am writing a console application that does some monitoring of the site. I want to access the database to check values in the product table. I would like to reuse all of the repository code I have written. In an attempt to do so, I added a reference to the MyModules.dll file so I would only have one copy of the base code. This works to give me access to all the objects and the associated repositories but when I attempt to query data it fails. When debugging I can see that it fails on the line:
using (IDataContext ctx = DataContext.Instance(MyModuleSettingsBase.DATABASE_CONNECTION_STRING_KEY))
When viewed in a debugger, the string value MyModuleSettingsBase.DATABASE_CONNECTION_STRING_KEY is correctly set to "ProductDatabase" but the code is unable to link this with the actual connection string. I don't know where it would be checking for the connections string when running from my console application. I attempted to put a <connectionStrings> section into my App.config file but this didn't do the trick.
Is it possible to have MyModuleSettingsBase.DATABASE_CONNECTION_STRING_KEY map to the connection string in an external application which references the DLL?
If so, where can I set the value of my connection string so it matches up to the key value stored in MyModuleSettingsBase.DATABASE_CONNECTION_STRING_KEY?
I was faced similar problem 3 months ago, at that time I want to use DNN core libraries in my console application but I was failed.
I placed my queries in DNN official forum website and I got a valid response from Wes Tatters (DNN MVP).
Here is the post link: Reference URL
As your requirement of monitoring, I suggest you to create DNN Schedule Application. You can schedule it within DNN (Host->AdvancedSettings->Schedule), even good point is that you can use your repositories (DNN Libraries) in that schedule application.
I hope it solved your problem. Let me know if you have any questions.

Is there any basic string obfuscation I can use whilst pair programming?

Whilst pair programming with database systems, sometimes we end up temporarily hardcoding credentials (typically of our own accounts), which leads to slight awkwardness with the partner trying to look away whenever the password is onscreen. Is there any simple way of using basic obfuscation (ie, rot13) to hardcode a password without other developers taking a quick look and seeing my password?
It doesn't need to be secure. It only needs to grease the social aspect. I don't want anything complex involving super secure encryption or reading passwords out of files etc. This has to be quick to implement (i.e. 10 seconds max) whilst coding on the fly. Ideally I want something like:
string password = string.rot13("zlcnffjbeq");
Does anything like this already exist?
To configure SQL Server for Windows integrated security
From the Windows Start menu, select Microsoft SQL Server, and then select Enterprise Manager.
Open the node for the server and expand the node for the database you want to give users permissions for.
Right-click the Users node and select New Database User.
In the Database User Properties dialog box, enter domain\username in the Login name box, and then click OK. Additionally, configure the SQL Server to allow all domain users to access the database.
From MSDN. Connection strings become Server=x;Initial Catalog=y;Integrated Security=true instead of Server=x;Initial Catalog=y;User=you;Pwd=yourpassword.
I would suggest to store your password in a config file. For source control, use a dummy one. Then after getting latest version of the config file on your PC, you can modify the config by adding your password.
You could use base64 and just keep the base64 version of your password somewhere handy for cut and paste, bearing in mind that your system admin will have a blue fit if they find out about this. Both the suggestions in comments (#Oli/#CodeCaster) are preferable to this, imo.
DPAPI is more work but arguably a balanced solution to your requirement, with some security.
The .NET Framework provides access to the data protection API (DPAPI),
which allows you to encrypt data using information from the current
user account or computer. When you use the DPAPI, you alleviate the
difficult problem of explicitly generating and storing a cryptographic
key.
Maybe you can store your password in a String variable like here
/* Variable that stores the password */ string pwd = "12345";
string password = string.rot13(pwd);
and tab it out of the visual range of the editor. This would be a proper solution to your problem.
Then you can use the string variable somewhere else in your code and no one can see your password unless he scrolls to the right

How to read a web.config from .Net Window Application

I'm developing a .NET Framework 4.0 based Windows application.
I have a requirement of distributing this window application, along with source code to client.
When I test I'm using my own database credentials.
So I want a method to somehow hide the app.config details.
For this, I tried with encrypting values in app.config but faced an issue with token keys.
While researching about it, I found that I can use:
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration.
But that again required username and password for accessing remote server and don't want to show them to the client.
So for this I planned to read web.config hosted on IIS 7.5 Server.
Could you please help me in that context?
Or if you have better ideas to achieve the objective, do share.
The code is designed to be very close in syntax to the usual method used for accessing web.config from a web app. Pass the constructor the location of the web.config file you wish to parse and then use the AppSettings method to obtain the desired value;
string filename = #"c:\temp\Web.Config";
UK.Org.Webman.ConfigurationSettings ConfigurationSettings =
new UK.Org.Webman.ConfigurationSettings(filename);
string PrimaryDatabase = ConfigurationSettings.AppSettings["PrimaryDatabase"];

Modifying configuration at runtime in ASP.NET

I am having the following problem. I have an ASP.NET (VB.NET) application that is trying to connect to Amazon Web services using the AWS .NET SDK, and in order to do that the user is entering their Access and secret key. I am then adding the key to configuration like so:
Dim config As Configuration = WebConfigurationManager.OpenWebConfiguration("~")
Dim settings As KeyValueConfigurationCollection = config.AppSettings.Settings
settings("AWSAccessKey").Value = AmazonAccessKeyText.Text
settings("AWSSecretKey").Value = AmazonSecretKeyText.Text
config.Save(ConfigurationSaveMode.Modified)
ConfigurationManager.RefreshSection("appSettings")
While this successfully modifies the web.config file, it still throws an exception at runtime saying that it can't find the Access key. Can anyone tell me what I am doing wrong?
If I understand correctly you have as ASP.NET application that connects to the AWS on the clients behalf, if so storing the clients credentials locally might be the best idea from a security point of view.
You can either
Only store the credentials in memory in the session only when needed in something like a SecureString
Store them encrypted on the disk using any crypt apis.
The amazon sdk doesn't need the credentials stored in the app/web.config. If you look at something like AWSClientFactory.CreateAmazonS3Client , you will notice that you can pass them as parameters to this function
Probably, it is better to keep your received in key in Application object? for example static.
It is much clearer and simpler and will not cause a recycle of application when web.config is modified

How to configure database connection securely

Similar but not the same:
How to securely store database connection details
Securely connecting to database within a application
Hi all, I have a C# WinForms application connecting to a database server. The database connection string, including a generic user/pass, is placed in a NHibernate configuration file, which lies in the same directory as the exe file.
Now I have this issue: The user that runs the application should not get to know the username/password of the general database user because I don't want him to rummage around in the database directly.
Alternatively I could hardcode the connection string, which is bad because the administrator must be able to change it if the database is moved or if he wants to switch between dev/test/prod environments.
So long I've found three possibilities:
The first referenced question was generally answered by making the file only readable for the user that runs the application.
But that's not not enough in my case (the user running the application is a person. The database user/pass are general and shouldn't even be accessible by the person.)
The first answer additionally proposed to encrypt the connection data before writing it to the file.
With this approach, the administrator is not able anymore to configure the connection string because he cannot encrypt it by hand.
The second referenced question provides an approach for this very scenario but it seems very complicated.
My questions to you:
This is a very general issue, so isn't there any general "how-to-do-it" way, somehow a "design pattern"?
Is there some support in .NET's config infrastructure?
(optional, maybe out of scope) Can I combine that easily with the NHibernate configuration mechanism?
Update:
In response to the first answers: There are several reasons why I would want to connect to the database directly and not use a web service:
(N)Hibernate can only be used with a database, not webservices (am I right?)
We plan to provide offline capability, i.e. if the database or network should be down, the user can continue his work. To manage this, I'm thinking of having a local, in-proc database, e.g. SQL Server Compact, and using MS Sync framework to synchronize it with the server database as soon as it is up again.
Do you have any further ideas taking this into account?
First of all, letting untrusted users connect to a database is generally not a good idea. So many things can go wrong. Put a web service inbetween.
If you absolutely have to do it, make it so that it doesn't matter even if they get the username and password. Limit their privileges in the database so that they can only execute a few stored procedures that have built-in security checks.
Whatever you do, you can't give the username/password of a privileged user to an untrusted person. It's just asking for trouble. No matter how well you try to hide your credentials within an encrypted string inside a binary file or whatnot, there's always a way to find them out. Of course whether anyone'll actually do it depends on how interesting your data is, but silently hoping that mean people with debuggers will just leave you alone is not a very good security measure.
Actually the WebService approach (mentioned in some other answer) means that you move NHibernate and its logic to the web-service. The WebService then, exposes the db functionality available to the application using the WebService's methods.
There is practically only one user for the database, the one the WebService uses and if you want the application user to have different db privileges you abstract it from the WebService layer
In the end, the WinForms application is only aware of the location of the WebService where it requests data through the WebService's methods and you can apply any required security measure between these two endpoints.
For off-line capability it all boils down to making a secure way to persist your data to local storage and providing a synchronization method via the WebService
I have actually done this using a webservice that communicated with the DB and a WinForm application (.NET Compact Framework) that only talked to the webservice and in case of no cellular network coverage it would serialize the changes to the memory card (the data was not important so for my case obscure/obscene security measures where not taken)
UPDATE with a small example as requested (i do find it strange though to ask for an example on this)
you have set up your domain classes and nhibernate configuration and (for example) your repository stuff in a project of type ASP.NET WebService Application. For the sake of simplicity i'm only going to have a single web-service class Foo (in Foo.asmx.cs) and well as a single Bar domain class
so you get this (actual implementation varies):
namespace FWS
{
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class FooService : WebService
{
private readonly ILog errorLogger = LogManager.GetLogger("ErrorRollingLogFileAppender");
private readonly IDaoFactory daoFactory = new DaoFactory();
private readonly ISession nhSession = HibernateSessionManager.Instance.GetSession();
}
[WebMethod]
public Bar[] GetFavoriteBars(string someParam, int? onceMore){
return daoFactory.GetBarDao().GetFavoriteBars(someParam, onceMore); //returns a Bar[]
}
}
and we abstract the daobehaviour, or just use the nhsession directly, exposed as a webmethod.
Now from the WinForm application all you need to do is Add a WebReference which makes all necessary changes to configuration but also generates all necessary classes (in this example, it will create a Bar class as the web-service exposes it).
namespace WinFormK
{
public class KForm(): System.Windows.Forms.Form
{
public void Do()
{
var service = new FWS.FooService();
string filePath = "C:\\temp\FooData.xml";
Bar[] fetched = service.GetFavoriteBars("yes!", null);
//lets write this to local storage
var frosties = new XmlSerializer(typeof(Bar));
TextReader reader = new StreamReader(filePath);
try
{
var persisted = (T)frosties.Deserialize(reader);
}
catch(InvalidOperationException)
{
//spock, do something
}
finally
{
reader.Close();
reader.Dispose();
}
}
}
}
there are certain things you have to take note to:
You essentially lose lazy stuff, or at least you lose it in your winform application. The XML serializer cannot serialize proxies and as such you either turn of lazy fetching on those collections/properties or you use the [XmlIgnore] attribute which in turn do what it implies on serialization.
You cannot return interfaces on the WebMethod signatures. They have to be concrete classes. So, returning IList<Bar> will have to be transformed to List<Bar> or something of the like
The webservice is executed by IIS and is visible from a web browser. By default, only local browser requests will be served (but that can be changed) so you can test your data access layer separately of what your winform does.
The receiving end (winform app) has no knowledge of NHibernate whatsoever.
In the example above i've kept the same name for the dao-methods for the web-methods; As long as you didn't keep nhibernate--specific methods in your dao's (lets say like a NHibernate.Criterions.Order parameter) you will probably find no problem. In fact you can have as many .asmx classes in your webservice as you want, probably even 'map' them to the corresponding dao's (like public class FooService : WebService, public class BarService : WebService, public class CheService : WebService where each corresponds to a DAO).
You will probably have to write some kind of polling method between your endpoints to keep your presented data fresh.
WebService data is verbose; extremely so. It is advisable to zip them or something before sending them over the wire (and maybe encrypt them as well)
the win application only knows a configuration entry: http://server/FWS/FooService.asmx
Webservices have Session disabled by default. remember that before starting using the session for user data.
You will probably have to write some kind of authentication for the webservice
In the example above i am returning a Bar[] with Bar being mapped with nhibernate. More often than not this may not be the case and you may be required to write an auxiliary class WSBar where it adapts the original Bar class to what the webservice and the winform application can consume. This class is actually just a data carrier. Again this depends on how much integration exists with your domain classes and nhibernate as well as how muxh complicated your classes are: Certain data structures cannot be serialized by default.
This model may not suit what you have already done with your application
I think it's hard to do : it's like you don't want a user of stackoverflow to know his password.
A user can always trace his network traffic and see the user/password (you can had an encoding, but it still won't be 100% sure I think).
I think that you should add a webservice between your user and your database with a unique id for each user.
This is why database desktop apps suck. There is no good way to slice it. Best bet would be to use stored procedures or web services. Basically, another layer that can be locked down and control access to the database.

Categories

Resources