SQL Server 2008 R2 跨数据库所有权链接不起作用?

发布于 2024-11-06 01:46:44 字数 1445 浏览 0 评论 0原文

我已将两个 SQL Server 2005 数据库(DB1 和 DB2)恢复到运行 SQL Server 2008 R2 的新机器上。

所有对象都属于 dbo

我有一个存储过程DB1.dbo.mp_SPTest。我已向 SQLUser1 授予执行权限。

CREATE PROCEDURE mp_SPTest
AS
SELECT DB2.dbo.mf_UserHasAccess("BasicUser", "bob")

mp_SPTest 调用 DB2 DB2.dbo.mf_UserHasAccess() 中的标量函数,该函数检查传递的用户名是否是 SQL 角色的成员......

CREATE FUNCTION [dbo].[mf_UserHasAccess] (@RoleName varchar(50), @UserName varchar(128))  
RETURNS bit
AS  
BEGIN 
    DECLARE @Result bit

    SELECT @Result = 1
    WHERE @RoleName IN (
    SELECT CASE
        WHEN (usg.uid is null) THEN 'public'
        ELSE usg.name
        END AS RoleName
    FROM    dbo.sysusers usu
    LEFT OUTER JOIN (dbo.sysmembers mem 
         INNER JOIN dbo.sysusers usg 
         ON mem.groupuid = usg.uid)
    ON  usu.uid = mem.memberuid
    LEFT OUTER JOIN master.dbo.syslogins lo 
    ON  usu.sid = lo.sid
    WHERE   
        (usu.islogin = 1 AND usu.isaliased = 0 AND usu.hasdbaccess = 1)
    AND (usg.issqlrole = 1 OR usg.uid is NULL)
    AND usu.name = @UserName)

    IF @Result <> 1
    BEGIN
        SET @Result = 0
    END

    RETURN @Result
END

当我以“SQLUser1”身份运行此过程,它告诉我 bob 不是 BasicUser 的成员,但当我以“sa”身份运行它时,它告诉我他是成员。

据我了解...因为过程和函数都由 dbo 所有,那么这就是 test2 db 中的函数将运行的上下文,因此它应该有权访问相同的用户和登录表。

这在 SQL Server 2005 上运行良好,但无法弄清楚。

希望这是有道理的,提前致谢。

I have restored two SQL Server 2005 dbs (DB1 & DB2) to a new box running SQL Server 2008 R2.

All objects are owned by dbo

I have a stored procedure DB1.dbo.mp_SPTest. I have given execute permissions to SQLUser1.

CREATE PROCEDURE mp_SPTest
AS
SELECT DB2.dbo.mf_UserHasAccess("BasicUser", "bob")

mp_SPTest calls a scalar function in DB2 DB2.dbo.mf_UserHasAccess(), this function checks if the username passed is a member of a SQL Role.....

CREATE FUNCTION [dbo].[mf_UserHasAccess] (@RoleName varchar(50), @UserName varchar(128))  
RETURNS bit
AS  
BEGIN 
    DECLARE @Result bit

    SELECT @Result = 1
    WHERE @RoleName IN (
    SELECT CASE
        WHEN (usg.uid is null) THEN 'public'
        ELSE usg.name
        END AS RoleName
    FROM    dbo.sysusers usu
    LEFT OUTER JOIN (dbo.sysmembers mem 
         INNER JOIN dbo.sysusers usg 
         ON mem.groupuid = usg.uid)
    ON  usu.uid = mem.memberuid
    LEFT OUTER JOIN master.dbo.syslogins lo 
    ON  usu.sid = lo.sid
    WHERE   
        (usu.islogin = 1 AND usu.isaliased = 0 AND usu.hasdbaccess = 1)
    AND (usg.issqlrole = 1 OR usg.uid is NULL)
    AND usu.name = @UserName)

    IF @Result <> 1
    BEGIN
        SET @Result = 0
    END

    RETURN @Result
END

When I run this procedure as "SQLUser1" it tells me that bob is not a member of BasicUser but when I run it as "sa" it tells me that he IS a member.

As I understand it... because both procedure and function are owned by dbo then that is the context that the function in test2 db would run, therefore it should have access to the same user and login tables.

This worked fine on SQL Server 2005, cant figure it out.

Hope this makes sense, thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

多彩岁月 2024-11-13 01:46:44

旧的 SQL Server 2005 很可能已启用跨数据库所有权链接选项打开,而新的 SQL Server 2008 R2 实例则将该选项保留为默认值(关闭)。

但是您认为 DB1 中的“dbo”等于 DB2 中的“dbo”的假设是错误的。 DB1 中的“dbo”是与 sys.databases 中 DB1 的owner_sid 对应的登录名。同样,DB2 中的“dbo”是与 DB2 sys.databases 中的 onwer_sid 相对应的登录名。如果两个登录名不同(如果两个数据库的owner_sid不同),那么DB1的“dbo”很可能会映射到其他用户,并且所有权链被破坏,即使启用了跨数据库也是如此。运行 ALTER AUTHORIZATION ON DATABASE::[DB..] TO [sa] 将解决此问题(即,它将强制 Owner_sid 匹配)。

最后,您所做的事情从根本上来说是有缺陷的,因为它依赖于激活跨数据库的所有权链,这是一个巨大的安全漏洞,请参阅潜在威胁。一个更好的途径就是使用代码签名。

Most likely the old SQL Server 2005 had the cross db ownership chaining option turned on, while the new SQL Server 2008 R2 instance has the option left at its default value (off).

But your assumption that 'dbo' in DB1 equate to 'dbo' in DB2 is wrong. 'dbo' in DB1 is the login who corresponds to the owner_sid of DB1 in sys.databases. 'dbo' in DB2 is, likewise, the login that corrsponds to the onwer_sid in sys.databases for DB2. If the two logins are different (if the owner_sid of the two databases is different) then very likely 'dbo' of DB1 will map to some other user and the ownership chain is broken, even if enabled to cross databases. Running ALTER AUTHORIZATION ON DATABASE::[DB..] TO [sa] would fix this problem (ie. it would force the owner_sid to match).

And finally, what you're doing is fundamentally flawed, as it relies on activating ownership chaining across databases, which is a huge security hole, see Potential Threats. A much better avenue is to use code signing.

没企图 2024-11-13 01:46:44

我通过使视图或过程的架构在其需要访问的数据库中架构的所有者下运行来解决了这个相同的问题。

使用 [TargetDB]

ALTER AUTHORIZATION ON SCHEMA::[TargetSchema] TO [SourceSchema]

例如
使用 [DB1]

将 SCHEMA::[mem] 上的授权更改为 [dbo]
GO

假设链接已打开,将允许视图作为 DB2.DBO.view 运行,以访问 DB1.mem.table 中的表。本质上,跨数据库链接导致它访问目标数据库作为视图所在的模式,而不是拥有数据库的用户。

I solved this identical problem by making the schema the view or procedure is running under the owner of the schemas in the databases it needs to access.

USE [TargetDB]

ALTER AUTHORIZATION ON SCHEMA::[TargetSchema] TO [SourceSchema]

For example
USE [DB1]

ALTER AUTHORIZATION ON SCHEMA::[mem] TO [dbo]
GO

Would allow a view run as DB2.DBO.view assuming chaining is turned on, to access a table in DB1.mem.table. Essentially cross db chaining causes it to access the target DB AS the schema the view is under, not the user who owns the database.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文