次の方法で共有


SQL Server での安全な動的 SQL の作成

ADO.NET のダウンロード

SQL インジェクションとは、悪意のあるユーザーによって、有効な入力データの代わりに Transact-SQL ステートメントが入力されることをいいます。 入力が検証されずにサーバーに直接渡され、挿入されたコードがアプリケーションによって誤って実行された場合に、この攻撃によってデータが破損、または破壊される可能性があります。

SQL Server では、構文的に有効であれば受信したクエリがすべて実行されるため、SQL ステートメントを構成するすべてのプロシージャに対して、インジェクションに対する脆弱性をレビューする必要があります。 高いスキルを持った攻撃者は、その気になればパラメーター化されたデータでさえも操作できます。 動的 SQL を使用する場合は、必ずコマンドをパラメーター化するようにし、パラメーター値を直接クエリ文字列に追加することは避けてください。

SQL インジェクション攻撃の構造

インジェクション プロセスは、途中でテキスト文字列を終了し、新しいコマンドを追加することによって行われます。 挿入されたコマンドが実行される前に別の文字列が追加される可能性があるため、攻撃者は挿入する文字列をコメント記号 "--" で終了させます。 後続のテキストは実行時には無視されます。 セミコロン (;) 区切り記号を使用して複数のコマンドを挿入できます。

挿入された SQL コードが構文的に正しい限り、改ざんをプログラムによって検出するのは不可能です。 そのため、すべてのユーザー入力を検証し、使用しているサーバーで作成された SQL コマンドを実行するコードを注意深くレビューする必要があります。 検証されていないユーザー入力は決して連結しないでください。 文字列の連結は、スクリプト インジェクションの最初の段階です。

有用なガイドラインを次に示します。

  • Transact-SQL ステートメントをユーザー入力から直接作成しないでください。ストアド プロシージャを使用して、ユーザー入力を検証します。

  • ユーザー入力の型、長さ、形式、範囲をテストし、検証してください。 Transact-SQL QUOTENAME() 関数を使用してシステム名をエスケープするか、REPLACE() 関数して文字列内の任意の文字をエスケープします。

  • アプリケーションの各層に複数の検証レイヤーを実装します。

  • 入力のサイズとデータ型をテストし、適切な制限を適用します。 これは、意図的なバッファー オーバーランを防ぐのに役立ちます。

  • 文字列変数の内容をテストし、予測される値のみを受け入れる。 バイナリ データ、エスケープ シーケンス、およびコメント文字を含む入力は拒否します。

  • XML ドキュメントを扱う場合、入力時にすべてのデータをスキーマに照らして検証します。

  • 多層環境では、信頼済みゾーンに入ることを許可する前にすべてのデータを検証する必要があります。

  • ファイル名の作成に使用できるフィールドでは、次の文字列を受け付けない:AUX、CLOCK$、COM1 から COM8、CON、CONFIG$、LPT1 から LPT8、NUL、PRN。

  • ストアド プロシージャおよびコマンドで SqlParameter オブジェクトを使用して、型チェックと長さの検証を行います。

  • クライアント コードで Regex 式を使用して、無効な文字を排除します。

動的 SQL 戦略

プロシージャ コードで動的に生成された SQL ステートメントを実行することで組み合わせ所有権を破棄すると、SQL Server は動的 SQL によりアクセスされるオブジェクトに対する呼び出し元の権限をチェックします。

SQL Server には、動的 SQL を実行するストアド プロシージャやユーザー定義関数を使用したデータ アクセスをユーザーに許可するための方法があります。

  • Transact-SQL EXECUTE AS 句による権限の借用を利用します。

  • 証明書を使用したストアド プロシージャへの署名。

EXECUTE AS

EXECUTE AS 句では、呼び出し元のアクセス許可を、EXECUTE AS 句に指定されたユーザーのアクセス許可で置き換えます。 入れ子になったストアド プロシージャまたはトリガーは、プロキシ ユーザーのセキュリティ コンテキストで実行されます。 これにより、行レベルのセキュリティに依存する、または監査を必要とするアプリケーションが中断される可能性があります。 ユーザーの ID を返す一部の関数では、元の呼び出し元ではなく、EXECUTE AS 句に指定されたユーザーを返します。 プロシージャの実行後、または REVERT ステートメントが発行されたときにのみ、実行コンテキストが最初の呼び出し元に戻ります。

証明書の署名

証明書により署名されているストアド プロシージャが実行されると、証明書ユーザーに許可される権限が呼び出し元の権限にマージされます。 実行コンテキストはそのままです。証明書ユーザーが呼び出し元を偽装することはありません。 ストアド プロシージャに署名するには、いくつかの手順を実装する必要があります。 プロシージャが変更されるたびに、再度署名する必要があります。

複数データベース間アクセス

動的に生成された SQL ステートメントを実行する場合、複数データベースの組み合わせ所有権は機能しません。 SQL Server では、別のデータベースのデータにアクセスするストアド プロシージャを作成し、両方のデータベースに存在する証明書でそのプロシージャに署名することによって、この制限を回避できます。 これにより、ユーザーは、データベースへのアクセス許可が付与されていなくても、そのプロシージャによって使用されるデータベース リソースにアクセスできるようになります。

外部リソース

詳細については、次のリソースを参照してください。

リソース 説明
ストアド プロシージャ」と「SQL インジェクション」 (SQL Server オンライン ブック) ストアド プロシージャの作成方法と SQL インジェクションのしくみについて説明します。

次のステップ