拒绝访问SQL Server中的信息架构


13

我正在寻找对SQL Server中的用户/组禁用对sys.tables/的访问的最佳方法Information Schema

从2008年发现了这个话题

它显示了一种如何拒绝访问的方法,[sys].[something]如下所示:

 DENY SELECT ON [sys].[columns] TO DenySystemTableSelectRole
 GO
 DENY SELECT ON [sys].[tables] TO DenySystemTableSelectRole
 GO
 DENY SELECT ON [sys].[syscolumns] TO DenySystemTableSelectRole
 GO
 DENY SELECT ON [sys].[sysobjects] TO DenySystemTableSelectRole
 GO

但是没有办法如何禁用对的访问Information Schema

DENY SELECT ON INFORMATION_SCHEMA.TABLES To DenySystemTableSelectRole

这似乎行不通。

如何禁用对information_schema的访问?

还有一种更简单的方法来禁用对所有sys/的访问information_schema吗?

更新: 实际上我不能同时运行以下语句:

DENY SELECT ON [sys] TO reducedDBO
GO
DENY SELECT ON INFORMATION_SCHEMA To reducedDBO
GO

我试图在用户所在的特定数据库上运行它们,并且还尝试了“主”数据库。

我仍然可以运行:

 SELECT * from
 INFORMATION_SCHEMA.TABLES 

->仍然返回结果

 SELECT * from
 sys.TABLES 

->没有结果了

包含SCHEMA::在查询中使得可以创建安全对象

DENY SELECT ON SCHEMA::[sys] TO reducedDBO
GO
DENY SELECT ON SCHEMA::INFORMATION_SCHEMA To reducedDBO
GO

但是现在我仍然可以从数据库中选择所有信息。

我在Management Studio 2008的用户“属性”窗口中查看了“ Securables”标签,如下所示:

确实阻止sys.tables选择的条目

模式:sys,名称:表,类型:视图

sys.tables的权限:Permission:Select,Grantor:dbo,Deny被选中

不阻止任何选择的条目

模式:,名称:INFORMATION_SCHEMA,类型:模式

INFORMATION_SCHEMA的权限:Permission:Select,Grantor:dbo,Deny未选中(我尝试进行检查,但没有机会。)

权限:选择,授予者:INFORMATION_SCHEMA,拒绝已选中


我试图通过GUI设置权限,但是随后出现了同样的错误,即只能在主数据库上设置权限。但是我没有将用户/登录添加到主数据库安全性中。

解:

我可以做的唯一途径deny的工作information_schema将用户添加到主数据库,并运行deny select在主:

DENY SELECT ON [sys].[tables] TO reducedDBO
GO
DENY SELECT ON INFORMATION_SCHEMA.TABLES To reducedDBO
GO

就像这段代码一样,它只能对单个表执行。


1
还检查了这个dba.se提问和瑞摩斯Rusanu其答案 -排序的封面同样的话题
marc_s

是的,谢谢。实际上,拒绝[information_schema]视图和[sys]视图之间的区别在于,必须在主数据库上禁用[information_schema](这会影响所有DB),而在[in]中必须禁用[sys]视图每个数据库本身,即使在主数据库上也被禁用,即使在主数据库上也被禁用,用户仍然可以从视图中进行选择。
SwissCoder 2012年

Answers:


10

你应该能够只是否认对整个权限sysinformation_schema架构作为一个整体:

DENY SELECT On SCHEMA::sys To [user_name]
DENY SELECT On SCHEMA::INFORMATION_SCHEMA To [user_name]

基本上,这应该只是防止该用户在这两种模式中进行任何选择。


标记为答案,但问题是SCHEMA ::没有帮助,最好再次将其删除。解决方案是将用户添加到master数据库,然后在master数据库上运行deny脚本。谢谢您的帮助!
SwissCoder 2012年

哦,实际上我也无法禁用整个SCHEMA,只能像这样禁用单个表的访问。
SwissCoder 2012年

5

首先,您的正确做法是:要防止访问[sys]和[INFORMATION_SCHEMA]模式的方式(略有违反直觉的方式)是首先确保登录名(以及服务器级主体)作为用户(erm,数据库级别的主体)。

为了简单起见,假设您有一个SQL登录名:

CREATE LOGIN [testy] WITH PASSWORD=N'SCoBIqlJELGzrY9zYsKWC5z3kHtMsyCAP6yBHLUYQ0w='
go

现在在master数据库中创建一个相应的用户:

use [master]
go
CREATE USER [testy] FOR LOGIN [testy]
go

现在,您要阻止此登录访问系统提供的架构中的任何表-[sys]和[INFORMATION_SCHEMA]。

似乎SQL Server 2008 R2和SQL Server 2012之间的行为发生了变化:

在SQL Server 2012(以及可能更高的版本)中,可以在[master]数据库中运行以下操作,如您所愿:

DENY SELECT, VIEW DEFINITION ON SCHEMA::[sys] to [testy];
GO
DENY SELECT, VIEW DEFINITION ON SCHEMA::[INFORMATION_SCHEMA] to [testy];
GO

但是,在SQL Server 2008 R2(可能是较早的版本)中,将这些模式中的对象授予[public]成员访问权限的股票授予语句似乎覆盖了上面的DENY语句,这对我来说似乎是一大堆失败。因此,在2008 R2上,您需要为[公共]的每个GRANT明确拒绝。这是执行此操作的脚本:

declare
    @database_principal sysname,
    @cur cursor,
    @sql nvarchar( 4000 );

set @database_principal = 'testy';

set @cur = cursor local forward_only static for
    select 
        'DENY ' +
        permission_name + ' on ' +
        case class 
            when 1 then
                case minor_id
                    when 0 then 'OBJECT'
                    else 'COLUMN'
                end
            else
                class_desc
        end + '::' +
        case class
            when 0 then db_name()
            when 1 then quotename( OBJECT_SCHEMA_NAME(major_id) ) + '.' + quotename( object_name( major_id ) ) + case minor_id when 0 then '' else ( select '.' + quotename( name ) collate database_default from sys.columns where column_id=minor_id) end
            when 3 then schema_name( major_id )
        end + ' to ' +
        quotename( @database_principal )
    from
        sys.database_permissions
    where
        [grantee_principal_id] = 0 -- public
        and
        [state_desc] = 'GRANT'
        and
        [permission_name] = 'SELECT'
;

open @cur;

while
    1 = 1
begin
    fetch @cur into @sql;
    if @@fetch_status <> 0 break;

    print @sql;
    exec sys.sp_executesql @sql;
end;

close @cur;

deallocate @cur;

在master数据库中运行上述命令,您已经删除了对这些模式内容的访问。

笔记:

  1. 由于这些是显式的DENY语句,因此在脚本运行时它们是正确的。如果随后有人更改了授予公共的权限(例如,Service Pack创建了一个新的系统表),则该权限将暴露给被拒绝的用户
  2. 最好使用数据库角色作为DENY语句的目标,并将拒绝的用户放在该角色中。
  3. 您可以通过将DENY更改为REVOKE来撤消此操作
  4. 如果您在上面的脚本中注释了以下两行:

        and
        [permission_name] = 'SELECT'

    它将具有撤消所有公共默认GRANT 的效果。这将阻止对sys.sp_tables的访问,从而破坏Microsoft Access的功能,例如枚举表,但是这样做在高安全性场景中很有用,因此用户仅在您明确授予权限的情况下才可以访问它。


3

我不确定何时可以使用此技巧-因为没有人提到过-但看来至少从SQL Server 2008起它就可以使用。

DENY VIEW DEFINITION to [database-role / database-user];

上面的方法无需master像其他一些答案中提到的那样将用户添加到数据库中。


很好的答案!Per technet.microsoft.com/zh-cn/library/ms175808(v=sql.105).aspx “为指定数据库中的受赠方否定基于权限的元数据访问”
克里斯·安顿
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.