I am developing an accounting application using C# with SQL Server Express 2008, the application only accesses the database locally. i want the customer to enter a user name and password when he installs the application, that way he is the only one who can run the application, and my question is:
1. should i store the log in credentials in a local file, or create an sql server user account with those credentials and rely on the database keeping them a secret ?
2. if the second option is doable, how to do it from the installer package ?
There's a lot more to this.
If whoever installed sql server selected sql server security that user (sa) will have been defined and will have access to everything.
If windows only then it will be the windows user who installed sql server, and they will have access to everything
If Mixed, both will have access to everything
Then which user created the database on the server, they'll be dbo by default and have full access to their database.
So it all depends on who's doing what.
Does your app intaller call the sql server install?
Does it create the database?
Admin and dbo, can both grant access to said database to anyone they like.
Adding the windows user installing the app is simply a matter of getting your installer to execute a sql command or two. At that point you have Single Sign on. No need for password you are adding the windows user and mapping them to a database role/user.
If you want a username and password any user could use if they know it, then perhaps sql only / mixed mode is the way to go. Again a couple of sql commands executed from your chosen installer to caete user fred password ?, job done.
The point to remember is in order to execute the instructions to add logins and users, roles etc, you need to connect as someone else with permission to do that, e.g. windows admin or sa.
Also most application users on managed networks do not have admin permissions, so you could have a bit of fun round that as well.
I suggest you have about of a read about sql server security, there's a few ways to skin this cat, only you have enough info to choose the best option.
You might even want to have a think about application based security, if each install of your application creates it's own database and role....
You could do something like, store database settings, such as IP, Port, Username and password login attempt credentials locally, perhaps in an XML file, but then store the login credentials for the program in the database.
Note: Obviously i don't know how much you know about security, but here's a few tips:
1)Don't store the password directly in the database. Use a hash and some method of encryption.
2)Check the hash of a given password a user attempts to log in with, with the database stored variable you created for the program, which should also be a hash.
Basically, at no point should the database know what the actual password is, only a given hash that you passed it, and can compare to in the program itself.
With regards to the database access, I would create a user which has access to only the schemas you want it to. From there, get the logged in user in your application / program to log into the database with the credentials in, for example, an XML file. It's also an idea to encrypte these details in the XML file too, so they can't be tampered with locally.
Related
I have an application that accesses a database directly. This application controls what user can do according to the context.
At the moment, I am using Windows authentication, but all the users has permissions to select, insert, update and delete, because it is the application which controls the action.
For example, one user can modify a document, but only if the document is created by this user. So in the database the user has to have permissions to create a update, but only if it is the owner of the document. I am not sure if I can handle this case with SQL Server user roles.
But the problem is that all users have all the permissions to the database, so they could use another application, like SQL Server Management Studio, to access the database and do what they want.
So I was thinking in the option to use SQL Server authentication, with full access to the database. This user is not known by users, so they can't use another applications to modify the database.
The problem that I see with this solution is that I have to store the credentials in the client application, and I don't know if it is really a secure way to do it.
If using SQL Server authentication is an good option, how could I store the credentials of the user in a safe way?
I have read about application roles too, but it is needed to store the password in the client application, so I think I would have the same problem. And also I don't see the difference between application role and to use SQL Server authentication.
In summary, is it a good solution to use SQL Server authentication in the way I explained above? And if it is a good option, how could I store credentials in a safe way?
Thanks.
The difference between an application role and using SQL Auth is that the application role password is not enough, by itself, to access the database. The user must be individually authorized first and can be individually monitored and audited.
how could I store the credentials of the user in a safe way?
The application role (or SQL Auth) password is never truly secure when used from a client application running on a machine where the user is an administrator. So you could run the app in desktop virtualization, or a kiosk-mode PC.
But for many scenarios involving mostly-trusted users application role security is good enough, especially when combined with Windows Integrated auth so the users access to the database can be audited.
Background
I'm building a single tier application Winforms application using C#. A SQL Server localdb database is attached to the application that runs when the application does. The plan was to use Windows Authentication to verify that the user is part of the MyApplication role/group and can use the application. But, in order to prevent users from accessing the database via other means, I was thinking of using an Application Role so that only the one SQL application user can edit the db tables.
Question
My understanding is that in order to use an Application Role, you need to provide a username and password in the connection string. I can encrypt this information, but obviously it will need decoded before being sent to the database. Is this a concern in a single tier application? What are other alternatives?
To use an application Role, you'll use the sp_setapprole stored procedure where you will provide the name of the application role and the password, rather than sending it in the connection string. When you use application roles, you still connect using an ordinary login, but once you successfully sp_setapprole, your connection loses its user permissions and instead gains the permissions of the application role. Having the decoded password in memory is a concern if you have reason to believe that users may decide to use a debugger to attach to your process to extract the password. Any administrator would also be able to decrypt the encrypted password on disk as well if you choose to use windows machine-level key containers. Using only a single tier for an application that uses a database is a security risk, and you have to decide based on the circumstances surrounding the application whether it is an acceptable risk to gain the reward of skipping a few weeks of design and development.
Source:
https://technet.microsoft.com/en-us/library/ms190998(v=sql.110).aspx
I highly recommend implementing a web api to manage your application's interactions with the database as well as security. This web api could use a windows "service" account to authenticate with the database, and users would authenticate with the api using their individual windows accounts. This has the added benefit of you never having to think about passwords. As far as managing API permissions, that is an issue that is up to you to design and implement as you see fit. The main issue you need to understand and deal with is uniquely identifying AD users. Take a look at this SO post for more info on that: What Active Directory field do I use to uniquely identify a user?
Your service account would have all necessary permissions on the database to do what the application needs to do, but not all api users would necessarily have permission to use all api functions. You would manage a store of uniquely identified AD users that have permission to use the application and what permissions they have. The rest is design and implementation details that are up to you.
Define user with privilege only to execute stored procedures. By this way if someone use SQL Management Studio, s/he cannot browse/edit tables and even cannot see the table names.
I have created a WPF application that connects to a SQL Server database directly (not through services), located on database server. Now I need to create user management, where each user will have its own log in credentials (not windows authentication). This is how I thought of doing it:
During the application installation, DB administrator will provide me with an account that contains enough permissions to create database
Using these credentials I will connect to SQL Server, execute a script to create database, and also execute a script to create one default admin user for this database, that will have full permissions.
I will use this new user to manage all users and roles for my database.
for each user in my application I need to create a user in my database.
Questions:
is this correct way of doing it?
I am confused about how to manage this. If I have a table Users and Roles in my database, and I also need to create users and roles on database level, then it looks like I am duplicating stuff?
Or I am missing something?
I would probably do it differently by creating roles and managing things through roles rather than user names/logins.
It would be better to create one application login in Database, whose credentials will be used for communication between your DB and application.
There is only very minor overlap. In your Users table you store the username that matches up with the SQL account, the username is the only overlap. All other information is stored in the Users table.
I don't see any problem with doing it this way, the only downside is that you are required to have an admin account with a considerable amount of access on whatever SQL Server it's installed on, but it sounds like you have already taken that into consideration.
We currently have a winforms app that allows users to log in in order to access the system. The authentication system is a custom made kludge. I'm working on a implementing a change that links users NT username and domainname to their existing custom account so that they don't need to repeatedly log in. I'm using WindowsIdentity.GetCurrent().Name then storing that information in a database table that maps to their old accountid. What I'm wondering is if it would be possible for a user to vpn into the network with a computer name that mirrors the real domain name? This could potentially give a rogue user access to someone elses account. I guess the real question is: is there a way to differentiate between the sql servers domain and a users domain without just doing a string compare on the names.
Yes it would if your app was using SQL Authentication to access the database. If you change the Database connection to use trusted authentication then the SQL Server will authenticate the login against the domain controller. So despite the user having access to the application they wouldn't be able to access the database driving the applicaiton. If you did this you could also move the capturing of the user name to a SQL Server stored procedure which would ensure that the name captured matched that of the Domain rather than the local users.
THE SERVER MUST NOT TRUST THE CLIENT.
If the client can get and use credentials to log in to the database server you're toast.
If your server is only a database server and your application does not use trusted connections and your application does not prompt for db credentials you're toast. (See previous statement.)
I'm lazy. I'll patch WindowsIdentity.GetCurrent().Name to return "Administrator" if I feel like it.
I have written some C# which connects to a live production database. I want to give my application read only access to the DB but am unsure how to achieve this.
Is there any trivial way to get this done by amending the connection string?
My understanding is that the application will logon with the credentials of the person running the application and hence may or may not have write access to the db based on that fact. Can I statically limit the permissions of the application so that if someone changes the program to do something devastating at a later date any manipulation will fail?
Apologies for how trivial the question may be but it's my first venture into the world of MS programming.
Thanks,
Gav
You can't change the permissions for the account by changing the connection string. There is a user account in the database that determines the permissions.
Unless you want different people to have different permissions, you should set up an account for the application and use in the connection string.
For any account in the database you can specify which databases it can access, and what it can do with the databases. The permissions can be specified down to the level of objects and operations, so you can for example specify that it can only do selects on certain tables.
Have it login to the database server as a user that only has read-only permissions. That and just don't try to write anything to the database.
You can always grant the user connection to your database just the "db_datareader" role on that database.
db_datareader gives your user SELECT permission on all tables - but nothing more.
There are basically two main types of SQL Server authentication:
Integrated Windows authentication and
Mixed authentication mode (SQL Server authentication)
It sounds like you are using the former. If you use the latter you can create a specific user account within SQL Server, give it a username and password, and then grant access to the tables you wish it to be able to read. You can control at the account level what access it has to any object in the database.
See http://msdn.microsoft.com/en-us/library/ms144284.aspx for more details.
Just a thought; usually not every logged in user gets to access the database, let alone a read-right. Therefore you in your case you can create a database user for your application with read rights; and use that in your connection string.