web-dev-qa-db-ja.com

SQL Serverの情報スキーマへのアクセスを拒否する

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

ユーザーが存在する特定のDBでそれらを実行しようとしました。また、「マスター」でも試行しました。

私はまだ走ることができます:

 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

しかし、今でもDBからすべての情報を選択できます。

Management Studio 2008のユーザープロパティウィンドウにある「セキュリティ保護可能」タブを確認しました。次のようになります。

sys.tablesの選択をブロックするエントリ

スキーマ:sys、名前:テーブル、タイプ:ビュー

Sys.tablesの権限:Permission:Select、Grantor:dbo、Denyがチェックされています

選択をブロックしないエントリ

スキーマ:、名前:INFORMATION_SCHEMA、タイプ:スキーマ

INFORMATION_SCHEMAの権限:Permission:Select、Grantor:dbo、Denyはチェックされていません(チェックしようとしましたが、チャンスはありません。)

権限:選択、付与者:INFORMATION_SCHEMA、拒否がチェックされています


GUIで権限を設定しようとしましたが、マスターDBでのみ権限を設定できるという同じエラーが発生します。しかし、私はユーザー/ログインをマスターDBのセキュリティに追加していません。

ソリューション:

denyinformation_schemaに対して機能させる唯一の方法は、ユーザーをmaster-dbに追加し、マスターでdeny selectを実行します。

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

そして、このコードのように、単一のテーブルに対してのみ実行できます。

13
SwissCoder

sysスキーマとinformation_schemaスキーマ全体に対する権限を拒否することができるはずです。

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

基本的には、そのユーザーがこれら2つのスキーマで選択を行うことを防ぐだけです。

10
marc_s

まず、[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では、[public]への各付与に対して明示的に拒否する必要があります。これを行うスクリプトは次のとおりです。

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ステートメントであるため、スクリプトが実行された時点で正しいです。その後、誰かがパブリックに付与されたアクセス許可を変更した場合(サービスパックが新しいシステムテーブルを作成するなど)、拒否されたユーザーに公開されます。
  2. データベースロールをDENYステートメントのターゲットとして使用し、拒否されたユーザーをそのロールに入れることをお勧めします。
  3. DENYをREVOKEに変更すると、これを元に戻すことができます
  4. 上記のスクリプトで次の2行をコメント化すると、

        and
        [permission_name] = 'SELECT'
    

    これは、パブリックのデフォルトGRANTの[〜#〜] all [〜#〜]を元に戻す効果があります。これにより、たとえばsys.sp_tablesへのアクセスが妨げられるため、たとえばMicrosoft Accessの機能はテーブルを列挙するだけですが、セキュリティの高いシナリオでは、これを行うとユーザーが明示的に許可した場所にのみアクセスできるため便利です。

5
Alasdair C-S

このトリックがいつ利用可能になったのかはわかりませんが、誰も言及していないためですが、少なくともSQL Server 2008以降は機能しているようです。

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

上記は機能しますなし他のいくつかの回答で述べたように、ユーザーをmasterデータベースに追加する必要があります。

3
Jesse