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).
Related
I want to create a publication task in Jenkins to automatically publish my database changes along with my application.
If I understood correctly, a common practice is to create a publish profile that includes the database name as well as the account (login and password) of the account used for the deployment.
This means that the deployment account username and password will be stored in clear text on each developer computer as well as on the version control server and the continuous integration server.
Even though I created a specific login and password for the deployment, it seems pretty unsecured to me.
Is there a workaround? I can only think of replacing the password within the msbuild command line on the continuous integration server.
tl;dr version
Windows Authentication is the preferred, secure method of connecting to your SQL Server instance and if it's possible to use that then it's recommended to use that for connections.
If SQL Authentication is used then the default in publish profiles is that the password isn't saved. For build servers and other shared profile scenarios you may need to accept lower levels of security (by editing the publish profile to add the password, or setting it as a parameter in the build configuration) or work around it in some other way (custom script that reads it from some kind of a secret store, such as an encrypted value).
Long version
Windows Authentication: If at all possible use Windows Authentication, giving permissions as required to users who need it. For Continuous Integration scenarios you would need to give appropriate permissions to the account the build server executes under - full details are in the recent whitepaper on the SSDT blog.
SQL Authentication: If you look at the publish profile (Open With... Xml Editor) you'll see that the password information isn't actually stored there.
If you choose "Save Password" you'll have "Persist Security Info=True;" stored in the connection string rather than the password itself.
When a connection is made to a server/database in SSDT with "Save Password" enabled, the connection info is encrypted and stored in the registry under "HKEY_CURRENT_USER\Software\Microsoft\SSDT\ConnectionStrings". This has to be present on the machine in order to successfully publish using the publish profile.
Hence in a team environment every user would need to connect at least once before that publish profile would work for them. However, the password would be safely encrypted on user machines.
For the build server, your options are more limited. One possibility is to manually log in as the build server user and then connect to the database, but this isn't very scalable. To avoid the less secure options you mentioned you'd need to implement your own logic for persisting the password securely. You can look at the Protected Data API which can be used to do something similar to what SSDT does but on a per-machine level, or use an encrypted configuration file.
If you have to use SQL Authentication I think passing the password into the publish action as part of the build configuration may be the "best" way to go in terms of a tradeoff between ease of development and security. At least that way you can restrict who can view and edit the build configuration in TFS and regular developers won't see it.
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.
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.
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.
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.