SQL Server authentication - limit access to database to only connect through application - sql-server

I have a database which users should not be able to alter data in unless they use the specific app. I know best practice is to use windows authentication however that would mean that users could then connect to the database using any other data enabled app and change values which would then not be audited.
Unfortunately SQL 2008 with its inbuilt auditing is not available.
Any ideas how to ensure that users cannot change anything unless its through the controlling app?

Use whatever means for users to log in. Windwos authentication encouraged.
make sure the user has no rights to change any data ;)
The application then, on the existing connection, post-authorized using application roles.
More info on that is on http://msdn.microsoft.com/en-us/library/bb669062.aspx
Basically the application can get a separate sets of rights by using an application password (that sadly has to be coded into the application - use sensible means to protect it), replacing the limited rights the user has with more rights for itself.
I would ask you to consider using an application server, but if you have a classical client/server architecture that is as good as it gets.

Related

SQL Server Application Role

I'm thinking of using application roles in SQL Server I've read the following on the Microsoft MSDN site:
http://msdn.microsoft.com/en-us/library/ms190998.aspx
Connecting with an Application Role
The following steps make up the process by which an application role switches security contexts:
A user executes a client application.
The client application connects to an instance of SQL Server as the user.
The application then executes the sp_setapprole stored procedure with a password known only to the application.
If the application role name and password are valid, the application role is enabled.
At this point the connection loses the permissions of the user and assumes the permissions of the application role.
I'm wondering, if the application must know the password, how best to achieve this. I would assume storing the password in source code is a security risk. Is there another secure way to deploy the password with the application (note this is a windows client application that will be deployed to user machines).
There is actually another way to deploy the password with the application.
You can store the password as a secret in the database itself.
For instance, use a stored procedure or a scalar function which returns this "secret". This is an additional step in the logic you describe, to be executed just after the connection is made by the application with the user credentials.
This is possible because the users will have access to the database using Windows Authentication anyway.
The permissions need to be setup so that users are granted access to connect to the database and to the programmable object only.
To "obfuscate" (NOT secure) the password, you can store an encrypted version in the database and use a simple encryption / decryption (like this one).
This approach has the following advantages:
The password is not stored in clear text anywhere (please note though that it will travel in clear text on the network if you do not use SSL Encryption)
Users of the application are not required to provide any input
The application source code does not include the password
The application deployment does not include the password
The password can be reset very easily, for instance on a schedule
There is no way to deploy a password on a user workstation w/o a local administrator being able to discover it. You can only raise the bar so high, but if the price is worth it they will find it.
You should rely on the user providing the password, which ultimately boils down to using Windows authentication instead, if possible. You should always assume that whatever privileges the application has, the user has them as well and he/she can exercise them using an alternative access API (ie. any query tool). If you cannot trust the user with certain privileges, then you must not deploy the application on his/her computer. For example use a multi-tier solution that isolates the database from the user and add any necessary validation in this intermediate tier (most ASP.Net and/or WCF apps would qualify as such multi-tier when done properly).

SQL Server Integrated Security

I've been searching hard to get my head around security related issues in a SQL Server.
We're developing a .NET application that targets SQL Server 2008 and we want to use FileStream.
Now I've found out that SQL Server only allows FileStream through the Win32 API if you use Integrated Security. The problem is that we have around 80% of our application finished, but it is entirely based on SQL Authentication. So we are doing INSERT's straight form our application and are not using Stored Procedures for every CRUD operation.
This is relatively safe because I can store the the SQL username and password in an encrypted form. I know the password is transported in Clear Text, but I'm willing to accept that.
We want end-users to be able to connect to the databse through tools such as Crystal Reports and for that we have an extra SQL login that has only SELECT-rights granted.
Now, if we change to Integrated Security we would have to give individual users (via AD groups, etc.) rights to do the things the application can do. Otherwise the application would not be able to do it's work. But then the end-user would also have these rights when he connects straight to the DB.
I see people saying that you should use Stored Procedures for every CRUD operation and grant the EXEC-rights only to the AD-group, but how would I do this? I do not see how a user would have different authorizations when he connects directly or through the application... Can anybody enlighten me on this.
An extra question for bonus-points: Intergrated Security will not work on a Workgroup as far as I understand. How do people get FileStream to work in a Workgroup then? Or is this considered an impossibility?
Integrated security WILL work in a workgroup, using the legacy mechanism, where you have a matching username and password on the two machines. Also, a domain user can use the legacy mechanism to log into a non-domain server if the server has a matching user account.
Integrated security can even work with non-matching usernames and passwords. This may help you in your scenario.
Try this:
NET USE \\DBSERVER /USER:DOMAIN\USERNAME
You will be prompted for your password. This establishes a NetBIOS session with the database server. You should be able to see the shared folders and shared printers on the database server once you have done that.
Once a netbios session has been established between the client computer and the database server, you will THEN be able to use integrated security without being prompted for a password.
You may have to specify "named pipes" as the network protocol to usem, if it doesn't work with TCP (but I think it will). Named Pipes inherits your existing NetBIOS session, so provided you can list the shares you are probably good to go.
You can also establish the logon session using the windows API function NetUseAdd with USE_INFO_2 (level 2) information which incorporates the password.
I guess the short answer then is that you can have a special Windows logon for your application and have the users log in using that. However note that they cannot also be connected to the same server using their own username and password.

SQL Server Windows Authentication Security

We have an application that uses Windows authentication to authenticate users with the database, and the SQL Server user accounts need to have certain read/write access to database tables.
The trouble is that the users can then install SQL Server Management Studio and potentially use the database in ways it's not supposed to be used, which isn't what I want.
Everything that I have read says that using integrated authentication is more secure but at the moment, any user can use Management Studio or Access/Excel to just connect to the database.
I have read question SQL Server Authentication or Integrated Security?, which suggests some workarounds, but I don't really have the option of changing the app as drastically as re-factoring all of the stored procedures etc. so I was hoping there might be another option?
Thank you,
NIco
Everything that I have read says that
using integrated authentication is
more secure
--> It's more secure in a way because it's more difficult to get the password.
If you use SQL Server authentication, the connection string contains user and password. If you know where the connection string is (often in a config file), you can open it and see user and password.
On the other hand, if you use Windows authentication, the connection string just says "Integrated Security=True" and you connect to the server with your Windows account, with the actual password buried somewhere deep in Windows' guts and more difficult to retrieve.
Of course, the big downside of Windows authentication is that if your users need write permissions on a certain table for your application, this means that they can write to the same table with ANY other application as well.
There are some workarounds, but none of them is THE silver bullet:
If your app only needs certain tables of the DB, you can just give permissions on these. So at least, the users can't do stuff in all the other tables
If the users are not allowed to access any tables at all from outside your application, there are unfortunately only two things you can do:
Change your app to SQL authentication and remove all permissions for Windows users
(you can also use a proxy service like Will Hughes suggested, but the effect is the same when the app accesses the DB directly...the point is that your users' Windows accounts don't have any permissions anymore!)
Create views and stored procedures (if they don't already exist anyway) for the stuff your app can do with the database. Give the users permissions to use these, and remove the permissions to the real tables.
--> the users can access the views and SPs directly with other tools (even if they don't have any permissions on the underlying tables...permissions on the views and SPs are enough), but they can't do anything that they can't do in your app as well.
If you don't want users to have access to your database, don't grant them access.
If you need to control what they can do - then you should do your access control in a webservice (or some other form of proxy service), which will then execute approved queries, return data, etc.

Secure SQL Server accessed by fat client

Is there a way to secure a sql server database which is accessed by a fat client? Meaning: The application communicates directly with the database as it places sql statements itself. That means, the connection string has to be somewhere on the client. Using this connection string (either with winauth or sql server authentication) any user can access the db using some management studio or command line and place different statements to the db than the GUI would let him.
What to do about that? I cannot place another layer between the client and the database as this architecture is fix.
In all security models, including Windows and SQL Authentication, access rights are granted to an user (an identity), not to an application. therefore, any access right needed by the application must be granted to the user running the application. When Windows authentication is used this means that the same user can leverage all the privileges needed by the application himself, from an SSMS query. This is a fundamental rule any administrator must understand. From a security point of view (meaning things like CC compliance and such) this is a fact and any attempt to circumvent it is doomed.
But from a practical point of view, there are certain measures that can be deployed. The most commonly used one is to use a logon trigger that validates the APP_NAME() and allows access for SSMS only from a well defined set of client workstations, and for a well defined set of users.
CREATE TRIGGER reject_SSMS
ON ALL SERVER WITH EXECUTE AS '...'
FOR LOGON
AS
BEGIN
IF (APP_NAME() = 'Microsoft SQL Server Management Studio'
OR APP_NAME() = 'Microsoft SQL Server Management Studio - Query')
AND (ORIGINAL_LOGIN() NOT IN (...)
OR HOST_NAME() NOT IN (...))
ROLLBACK;
END;
What is important to understand that such mechanisms are NOT security features, as they can be easily circumvented by a malevolent user. They are more like door locks: they don't keep thieves out, they keep honest users honest.
That is what SQL Server permissions are for.
You can do things like give permissions to a user on a View or Stored Procedure without giving the user permissions to the underlying tables.
You might want to look into Application Roles
http://msdn.microsoft.com/en-us/library/ms190998.aspx
http://www.sqlservercentral.com/articles/Security/sqlserversecurityprosandconsofapplicationroles/1116/
First and foremost the whole point of a SQL Injection vulnerability is that the attacker is able to manipulate queries. This purposed protocol is an even worse vulnerability. But not only that this is also a clear violation of CWE-602: Client-Side Enforcement of Server-Side Security and CWE-603: Use of Client-Side Authentication.
In order to make this secure you must do the following:
Each user must also have their own locked down database. As in they only have select/update/delete/insert and no other privileges (especially not xp_cmdshell()!!!!). You cannot allow users share a database, or an attacker will be able to view other users information. An attacker will always be able to obtain the username/password for the sql server and be able to connect directly with his own client. Its hard to think of this relationship as being secure, in almost all cases this is massive vulnerability.
In all reality this is a very serious architectural flaw and you must build a server side component that builds quires for the client. This is usually done with SOAP (wcf for ms platforms).

What's the point of creating a user in order to access the DB located at SQL Server 2008

So far, after creating DB with all the schema, all I have done so for was accessing them (tables) by reference through ConnectionStrings.
Now, twice, I've read that it's better to create a DB user and access the DB trhough that user by including him in the connectionString.
I'd like to know why so?
Thank for helping
Your question isn't that clear. It seems that you're asking if it is better to use windows security ("Integrated Security=SSPI" in the connection string) or a username/password ("User ID=myUsername;Password=myPassword;").
Its always better to use windows security. Having login information within the connection string is a security risk. Its in cleartext (unless you take some complicated steps to secure that section), and is sent across the wire as cleartext unless you set up a trusted connection between application and server.
Is it better to "create a db user and access the db trhough that user by including him in the connection string?" No. Its better to create a sql server login for user's windows identities and let them use those credentials to access the server.
You do this if you wish to connect as a specific user, rather than (for example) just using the context of the current user which your application is running under. However, if you use SQL Server authentication (i.e. username and password), you'd need to provide that password in the connection string, which is something of a security problem.
If the application has a group of anonymous users (or manages users/passwords itself) then its better to use a Windows login and run the application under a service account (which has minimal required access to the database).
If you're running an interactive application on the desktop, you should let those users connect to SQL server in their own context, by adding them to SQL Server with the required rights (e.g. db read/write , remove any higher functions). Obviously you would use groups to make administration simpler rather than adding individual users.

Resources