I am using a C# application and connection to database using sql server 2008 using windows authentication. I have created several users for the database but i am unable to understand how to use them on my application level. My goal is to install this application on any pc and make the database un-accessible by the users if he tries installing sql management studio.
Can somebody please explain or give me any good references to understand what i want to do ?
IF you want to make sure the users can't access the DB without your app you have several options:
implement "virtual users"
This would mean you implement your own user management and don't create real DB users for your app users but only "virtual users" in your own structure... your app would use a general app user for DB access which is unknown to your users... since the app users aren't reall DB users they can't access the DB directly with their users/pw.
implement a "special password scheme"
This would mean you create real users... but only your app can create an app user... when the user is created or changes his password you don't set the users DB password to that but use some calculation (for example a hash) to create a different password and set that on the DB level... your app knows the calculation so when the user logs in your app does the calculation and uses the result to log into the DB... this way the real DB user can't log into the DB directly because the password they know (which works only when used with your app) is not the one the DB knows...
BEWARE that none of the above is 100% secure since your .NET app can always be decompiled/reverse engineered etc. - although the above is certainly enough to block "normal users" from accessing the DB directly...
Related
I am developing a desktop app in c# using "entity framework database first approach" that is required to be highly secured i.e. no one can access its database without login into that application and no one can extract the data directly using database file. The database have 20 table. Although I Tried to encrypt the database but when the application will start i will have to decrypt the database file in order to connect and leave it decrypted until user tries to exit the application.
No offence, I am a noob to sql server and I want to create a highly secured sql server database for my c# desktop application that can only be opened by that application only. I know that there are two authentication model by which you can connect to a sql server i.e. windows authentication and mixed authentication. But i don't want my database to be opened using windows authentication.
Is there a way by which only one user can open the database with password?
if you used SQL compact the database server is only really there for your app, which is probably the closest, however it doesnt stop people taking the file and putting it into SQL express/server
Similarly: embedding sql express may help but again the files are still there.. and ..
If SQL is in an instance yes, you may control it with a username/password but anyone with admin rights to the instance can get in it.
You also would need to consider how they would backup the data
Yes. You can easily handle this.
Go to Security >> Logins and then create an user with password. You can also give him access to a specific database. You can specify the Server Role section.
I create a connectionstring to connect to the database, there are also users that i can create with specfic permissions for each database i have. If i can access that database by the connectionstring from my code without using any if the users created for the database then what good the users are ? please explain. thanks.
You can only access the database as a user.
It is not possible to use a connection string that doesn't have a user (or uses Windows authentication).
You normally use one of the users you created in the database inside the connection string. Unless you are using integrated authentication in which case you are impersonating a user and that user needs to be created in the database too. Either way you'll need a user in the database to access it through the connection string.
Just three quick benefits of separate users.
1) Direct access to the database: If they're using SQL Server Management Studio (or similar) for ad hoc queries, you want each user to have a separate username and password.
2) Auditing: By using different usernames and passwords, you can log activity to specific users, so you'll know exactly who accidentally ran the command DROP TABLE CUSTOMERS
3) Security: Different users can be given different levels of access, so no one who shouldn't be able to CAN accidentally run the command DROP TABLE CUSTOMERS
Further, you can set up your connection string so that it accepts usernames and passwords (if you desire) such that your client application will still request the credentials from the user to verify what level of access they need (if such is appropriate to your application).
Auditing purposes is one of the uses of this. You know which users performed what if your tables store this information.
For example SUSER_SNAME() or USER_NAME() returns the username of the person executing the queries.
On ASP.NET using Sql Server auth, the username of the person executing the statements will always be the one specified in the connection string. For a Windows app using Integrated Windows Auth, for example, the username will be picked up from his domain account but still needs to be mapped as a user on the particular database.
Many desktop applications use SQL tables to manage their users permissions and roles. In fact they restrict access to some parts of application in their application code. It means they need a constant connection string to SQL server with maximum permissions.
My target is C# 2010, Sql Server 2005 or 2008.
What if with any reason someone find that connection string ?(Network tracing, Software hacking, Fired Employee or ...), He can change everything with just Managemenst Studio and you can't understand which client did it. If you want to change connectionstring. You must do it in many clients and in a bad design you need to recompile application.
So i want to know is it good idea to use real SQL login instead of username and password in tables ? make connection string for each user by SQL Logins ?
In this way there is no afraid to loose connection string. Also in SQL codes you can use GetUser() function to indicate which user really runed the query ?
But maybe the managing permission is difficult with this way because there is no simple table to manage permissions and users.
In one long sentence. I want to know What is the best way for authenticating desktop application users in a way that managing permission can be done and also sql server can log user activity ?
Whenever possible, use Windows Authentication.
Define Roles. Add Groups to Roles. Add Users to Groups (as per usual Windows way of managing file system permissions).
Choosing an Authentication Mode
See: Application Roles
You can encrypt sensitive sections of your app.config file. Last time I checked, you have to go through some hoops, but it's not that difficult to set up.
See for example this question
For best security, you need one dedicated database account per user; each account should only have the privilegeds necessary for the tasks that the corresponding user may perform. Normally you grant privileges to roles (e.g. "clerk", "manager", "supervisor") and grant those roles to the users. Obviously, it requires some work to identify which privileges each role needs. In many cases, it might be necessary to not allow direct access to some tables, but only to database views that hide some parts that should not be visible to that role, or to stored procedures that do some additional checks and make sure that each transaction is processed as a whole.
The basic setup is classic - you're creating a Windows Forms application that connects to a DB and does all kinds of enterprise-y stuff. Naturally, such an application will have many users with different access rights in the DB, and each with their own login name and password.
So how do you implement this? One way is to create a DB login for every application user, but that's a pretty serious thing to do, which even requires admin rights on the DB server, etc. If the DB server hosts several applications, the admins are quite likely not to be happy with this.
In the web world typically one creates his own "Users" table which contains all the necessary info, and uses one fixed DB login for all interaction. That is all nice for a web app, but a windows forms can't hide this master login information, negating security altogether. (It can try to hide, but all such attempts are easily broken with a bit of effort).
So... is there some middle way? Perhaps logging in with a fixed login, and then elevating priviledges from a special stored procedure which checks the username and password?
Added: OK, so integrated authentication and windows groups seem to be a fair choice in most situations, so I accepted the relevant answer. Still, if anyone can come up with a non-integrated authentication solution, they'll get an upvote from me.
For WinForms use Windows groups. No passwords are needed because the credentials are inferred from the Windows login using your application.
This is best practice
Basically:
The user belongs to a group (assumes single domain)
Group is a login in the SQL Instance
SQL login maps to a database user
DB User belongs to a DB role
Role has object permissions
It's worth reading up first before having someone try to capture all the information here
Edit:
If you have a workgroup, you can still do it by setting up sqlbox\bob, sqlbox\hans etc in a sqlbox local group.
When someone tries to connect (say bob on his PC) windows will ask them for their details. As long as bob knows his SQLbox account detailsm he can connect.
But then, I've not tried this in a workgroup setting...
In addition to using Windows Domain/AD Groups (put the AD groups in appropriate roles you create in SQL Server, so all account maintenance moves to AD), be sure to use the Application Name in your connection string - this allows you to see which applications are performing operations in the profiler etc.
Because when everyone is logging on as themselves from different applications - windows and web, it helps to know that it's actions taking place through an application and not just any user's ad hoc query through ODBC and Excel, say (if you allow users access to certain views for data export or report writing).
Can't you use Active Directory Groups to make the management of the db connections easier?
From MSDN...
The name can be a Windows user name or a Windows group name, of the form DOMAIN\Name.
That way you may have a few groups, read-only, editor, manager, admin etc. It's how I have achieved similar things in that past with Click-Once apps.
It really is the best choice for what you are doing.
I am assuming this is an existing app? If it was new I would otherwise say to go client server with web-services or similar.
PK :-)
With regards to wanting to hide your authentication and use a single application login with WinForms, if the login has very little privilege - select only on views and execute only on stored procedures, anyone who manages to reverse engineer your encryption of the login information in your application will only be able to perform the same functions they could perform in your application. If you absolutely have to raise the level on the security, you could authenticate each stored proc against your users table (poassing user and hash to each SP). Also, rotate the central application login on a regular basis.
All this is a lot more difficult than using integrated authentication and implementing AD platform in your environment. So you're effectively writing your own directory and authentication instead of using one off the shelf.
In addition to gbn's update about workgroup versus domain, you can run the application with RUNAS /NETONLY /USER:SERVER\USER with user credentials on the domain or server which your machine is not a member of. At the point that the application makes the connection to the database, the remote credentials will be authenticated and used. I have an application which actually checks to see how it was run and if it not run with a particular switch, it prompts for username and password and then re-runs itself using the Windows API using a function equivalent to RUNAS /NETONLY /USER:DOMAIN\USER. This is because our workstations are not currently on the domain (or on a domain with a trust relationship) of the SQL Server. In this case, you could still manage the security in local groups on the SQL Server or groups on the domain of the SQL Server. You would basically just lose out on the automated authentication token.
I have a situation that users access remote MySQL server in C# application.
Basically,
A user using C# application on his/her desktop ->>>> connects to remote ->>>>>>>> [ REMOTE ]
How do I securely hide database connection detail?
I have few ideas, but I don't think they are safe.
Encrypt database connection data into a file and store it within application directory.
prompt login page and let a human enter username/password, then transfer database connection data to user's computer.
No matter what you do if the credentials end up in the application in cleartext you are vulnerable.
Either implement a service layer in front of the database or if direct connections are essential try and come up with a scheme that allows a unique databse account for each user and then authorise them appropriately on the database.
Generally, it's better to ask the user for the credentials so that each account can be enabled or disabled by the administrator. Barring that, there are APIs for encrypting all or part of the configuration file. Here's a sample article:
http://www.codeproject.com/KB/dotnet/EncryptingTheAppConfig.aspx
I would suggest some form of session management based on user credentials. This can be accomplished in many ways.
For instance, you may accomplish this by simply wrapping your database access with a back-end system. Your desktop clients are oblivious to the database and interact solely with the back-end system. Unfortunately, implementing this level of indirection is not trivial if you have to do it from scratch but it will certainly make your application more robust and flexible. WCF services can help accomplish this.