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.
Related
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.
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.
I am aware of the many cryptography providers that are available in the .NET framework along with the basics of how to use them. This is simple enough.
But my concern is this.
Lets say I want to use these libraries to encrypt XML serialized objects to prevent tampering and the ability of anyone to come along and view the contents of these files.
The problem that I am always left with is that the key to decrypt this data would need to be stored as a constant somewhere in my application. Essentially rendering the entire exercise pointless.
So, how does one store a key for an encryption algorithm securely inside of a disassemblable application?
EDIT: So If I am understanding both answers below correctly. What this means is that essentially any implementation (to be secure) requires it to be readonly or writeonly but never both? Is this correct?
You don't. If the application can access the key, it is just security by obscurity. It is better to authenticate the user in some way (a password is the simplest example), to make sure he is allowed to access the data. You can't let the application do that for you, because it simply isn't trustworthy. Anyone can obtain the information stored in the application.
If the key information is stored somewhere else, a malicious user or application can probably access it, too. If not, then store your data directly to that magical safe place.
Now if you still want to go down that path and store sensitive data without authentication, your best bet - or at least an easy way that is halfway secure - is probably the DPAPI (see the ProtectedData class in System.Security.Cryptography). It will encrypt the data either with the machine key or to the user account key (you can select that). So that a program running on another machine or with another user account can't access it. Windows will try to protect those keys but in effect any application running on the proper machine or with the proper user account may be able to access your data.
We'll assume you're using some kind of public key cryptography scheme, because otherwise it would be pointless.
The answer is you do not store the private key anywhere in the application. You store it somewhere where only your application can get to it. For example, a file in the local system that only admins and your app have rights to read it. On a protected network share. Etc.
Think about how we manage keys as people. We keep our private ones in a file maybe, or an encrypted USB drive or something like that. The same principles apply to applications.
There a various possible solutions. One of them is using RSA. Alternatively you could use the same approach used in TLS.
One good way would be to generate a pair of public and private key. Encrypt with the private and destroy the key. With the public key, you could decrypt but not tamper the data.
Collecting given answers: All encryption security relies on protection of a "root" password. This cannot be guaranteed in a compromitable system.
A feasible hardware architecture is given by e.g. Chip Card Readers. As external systems they cannot be compromised by internal malicious manipulations.
Accordingly you could set up a separate "Secure Server" with strongly restricted access, e.g. key board and local network. This server would provide sensitive data like passwords by secured communication with authenticated clients in a limited time window.
Suggested measures for clients in this time window are clamping spyware, messengers, remote control server and basically internet access, process monitoring, ...
... or you do all sensitive data processing on secure platforms, excluding talkative ones like Windows.
Greetings!
I'm needing to deploy a compact database with an application I am working on. The database acts as a cache for data the app has already seen, and that data will never change, so the cached values will never become outdated. I've chosen SQLite, and I'm writing in C#.
I'd like to protect the database files so they cannot be easily accessed or edited by the user - keeping access to my application only. Now, one option is to use password protection which is fine except that with tools like Reflector one could easily view a near original version of the source and check the passwords/how they are generated per file and replicate this.
Are there any suggestions on how to achieve this result or something close? Have people done something like this in the past?
Thanks!
Security by obscurity.
If your apps can decrypt it, then your user can do it too.
If you want to keep it secure, you'll have to keep it for yourself. Your best bet is to store the database on a server and make it available via a web service. Perform access control checks on your own server so that the application can only access the parts of the database it has to see.
I don't have a clearcut answer for you (obfuscate your code during release deployment, make the password obscenely long) as the golden rule stands: If they have physical access to the executable (substitute machine/car/door) they can get in if they want(and have skills).
All you can do is make things difficult for them.
This area is not my forte, but one thing I could suggest is to just think about what data you are actually sending and determine if there is any way that you can limit any of the more sensitive data from being transmitted to the client in the first place.
If your concern is over sending things like ID numbers account numbers to the client, then perhaps you could translate those values into a client-only version that is meaningless outside of your application. Your server could have a table that contains the translation between the real values and the client-only values.
Let's say you have this table stored in your server's database (not the client database!)
RealAccountNumber ClientOnlyAccountNumber
981723 ABC123
129847 BCD234
923857 CDE345
...
So the client only sees the account numbers in the ClientOnlyAccountNumber column, and when a client sends a request to the server for an action to be performed on account "ABC123", the server knows to translate that into account number 981723.
I'm writing a database driven windows application and both the executable and database need to be installed on the customers machine.
Is there a database that I can use as a backend to my application that the user can't get into even though the user is using the same machine that the database is stored on.
As far as I can tell, Postgres won't work for this, and the versions of access that I have tried are easy to get the crack the passwords for.
My application has to be able be installed on a laptop and be useable even when there is no internet access, so the usual client-server database models just don't work.
I have considered using a VMWare virtual appliance with Postgres installed on some version of linux, but this would have a pretty heavy system load.
I would prefer to not have to use encripted text files or something like that.
Since users (or hackers) own the machine, there is nothing you can do to make it secure. Anything you try will fall into a category called Security Through Obsecurity.
Your best bet is to encrypt your database and try to hide the key in some obscure place in your binary. Since this is an installed application, don't use Database servers. Just use a DB library like Postgres.
How critical is the data? Encrypting data on your system using standard RSA or AES with a key stored and encrypted in your application will keep your mum and dad user away.
But if you can't keep the secret out of the client application, then you're going to have trouble here.
There's a couple of options available to you, depending on your budget.
First, I have used SQL Server Compact Edition 3.5 with a .NET program for doing a local database that was encrypted. The good news was that the file was encrypted and could only be accessed if you had the password. The bad news of course is that your password will probably be in your connect string, unless you do something like a seeded PRNG to generate up the password for you. Also, SSCE requires that it be installed independent of your application -- if for any reason the user uninstalls it through Control Panel, your application won't run.
Second, I have also used a commercial product called VistaDB, and it also supports local database files that are encrypted. There are comparison features of VistaDB versus other database engines available on their website -- but another thing they offer is that they don't have a runtime that has to be preinstalled -- you just add another assembly to your distribution (they claim you can statically link it, but I haven't tried that personally). The local file on disk is also encrypted with VistaDB, and without the password you can't access the underlying database.
Good luck!