【问题标题】:Why can "exec as user" bypass permission checking in a proc?为什么“exec as user”可以绕过proc中的权限检查?
【发布时间】:2016-09-03 14:57:06
【问题描述】:

关于我看到但无法弄清楚的行为,我有一个非常具体的问题。我会用代码引导你完成这个问题。

使用系统管理员用户启动 SSMS:

1.创建一个新的测试数据库

create database test

2。创建一个新的登录名

create login newuser with password='newuser', check_policy=off

3.在测试数据库中创建一个用户并将其映射到登录名

create user newuser for login newuser

4.创建一个新表并对其进行测试

create table dbo.newtable (id int identity(1, 1)) insert dbo.newtable default values select * from dbo.newtable

5.以新用户身份执行

这一步会证明newuser对表没有SELECT权限。

exec as user = 'NewUser' select suser_sname() as [suser_sname()], original_login() as [original_login()] select * from dbo.NewTable revert

输出:

消息 229,第 14 级,状态 5,第 3 行
对象“newtable”、数据库“test”、模式“dbo”的 SELECT 权限被拒绝。

现在,下一步是乐趣的开始。如果你把上面的代码sn-p封装在一个proc里面,你会看到newuser突然可以查询表了。

  1. 创建一个过程

create proc dbo.newproc as exec as user = 'newuser' select suser_sname() as [suser_sname()], original_login() as [original_login()] select * from dbo.newtable revert go -- Note I haven't granted any permissions to newuser whatsoever. exec dbo.newproc

输出:

suser_sname() original_login()
----------------------------------
新用户域\louie.bao

ID
--
1

谁能向我解释一下,在 proc 中执行相同代码的权限检查有何不同?

编辑

更麻烦的是,即使你专门发出了 DENY,newuser 仍然可以访问 dbo.newtable:

deny select on dbo.newtable to newuser exec dbo.newproc

我了解所有权链接将授予对 proc 调用者(在本例中为我)的访问权限,但当我特别想作为另一个用户执行时,我希望检查该用户的权限。

【问题讨论】:

  • 即使有人可以重现相同的输出,我也很想知道。

标签: sql-server permissions sql-server-2012


【解决方案1】:

这是所有权链的问题。

参见在线图书> 所有权链:https://technet.microsoft.com/en-us/library/ms188676(v=sql.105).aspx

首先我们可以演示所有权链是如何工作的,在存储过程中没有 EXECUTE AS,然后我们可以看到它是如何与 EXECUTE AS 一起工作的。

创建两个表并插入数据。

CREATE TABLE dbo.T1 (id int IDENTITY(1,1));
CREATE TABLE dbo.T2 (id int IDENTITY(1,1));

INSERT INTO dbo.T1 DEFAULT VALUES;
INSERT INTO dbo.T2 DEFAULT VALUES;

创建两个用户。

CREATE USER U1 WITHOUT LOGIN;
CREATE USER U2 WITHOUT LOGIN;

将表 T2 的所有权更改为用户 U2。

ALTER AUTHORIZATION ON OBJECT::dbo.T2 TO U2;

确认我们已更改所有权。

SELECT name, principal_id
    FROM sys.tables
    WHERE name IN (N'T1', N'T2');

证明用户 U1 对表 T1 或 T2 没有 SELECT 权限。

EXECUTE AS USER = 'U1';
SELECT * FROM dbo.T1;
SELECT * FROM dbo.T2;
REVERT

创建两个存储过程并允许用户 U1 执行这两个过程。

CREATE PROCEDURE dbo.P1
AS 
    SELECT * FROM dbo.T1;
GO  
CREATE PROCEDURE dbo.P2
AS 
    SELECT * FROM dbo.T2;
GO

GRANT EXECUTE ON dbo.P1 to U1;
GRANT EXECUTE ON dbo.P2 to U1;

以用户 U1 的身份执行 P1。这是有效的,因为有一个完整的所有权链。 P1 和 T1 具有相同的所有者(它是模式 dbo 的所有者)。在这种情况下,将跳过存储过程中的权限检查。

EXECUTE AS USER = 'U1';
EXEC dbo.P1;
REVERT

以用户 U1 的身份执行过程 P2。这会失败,因为所有权链已损坏,因此会检查存储过程中的权限。 P2 和 T2 拥有不同的所有者。

EXECUTE AS USER = 'U1';
EXEC dbo.P2;
REVERT

接下来,演示存储过程在包含 EXECUTE AS 时如何工作。

再创建两个存储过程。

CREATE PROCEDURE dbo.P1A
AS 
    EXECUTE AS USER = 'U1';
    SELECT * FROM dbo.T1;
    REVERT
GO  
CREATE PROCEDURE dbo.P2A
AS 
    EXECUTE AS USER = 'U1';
    SELECT * FROM dbo.T2;
    REVERT
GO

执行 P1A 即可。完整的执行链,因此不会检查存储过程中的权限。

EXEC dbo.P1A;

执行 P2A 并失败。执行链中断,因此检查存储过程中的权限。

EXEC dbo.P2A;

请注意,我们在这些示例中使用了 EXECUTE AS 语句。还有一个 EXECUTE AS 子句,用于存储过程、函数和触发器。

在线图书 > EXECUTE AS (Transact-SQL):https://msdn.microsoft.com/en-us/library/ms181362.aspx

在线图书 > EXECUTE AS 子句 (Transact-SQL):https://msdn.microsoft.com/en-GB/library/ms188354.aspx

【讨论】:

  • 在您的示例中,如果您从 U1 撤消 exec,我可以理解由于所有权链接,proc 调用者(U1 除外)可以访问 dbo.T1,但我不明白为什么 U1 可以绕过权限检查,因为我们从未向 U1 授予任何权限。这不是违背“以用户身份执行”的目的吗?
【解决方案2】:

由于“所有权链接”,这是正常行为

在例程内部,如果引用的表具有与存储过程相同的 AUTHORIZATION,则不会检查权限。在这种情况下,它们都在“dbo”模式中,因此不会检查权限。这包括 DENY 权限

create proc dbo.newproc2
with EXECUTE AS CALLER
as
select * from dbo.newtable
GO

GRANT EXEC ON dbo.newproc2 TO newuser
EXEC as user = 'newuser'
exec dbo.newproc2
REVERT


GO

DENY SELECT ON dbo.newtable TO newuser
exec dbo.newproc
GO
EXEC as user = 'newuser'
exec dbo.newproc2
REVERT
GO

【讨论】:

  • 在我的示例中,我从未将 proc 上的 exec 授予 newuser。
  • 这是必需的,因为我在 EXEC AS 之后有 storec proc 调用
  • 感谢您提供 DENY 示例。我已对您的答案投了赞成票,但会选择更全面的答案作为答案。仍然不满意所有权链实际上可以在 exec 作为较低特权用户时绕过权限检查。
  • @user763539 是的,只需将 newuser 更改为 newrole。相同的链接适用
猜你喜欢
  • 2019-02-24
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-12
  • 2011-04-21
  • 1970-01-01
相关资源
最近更新 更多