WinForms dynamically specifying and managing SQL connection string info - c#

I have a requirement to allow the user specify, at time of first use, the connection string with which to connect to a database, and change it later on, in Windows client application. My current idea is to store the information in a text file which is checked each time user opens the application for use, and prompts user for update if information has been deleted or is invalid. I am not however confident that this is a secure approach to handling this issue and would appreciate other suggestions to help me better manage this.

I'd store them in the app.config, as is the usual practice. You can modify the settings in code easily. Here's how
They should also probably be encrypted, which can also be done in the applicaiton's launch. You can encrypt/decrypt from code just as easily as you can modify the settings. Here's how.

You can
Use Windows Authentication for SQL so that you don't need to manage passwords.
Use CryptProtectData to encode / decode the password and save in on disk
From CryptProtectData documentation
The CryptProtectData function performs encryption on the data in a
DATA_BLOB structure. Typically, only a user with the same logon
credential as the user who encrypted the data can decrypt the data. In
addition, the encryption and decryption usually must be done on the
same computer. For information about exceptions, see Remarks.
So even though SQL and windows might have a different login if there is a 1-1 mapping your saved password encrypted text is relatively safe

I would store the connection string in either the App.Config or the registry. I do not think you can modify the App.Config at runtime, so if your application is using a database, that should be your first choice. If not, go with a flat file or the registry. You will definately want to encrypt it. See this question on how to encrypt and decrypt string and Base64 Encode it.

To start with, I would not write your own dialog to get the initial connection string; instead you could use the VS2010 database connection dialog that Microsoft have released (download from here). This will do exactly what you want without you having to do the hard work (and for pretty much any remote connection you want).
No, your persistance of the connection string information, should not cause any major security issues; as it is the connection string itself that should provide the security to the connection; you will have to ensure that the saved connection string does not contain the password - and bring up the dialog for each successive connection. If you use Windows Authentication, without passwords then of course there could be a security issue, but I would say it is down to the users to use the correct security.
If the above is not sufficent, I would store the connection string in Properties.Settings.Default and encrypt the string using one of the .NET libraries, or even a hash. There are many approaches to this, but I would go with the referenced dialog to get the initial connection string, then persist this in the app's .config with properties. Simple.
I hope this helps.

Related

Trying to understand the concept and best practices (and code?) of keeping credentials secure in an application

There is a ton of material available for encryption in general, and I've been reading through it. But this question will not be about the actual encryption...it's how to secure the thing I use to do the encrypting.
I feel like the problem I am trying to solve is a simple one: my application needs to connect to a MySQL database on a website to fetch some information. That requires credentials to log into the database.
The application needs to have those credentials at the ready, so that means storing them securely, such as in app.config. I can encrypt those items and then store them easily enough. I even took a stab at doing that, using aspnet_regiis -pef to encrypt the section of the app.config where those were stored, but that seems to be a non-portable solution (e.g. worked on my dev PC, failed to decrypt on another computer). So if I am wrong about that, then let that be my question: how might that have failed me?
Otherwise, my question is this: how am I supposed to secure the key with which I encrypted the credentials? Is there an established best practice for making the key available to the application, while still protecting it in some way?
"You cant hide secrets"
Realistically you cannot secure anything you distribute. Your connection string is distributed in your app.config to potentially millions of customers, or at least can be copied millions of times. Your encryption algorithm may be very complex, but you must at least contain the decryption code in your .net application; which can be readily decompiled. All the hacker has to do is work out how/where your store your key. If they user doesn't supply it as part of the login process then you can't really secure the connection.
In the web application world we keep the connection string in web.config encrypted using the application pool service account credentials; only the app pool service account can read it. The user of the web site never gets access to the web.config, and if they did, the firewall between the DMZ and the database server would prevent them from attempting a connection. You lack any of these safeguards in a client-server application.
Ideally you would provide your end user with a SQL Server login based on their windows account credentials, or a username/password; you secure their SQL account rather than the ability to attempt to connect. This is reasonably secure in an intranet scenario, as SQL Server can delegate authentication lockout etc to the Windows Server allowing you to do three-strikes based login policies; but you cannot secure the attempt to connect - only the success of the connection attempt.
To be honest, you're not going to have a failsafe way of doing what you want - anyone you're distributing the app to can decompile and examine what you've sent them. Literally any security scheme you can think up, the attacker can simply read the code for.
Instead, I think you should put some minor security on that end (block the casual/curious people with some straight-forward hard-coded-key encryption, knowing that you're not going to stop a determined attacker) - and instead focus on locking down the SQL end as much as possible. Those account credentials you're giving out through your app? Give it the bare minimum of Stored Procedures it needs to do its job, and then lock it out of all the other tables/views/etc. Connect in to the SQL database as your app's account user, and try to see if you can perform anything malicious - screwing with table data, dropping objects, etc - and then take steps to mitigate/remove those vulnerabilities.
If that's not sufficient, your next best bet is to program a middle layer. Make a web service, and have it be the one to connect in to SQL. The WPF App doesn't hook into SQL at all, and has to go through the web service to get/change/etc the data. But it's important to realize that an attacker can still screw around with your data - they can directly call your web service instead of going through the WPF app. The only thing you gain is that the attacker doesn't have a SQL login.

Encrypting Connection string for a forms Application

I have created a forms application for my project. I want to host on my website for users to download and test it. Because I am using a configuration manager I have to include the config file along with the .exe as there is a back end remote database for the application. And of course I only now realize my connection string is there for all to see. I tried renaming the app.config to web.config, but the aspnet_regiis -pef command just returns a help menu when ran as admin on my vista machine! Even if this command works and I rename web.config back to app.config, will the machine which runs the app when downloaded automatically decrypt the connection string? So in conclusion what is the best way for a novice like to approach this dilemma? Why does aspnet_regiis -pef not run? I have also looked at other posts about this topic but unfortunately they have not worked for me so far.
Either create user/specific connection string, or wrap all your data access in some web services, where you can control the autorization.
Creating user specific connection string is the simplest, but may have impact on the DB charge. You can still keep one connection string, but using windows identity to connect. In both case, you will have to spent some effort to ensure users won't able to do more than what they are allowed to do.
Wrapping your data access in web services is far more manageable but will require an extra work to make it works. Maybe you can take a look at RIA Services. The advantages are multiples: you can control the permissions within the web services, and you are reducing the exposure of unwanted queries.
Please also note that even if you encrypt the connection string in the configuration file, any malicious user will be able to decrypt it. A simple decompiler will highlight your decryption key.
You could just store an encrypt the connection string in the app.config but you will have to include the encryption key somewhere in the application. Therefore this is not safe because everyone can just decompile the application or attach a debugger and extract the connection string. Or monitor the network traffic. Actually there is now way you can prevent this from happening - whatever your application can do can be done manually by everyone (with access to the application).
The flaw in the design is that the application needs direct access to the database in the first place. It is close to impossible to ensure that the database can not be corrupted in this scenario (unless the database is only used for reading data). Essentially you would have to replicate a large portion of your business logic at the database server to ensure that no sequence of requests will corrupt the state.
A better solution would be accessing the database only indirectly through a web service. This allows you to perform better and easier to implement server-side validation and even authentication and authorization per user.

Safely connect to mySQL database in c#

I'm pretty new to C#, I've been doing a bunch of stuff but I'm missing a lot of basics.
Anyways, I'm making a program where the user has to log in and and then it checks if the entered password is the same as the one on the database.
Anyways, I know that there's ways to get get into the code of a compiled program and I wanted to know if there's anything I should do to make sure that nobody can see the login info of the MySQL data somehow.
Thanks
There are many different ways you can Protect Connection Information depending on your specifications and requirements.
One simple rule, never include database connection strings in compiled code!!!
Some Links
Protect Connection Information
SO - Encrypt connection string in NON ASP.Net applications
MSDN Securing Connection Strings
Further to a questions raised in the comments.
Secondary to ANY connection string configuration you should also limit the applications access to the Database by using Role Base Access Control to reduce the permissions granted to the application and the procedures or Sql commands it can execute to a bare minimum.
The only way to prevent people from seeing your MySQL connection string credentials would be to use a three tiered architecture where you have a webserver or service running on a server which holds the connection string and makes the requests to the database. Your client applications would communicate with the with the webserver/service.
I agree with Lloyd.
In addition to the security aspect, keeping the connection string out of compiled code means that if you need to change it for some reason, you don't have to recompile and redeploy your code. Often, you don't know that someone messed up the server name or database name or credentials until your site suddenly stops working. In the middle of the night.
I was thinkinging this would be an issue with my program, So I am makeing a PHP file to process POST data and return a response, Where the PHP file on my sever side holds the Database connection as well as only return's limited data to my C# program. And the C# program then read's the response and get's the appropriate data. This will make it so the program it's self does a HTTP POST and doesn't know the database user and password. As well as give's me control over what data can be sent to the C# Program.
There is no way to hide your connection credentials from someone that can get into your code using some ILSpy like intrusion.
«Intruder» can see anything needed to find them. For example he/she can see how you decrypt the (so called...) encrypted xml and use the same method.
The only way to hide user credentials is in database itself, where the user has no access.
Explain: If user has to enter its own credentials to login to database, the credentials will be checked by the database server, so no credentials are exposed in your app residing in user's machine. And user cannot see other's credentials.
So:
Create the users in the database as database users.
Allow them to access any tables they should access.
In your program:
Ask user for credentials.
Check if you can connect to database with those credentials.

Best practice for storing settings

I have only been programming for the better part of 1-2 years, C# the last 7 months or so, Up til now I have used the .config file to store needed settings that cannot be stored in the database, and it was okay to do so.
Now I have a client where there are many users that will access a database, and part of the spec is that the application must log into sql using the sa username, obviously if anyone gets hold these settings it would be a problem.
I want to know what the best practice for something like this would be, I can encrypt the password and server address, but I still feel uneasy about this.
What is the best practice in the industry for storing settings that cannot be in the database, especially the ones that are sensitive configurations
Many Thanks in advance
You can put settings into a local database. I prefer MS SQL Server Compact 3.5, which is free. This way you can store your settings into a local SDF database file, which can be encrypted and password protected. The data stored in the SDF file can be accessed using e.g. ADO.NET+SQL, but I prefer Linq-to-SQL.
EDIT:
Please take into account that although SDF files can be encrypted and password protected, if the file is stolen, it can definitely be cracked by a brute force method. The same is true for any other solution, which stores sensitive data on client machines.
You can try to store information in Isolated Storage
I can't recommend highly enough to revisit the requirement to have the sa account used by the application. That is a HUGE security hole. Given the information provided, I would recommend encrypting the connection (won't really matter where you store it). Make sure that if your database connection methods fail, the error result won't display the user name and password.
The best practice method (I think) would be to use SQL server integrated security: (you authorize a Windows/Active Directory user to access the server, the security aspect is now handled by Windows and your Domain configuration) - however this is not always practical, and you might not want to give the windows user that much access to the database outside the client software (eg, the application must insert/update/delete records in the database, something you wouldn't necessarily want the user to be able to do if they logged into the DB via SSMS)
Another method would be to use the 'Protect' and 'Unprotect' methods of the System.Security.Cryptography.ProtectedData class to encrypt and decrypt the password, and/or the connection string. (you will need to set a reference to System.Security.dll).
This gets around the "where do you hide the key" issue - the ProtectedData class uses your Windows machine's entropy pool to generate a key. You can add your own salt (by way of a byte-array as "additional entropy") to ensure that the data cannot be retrieved by another .NET program running under the same user-context also using the ProtectedData class. You can 'protect' the password/data so it can only be 'un-protected' by the same user on the same machine that protected it.
Hope this helps :)
Cheers,
Simon.

How secure is using an encrypted appSettings element in your app.config?

In a CodingHorror blog post a commenter made the observation that it is more difficult to obscure sensitive configuration information (e.g. SQL Server connection strings) in a program than it used to be, because the obscuring algorithm can be disassembled quite easily with Reflector.
Another commenter suggested that encrypted appSettings could be used as an alternative.
How secure is encrypted appSettings? Is it a bank vault, a locked door, or an open window, and why? Is it ever safe to store "sensitive information" in an executable?
Encryption algoriths are secure: the main issue with using encryption for security is the secure management of keys.
Hiding keys in the application executable was never secure, but it's probably true to say that they would be easier to find in a managed executable using a tool like Reflector than in a traditional unmanaged executable.
Encrypting a configuration file can be useful on a server. For example, if you encrypt web.config using DPAPI with the machine key, only users who can log in to the server or have write access to the server disk will be able to decrypt it:
Anyone with read access to the server disk over the network, or access to a backup copy of the application directory won't be able to decrypt it.
The real question is who are you trying to shield the user and password from? On a desktop app the user is likely to have access to the database with his/her own account, no pwd needed (trusted). On a web app, the config file sits on a (hopefully) protected place. So far I didn't find many reasons to encrypt the config file.

Categories

Resources