How GRANT EXECUTE and cross-database reference works in SQL Server? - sql

I've got 2 databases, let's call them Database1 and Database2, a user with very limited permissions, let's call it User1, and a stored procedure in Database1, let's call it Proc1.
I grant EXECUTE permission to User1 on Proc1; GRANT EXECUTE ON [dbo].[Proc1] TO [User1] and things worked fine as long as all the referenced tables (for SELECT, UPDATE ... etc.) are in Database1, although User1 does not have explicit permission on those tables.
I modified Proc1 to SELECT from a table, let's call it Table1, in Database2. Now when I execute Proc1 I get the following error: The SELECT permission was denied on the object 'Table1', database 'Database2', schema 'dbo'
My understanding is that SQL Server will take care of the required permissions when I grant EXECUTE to a stored procedure; does that work differently when the table (or object) is in another database?
Notes:
User1 is a user in both databases with same limited permissions
I'm using SQL Server 2005

There seem to be a difference when SQL Server checks the permissions along the permission chain. Specifically:
SQL Server can be configured to allow ownership chaining between specific databases or across all databases inside a single instance of SQL Server. Cross-database ownership chaining is disabled by default, and should not be enabled unless it is specifically required.
(Source: http://msdn.microsoft.com/en-us/library/ms188676.aspx)

Late to the party, but I recommend taking a look at signed stored procedures for this scenario. They are much more secure than granting users permissions to multiple databases or turning on database ownership chaining.
... To make it possible for a user to run this procedure without
SELECT permission on testtbl, you need to take these four steps:
1.Create a certificate.
2.Create a user associated with that certificate.
3.Grant that user SELECT rights on testtbl.
4.Sign the procedure with the certificate, each time you have changed the procedure.
When the procedure is invoked, the rights of the certificate user are
added to the rights of the actual user. ...
(From http://www.sommarskog.se/grantperm.html#Certificates)
Further documentation is also available on MSDN.

Be sure that the user is actually the same in both databases. Not just NAMED the same. Try deleting the user from both databases, then create the user under the SERVER users, and assign the appropriate permissions on each database from that single user account.

To expand on #Szymon's answer with updated text from Microsoft at the end of 2018:
Ownership chaining across databases is turned off by default. Microsoft recommends that you disable cross-database ownership chaining because it exposes you to the following security risks:
Database owners and members of the db_ddladmin or the db_owners database roles can create objects that are owned by other users. These objects can potentially target objects in other databases. This means that if you enable cross-database ownership chaining, you must fully trust these users with data in all databases.
Users with CREATE DATABASE permission can create new databases and attach existing databases. If cross-database ownership chaining is enabled, these users can access objects in other databases that they might not have privileges in from the newly created or attached databases that they create.
There is also mention about dynamic SQL and certificate signing for procedures like #Rozwel mentions in their answer.
(Source: https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/enabling-cross-database-access-in-sql-server)

Related

Granting a user access to all databases in Postgres cluster

I have only seen examples of SQL statements granting users access to one database in a Postgres cluster at a time. Is there a way to grant a non-superuser access to all databases and their tables including future databases that get created in the cluster?
Since PostgreSQL v14, this is fairly easy, and you can use the following SQL script:
-- exempt the user from row level security
ALTER ROLE seeall BYPASSRLS;
-- allow the user to read all data
GRANT read_all_data TO seeall;
If you want write access as well, there is also a predefined role pg_write_all_data.
This relies on the fact that by default, everybody has the CONNECT privilege on databases. Of course you also have to configure pg_hba.conf to allow access.
And in case you wonder: no, before v14 you have to grant access to all objects individually. Group roles help with that.

SQL Server scripting permissions for my database

I am deploying a web application, this is not a production application but it's important to me none the less. I am deploying it via dacpac and I would like to script out the creation of a login / user account with sql server authentication.
At minimum this users will need access to read, write, update, and delete on all of the database tables, these tables are separated into different schema's. The user will also need access to execute all stored procedures and functions in my database.
How would i script this out? What permissions do I give to the user?
This is what i got so far, I actually have no database tables in the dbo schema, but since this was the default for sql server i figured it might make sense to leave it the default for the user, but i would like to finish this script giving explicit access to all tables in a given schema with all of the permissions i listed, as well as permission to sprocs and functions.
CREATE LOGIN [webProcessLogin] WITH PASSWORD = 'Pa$$word';
CREATE USER webProcessUser FOR LOGIN
[webProcessLogin]
WITH DEFAULT_SCHEMA=[dbo];
GRANT CONNECT TO [webProcessUser]

Does GRANT EXECUTE to a stored procedure give you permission to access all objects inside it?

I have a procedure which selects data from a table in another database and also uses sp_send_dbmail. It seems execute permission is denied on cross database calls inside the procedure.
Can someone confirm that I need separate permissions on these cross database objects too or is there any way to grant execute permission so it can access anything under that proc?
This is the SQL statement for granting execute permission:
GRANT EXECUTE ON OBJECT::uspAppStoredProcedure TO AppRole;
This is the error I got:
The EXECUTE permission was denied on the object 'sp_send_dbmail',
database 'msdb', schema 'dbo'.
I got a similar error for trying to select data from another database.
This behavior is controlled by the cross db ownership chaining option in SQL Server, which is disabled by default.
uspAppStoredProcedure is attempting to execute a stored procedure outside of its ownership chain, so it would need explicit permission granted to execute the sp_send_dbmail.
It would be possible to enable ownership chaining on the databases involved, which would remove the need for granting specific permissions, but doing so would present a security risk... so it would likely be better to grant explicit access as needed.
This article goes into additional details on cross database ownership chaining.
Another potential solution would be to make use of the EXECUTE AS clause when defining the stored procedure, which would allow you to execute under the context of a different user as described in this article.
This would allow you to create a stored procedure that would allow specific users to execute it while avoiding having to grant permissions to the underlying objects directly to the users.

sql 2005 - strategy for restricting access via stored procedures only

I want to give access to certain data, in various databases on a single sql instance, to our parent company. They don't want a web service but instead want a stored procedure, which would compile data from different data sources and return a record set.
There is a trust between our two domains so essentially they are on our domain and I will just give the required permissions to sql objects (stored procedures)
I plan to create an 'integration' database which would have the required stored procedures.
While the integration database will have no tables itself, at least for now, I do want to lock the database down so that there are no holes such as the parent company being able to create tables on database or affect permissions etc.
What is the recommended approach to lock my 'integration' database down such that the parent company only has access to run the stored procedures I explicity give permissions to.
As a sql DBA I make a good .net programmer ie from what I understand it will require the user of commands such as GRANT EXECUTE ON [procedure] TO [user] to grant permissions on selected stored procedures, but beyond this I am not sure of a clear strategy to achieve what I need.
I want to make sure I don't leave holes in the security.
If anyone can advise the steps I need to take, ie what commands I need to run to achieve what I want, or point me to a good article I would appreciate it.
I have already run the command REVOKE CONNECT FROM GUEST on the database.
What is the recommended approach to lock my 'integration' database down such that the parent company only has access to run the stored procedures I explicitly give permissions to.
Create a role specifically for the users from the parent company
Only grant EXECUTE to the role for the specific store procedure(s)
Grant the role the db_datareader role -- that will make sure they can't create tables, etc.

Cross-database permissions problem

Can anyone help me with this problem please?
I have 2 databases on the same server, both owned by sa. A Windows login has permission to execute a stored proc in database A that selects data from a table database B. The stored proc and table are also both owned by dbo. The Windows login is a member of a Windows domain group that is a member of a database role in database A that has the permission to execute the stored proc, but it has not been granted or denied any permissions on database B directly. The login is able to execute stored procs in database A that use database A and other procs that access other databases that the login has permissions to already but when it attempts to execute this stored proc it generates the error "The server principal "" is not able to access the database "B" under the current security context." Cross database ownership chaining is enabled at the server level but the two databases have is_db_chaining_on = 0 in sys.databases.
Is it as simple as you have to enable cross-database ownership chaining at both the server and database level?
From memory if you enable cross-database chaining at the server level it is available for all databases, you do not have to specifically set it on the database level.
How did you set chaining on? For some system settings a restart is required, or you can run the RECONFIGURE command in a query window.
http://msdn.microsoft.com/en-us/library/ms176069(SQL.90).aspx