I'm building a Windows application that will go against a SQL 2008 database. Some of the table data is very sensitive but some of our users will still need at least read if not read/write access to those tables. We're going to use Windows Security to control their access to the database.
I want to know if those same users can access the data in those tables through something like Excel or MS Access? It's about blocking a bad apple from trying to steal the data inside and walking off with it. If they have read access to the data, though, is there any real way to stop them?
Sorry if this is a SQL Server 101 question, but I'm not finding good answers to the question.
Thanks for the help!
If they have to have read access, then you should pretty much assume they can do what they want with the data. If you render data on the screen, you have to assume someone can write down what they see with a paper and pencil.
With that said, I'd create a service account that has permissions to access SQL Server from your application. Control the access in your app via roles. Do not grant any users access to your database directly - they have to go through your app.
If you try to open Access or Excel and point it to your SQL Server database, they won't have permission to do anything.
A good way to do this might be to author stored procedures that fulfill all of your needs and grant all the users execute only privileges.
If you grant full read access to your users, then yes its going to be difficult to prevent them from what your talking about.
As mentioned by others, you can create a SQL account for your application. This will disallow any outside access from anything other than your application itself. Of course, this would mean that access to your application itself would have to be restricted. This is also easily accomplished by limiting read access to the executable to an active directory group which contains users whom get access. Further to that, you application may also use active directory hooks to determine whether to allow write access for those users who need it.
That all being said though.... your biggest problem will be the physical security. If just one user in the authenticated group is untrustworthy, then a certain acceptable usage policy, HR employee screening, and user environment checks and balances must be in place. A proper workstation deployment policy will also be good here, allowing you to restrict removable drive usage, logging all access, connectivity details etc etc.
It's more about the operational environment at this point if you can't trust the user.
Users could access SQL tables using linked table in Access or external data query in Excel, however the permissions are controlled by the SQL server, which means the users have read-access, they will be able to access data in read-only mode.
Related
The Problem
Good Morning! I work on an application team that supports a few applications which utilize SQL Server for data storage. Recently, our Database Support team decided that SQL Authentication was no longer permissible (for security and logging reasons) and so my team was forced to convert all connections to Windows Authentication including several dedicated Service IDs that our applications had been utilizing for data retrieval.
First, let me say there most certainly are advantages to moving to Windows Authentication, I am not trying to dispute that. But this change has raised a huge problem for us... by switching our Service IDs to Windows Authentication we have now opened up our back-end databases to every internal business user with front-end application access.
MS Access is pushed out to every user desktop and a few superusers even have access to SSMS. At this point we are relying entirely on user ignorance to prevent internal users from accessing the back-end database directly. And given that certain roles have elevated DML rights, this presents a possibility for some nasty data consequences.
This new enterprise standard has left my team stuck between a rock and a hard place at this point so we looking for any database, account or architecture solution that would allow us to restrict user access to front-end only.
Questions
Has anyone else run into this problem? Is there an architectural solution we are missing that would allow us to eliminate SQL Authentication without exposing our databases?
Does anyone know of a way to restrict access to a SQL Server database to only certain connection methods? I'm wondering if there is a way to designate a specific ID (or role) as only allowing a connection through a front end (and eliminate ODBC connections entirely).
Does anyone have any clever workarounds?
-------------EDIT---------------
A couple people brought up a good point about role access so I wanted to clarify our former and current solution... Previously, all role access was managed on the front-end and data retrieval was handled entirely by private system SQL Authenticated IDs to which end users had no visibility.
When we were forced to eliminate these SQL Auth IDs, we created a similar role-based setup on the back-end database as existed on the front end. Active Directory Groups were created to house different groups of users and these groups were assigned specific role privileges in the database. So currently access is limited by role as much as feasible.
The problem is that even the lowest privileged roles have INSERT, UPDATE and DELETE access to some tables (access which is normally controlled through code). So while we were able to mitigate risk somewhat by utilizing database roles, we still have areas where a user can bypass front end protections by logging directly into the database.
EDIT: Question clarification makes this answer obsolete, but leaving it for reference since some comments discuss it.
Assuming you mean that you have to (based on your architecture) allow access to the DB to each windows user account, one options is to use database roles.
You disable public access to your database, then define a set of database roles, depending on your use cases. Each role is granted permissions such that members of that role are able to manipulate the data they need and or work with the objects they need. Users are then mapped into the roles they require. When connecting to your database, the user will be granted permissions according to the roles they are members of.
For example, we have a role in one of our databases named MyAppUser (our name is actually related to the app which uses the db), which is designed for end users to read and insert data only. These can be created simply as follows:
CREATE ROLE [MyAppUser]
The role is granted just the permissions it to the relevant schemas or tables (assume all our "public" tables are in dbo schema for now).
GRANT SELECT ON SCHEMA::[dbo] TO [MyAppUser]
GRANT INSERT ON SCHEMA::[dbo] TO [MyAppUser]
GRANT DELETE ON SCHEMA::[dbo] TO [MyAppUser]
Each user who should have this public read-write access is then mapped into the relevant role.
ALTER ROLE [MyAppUser] ADD MEMBER [UserName]
This separates users and roles / permissions within your database and allows you to have a single point of entry to control who has access to what in your databases.
By having the "View Definition" permission denied by default (to end users), they won't be able to "explore" the database / view table definitions etc using access, or even SSMS.
NB: SSMS provides wizards for managing and viewing permissions and memberships which are very handy for getting things initially setup / tested / fiddled around with.
Microsoft recommends using Windows authentication when connecting a Windows application to an SQL server database.
http://msdn.microsoft.com/en-us/library/89211k9b.aspx
I understand this to mean that the database must have a user with enough permissions to manipulate data and that user links to the currently logged in Windows user. If this is true, how do I prevent the user from bypassing the application and simply modifying data directly in the database?
It seems like I am stuck between using Windows Authentication and potentially allowing users to modify data directly in the database, or attempting to hide the connection string password somewhere so only the app can modify this data.
If you're that concerned about it, you can implement a logon trigger on the server that for certain people (e.g. members of a certain Windows group), they can't log in unless the application name has a certain value. Note that this is weak security since it's pretty easy to set the application name (even in SSMS). It can/will slow down the logon process, though. So keep that in mind if that's a concern for you.
Alternatively, you can have your application authenticate to and interact with an application server, after which the application server connects to and interacts with the database. The application server can run as a service account, to which you'd grant the permissions you need. This way, the end users' accounts aren't in the database to do raw DML against the db.
But I agree with the other answer here: stored procedures are the classic answer to this question.
It is possible to create stored procedures / views etc and only allow the user permission on those. This prevents the user from accessing the database structure directly, and you maintain control over what the user can do (via creating the functionality in the stored procedures / views). If using windows credentials, I think that this would be the best solution.
This site explains how to grant there permission on stored procedures.
http://msdn.microsoft.com/en-us/library/ms345484.aspx
Here is the list of options, for posterity:
Windows authentication only
Pros: simple, No secret to hide.
Cons: user can easily modify data bypassing your app
Password in connection string
Pros: simple, prevents user meddling in your db's.
Cons: have to hide a password yourself, which is always the worst option.
Sprocs access
Create sprocs to access your data, grant access only to those sprocs. No one but the dbo can alter tables.
Pros: Tightest control over what both the user and the application can do to the data
Cons: Higher coupling of database and application; more expensive than the first 2 options.
Proxy
Create a second executable, whether a web or a windows service, with which your GUI application communicates. The 2nd executable can run with different, securely hidden credentials (IIS, Windows Services).
Pros: Decoupled database and executable, securely hidden secrets.
Cons: By far the most expensive solution.
We have a problem where one of our customers is changing data directly in the database.
As we have an API, we'd prefer our customers to use this. We have threatened not to support their solution if they persist in manually changing data.
My query is, is there a technical way we can prevent access to the database from anything other than our application?
This is a sql server database, and our customers own the server and administer the DB server, So essentially we need a way to lock out SA.
Thanks
First things... you can't:
lock out sa or sysadmin rights at all at the server level
lock out db_owner/dbo at the database level
Now we've cleared that one up, who is accessing data directly?
If you mean end users are changing data, then you have a security issue: they should only be able to use the API and not even be able to connect.
If you mean sysadmin level users (eg DBAs or BOFH types) then there may be a legitimate reason. Does your API support all operations? As a DBA, I had to do open table surgery on badly written 3rd party apps now and then
If end users have sysadmin level rights, then you have a politics issue within the client company
Edit:
After comment by OP on their question... sysadmin users can disable triggers...
Is you API public? It shouldn't be if you can change data without any authentication. I recommend using some internal authentication mechanism. A basic challenge/response protocol that ensures that the incoming query is safe to execute, or something like that.
I have a client-server application where a .NET client accesses all the data and stored procedures in a SQL Server 2008 database.
Is there any way to protect all this data so that only the users I create and authorize can access this specific database? Especially the user 'sa' comes to mind. I don't like him to access all my data.
You cannot prevent the system admin from accessing data, nor should you.
However, no one except the designated dba should have the password for the sa account. If sa doesn't have a password or if lots of people have the password, change that now. If the application accesses through sa, change that immediately.
Other than that way you can best limit access is remove access to all other accounts from the tables and views (including select access) and only allow exec access through the stored procs. That way anyone except the designated admin can only do waht the stored procs do and nothing else. You cannot do this however if you have used any dynamic sql either inthe application or the stored procs which is one reason why dynamic sql is a poor idea.
You can't block sa or another system administrator, as access to the full system is integral to their role.
You could try encrypting the data so it's meaningless outside your application, although it might complicate any future reporting needs.
We have some corporate intranet users using a WinForms app to work on a system with SQL server behind. Integrated Security is setup, allowing all users update and delete permissions, where application security limits how and where table updates take place.
However, some users are power users with SQL query tools at their disposal, and access the DB directly for building reports. However, with integrated security, they have default update rights on tables where they should not have, as the application apply rules to the updates.
Is this an example of where it's more appropriate providing the app with a central SQL authenticated login, whilst users get read only rights for integrated security?
As Jon mentioned stored procedures would give you the protection over direct table modifications. There are other options too. You can use SQL Server's "Application Role" (via sp_setapprole proc). This enables you to continue to use a separate ID for everyone but only at application connection time (through the front-end) are the user's rights elevated.
A major downside to using a shared ID is you lose track of who is submitting SQL to the server though if they're all internal you can get to the machine name.
Something else is concerning though. It sounds as if your users can connect to the database and run queries at will. You run a major risk of downtime in the application due to user behavior in the directly connected SQL sessions. If you can pull it off you may want to try to have a reporting database created that is updated at intervals that your business can tolerate, i.e., daily. HTH
I presume from the way that you've worded your question that your app executes sql statements directly. If you could refactor it so that it executes stored procedures, you could grant exec rights on the procedures and deny direct updating of the tables. This might not be possible though, depending on what your app does.
sql authentication is one option. Stored procedures are another. However, building more granular roles for assigning just the appropriate permissions to just the appropriate user types is where you should really be looking.
Additionally, I would really avoid giving these users direct access to the DB at all. Security reasons aside, it doesn't take much for a user who isn't proficient in SQL to accidentally execute a query that will swamp your database server and create an effective denial of service. Even pros can do this accidentally from time to time.
Instead, give them access to a reporting services or analysis services type solution, or use replication to give them access to a clone of the data. This way your production system is protected.
Personally I would do all application data access through stored procedures. I would set Integrated security to only allow users to run the SP's and not manipulate the data directly.
Advanced access can be given to DB admins to manipulate the data directly when needed.
Group based permissions will provide you with much more flexibility for access rights, and less administrative burden when controlling these with integrated security.