I was here making an sql connection in a class library and I was wondering how can I encrypt/decrypt an SqlConnectionString (or other things, if need be) in a config file (whether it's config from desktop, mobile or web)?
I already have functions to encrypt/decrypt strings. But I want to have it encrypted even when outside the program, so even if someone gets to the config file he won't know what the string is.
Must I do it "manually" (encrypt it in a program and copy/paste it to the config file) or is there another way to do it?
EDIT: I just read that it'd be best if the connection string was on the internet, in an API, only. Is it true? If it's true it'd be perfect because, I'm making an app/desktop/website that all connect to the same database, which is on a server. So, all of them have to connect to the internet anyway.
If you encrypt the connection string (or any other sensitive information) using an algorithm that the app, sitting on the user's PC, can decrypt, then anyone who gets to the config file AND the app executable can decipher how it is encrypted and get to the original connection string.
For the web app, this shouldn't be an issue (assuming you secure your server so that unauthorized people cannot access it), for the desktop app, it will be.
You could put some kind of gateway in front of the cloud database such that the desktop user would have to authenticate to obtain the connection string. That, or abstract the database access by building a web API, which you can secure by OAuth or something similar, and have the desktop user authenticate before using the app. Given that the database is on the internet, that's what I would do.
Related
I have googled for a long time for ways to secure the SQL connection string stored in a Winforms app. Encrypting the app.config (connection string included) of a Winforms app could be useful; however, it is not as safe as a webform app since the app is installed on user's PC. Any malicious users who want find out the connection string can reverse-engineer the app using the locally saved certificate to decrypt out the connection string.
Recently, I think of a possible way for protecting my connection string.
It is like this:
I'll create a read-only user and a read-write user using MS SQL Server Management Studio. The readonly user's connection string is located in the resource properties unencrypted. It is used to connect to SQL Server and check for the login passwords into my app.
Once the password has been checked, I will call a user defined SQL function (secret key included) which input is a ciphertext and return me the connection string to login the SQL Server with the read-write user account.
Will someone view my secret key hid in the user-defined function? Will this work to protect my connection string for logging in the read-write user account?
Thanks for all your answers. After watching TimCorey's YouTube video (https://www.youtube.com/watch?v=rFncI9yfY-E), I think I am sort of knowing that my idea is too simple. Using stored procedures in a SQL server should be a safer choice than the user defined function.
Here I would like to make a summary, as suggested by Mouse Power and Charlieface, for a win-forms app to connect to a SQL server with more safety, we can get data from a SQL server either through:
(1) executing stored procedures (with limited permission) or through
(2) web APIs wherein SQL connections are made within the server.
Conventional encryption(using ASPNET_REGIIS) of connection string in web.config of a web-forms app can not be applied directly to the app.config of a winforms app. This is because the app.config and its encrypted key are both located on the client side, so it is difficult to prevent any malicious users using reverse-engineering to crack out the connection string. Nevertheless, encrypting the connection string using a key hidden somewhere (in codes, file, or resource) is still suggested, as a preliminary protection.
Using a separate account for each connection may also be an option, but this may make the programming of SQL connections relatively more complicated.
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.
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.
Im working in c#, I'm using mysql .net connector to interact with a remote mysql db. Is it safe to include the connection string inside the code and work with the db directly through the command object or should I be posting to a php middle layer to hide the connection string?
Thanks in advance.
In my opinion:
You shouldn't put Your connection
string directly in Your C# code if
Your application could be
decompiled = I mean WinForms application.
If You are working on a Windows
application, then try to implement a
log-in window. Where user will pass
his/her user name and password. This
solution needs a mysql user or users
for every person that would have
access to the system.
If Your are working on a web
application, then put You connection
string inside web.config file.
If You are working on application
with unrestricted access, then I
think You should implement some
layer... but remember, never pass
SQL queries as plain text via
network, as someone could sniff it.
I would recommend some kind of
webservice.
Then the connection string is just stored in the PHP middleware layer, so what's the difference? It has to be stored somewhere.
I would keep it simple and store it in the app.config or web.config of the C# app your writing.
Couple notes about storing it:
- Production connection strings should not be stored in version control.
- A production configuration file should exist on the production servers with the connection string.
- For added security, you can encrypt your connection string (http://msdn.microsoft.com/en-us/library/89211k9b(v=vs.80).aspx)
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.