授予ALTER TABLE权限有多危险?


11

想象以下情况

CREATE DATABASE test

GO

USE test;    

CREATE TABLE dbo.Customer
  (
     CustomerId   INT,
     Email        VARCHAR(100),
     SensitiveData VARCHAR(20)
  );

INSERT INTO dbo.Customer
VALUES     (1,'abc@foo.com','12346789');

在某个时候,编写了一个ETL过程,该过程在test数据库中执行某些活动。

CREATE USER etlUser WITHOUT LOGIN; /*For demo purposes*/

CREATE TABLE dbo.StagingTable
  (
     StagingTableId INT,
     SomeData       VARCHAR(100),
  )

GRANT UPDATE,INSERT,DELETE,SELECT,ALTER ON dbo.StagingTable TO etlUser;

DENY SELECT ON dbo.Customer TO etlUser;
DENY SELECT ON dbo.Customer (SensitiveData) TO etlUser; /*For good measure*/

etlUser应该没有对该Customer表的权限(当然也没有该SensitiveData列的权限),因此上面明确拒绝了这些权限。

ETL进程将被截断,dbo.StagingTable因此ALTER为此授予了表权限。

这是在安全审核期间标记的。这种情况有多危险?


为什么相对无害的操作(如ALTER TABLE ADD COLUMN)与其他操作(ALTER,DROP,约束,触发器)一样对待?
smci

Answers:


16

很危险

除了显而易见的更改StagingTable自身结构的ALTER TABLE权限外,该权限还允许他们在表上创建触发器。因此,在这种情况下,通过所有权链接,他们既可以查看敏感的客户数据(尽管有明确的DENY权限),也可以在第二张表上进行破坏。

EXECUTE AS user='etlUser'

GO

CREATE OR ALTER TRIGGER TR ON dbo.StagingTable AFTER UPDATE AS 
/*Exposure of sensitive data*/
SELECT * FROM dbo.Customer;

/*Vandalism*/
DELETE FROM dbo.Customer;

go

--Fire the trigger
UPDATE dbo.StagingTable SET SomeData = SomeData WHERE 1=0;

REVERT

8

除了能够添加触发器之外,ALTER TABLE权限还允许:

  1. 禁用触发器(避免审核跟踪)
  2. 禁用约束(允许不良数据)
  3. 更改约束(允许不良数据)
  4. 更改列定义(更改数据类型,最大大小,可空性)
  5. 添加一个调用T-SQL UDF的计算列(这使得获取并行计划非常困难,这很容易损害性能)

它还允许删除列,但这不太可能会被忽略(因为似乎我们在这里寻找的是比恶意更具欺骗性的潜在行为)。

幸运的是,永远不必向任何人授予此权限,也不必将其包装在使用该EXECUTE AS子句的存储过程中(通常在'dbo'或之后OWNER)。模块签名允许轻松地对签名代码(存储过程,触发器,标量UDF和多语句TVF)背后的特权操作进行抽象。我有示例代码显示了如何在以下答案中(在DBA.SE上)完成此任务:

这两个答案之间的区别是授予基于签名的用户的权限。授予的权限(或要添加的数据库角色)取决于所需范围。如果您只需要单个表的权限,则仅ALTER在该表上授予权限。如果特定模式中的所有表都需要权限,则不要将权限授予单个表,而应将权限授予模式本身。等等。

与专门为ETL用户创建模式或使用EXECUTE AS子句相比,模块签名是一些额外的步骤,但是:

  1. 鉴于上面链接的两个答案中都提供了代码,因此它实际上只是一个简单的复制和粘贴,并且
  2. 它无疑是最安全的选择。它仅允许通过该代码段进行该操作,并且仅EXECUTE允许该代码段被允许的操作。作为架构所有者,可以允许某些不必要的隐式权限。而且,使用EXECUTE AS 'dbo'EXECUTE AS OWNER(假设所有者dbo)会给整个过程,从这一点向前,dbo权限,而不仅仅是存储过程/触发器/函数,您使用EXECUTE AS与。模块签名将权限限制为仅对您签名的代码进行限制,而不是对已签名代码所调用的任何代码进行限制。

2
在某些系统(至少某些MySQL版本)上,有一种非常愚蠢的方法来有效消除VARCHAR列,而不会被程序错误立即注意到:将其大小减小为0。这将清除它,并以静默方式丢弃写入的任何内容它…
rackandboneman '18

2

更好的做法是创建由ETL用户拥有的登台模式。然后,ETL过程可以在过渡模式中截断表,禁用约束,执行分区切换等。ETL用户只需要对其他模式的有限权限。

您也可以使用数据库角色而不是单个用户。

当然,您还可以使您的受限用户使用dbo拥有的存储过程执行表截断,如下所示:

create procedure truncate_t 
with execute as owner
as
begin
  truncate table t;
end
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.