Simple and contrived example:
C# desktop application talks to SQL Server database. All orders exist in Orders table.
Application views, creates and amends orders. In this example a user can only amend their own orders.
Concerns:
Storage of connection string if using dedicated sql credentials.
Even if user credentials are used, application security could be bypassed by connecting directly through Excel or Access.
Solutions:
Provide access to SQL through web service/middleware only. Good, but not necessarily viable in this case.
Encrypt connection string in application somewhere. Not hugely secure, security through obscurity.
Secure database by granting access to specific stored procedures, views, etc and no access to actual tables. SP's and views take into account the user's rights/credentials. Pretty awful. Ok for simple examples (Select where user , becomes complicated once you introduce users in different groups, manager relationships, etc.
Alternatives:
How would you approach this?
Thanks
Even if user credentials are used, application security could be
bypassed by connecting directly through Excel or Access
what do you mean? you should not allow users to connect to SQL Server directly or with Excel or Access. They should NOT know the sa or other password.
After this, surely you could encrypt some sections of your app,config so that nobody can see its content.
I would really have the logic that a user can only modify his/her own Orders at the application level. Could be done also in the stored procedures I guess but it depends and more details should be known about this to suggest the best or most appropriate approach.
Use windows authentication instead of sql authentication.
To allow users to see only their data you can create view and filter data based on the currently logged in user by using SYSTEM_USER to get the data for the current user only and deny select permission on the table itself.
You can't do row level security in SQL Server (well you can, but it's not straightforward). So your only choice to be totally secure is to go through a data-layer which controls access. You can store your credentials encrypted, but that's not totally secure, as you say. It depends what you need.
Well in our application we handle we store the connection string encrypted in a file.
So the user has no direct access to this file.
We also use sql connection only to our database and grant the user for this only.
If you use Windows Credentials to access it and want to prevent any manipulation you can disallow write access to table.
For reading the data you can build queries or access the tables.
For writing/adding/manipulating data you can create stored procedures. One of the parameter is the username. Inside the procedure you build your bussiness logic, impersonate to a user that has write access to finally write/update the data.
There you have your "layer" inside the SQL server.
But I wouldnt suggest to go this way :) It is possible but to many business logic inside the database imho. So the safest way is to find a good encryption class in your language, use sql auth only and store those data inside your code.
Related
Okay so my problem is this:
Firstly, user access to the SQL database is controlled by windows authentication, but the app is doing a second check to set user privilege levels within the app.
When I create a new user in my WinForm client App it asks for a password which I then hash with a random salt, these data are then stored in the users table of my SQL database thusly:
users
username, firstName, lastName, pHash, pSalt, accessLevel etc.
When that user, in a later session, tries to log in he gives his password. I pull the salt out of the database and hash the given password.
Now this is my problem: I'm obviously insecure if I pull the hash from the database and compare it with the computed hash locally.
My App maintains a 'user' object that sets a flag for 'authenticated' and has a property that is set based on the 'accessLevel' column in the users table in the database.
There must be a usual way of doing this - or is my answer, you need to be using the SQL Server access facilities to do this not trying to re-invent it in managed code?
You're right in that you can't trust the client to do authentication or authorization. That must be done on the server side.
In your case when you are accessing the SQL server directly from the client you would have to use SQL servers built in functionality for protecting different database objects.
That's usually quite hard to do in a good way though, so a more normal architecture is to create a separate server application such as a WCF service. The clients access the WCF service, which does the authentication and then is in charge of all database operations.
I have a very basic question and want to know how other experts do this
I have an application with some 100s of users. I have been using SQL LOGINS to authenticate these users. These users have password policy enforced. and I face difficulty when any user's password is expired i.e. i have to reset it from SSMS myself. It sometimes becomes a difficult job along with other tasks that i do.
I was told by some experts that it is a good practice to create my own user table and have all the user details in that table. I have created a user table with following columns.
User Id
User Name
Password
PasswordCreationDate
PasswordExpiryDate
PasswordActive
One simple question. How do my users connect to the database . Offcourse i would need a connection string from the application. That connection string would require a user name and a password isn't it? and I can not get the information from the user table until and unless i am connected to the database.
Another problem, how do i keep track of last 5 password. The policy says that the user can not use any of the last 5 already used passwords.
All this can be avoid if I can get a solution of notifying my users that their Password is due to expire in 'n' days and they must change it before it expires.
What do the other developers do when authenticating their users. Please Guide Me
If you keep your user's login credentials in the database, then for access to sql server itself you may only need one login for the entire app. This login would have full access to your database, because it would be up to your application to enforce access rights.
If you go this route, you need to be aware of two things:
There is still a security concern for larger applications that need to give ad hoc reporting capabilities to users through tools such as Reporting Services, Crystal Reports, Infomaker, etc. In this case, users can use these reporting tools to gain read access to areas of the database they should not be able to see.
If you store your own credential information for your users, you need to make sure you do it properly. That means no plain text passwords. You need a cryptographically secure password hash (not md5!) and a per-user salt. If that's greek to you, best to leave this alone.
Another option open to you is to use Active Directory/Windows Authentication for your database. The trick here is that you still have to set up access rights for all your users. However, you can use Active Directory groups for this to reduce the number of logins you need to create, and it will at least prevent you from needing to reset Sql Server logins by hand, because users will log in with their Active Directory account.
A pretty common scenario amongst web applications is to use one username/password (so only one sql login, typically some kind of dedicated login with minimal rights for the application). This way, connection pooling can be used. This is of course a backend account, configured in the web.config and not visible to the end-users.
The users are maintained as a type of data within the application. Asp.net comes with a solution that is called Membership. User authentication is done against the Membership provider and several classes give you programmataic support for authentication, roles, etc. You can use AD as a provider for example, or forms authentication. Or you can write your own.
Since you are now using a dedicated sql login for each user, you need to be aware that this approach moves data access security to the application level. So this might not always suit your needs.
Ideally you'd use existing Active Directory infrastructure to handle your authentication/authorisation of individual users, and you could then have end-users' credentials passed via the web server to your SQL server (You'd probably need to look into handling the Kerberos "double-hop issue" to effect this).
But failing this, it's easy to set up so that the application it self has a SQL login to access the database in order to retrieve user level authentication information. One-way hashes on user passwords would ensure that even if the app's password is read from connection string, user passwords can't be obtained.
Or somewhere in between those two solutions, where the application has a service account within AD, which has access to the SQL database, in order to retrieve the user account info from within the DB.
Either way, if AD is available you can secure further with Kerberos Service Point Names to ensure database access from only your expected end-point (ie the ASP.NET server).
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.
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.