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.
Related
As I developped a WPF .NET Core Application that interacts with an online MySQL Database using EntityFramework, I noticed I had absolutely no way of protecting my Database from being read or modified using the easily accessible connection string if my app was deployed and someone code reversed it.
I searched a bit and found these few possible solutions:
Storing the connection string in an encrypted app.config using aspnet_regiis (but .NET Core seems to be more oriented on .json configuration files, and therefore cannot be encrypted using aspnet_regiis)
Obfuscating the source code using an c# obfuscator like ConfuserEx (if I understood correctly it's just making the connection string harder to read, but it remains possible to get it and mess with the DB right?)
Building and interacting with API instead that would do the changes to the DB (but even then how to make sure the API requests are truly coming from my WPF app and not from a malicious user?)
If you know any more precisions about these solutions or perhaps have another way of making it secure and safe to connect to an online Database, detailed steps/links are very welcome!
Building and interacting with API instead that would do the changes to the DB
This would be the recommended approach.
(but even then how to make sure the API requests are truly coming from my WPF app and not from a malicious user?)
You can't really.
When you embed some kind of access key or a public URL in a client application that you expose publicly, you basically accept the fact that it may be exposed. You should assume that a malicious user can extract the key/URL from the client app regardless of any obfuscation.
The service may reject requests from IP addresses that it considers to be misusing the API but it will still need to handle those requests.
Managing a public API is not trivial. You may want to consider hosting your app in a managed cloud.
After some researches and tests, I found that the proper way to prevent a malicious user from reading and messing up with the connected database (even if he gets access to the connection string) is by Limiting my app to only execute Stored Procedures that will give the minimum data required. And for stored procedures that will read or change a user's sensitive data, also by having in their required parameters the user's secret token, which would be a random string generated in SQL the same time the user registers.
The only issue remaining is if the hacker spams requests to try to bruteforce (even if it's almost impossible to bruteforce a very long and safe token), it might still makes the MySQL server overload or even crash. To prevent that from happening the only solution seems to use an API.
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 an application which is executed when a user logs out. This is achieved via GPO. The application needs access to a database.
My App.config contains the connection string. I tried to encrypt it using aspnet_regiis but I just read that this works only per machine. While it worked on mine flawless it of course crashed on other machines.
I can not find another way on how to protect the connection string in this scenario. I have no setup so I can not execute aspnet_regiis on the local machine. How do you usually handle this problem?
Could you deploy the key for encrypting the App.config via GPO? Where do I find that key?
It's very hard if not impossible to achieve this.
See: http://www.grouppolicy.biz/2013/11/why-passwords-in-group-policy-preference-are-very-bad/
You will need to create a service that recieves the requests and communicates with the database, this service will be run on your server and thus you can keep your connectionstring safe.
One way would be to create a webpage that recieves postdata from the clients.
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 will develop utility program for a company with more than 1000 client and the program must be win application with .Net because my program will act with another program.
What is your suggest for place of app.config?
one scenario:
We put the app.config on the server that configured once and write a windows service for it that publishes the connectionString through TCP/IP Socket.
In Socket programming we don't need for anything because we just use a free Port for send ConnectioString from server to clients. My Scenario based on this approach. (Default port embedded in app).
Reading your question (I am deciphering a bit) I can see that clients may be separated from eachother, and even if it's just in the LAN, the following solution would work:
Develop a WebService whose only job is to give the ConnectionString when called.
This enables you to have an "easy" and robust way of doing this, and could implement it only on the local intranet for security.
Regardless of this, make sure you encrypt the Data and perhaps even RSA sign it good measure. This will give you a secure, robust and less time consuming solution to your problem.
The app.config belongs with the client app - I wouldn't even try and hack together something else. Ship it as part of your app and install it. Especially the connection strings cannot really be outsourced anywhere else.
We use a hybrid scenario where we have just about only the connection string in the app.config on every client, and anything else that needs to be configured is in a database table which everyone reads.
But the connection string can't really be centralized in the database..... how would you connect to the database to read the connection string then? :-) A classic "chicken-and-egg" problem.
So: just use app.config and put your connection string there (if needed, encrypt the <connectionStrings> section).
The only viable alternative would be to embed the connection string into the app itself - as a constant string in a "Constants.cs" file or something.
Marc
The ideal architecture would be to provide a service that acts as your data layer - your WinForms application would make calls on this service to perform all its interaction with the database. Not only does this provide an abstraction layer for your data access, but it centralises your data connectivity into a single area (your data service), so you can store your connection string securely on the server that hosts this data service.
If you want central configuration, I would put the configuration into Active Directory, under the CN=Services, CN=Configuration node.
I use an adaptive connection string that configures itself based on the network and/or machine that the application is running on. I wrote a blog post about this approach some time ago. The key is to override the SettingsLoaded event to reconfigure the baked in connection strings. This will work on any .NET Windows client application or DLL. I even used this technique within DLLs to control the connection string for web applications. It really makes deployment a snap!
Of course this is not the best approach for all scenarios. One drawback is that users and administrators can't change the connection string with the configuration file.
On your server you will have IIS, you can define a url http://myapp.myserver.com and you can put an xml page there, wherever your clients can be, when they start, they can query http://myapp.myserver.com/myapp-config.xml , and on this file you can store version, connection string etc.
And you will have to manually instantiate all variables that you intend to load from this xml instead of app.config, but its not difficult to store your connection string in your program in static variable initiated after reading myapp-config.xml
Shipping app.config at client's place is not good because in case if you need to change any values, change server or distribute load, it will be difficult to redistribute everything.
Instead you can also keep a check on version of xml, if version changes, you can notify to download new version from same server and upgrade their program.