Safely connect to mySQL database in c# - 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.

Related

Do I need to improve the safety of my Cloud SQL connection?

I am working on a C# winform project and during several operations I save and retrieve data to and from my google cloud SQL database.
In order to implement this, I set up the SQL instance, allowed the public 0.0.0.0/0 IP (so I can use this app from different PCs) and created a database user with a strong password. In the connection string in my c# project I connect to the IP with the created database user + Password.
Now my question is, how save is this? For my project and the enduser it is essential, that the data is as save as it can be. The only safety I have now is basically my google account Password and the database user Password.
Would there currently be a way to bypass that and retrieve data without me noticing?
best regards
Steffen
This was fine "back in the days".
Now, it is good practice to have a front-end proxy that uses APIs to serve data to the application.
If you can build and application that will run in the Cloud, next to your database, it would be best. Have that application authenticate users of the Winform Application and send them the information they need through API calls.
Without this, and having your application access directly the database you will have 2 issues:
lower security
high latency (and this will probably be more problematic). Database requests don't really like latency.
On top of it, you could use that server-side app to cache data and do some consistency checks.
However, for DEV purposes, direct connection is acceptable. Just don't put production data there.

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.

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.

Protecting app database access on user PC

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.

Categories

Resources