MySQL 8.0 リファレンスマニュアル


MySQL 8.0 リファレンスマニュアル  /  ...  /  クライアントプログラミングのセキュリティーガイドライン

6.1.7 クライアントプログラミングのセキュリティーガイドライン

MySQL にアクセスするアプリケーションは、ユーザーによって入力されるあらゆるデータを信頼しないようにしてください。ユーザーは Web フォーム、URL、または構築されたあらゆるアプリケーションに特殊文字またはエスケープ文字のシーケンスを入力することによってコードを欺くことを試すことができます。 ユーザーが ; DROP DATABASE mysql; のような入力を行なっても、アプリケーションがセキュアな状態に保たれるようにしてください。 これは極端な例ですが、同様の技術を使用するハッカーに備えていない場合、結果として大規模なセキュリティーリークおよびデータ損失が発生することがあります。

よくある過ちは、文字列データ値のみ保護することです。 数値データも忘れずに検査してください。 ユーザーが 234 という値を入力したとき、アプリケーションが SELECT * FROM table WHERE ID=234 のようなクエリーを生成する場合、ユーザーは 234 OR 1=1 という値を入力して、SELECT * FROM table WHERE ID=234 OR 1=1 というクエリーをアプリケーションに生成させることができます。 その結果、サーバーはテーブル内のすべての行を取得します。 これはすべての行を公開し、サーバーに過剰な負荷がかかります。 この種類の攻撃から保護するためのもっとも簡単な方法は、数値定数を囲む単一引用符を使用して、SELECT * FROM table WHERE ID='234' とする方法です。 ユーザーが余分の情報を入力すると、その情報はすべて文字列の一部となります。 数値コンテキストでは、MySQL は自動的にこの文字列を数値に変換し、あとに続く数値以外のすべての文字を取り除きます。

データベースに格納されているデータが公開されているもののみであれば、保護は不要だと思われることもあります。 これは正しくありません。 データベース内のどの行も表示が許可されている場合であっても、サービス妨害攻撃 (前のパラグラフの技術に基づいた、サーバーにリソースを浪費させるものなど) から保護するべきです。 そうしない場合、サーバーは正当なユーザーに対して応答不能になります。

チェックリスト:

  • 厳密な SQL モードを有効にして、サーバーが受け入れるデータ値の制限を厳しくするようサーバーに指示します。 セクション5.1.11「サーバー SQL モード」を参照してください。

  • すべての Web フォームに一重引用符および二重引用符 ('および") を入力してみてください。 何らかの種類の MySQL エラーが出る場合、すぐに問題を調査してください。

  • %22 (")、%23 (#) および %27 (') を追加して、動的 URL の変更を試みます。

  • 前の例で示した文字を使用して、動的 URL のデータ型を数値型から文字型に変更してみます。 これらの攻撃や類似の攻撃に対してアプリケーションが安全であるようにしてください。

  • 数値フィールドに、数値でなく文字、スペース、および特殊記号を入力してみます。 アプリケーションはこれらを MySQL に渡す前にこれらを削除するか、またはエラーを生成します。 検査済みでない値を MySQL に渡すことは非常に危険です。

  • データを MySQL に渡す前にデータのサイズを検査してください。

  • アプリケーションがデータベースに接続するときは、管理目的で使用するものとは異なるユーザー名を使用するようにしてください。 アプリケーションに不要なアクセス権限を付与しないでください。

多くのアプリケーションプログラミングインタフェースには、データ値の特殊文字をエスケープする手段が備わっています。 適切に使用すれば、これにより、意図とは異なる効果を持つステートメントをアプリケーションに生成させる値を、アプリケーションユーザーが入力できないようにすることができます。

  • MySQL C API: mysql_real_escape_string_quote() API コールを使用します。

  • MySQL++: クエリーストリームに対して escape および quote 修飾子を使用してください。

  • PHP: mysqli または pdo_mysql 拡張子を使用し、古い ext/mysql 拡張子を使用しないでください。 推奨される API は、プレースホルダを持つプリペアドステートメントのほかに、改善された MySQL 認証プロトコルおよびパスワードをサポートします。 Choosing an APIも参照してください。

    古い ext/mysql 拡張機能を使用する必要がある場合、エスケープには mysql_escape_string() または addslashes() ではなく mysql_real_escape_string_quote() 関数を使用します。これは、mysql_real_escape_string_quote() のみが文字セット対応であるためです。マルチバイト文字セットを使用している場合は、他の関数を「バイパス」にできます (無効)。

  • Perl DBI: プレースホルダまたは quote() メソッドを使用してください。

  • Ruby DBI: プレースホルダまたは quote() メソッドを使用してください。

  • Java JDBC: PreparedStatement オブジェクトおよびプレースホルダを使用してください。

ほかのプログラミングインタフェースも似たような機能を持っている場合があります。


関連キーワード:  ユーザー, セキュリティー, パスワード, 認証, アプリケーション, プラガブル, 監査, サーバー, アカウント, 関数