SQL Server でのストアド プロシージャを使用したアクセス許可の管理 (ADO.NET)
更新 : November 2007
データベースを多層的に防御する 1 つの方法として、あらゆるデータ アクセスをストアド プロシージャまたはユーザー定義関数を使って実装することが考えられます。テーブルなど、基になるオブジェクトに対する権限をすべて取り消すか拒否し、ストアド プロシージャに対して EXECUTE 権限を付与するようにします。こうすることで、データやデータベース オブジェクトの周囲にセキュリティの境界を設けることができます。
ストアド プロシージャの利点
ストアド プロシージャには、次の利点があります。
データ ロジックとビジネス ルールがカプセル化されるため、ユーザーが、開発者およびデータベース管理者の想定外の方法でデータやオブジェクトにアクセスするのを防ぐことができます。
すべてのユーザー入力を検証するパラメータ化されたストアド プロシージャを使用することで、SQL インジェクション攻撃を阻止できます。動的 SQL を使用する場合は、必ずコマンドをパラメータ化するようにし、パラメータ値を直接クエリ文字列に追加することは避けてください。
アドホック クエリおよびデータ変更を禁止できます。悪意からまたは不注意によってデータが破壊されたり、サーバーやネットワークのパフォーマンスを損ねるようなクエリが実行されるのを防ぐことができます。
エラーをクライアント アプリケーションに直接渡すことなく、プロシージャ コード内で処理できます。これにより、返されたエラー メッセージがプローブ攻撃に利用されるのを防ぐことができます。エラーはログに記録しサーバー上で処理するようにします。
ストアド プロシージャは 1 度作成すれば、さまざまなアプリケーションからアクセスできます。
クライアント アプリケーションは基になるデータの構造を意識する必要がありません。パラメータ リストや返されるデータ型に影響が及ばない限り、ストアド プロシージャのコードを変更しても、クライアント アプリケーション側に変更を加える必要はありません。
ストアド プロシージャによって、複数の操作を 1 回のプロシージャ呼び出しにまとめることができるため、ネットワーク トラフィックを削減できます。
ストアド プロシージャの実行
ストアド プロシージャを使用すると、所有権の継承によるデータ アクセスを利用できるため、データベース オブジェクトにアクセスするための権限をユーザーに明示的に付与する必要がありません。所有権の継承は、連鎖的にアクセスされる複数のオブジェクトが同じユーザーによって所有されている場合に適用されます。たとえば、あるストアド プロシージャが別のストアド プロシージャを呼び出したり、特定のストアド プロシージャが複数のテーブルにアクセスしたりすることができます。実行の連鎖に含まれるすべてのオブジェクトが同じ所有者を共有していた場合、SQL Server は呼び出し元の EXECUTE 権限だけをチェックします。つまり、他のオブジェクトの呼び出し元の権限はチェックされません。したがって、EXECUTE 権限はストアド プロシージャにのみ付与すればよく、基になるテーブルの権限はすべて取り消すか拒否できます。
ベスト プラクティス
単にストアド プロシージャを作成するだけでは、アプリケーションを適切に保護することはできません。同時に、次の点を考慮してセキュリティ ホールを防ぐ必要があります。
データ アクセスを許可するデータベース ロールに、ストアド プロシージャの EXECUTE 権限を付与する。
基になるテーブルのすべての権限を取り消すか拒否する。public ロールを含め、データベース内のすべてのロールおよびユーザーが対象になります。すべてのユーザーは public から権限を継承します。したがって、public の権限を拒否することは、所有者と sysadmin メンバだけがアクセス権を持つことを意味します。それ以外のすべてのユーザーは、他のロールのメンバになっても権限を継承することはできなくなります。
sysadmin ロールまたは db_owner ロールに対してユーザーまたはロールを追加することは避ける。システム管理者およびデータベース所有者は、すべてのデータベース オブジェクトにアクセスできます。
guest アカウントを無効にする。こうすることで、匿名ユーザーがデータベースに接続することはできなくなります。新しいデータベースの guest アカウントは既定で無効化されています。
エラー処理を実装し、エラーのログを記録する。
すべてのユーザー入力を検証するパラメータ化されたストアド プロシージャを作成する。どのようなユーザー入力も "信頼できないもの" として扱うようにします。
どうしても必要な場合を除き、動的 SQL は使用しない。文字列値を Transact-SQL の QUOTENAME() 関数に渡すことで、入力文字列に含まれている可能性のある区切り記号をエスケープできます。
外部リソース
詳細については、次のリソースを参照してください。
リソース |
説明 |
---|---|
ストアド プロシージャおよび SQL インジェクション (SQL Server 2008 オンライン ブック) |
ストアド プロシージャの作成方法と SQL インジェクションのしくみについて説明します。 |
ストアド プロシージャおよび SQL インジェクション (SQL Server 2005 オンライン ブック) |
ストアド プロシージャの作成方法と SQL インジェクションのしくみについて説明します。 |
ストアド プロシージャおよび所有権の継承の使用 (SQL Server 2000 オンライン ブック) |
ストアド プロシージャの作成方法、および、SQL Server 2000 における所有権の継承の活用方法について説明します。 |
参照
概念
SQL Server におけるアプリケーション セキュリティのシナリオ (ADO.NET)
SQL Server での安全な動的 SQL の作成 (ADO.NET)
SQL Server でのストアド プロシージャの署名 (ADO.NET)
SQL Server での借用を使用した権限のカスタマイズ (ADO.NET)