SQL Server permission types - sql-server

My team has recently moved into a more formalized system of SQL Server database auditing and deployment controls, and as a result several permissions have been restricted.
Many of us are not familiar with SQL Server security, and have encountered scenarios where we deploy something only to have a permissions restriction on, say, TRUNCATE TABLE denied in production.
It's just an annoyance at this stage, but I've tried to find some consolidated list (cheatsheet? cribsheet? reference lookup?) to easily check against for such functions so that it doesn't happen so easily, but I haven't found any.
I know that the MSN article for each function lists these, but I don't want to have to individually browse to the specific website for every common and rare function just to check, especially if I have to do it more than once because I forgot (for example).
The closest I found were sites like these:
https://www.mssqltips.com/sqlservertip/1718/database-level-permissions-for-sql-server-2005-and-2008/
https://www.simple-talk.com/sql/database-administration/sql-server-security-cribsheet/
...but they were incomplete (couldn't find TRUNCATE in both of them) and a little long: I'm hoping there's a table somewhere that simply put 'action -> action name -> permission name -> server/table level -> default role' or something together in one place.
Is there such a list somewhere?

Unfortunately I am not aware of any document that shows every action possible in SQL Server with the permissions required for it. Such a table would be impractical as there are a huge amount of possible actions, and some actions require multiple permissions, including scenarios where the permission requirements would change according to sub-portions of the action.
For the scenario you are trying to solve, it seems like you are using modules (SPs) to clearly define the actions allowed to the non-admin users, correct? In that case, you may be able to use digitally signed modules to grant the appropriate permissions when executing the SP instead of assigning the permission directly. For example:
CREATE USER [low_priv_user] WITHOUT LOGIN
go
CREATE TABLE [dbo].[myTable](data int);
go
CREATE PROC [dbo].[sp_truncate_my_table]
AS
TRUNCATE TABLE [dbo].[sp_truncate_my_table];
go
GRANT EXECUTE ON [dbo].[sp_truncate_my_table] TO [low_priv_user]
go
-- Will fail due to permission
EXECUTE ( 'EXEC [dbo].[sp_truncate_my_table];' )AS USER = 'low_priv_user';
go
-- Create a certificate to sign the SP,
CREATE CERTIFICATE [signing_cert]
ENCRYPTION BY PASSWORD = '<you_could_use_masetr_key_instead_of_p#55w0rD5>'
WITH SUBJECT = 'demo - module signature';
go
-- sign the SP
ADD SIGNATURE TO [dbo].[sp_truncate_my_table] BY CERTIFICATE [signing_cert]
WITH PASSWORD = '<you_could_use_masetr_key_instead_of_p#55w0rD5>';
go
-- destroy the private key
ALTER CERTIFICATE [signing_cert] REMOVE PRIVATE KEY;
go
-- Create a user for the certificate & grant it all the permissions you would need for running teh SP
CREATE USER [signing_cert] FROM CERTIFICATE [signing_cert];
go
GRANT ALTER ON [myTable] TO [signing_cert];
go
-- Permission check will be OK for the low privileged user
-- You control what this user is allowed to do via SPs
EXECUTE ( 'EXEC [dbo].[sp_truncate_my_table];' )AS USER = 'low_priv_user';
go
As you can see, I created a module that allows the caller to call TRUNCATE on a table, without granting ALTER permission directly to the user.
Ideally, when using this mechanism you would like to follow the least-privilege principle, and grant only the permissions you require and nothing else; but if you are having trouble finding the exact permissions you need, you may use a shortcut: GRANT CONTROL TO [signing_cert].
Obviously such shortcut has significant security implications, as you are literally granting full control of your database to the signed code (including dynamic SQL executed within these modules), but if you decide to do it, I would recommend the following precautions:
Destroy the private key to prevent anyone from abusing it
Do not use dynamic SQL within your signed modules (or at least make sure you are not subject to SQL injection)
If possible, avoid giving CONTROL permission on modules where you can grant the minimum privileges.
Audit all activity on your database.
I am also including a copy of the SQL Database Engine Permission Poster link, which may be useful.
I hope this information helps.

Related

SQL Server roles and permissions

I really need some advice about adding roles at the server level and apply some permissions that will be applicable to each database on my server.
Basically I need to two roles read only and read write.
The read will have permissions to select and see any object
The write will have permissions to select/insert/delete and execute any object
I want to create a server role, then a login associated to this role (which can be a AD group) and after that for each database create a user that will inherits all permissions from the server role.
So on each database, I will have each user that belongs to the server role created, the problem is to clearly define the permissions, is not straight forward in my opinion.
What I can see, I cannot assign read or write to a role and then use it on each db, on the contrary on the General tab of the server role I have a bunch of permissions that is not clear which one to use for this purpose.
Maybe I'm doing it wrong but I want to have something at the server level and not define the same role on each db for that purpose. I'm using SQL server 2014.
The short answer is you can't.
Generally, server-level permissions are not propagated down to individual objects within databases. The only exception is a sysadmin role, which I would strongly encourage you not to use for this purpose, as you would essentially give up the control of the entire server instance to every member of it.
As a kind of a shorthand, you can use built-in database roles to save yourself a bit of trouble. For read-only access, a membership in db_datareader role is usually enough, unless you have stored procedures that return datasets which this role is supposed to be able to execute. There is also a similar role for modification, db_datawriter, but it doesn't cover the execute permission. So you will have to create a custom role for that:
create role [DataChanger] authorization [dbo];
go
alter role [db_datareader] add member [DataChanger];
go
alter role [db_datawriter] add member [DataChanger];
go
grant execute to [DataChanger];
go
-- Now you can add your members. Here is a reader
create user [Domain\MyUser1] from login [Domain\MyUser1];
go
alter role [db_datareader] add member [Domain\MyUser1];
go
-- Writer
create user [Domain\MyUser2] from login [Domain\MyUser2];
go
alter role [DataChanger] add member [Domain\MyUser2];
go
These permissions will automatically pick up newly created objects, without you having to explicitly add new permissions after every schema modification.
You will have to do this in the context of every user database that you want to manage in this way. You can probably create a SQL Agent job which will run periodically and introduce these changes in any user databases which don't have them already (for example, if a database has been restored from earlier backup, or brought from another server, or a new one was created). Also, since you can't loop through databases in static code, you will need to wrap it into a dynamic SQL and loop through sys.databases, or maybe via an undocumented sp_MSforeachdb system stored procedure. Oh, and don't forget to remove all these go statements from dynamic code, as they are not part of SQL, and are only recognised by SSMS and sqlcmd.
P.S. All that being said, I hope you are not going to manage any production databases in this manner. I don't even know where to start on how insecure this approach is.

SQL Public role audit findings

Our SQL auditors have issues with the Public role being able to query master.sys.syslogins, master.sys.databases, master.sys.configurations from a specific database. Has anyone had to remove these rights to the Public role and does this cause any issues? Thanks all.
This is unfortunately a common false positive when using DB vulnerability scanning tools, and unfortunately there are no absolute answers. It will depend on your particular scenario & auditors to determine if such findings are indeed something you need to change, or accept it as operational risks.
For the most part, I have been able to argue that these permissions are acceptable, especially since the typical best-practice recommendation is to not modify the default permissions granted to public role.
The default permissions granted to public on SQL Server are intended to make tools & some features in SQL Server work, and typically there will be mitigating factors around these permissions.
In the particular case of catalog view access, it is not only governed by having select permission to the catalog view itself, but also by metadata visibility rules. For details Please visit Metadata Visibility Configuration (https://msdn.microsoft.com/en-us/library/ms187113.aspx) on BOL; I especially recommend reading the "Benefits and Limits of Metadata Visibility Configuration" section.
For example, a low-privileged user in the system will have different visibility on sys.server_principals (master.sys.syslogins is deprecated) that a user with sysadmin access:
CREATE LOGIN [test00] WITH PASSWORD = '<s3cr3t P#zzw0Rd>';
ALTER LOGIN [test00] DISABLE;
CREATE LOGIN [test01] WITH PASSWORD = '<s3cr3t P#zzw0Rd>';
ALTER LOGIN [test01] DISABLE;
CREATE SERVER ROLE [srvrole00];
go
ALTER SERVER ROLE [srvrole00] ADD MEMBER [test00]
go
SELECT * FROM sys.server_principals -- Can see all server principals
EXECUTE ('SELECT * FROM sys.server_principals') AS LOGIN = 'test00' -- besides the system principals, can see only himself & the server role he is a member of
EXECUTE ('SELECT * FROM sys.server_principals') AS LOGIN = 'test01' -- besides the system principals, can see only himself
go
You will notice on the results that the 3 principals have a different view of the metadata.
If your SQL auditors think any of these permissions is not acceptable for any reason, you may revoke the permission as they deems as necessary, but the cave-at is that such actions are likely to limit (or in some cases completely break) functionality of SQL server and/or tools. I would strongly recommend looking at what operations they are trying to block/prevent, and act accordingly.
For example. For access to DB metadata, there is one special permission granted by default to public: VIEW ANY DATABASE. This permission was introduced to allow users using SSMS & similar tools to navigate to different databases.
Revoking this permission will affect how some tools work in order to allow you to switch between databases, but it doesn't change the access to the DB; therefore it may be an acceptable trade-off if your users do not need such functionality and you want to prevent users from looking at all the DB metadata.
I hope this information helps. Please feel free to follow up with any question. I will be glad to help.
-Raul
None of our general users even have public access to the Master database, and likely shouldn't in most environments. Only DBAs really need access to the Master database generally. As long as you only grant the public role on the Master database to logins that have any business being in it... then it's really not necessary to remove the public role from any objects in there. If you remove the public role access to those objects, then only system administrators will be able to query them.

Service broker - Cross-database SELECTs to insert into local DB?

I'm using Remus' article http://rusanu.com/2006/03/07/call-a-procedure-in-another-database-from-an-activated-procedure/ as a guide.
What I'm trying to do:
I have a Activated Stored Procedure that (within the Activated SP) calls 2 different stored procedures. One of those stored procedures needs to access tables in another database to lookup some data, after which it writes the record locally with the extra info. Since I'm crossing databases, my options are
"trustworthy" (pass, thanks)
"replicate lookup tables to the same database service broker is in"
"get certificates working" (this approach)
So I did the following, but it's still failing with "lock time out exceeded" and "not able to access database... under the current security context.
In the database service broker is running in:
USE database_with_service_broker_and_queue
GO
CREATE CERTIFICATE mysp_Auditing ENCRYPTION
BY PASSWORD = '123457'
with subject = 'god_i_hope_this_works'
ADD SIGNATURE TO OBJECT::myschema.mystoredprocedure
BY CERTIFICATE mysp_Auditing
WITH PASSWORD = '123457'
ALTER CERTIFICATE mysp_Auditing REMOVE PRIVATE KEY
BACKUP CERTIFICATE mysp_Auditing to file = 'c:\mysp_auditing.CER'
Now in the database with the additional tables:
USE db_with_tables_I_need
GO
CREATE CERTIFICATE mysp_Auditing from file = 'c:\mysp_auditing.CER'
CREATE USER mysp_Auditing FROM CERTIFICATE mysp_Auditing
GRANT AUTHENTICATE to mysp_Auditing
GRANT SELECT ON TABLE1 to mysp_Auditing
GRANT SELECT on TABLE2 to mysp_Auditing
I then ENABLE the queue and watch alllll the error messages scroll by. I even tried changing the stored procedure to add EXECUTE AS OWNER, but still doesn't work.
Any help appreciated.
too long to post as comment
not able to access database... under the current security context.
This means the certificate business is not set up correct (I don't blame you, is ungodly hard to pull it off on first try). I would look at these:
make sure 'dbo' is a valid user. Try running EXECUTE AS USER='dbo'; on both DBs involved. If one fails (it means the DB was created by a Windows SID that is no longer valid) run ALTER AUTHORIZATION ON DATABASE:<dbname> TO sa.
make sure you do not change the procedure after you sign it. Any ALTER will silently drop the signature and invalidate your trust chain.
add EXECUTE AS OWNER
The procedure must have an EXECUTE AS clause, but it should not matter much what it is, as long as there is one. You are granting the SELECT permission to the certificate (hence to the signature) so it should work no matter who the procedure impersonates.
For debugging, I recommend you do it by simply running the stored proc manually, from SSMS query window:
USE myactivateddb;
GO
EXECUTE AS USER='dbo'; -- does not matter who, is important to be AS USER
GO
EXEC myotherdb.dbo.myotherproc ...;
GO
REVERT;
GO
This is easier to debug that trying to do it from activated procedure. If this works, then try the same but instead of executing the other DB stored proc, execute the activated procedure from the SSMS query window (w/o truning on activation on the queue).
Looks like metadata lock. If you do any DDL in your activation procedure, like creating an index or manipulating columns, you can expect lock timeouts if multiple instances of activation procedure are in service. Remember that activation procedure is typically a long running transaction, and if it takes a lock on any object, it keeps it locked until the end of transaction.

set user's default database/schema in Sybase IQ

i googled it and find nothing. Short story, i created a user and granted to a table in my SyBase. but when i try
select * from table1
it didn't work. Error show Permission denied: you don't have permission to select from "table1" and i try add dbname before table name like this and it works :
select * from dbname.table1
i suspect that user default database is something else so i want to set dbname to his default database. Anyone know how to do this?
This has nothing to do with database names (or login policies). Given your comment that "dbname" is actually the user who owns the table, here's what's happening.
When you specify a table name without an owner, the server has to figure out which table you mean. It first looks for a table that you own with that name. If it doesn't find one, it looks for tables owned by any groups that you are a member of. I suspect that one of these groups has a table named "table1" that you do not have permission to select from.
When you specify a table name with an owner, the server knows exactly which table to use. Since you do have permission to select from that table, you get the results you want.
IQ doesn't have default databases/schemas. Instead it uses login policies. Each database has a login policy assigned to it, which can be altered. You can also create custom login policies.
When you create a user account with out specifying a login policy, it automatically gets the root login policy.
For more information, check the following SAP Sybase IQ docs:
Intro to IQ: Managing Users and Groups
System Admin Guide V1: Managing User IDs and Permissions
Using a view or procedure is a useful method. That said, to establish a "default" schema in (IQ 15.x) one would use groups. Essentially, one grants group to the schema owner and makes the individual login accounts (or other groups) members of that group. Note that this only gives the user access to the schema--that is, it eliminates the need to preface the object with the schema/owner name (unless there are object name conflicts only resolvable with explicit schema.object naming). This does not include a grant of permissions. None of the implicit table-owner related privileges will inherit. However, as the schema/owner is now also a group, permissions could be granted at that level.
See: http://infocenter.sybase.com/help/topic/com.sybase.infocenter.dc00170.1540/doc/html/san1288042708174.html (Managing User ID's and permissions). Be warned: this material generally requires some close reading and experimentation before it becomes useful.
As I understand it, this method is complementary to (functionally replaced by) the new role-based model in IQ 16. However, as I am still feeling my through IQ 16, there is probably a great deal more to be said, and I am not ready to comment just yet.

Is it possible to use SqlBulkCopy in SQL 2008 without permission 'db_datawriter'?

I want to limit my database possible access ways to only using stored procedures. Everything works fine except System.Data.SqlClient.SqlBulkCopy. I'm using it only in one class for massive data import.
Is it possible to avoid this problem?
I tried to grant a right before calling SqlBulkCopy and remove it after:
EXEC [db_mod].[sys].[sp_addrolemember] N'db_datawriter', N'my_user'
EXEC [db_mod].[sys].[sp_droprolemember] N'db_datawriter', N'my_user'
but such approach raises an error:
User does not have permission to
perform this action.
I'm executing it under the same user. How can I allow what I need?
The error described, following an attempt at sp_addrolemember(), is related to the current user not having the necessary privileges to alter account and security settings.
With regards to running SqlBulkCopy, it requires write privileges, and the db_datawriter role is a convenient way to provide these, but maybe you can consider alternatives. For example, rather than increasing (if only temporarilly) the security privileges of the current account, you can modify the security settings associated with this particular database/tables.
Changing the security settings of "securables" such as database objects, also requires some administrative privileges, but these may be associated with the database ownership, and hence may be available to you even though the privileges of changing an account are not.

Resources