【问题标题】:Determining the current security checks being made (SQL Server)确定当前正在进行的安全检查 (SQL Server)
【发布时间】:2011-03-24 10:19:00
【问题描述】:

除了 MS SQL Server 中的任何东西之外,我一直讨厌的一件事是安全性的工作方式。如果您认为服务器很有趣,那么安全上下文会不断切换,而且通常很难(无论如何对我而言)预测或调试。

在今天处理一个问题时,“我希望我可以在我的代码中添加一行,以显示 SQL Server 在此代码运行时使用的安全上下文。”这样的命令存在吗?例如SELECT security_context()

更清楚一点...如果我在存储过程中并且因此受制于 SP 所有者的安全上下文,那么我希望看到这一点。如果我在 sp_executesql 调用的代码中,并且它导致安全性位于 SQL Server 服务帐户的上下文中,那么我希望看到这一点。

至少那时我可能能够弄清楚为什么 SQL Server 认为我不应该访问某些东西。

谢谢!


示例

-- Set up
CREATE USER Test_User WITHOUT LOGIN
CREATE TABLE Test_Security_Context (my_id INT)
INSERT INTO Test_Security_Context VALUES (1)
DENY SELECT ON Test_Security_Context TO Test_User
GO
CREATE PROCEDURE Test_Security_Context_SP
AS
  SELECT SUSER_SNAME()
  SELECT * FROM Test_Security_Context  -- This will return ok
  EXEC('SELECT SUSER_SNAME(); SELECT * FROM Test_Security_Context')  -- SUSER_SNAME() will match above but select fails
GO
GRANT EXECUTE ON Test_Security_Context_SP TO Test_User
GO

-- Switch to the new user
SETUSER 'Test_User'
GO

-- Do the test
EXEC Test_Security_Context_SP
GO

-- Clean up
SETUSER
DROP PROCEDURE Test_Security_Context_SP
DROP TABLE Test_Security_Context
DROP USER Test_User
GO

【问题讨论】:

    标签: sql-server security sql-server-2008 security-context


    【解决方案1】:

    是的,考虑到 EXECUTE AS 或代码签名等所有细节,有这样一对表示您当前安全上下文的视图:

    您获得的每一次访问最终都源自这些结果返回中的一行。请注意,某些访问权限是硬编码的角色成员身份隐含的(例如 db_datareader 数据库角色或 sysadmin 服务器角色)。

    其他:

    • 所有权链接与安全上下文无关:您不在 SP 所有者的“上下文”下。所有权链接只是说明对于与当前对象(SP、视图)拥有相同所有者的对象跳过访问检查。
    • sp_executesql不会以任何方式更改安全上下文

    【讨论】:

    • +1 哇。一个问题:为什么 builtin\administrators 的 login_token 会说 deny only ?我原以为这是我获得大部分资助的原因!
    • @Andomar:我认为是 Vista LUA,它将管理员令牌修改为仅拒绝。不过我不确定。
    • 我的术语可能很糟糕。我正在寻找的是,“这就是你没有权限的原因”和“这就是你有权限的原因”。我可能要求的太多了,但我知道并不是只有我一个人讨厌试图解决这些类型的安全漏洞,尤其是在涉及跨数据库访问、动态 SQL 等方面。
    • @Tom:你的例子都是关于所有权链接的。见technet.microsoft.com/en-us/library/ms188676.aspxTest_Security_Context_SP 中的代码可以访问Test_Security_Context,因为它们都属于同一个用户。由 EXEC 调用的代码不再 SP,由 SP调用,因此失去了所有权链接的好处。
    • 很高兴知道 SP 中的代码以用户 X 的权限运行并且动态代码,即使它在 SP 中在用户 Y 下。看起来不像就像 SQL Server 一样,虽然可以提供这些信息。感谢您的帮助。
    【解决方案2】:

    我认为您想使用CURRENT_USER 来查看当前的安全上下文。这是一个例子:

    SELECT CURRENT_USER AS 'Current User Name';
    GO
    EXECUTE AS LOGIN = 'junk'
    GO
    SELECT CURRENT_USER AS 'Current User Name';
    GO
    REVERT
    SELECT CURRENT_USER AS 'Current User Name';
    GO
    

    带输出(注意:我是我的 SQL Server 的管理员)

    Current User Name
    ------------------
    dbo
    
    (1 row(s) affected)
    
    Current User Name
    ------------------
    Junk
    
    (1 row(s) affected)
    
    Current User Name
    ------------------
    dbo
    
    (1 row(s) affected)
    

    【讨论】:

    • 这与Andomar的解决方案有同样的问题。请参阅我在上面添加的示例。
    【解决方案3】:

    不确定这是否是您所说的安全上下文,但您可以检索与您的会话关联的用户,例如:

    select SYSTEM_USER
    

    这适用于 SQL Server 登录或 Windows 登录。它甚至可以在带有execute as owner 的存储过程中工作。例如,

    create procedure dbo.Test
    with execute as owner
    as
    select SYSTEM_USER
    go
    exec dbo.Test
    select SYSTEM_USER
    

    打印:

    sa
    MyMachine\MyName
    

    如果您正在寻找 SQL Server 用来代表您执行操作的 Windows 帐户,您可以尝试从以下命令运行 whoami

    EXEC sp_configure 'show advanced options', 1
    RECONFIGURE
    EXEC sp_configure 'xp_cmdshell', 1
    RECONFIGURE
    
    EXEC master..xp_cmdshell 'whoami'
    

    对我来说,返回 nt authority\network service

    【讨论】:

    • 虽然 SUSER_SNAME() 是与会话关联的用户,但当您处于存储过程(使用 SP 所有者的安全上下文)或当您使用像 EXEC(@cmd) 这样的动态 SQL。更不用说所有权链接的混乱了。 :(
    • @Tom H:suser_sname()SYSTEM_USER 似乎都适用于存储过程(添加示例以回答问题。)也许您可以发布一个失败的示例?
    • 我添加了一个使用动态 SQL 的示例。在这两个地方都返回相同的 SUSER_SNAME(),但在一个地方选择失败,而在另一个地方成功。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多