【问题标题】:Azure SQL: Audit Triggers and Ownership ChainingAzure SQL:审核触发器和所有权链接
【发布时间】:2021-11-15 12:12:58
【问题描述】:

我有两个表 T1 和 T2,分别位于两个不同的模式 S1 和 S2 中。我在 T1 上编写了一个触发器 TR1(没有 EXECUTE AS 子句),它将插入(I)、更新(U)和删除(D)记录到 T2 中,T2 具有与 T1 相同的架构,并带有一些额外的元数据列. S1、T1、S2、T2 和 TR1 都归 dbo 所有。

我创建了一个角色 R1,它对 S1(以及 T1)拥有 S、I、U 和 D 权限。该角色还允许 S2(以及 T2)上的 S,但拒绝 I、U 和 D。我创建了一个用户 U1,并为该用户分配了角色 R1。

在 U1 的用户上下文下,如果我在 T2 上尝试 I、U 或 D,则如预期的那样被拒绝。但是,如果将 I、U 或 D 插入 T1,则审计行将成功插入 T2。这是我想要的行为,但想知道这是为什么,因为 U1 已被明确拒绝这些特权。

这是因为所有权链接,因此当 TR1 运行时,U1 的权限永远不会在 T2 上检查,还是其他原因?

Azure SQL 版本是 Microsoft SQL Azure (RTM) - 12.0.2000.8 Jul 23 2021 13:14:19 版权所有 (C) 2019 Microsoft Corporation

--

添加了触发代码:

CREATE TRIGGER TRG ON dbo.T1
FOR INSERT, UPDATE, DELETE
AS
BEGIN;

DECLARE @Operation CHAR(1);

SET @Operation =    (
                        CASE
                            WHEN EXISTS(SELECT 1 FROM INSERTED) AND EXISTS(SELECT 1 FROM DELETED) THEN 'U'
                            WHEN EXISTS(SELECT 1 FROM INSERTED) THEN 'I'
                            WHEN EXISTS(SELECT 1 FROM DELETED) THEN 'D'
                            ELSE NULL
                        END
                    );

IF @Operation = 'I'
    BEGIN;
        INSERT INTO     adt.T1(Operation, ID, C1)
        SELECT          @Operation, ID, C1
        FROM            INSERTED;
    END;

IF @Operation = 'D'
    BEGIN;
        INSERT INTO     adt.T1 (Operation, ID, C1)
        SELECT          @Operation, ID, C1
        FROM            DELETED;
    END;

IF @Operation = 'U'
    BEGIN;
        INSERT INTO     adt.T1 (Operation, ID, C1)
        SELECT          @Operation, i.ID, i.C1
        FROM            INSERTED i
        INNER JOIN      DELETED d
        ON              i.ID = d.ID
                        -- Hash indicated columns of INSERTED and DELETED to determine if there are any real changes.
        WHERE           (SELECT HASHBYTES('MD5', (SELECT i.ID, i.C1 FROM (SELECT NULL AS X) t FOR XML AUTO)))
                        <>
                        (SELECT HASHBYTES('MD5', (SELECT d.ID, d.C1 FROM (SELECT NULL AS X) t FOR XML AUTO)));
    END;

END;

【问题讨论】:

  • 也就是说,用户在 T2 上被正确拒绝 IUD 操作,那么为什么同一用户引发的触发器(在另一个表上)能够将记录插入到该表中
  • 据我所知,这种情况仅适用于 EXECUTE AS,这就是该子句的重点。请发布您的触发器创建脚本以验证
  • @ChrisSchaller 添加了触发代码
  • @ChrisSchaller 还补充说,表位于不同的模式中,并且权限是在模式上发布的,而不是在表本身上。游戏中的一切都归 dbo 所有。
  • 好的,是的,这就是所有权链的作用,因为您在架构级别进行保护。在其他情况下,您可能会考虑直接保护目标表以防止这种行为,但在审计上下文中它很有用,因为我们可以使用当前上下文将当前用户和 privs 记录到审计表中,我们会丢失一些此类信息如果触发器使用 Execute As。对于严格不基于审计的场景,您需要注意所有权链接可能会将受保护的表暴露给您可能没有预料到的更新。

标签: triggers azure-sql-database audit


【解决方案1】:

好的,是的,这就是所有权链接,因为您在架构级别进行保护。

Understanding SQL Server Ownership Chaining
当存在所有权链时,被引用对象的安全性被忽略

在这种情况下,有一个所有权链,因为两个模式具有相同的所有者,这意味着当触发器执行时重新评估权限访问假定的 secured 架构。

需要明确的是,执行上下文没有改变,没有EXECUTE AS 或模拟发生。针对表 T2 的操作仍在原始调用者的上下文中进行,但所有权链接规则意味着访问规则很简单,无需重新评估,甚至不会尝试检查。

所有权链接是 SQL Server 的一项优化功能,在许多情况下,它通过允许对访问规则进行一次评估而不是重新评估每个可能的安全上下文来提高查询吞吐量,因为引擎仅在上下文受到保护时才重新评估不同的所有者。

这是架构的所有者很重要的主要原因,也是为什么您可以指定专门为不同架构创建的不同任意所有者的原因。

在审核/更改日志记录的情况下,我们可以利用这种行为来维护我们数据的完整性,方法是阻止故意尝试修改审核记录的用户,同时仍然允许这些用户执行可能会执行的查询和命令具有将行插入审计表的副作用。

由于用户上下文没有被篡改,我们仍然可以捕获和记录有关当前用户上下文的信息,并将其包含在您可能正在记录的有关操作的元数据中。

对于严格不基于审计的场景,您需要注意所有权链接可能会将您的安全表暴露给您可能没有预料到的更新。

【讨论】:

    猜你喜欢
    • 2016-09-18
    • 2014-05-04
    • 1970-01-01
    • 2013-06-20
    • 2010-12-30
    • 1970-01-01
    • 2015-10-23
    • 2019-11-29
    • 1970-01-01
    相关资源
    最近更新 更多