SQL 服务器权限链
SQL Server Permission Chaining
我有以下问题:
我有两个不同的数据库,db1 和 db2。我有一个将数据加载到 db2 或 db3 中的应用程序。 db1 有几个表,应用程序使用这些表来确定行为,包括应用程序应将数据加载到哪个数据库。
用户需要对 db1 具有写入权限才能操作该应用程序(有一个控制台应用程序写入 db1 中的表,使用 windows 身份验证进行操作)。
除了一些预先确定的操作外,用户不应该拥有对 db2 和 db3 的 DML 权限。我们授予 AD 组数据库角色以从组织角度控制访问。具体来说,我正在尝试在 db1 中构建一个存储过程,操作员可以使用该存储过程通过适当的日志记录来反转加载到 db2 或 db3 的数据。
我正在尝试使用 create proc ... execute as owner 来完成此操作,但是当我尝试访问 db2/db3 中的表时它似乎不起作用(我认为“以所有者身份执行”在数据库级用户而不是服务器级登录上运行?)。以下导致权限错误,指出所有者(我自己)没有 db2/db3.
的权限
use db1
go
create proc dbo.wrapper @recordid int
as begin
/*
capturing user
*/
declare @usr varchar(255) = SUSER_SNAME()
exec dbo.inner @usr , @recordid
end
use db1
go
create proc dbo.inner @usr varchar(255), @recordid int
with execute as owner
as begin
/*
logic to determine whether to update db2 or db3 goes here
*/
insert db2.rolled_back
select * , @usr from db2.transactions where id = @recordid
delete from db2.transactions where id = @recordid
insert db3.rolled_back
select * , @usr from db3.transactions where id = @recordid
delete from db3.transactions where id = @recordid
end
有没有办法让它工作?我听说证书签名可以做到这一点,有没有人有使用证书用户的经验。我们的 DBA 宁愿不必维护证书,所以如果有一种方法可以在没有证书的情况下使它工作,那将是最好的。
任何建议都会有所帮助。
谢谢!
我将在这里介绍跨数据库链接方面的内容。请注意,使用此方法时肯定会有安全考虑。例如,有权在一个数据库中创建对象的人可以通过所有者访问另一个数据库中的数据,而他们自己对另一个数据库没有 no 访问权限。但是,安全问题超出了此答案的范围。
首先,让我们创建几个测试数据库。
USE master;
GO
CREATE DATABASE Chain1;
CREATE DATABASE Chain2;
现在我要CREATE
一个LOGIN
,它被禁用并成为这两个数据库的所有者。具有相同所有者的数据库很重要,否则链接将不起作用。
CREATE LOGIN ChainerOwner WITH PASSWORD = N'SomeSecurePassword123';
ALTER LOGIN ChainerOwner DISABLE;
GO
ALTER AUTHORIZATION ON DATABASE::Chain1 TO ChainerOwner;
ALTER AUTHORIZATION ON DATABASE::Chain2 TO ChainerOwner;
我还将创建一个 LOGIN
,我们将用它来测试:
CREATE LOGIN SomeUser WITH PASSWORD = N'SomeSecurePassword123';
太好了,现在我可以创建一些对象了; Chain1
中的 table,Chain2
中的 PROCEDURE
访问 TABLE
,两个数据库中的 USER
用于 SomeUser
.在 Chain1
中,USER
将被授予 无 权限,而在 Chain2
中,用户将被授予 EXECUTE
PROCEDURE
:
USE Chain1;
GO
CREATE TABLE dbo.SomeTable (I int IDENTITY,
S varchar(10));
INSERT INTO dbo.SomeTable (S)
VALUES ('abc'),
('xyz');
GO
CREATE USER SomeUser FOR LOGIN SomeUser;
GO
USE Chain2;
GO
CREATE PROC dbo.CrossDBProc @I int AS
BEGIN
SELECT I,
S
FROM Chain1.dbo.SomeTable
WHERE I = @I;
END;
GO
CREATE USER SomeUser FOR LOGIN SomeUser;
GO
GRANT EXECUTE ON dbo.CrossDBProc TO SomeUser;
GO
太好了,所有对象都已创建,现在让我们尝试 EXECUTE
PROCEDURE
:
EXECUTE AS LOGIN = 'SomeUser';
GO
EXEC dbo.CrossDBProc 1; --This fails
GO
REVERT;
GO
这失败了,出现权限错误:
The SELECT permission was denied on the object 'SomeTable', database 'Chain1', schema 'dbo'.
这是预料之中的,因为没有所有权链。让我们现在启用它。
USE master;
GO
ALTER DATABASE Chain1 SET DB_CHAINING ON;
ALTER DATABASE Chain2 SET DB_CHAINING ON;
现在,如果我再试一次,同样的 SQL 有效:
USE Chain2;
GO
EXECUTE AS LOGIN = 'SomeUser';
GO
EXEC dbo.CrossDBProc 1; --This now works
GO
REVERT;
GO
这样就成功了returns结果集
I
S
1
abc
所以,是的,您可以链接跨数据库,但它需要一些设置,并且(再次)有您需要考虑的安全注意事项。
清理:
USE master;
GO
DROP DATABASE Chain1;
DROP DATABASE Chain2;
GO
DROP LOGIN ChainerOwner;
DROP LOGIN SomeUser;
我有以下问题:
我有两个不同的数据库,db1 和 db2。我有一个将数据加载到 db2 或 db3 中的应用程序。 db1 有几个表,应用程序使用这些表来确定行为,包括应用程序应将数据加载到哪个数据库。
用户需要对 db1 具有写入权限才能操作该应用程序(有一个控制台应用程序写入 db1 中的表,使用 windows 身份验证进行操作)。
除了一些预先确定的操作外,用户不应该拥有对 db2 和 db3 的 DML 权限。我们授予 AD 组数据库角色以从组织角度控制访问。具体来说,我正在尝试在 db1 中构建一个存储过程,操作员可以使用该存储过程通过适当的日志记录来反转加载到 db2 或 db3 的数据。
我正在尝试使用 create proc ... execute as owner 来完成此操作,但是当我尝试访问 db2/db3 中的表时它似乎不起作用(我认为“以所有者身份执行”在数据库级用户而不是服务器级登录上运行?)。以下导致权限错误,指出所有者(我自己)没有 db2/db3.
的权限use db1
go
create proc dbo.wrapper @recordid int
as begin
/*
capturing user
*/
declare @usr varchar(255) = SUSER_SNAME()
exec dbo.inner @usr , @recordid
end
use db1
go
create proc dbo.inner @usr varchar(255), @recordid int
with execute as owner
as begin
/*
logic to determine whether to update db2 or db3 goes here
*/
insert db2.rolled_back
select * , @usr from db2.transactions where id = @recordid
delete from db2.transactions where id = @recordid
insert db3.rolled_back
select * , @usr from db3.transactions where id = @recordid
delete from db3.transactions where id = @recordid
end
有没有办法让它工作?我听说证书签名可以做到这一点,有没有人有使用证书用户的经验。我们的 DBA 宁愿不必维护证书,所以如果有一种方法可以在没有证书的情况下使它工作,那将是最好的。
任何建议都会有所帮助。
谢谢!
我将在这里介绍跨数据库链接方面的内容。请注意,使用此方法时肯定会有安全考虑。例如,有权在一个数据库中创建对象的人可以通过所有者访问另一个数据库中的数据,而他们自己对另一个数据库没有 no 访问权限。但是,安全问题超出了此答案的范围。
首先,让我们创建几个测试数据库。
USE master;
GO
CREATE DATABASE Chain1;
CREATE DATABASE Chain2;
现在我要CREATE
一个LOGIN
,它被禁用并成为这两个数据库的所有者。具有相同所有者的数据库很重要,否则链接将不起作用。
CREATE LOGIN ChainerOwner WITH PASSWORD = N'SomeSecurePassword123';
ALTER LOGIN ChainerOwner DISABLE;
GO
ALTER AUTHORIZATION ON DATABASE::Chain1 TO ChainerOwner;
ALTER AUTHORIZATION ON DATABASE::Chain2 TO ChainerOwner;
我还将创建一个 LOGIN
,我们将用它来测试:
CREATE LOGIN SomeUser WITH PASSWORD = N'SomeSecurePassword123';
太好了,现在我可以创建一些对象了; Chain1
中的 table,Chain2
中的 PROCEDURE
访问 TABLE
,两个数据库中的 USER
用于 SomeUser
.在 Chain1
中,USER
将被授予 无 权限,而在 Chain2
中,用户将被授予 EXECUTE
PROCEDURE
:
USE Chain1;
GO
CREATE TABLE dbo.SomeTable (I int IDENTITY,
S varchar(10));
INSERT INTO dbo.SomeTable (S)
VALUES ('abc'),
('xyz');
GO
CREATE USER SomeUser FOR LOGIN SomeUser;
GO
USE Chain2;
GO
CREATE PROC dbo.CrossDBProc @I int AS
BEGIN
SELECT I,
S
FROM Chain1.dbo.SomeTable
WHERE I = @I;
END;
GO
CREATE USER SomeUser FOR LOGIN SomeUser;
GO
GRANT EXECUTE ON dbo.CrossDBProc TO SomeUser;
GO
太好了,所有对象都已创建,现在让我们尝试 EXECUTE
PROCEDURE
:
EXECUTE AS LOGIN = 'SomeUser';
GO
EXEC dbo.CrossDBProc 1; --This fails
GO
REVERT;
GO
这失败了,出现权限错误:
The SELECT permission was denied on the object 'SomeTable', database 'Chain1', schema 'dbo'.
这是预料之中的,因为没有所有权链。让我们现在启用它。
USE master;
GO
ALTER DATABASE Chain1 SET DB_CHAINING ON;
ALTER DATABASE Chain2 SET DB_CHAINING ON;
现在,如果我再试一次,同样的 SQL 有效:
USE Chain2;
GO
EXECUTE AS LOGIN = 'SomeUser';
GO
EXEC dbo.CrossDBProc 1; --This now works
GO
REVERT;
GO
这样就成功了returns结果集
I | S |
---|---|
1 | abc |
所以,是的,您可以链接跨数据库,但它需要一些设置,并且(再次)有您需要考虑的安全注意事项。
清理:
USE master;
GO
DROP DATABASE Chain1;
DROP DATABASE Chain2;
GO
DROP LOGIN ChainerOwner;
DROP LOGIN SomeUser;