Hi i am trying to find the best way (or a good one) to store a ConnectionString (my App will connect to a Database in a Server, it will work with it continuosly) and how to handle with the Admin account. For default all the applications with Login must have an Admin account, right?
I think in that way...
So, you install an App on the Machine, how you will configure the ConnectionString? I think that is wrong asking the user to configure such thing if doesn't understand what it is or it really have to be?
And imagine one day that the ConnectionString have to be changed for any reason, if the Admin acoount credentials to Log in the App are in a Table in the Server, how then it will possible to Log in the App to change the ConnectionString?
This is my problem now... I don't know how this type of things is handled, if are there any rules to handle this, any common way because i am starting to work more seriously with this type of things.
Note: I think that is not important but my App is being developed in WPF.
A really easy way to do DB access security with MS SQL Server is use "Integrated Security = SSPI". With that, MS SQL server authenticates against the Windows user entity under which the database accessing process runs. It all happens seemlessly using MS SQL Windows Authentication without the need to store any usernames or passwords within the application.
Another way to do it is to distribute a config file with the database connection string in it, with at least the password encrypted.
We have many MySQL databases on several servers too, so MS SQL SSPI doesn't cover us.
For server side software I store database connection strings and credentials in a separate XML config file that all the server side software uses. The credentials are arranged topically with all database information encrypted. I use a common file for all the server processes and developed a little encryption / DB config file management GUI so management is simplified and access is universal to all the software using the same code.
For end user software it is too difficult to maintain with local config files because of user maintenance. For "fat client" software I maintain a separate database with encrypted credentials on a server in our DMZ that is universally accessible to anyone havinng that software (there is not that much distributed fat client software.) Our web app software has a consolidated user database that controls access for all users/roles for all apps, and everything is portaled through the one system so it is far easier to mantain the user database.
Frankly, the polyglot system is increasingly ugly to maintain. I would use our main domain LDAP server (Windows ADS), but our company policies keep ALL domain member servers completely firewalled off from access outside our most trusted VPN and thus inaccessible in too many circumstances.
I hope someday to have time to setup a *nix based LDAP server in our DMZ and centralize all credential information there.
With connection strings to a MS SQL server you basically have two options:
Either store a username/password pair in it. Your application has to be able to read it, so theoretically, any user of the application could do the same (he has access to your application, so he can decompile it). Practically, you can encrypt the connection string, with a key stored in your source code or application resources and be quite confident that your users won't be able to read the password.
If you have some users that should be able to use the application and you believe them, and other users that may have access to your application but that shouldn't be able to use it, you can use Windows Authentication, and set Integrated Security=True in your connection string. This assumes you configure your DB, so that the approved users have access to it.
Either way, your connection string should be bundled with the rest of the application. If you ever need to change it, you just release a new version. (This works even for the most primitive version of installation: “copy this bunch of files to a directory on your computer”).
Now, the connection string can be stored pretty much anywhere, the most convenient place probably being application settings file.
If you want to be certain that your users will be able to use only the functionality provided by your application and not access the database directly, you'd have to write something like a web service and connect to the database only indirectly through that.
If you need to store the connection string in a configuration file or somewhere else of your choosing, you might want to encrypt and base 64 encode the encrypted results back into a string. Check here for an Encrypt() and Decrypt() implementation.
It is possible to manipulate files (such as the .config file) during the install of the application. So it is acceptable to ask the user/admin (during setup) for the name of the server (and even for a user name and password provided you encrypt these but I'd rather use integrated security).
For updates of the connection string just make a new installer.
Alternative: store the connection string in active directory or in an other well-known store so all you need to do is change the value in one place.
Related
I have developed an app, which more than 2k users are going to use it. This app is connected to a database which contains some data.
I have some questions:
1. Is it ok to use mysql direct connection in app instead of API for just reading data?
2. Is there a way that someone find my server's information (address, pass, etc) from my application?
App is wpf.
Generally speaking (and as with all generalities there are all kinds of exceptions here, in both directions) it's okay to connect directly to the database if one of these two conditions is met:
The app and the database are on the same computer
or
The app and the database are on different computers, but within the same corporate network and traffic between the app and the database is adequately protected.
and if one of these conditions is also met:
The end user owns the app and doesn't share data with other users (they break it, that's their own problem and no one else's)
or
You issue separate accounts with only the necessary privileges to each user (the user owns the credential)
or
The machines where the application is deployed are controlled by the business, where you can securely deploy the application (and the account credentials it uses to connect to the database) in such a way that end users are not able to retrieve the account credentials directly. (The business owns everything).
It is not generally okay to connect directly to a database over the public Internet, or within a local network where traffic to the database is not adequately protected, and it is not generally okay to let end users have direct access to the database separate from the application (and if a user has ownership of their machine, they will be able to get that access).
I also need to expound on what I mean by "adequately protected". This involves a few things:
A good firewall between the clients and the database. In some smaller environments, the firewall on the OS hosting the database itself may be enough.
Measures to prevent MitM attacks on data packets to and from the DB. For traditional corporate networks, this usually means 802.1x is running even on the wired network, and wifi access is similarly protected (a pre-shared key wifi network like you use at home is not good enough, because anyone who can get the key can decrypt your traffic). Alternatively, you can implement encryption that runs from the client all the way into such a protected network. This is what many corporate VPNs are for (a public VPN service doesn't accomplish this for you). You may also be able to encrypt that actual database connection traffic. I know how to do this for Sql Server, for example, though I'm less clear on what direct support is in MySql in this area.
If you save the information inside your application, it can be found. You should consider using an API to handle the data reading. Applications can be reverse engineerd.
I wrote an application in c# & SQLite for storing data of all employees in a company which has around 500 employees. I want to put the database & the application in a file server/shared folder (MS server). Then all employees will have a shortcut of the application in their desktops. I want to make some input fields (text box) enabled/disabled based on the permission of the user runs the application. Whats the best practice for doing that?
I want the user can read/write in the database through my application only (the application is located in the same database folder). I don't want the user to reach the database without my application. How to do that?
I don't want the user to reach the database without my application
If your application will directly access the SQLite database via a Windows file share, this is impossible. Sure, you can make it inconvenient, but it's not really possible.
The only way to achieve this really is by introducing some middleware.
This would typically be a service (WCF perhaps) that listens for connections from your client application, authenticates them, and manages all access to the underlying database. The database would be stored in a location that is visible to the server only, and not visible through a Windows share to your users.
Also, SQLite isn't exactly a great choice for a multi-user system. You can kill two birds with one stone here - switch to a DBMS (MS SQL Server Express is free, also MySQL, PostgreSQL are common free choices) that accepts client connections over a network, and build your application to connect directly to the database server (using integrated Windows authentication may also be possible like this, so you can avoid an explicit logon). In a simple scenario this may be adequate and avoid you needing to build an explicit service layer.
In a more complex scenario, it can still make sense to have a middleware layer between the application and the database - this way, you can change the database design without changing the application design and deploying to all of your client machines - instead, just change the middleware layer in one place and your application won't know the difference.
If you don't want the users to reach your database you should create a client server architecture.
You can run your service on the same machine as the file server (running as a Windows Service) and use WCF for communication between your server and your client. You access your database from your server and let your server authenticate your users and validate that they have access to the application.
You can cheat and try to "hide" database credentials inside your client application, but that is security by obscurity and any one with some programming skills or similar can find out the credentials to the database and connect directly to the database.
We have an ASP.NET 4.0 Web application that connects to a SQL Server on a separate machine across a LAN. I use a ConnectionString (with SQL Server authentication) stored in my Web.config to do this. Basically, it's a fairly traditional Web-Server-to-SQL strategy.
However, one of our clients is arguing that this strategy is not secure. This client says that we should only connect to the SQL Server through a separate Web Services layer.
I really don't want to rewrite this app just to satisfy this client. What should I tell him? Does any one know how I might best refute this?
Thanks in advance...
Security is always a trade-off. What is the client really afraid of?
Having database credential "in the clear"? I have seen auditors point this out as a potential vulnerability, but really, if someone has compromised your web server they can run arbitrary code against the database, so encrypting database credentials doesn't really buy you much.
Your web app should be using a minimal-rights user to connect to the database, so compromising the web server should only give you the rights to read & update data. How would that change if everything went through a web services layer? Again, there is a very real cost - in complexity, and in performance - by going to a web services layer. Only the client can answer whether or not that cost is worth it.
If this is a web project, you need to change IIS servers running user to a domain user and give permission on sql server to that user.
Than you can use SSPI on your connection string like below.
Like this, you don't need to keep your username or password clearly on web.config.
<configuration>
<system.web>
<identity impersonate="true"/>
</system.web>
and your connectionString
"Integrated Security=SSPI;Initial Catalog=TestDb;Data Source=10.10.10.10"
There are many customers that argue the work of an IT professional, just like there are many people visiting the doctor asking for the medicine instead of what disease they have, because they already know the answer since they read about it on the internet.
I mean, they ask you to build the application and you as an IT professional should know best when your application works as expected. You as a professional should have balls to tell your customer that if he think can get somewhere else better, he should go there or perhaps build the application himself; that's what have done in the past with positive results :)
Regarding security; perhaps for their confidence you can encrypt the web.config and show them, but actually it means nothing; if someone can access the server, they could decode it. On the other hand, someone that want to break in to your database should pass trough a lot of barriers. It's hard to break in, perhaps impossible. Another options is simply blocking connections from outside network the network or ip range or whatever. I think this shouldn't be something to worry about.
There much more and either more realistic concerns to worry about, such as preventing cross site scripting and such common treats.
The client is wrong introducing another tier would not automatically improve security.
In a nutshell use SQL server roles for data access for example the built in data_reader and data_writer roles are a good place to start. Always use the most appropriate least privilege account for the application. If you only need to read data use an account that only has access to read.
Use Windows authentication where possible, if this isn't possible then at least encrypt the connectionstring.
More information on how to do what I've described can be found at http://msdn.microsoft.com/en-us/library/ff650037.aspx#pagpractices0001_dataaccess
One possibility is to encrypt the section in the web.config. So, only user who can access the webserver directly can decrypt this section.
Here is how this works with the help of the iisreg-tool:
http://msdn.microsoft.com/en-us/library/zhhddkxy.aspx
You could enable Encrypted connections in your database and tell the client that the connections are encrypted so fully secure?
To make it more secure, and satisfy your customer you can use Tunneling between your computers.
You setup a server tunneling program where the database exist, and client tunneling programs on the client computer. You connect the one computer to the other via tunneling, and the database connection happens over tunneling.
And everything is exchange high secure (and compressed if the tunneling support it).
http://en.wikipedia.org/wiki/Tunneling_protocol
http://en.wikipedia.org/wiki/HTTP_tunnel
Ps I connect to my server only via tunneling for anything that I do.
I never liked using the web config. The registry is more secure.
Best Practices is to:
Hide the important items of the connection string in the registry
Encrypt the important items in the connection like user names, passwords and server name in the
registry
Access the registry through a class
Build the connection string on the fly and only when needed per page
Error handle every page so the connection string won't show, in case of error
Always close the connections once done. Avoid memory leaks
Always close and reset DataReaders
For additional Security
You can build a separate program to create the connection string and
reference that project as a library inside the solution
If you want to be really secure your client is correct. Send the information to a dll that will communicate with the DB. This is a lot of work
Sources:
From ScottGu # http://msdn.microsoft.com/en-us/library/Aa302406
Scalability:
In regards to scalability: Creating\Editing registry keys across a web farm can be accomplished very easily, with custom admin software.
http://weblogs.asp.net/scottgu/archive/2010/09/08/introducing-the-microsoft-web-farm-framework.aspx
On a final note to all the people who voted me down. Security out of the box is just not enough. Security is an Art and not Science.
Hackers know where the password is stored by default......
ASP.NET 4.0 Fans
Microsoft makes it easy for asp.net 4.0 web sites to deploy registry settings:
http://msdn.microsoft.com/en-us/library/dd394698.aspx
Is there anyway to prevent people from using Reflector.net to decompile my .exe c# application? I know there is a tons of post about this but I don't really care if people can see my code the only thing I want to "hide" is my database connection string.
I am currently using "Settings" in my c# to keep the database connection's info.
I wanted to know if using those string in my project's Settings would prevent people from seeing it ?
I am using DotFuscator in visual studio 2008 but I heard it wasn't preventing people from decompiling my program.
I know I could use a Web Services but my server will be on linux so I guess I can't store web services on Linux.
No. Even if you encrypt the connection string in the program code or in a settings file, you will need to decrypt it, and the program must necessarily contain the decryption key somewhere, which means that someone who is interested enough in finding it will find it, no matter how creative you are in hiding it. Why do you need to hide the connection string? If you are afraid that someone who has your program might call the web services directly and trigger unintended actions, you should look into how the web services are structured, what they allow clients to do, and how the authorization works, and make security improvements there instead.
If your program has the connection string in it, users of your program can get it back out. Even if you encrypt it, they can sniff it when your program connects to the DB server.
If you don't want your users to know your DB login credentials, don't give your DB login credentials to the users. That's the only way.
You could do this by instead giving each user their own credentials, and using the permissions system in the DB server to control what they can or can not do.
As others have stated obfuscation is no real protection for a connection string stored in a client application where the user have access to the binaries.
Don't use a direct database connection from your program unless the user is trusted to use the database directly with the same privileges. Have a service (web service, REST-service, etc) in between that you host on your own server. Linux can host services of any of those types I mentioned (use Mono if you want them in .NET on Linux)
In order to expose your database via a web service using Mono or any other language/framework you can host on Linux you would create a web service method for each atomic operation you want to perform against the database.
An additional advantage over letting the client application access the database directly is that when the client application is using a service between itself and the database you are free to change your data store without affecting the client. You can decide to change the database schema in your database or replace the database with a NOSQL solution or even a flat file.
Having a service instead of communicating directly with the database moves the authentication/authorization requirement one step, so now you need to implement it in the service. Fortunately there is rich support for authentication in a web service.
Take a look at this guide on this specific topic from MSDN. Keep in mind, however that this only shifts the security burned. Now you need to manage the security of the key
If a C# application connects to a mysql server from a client, how do I store the mysql username/password for the connection? If I have it in a config file or embedded in the source it can be found by reverse engineering. It is not possible to give all users a MySql password.
Also, I have a log in for the application. How do I enforce that the user goes through the login process and does not just reverse engineer and comment out the C# code verifying the log in?
Is there anyway manage these connections between MySql and a client side application or must there be a third program on the server side interacting with the database locally to be secure?
Perhaps you can have a two-stage system: Have a SQL account whose only permission is to execute a stored procedure taking the user's username and password and giving them the credentials to use for the real account. When the user logs in, you connect using the restricted account, get the credentials for the real account, and then do your work using that account. You can change the SQL password fairly frequently, too. If you suspect a user of foul play, have the procedure return them a different set of credentials, and track those credentials.
For Winform clients that connect directly to the db this is an age old (10 years or so?) question that may never be solved.
The problem is that no matter how you encrypt or obfuscate the connection string there will always be a point in time at which the string will be represented as plain text in the client computer's memory and therefore hackable.
You have been recommended options by other SOers, i just thought i'd point out what you're trying to work around.
Here is the problem. You are trusting the end user with the binaries which will call MySQL queries. This means, beyond any shadow of a doubt, that a clever user could "take control" and run queries directly.
There are things you can do to improve the situation. It sounds like you are on a LAN. Why can't you give each user their own database user? That means that the authentication is (a) taken care of for you, and (b) you can use "real" MySQL permissions to limit what harm they can do. Also, you could use stored procedures and give them only access to the procs, really limiting what they can do.
You could also consider re-writing as a web-application where you process everything on the server out of their reach.
However, is there really a problem here, or are you just being theoretical?